From 732ba5d183b81606c1817a437097fb3b3fd4c62a Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Thu, 28 Mar 2024 07:47:19 -0500 Subject: [PATCH 01/23] update --- data/change_history/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/change_history/README.md diff --git a/data/change_history/README.md b/data/change_history/README.md new file mode 100644 index 0000000000..e69de29bb2 From c1139d9890fa27db168f56b5496b4ae29d67c940 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Thu, 28 Mar 2024 07:48:01 -0500 Subject: [PATCH 02/23] fix --- data/change_history/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 data/change_history/README.md diff --git a/data/change_history/README.md b/data/change_history/README.md deleted file mode 100644 index e69de29bb2..0000000000 From 4a99d74cf0e73ff8b91c501d575565596f59a909 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 9 Aug 2024 13:24:20 -0500 Subject: [PATCH 03/23] update --- cost/aws/cloudtrail_read_logging/CHANGELOG.md | 5 + cost/aws/cloudtrail_read_logging/README.md | 62 + .../aws_cloudtrail_read_logging.pt | 517 +++++++ ...aws_cloudtrail_read_logging_meta_parent.pt | 1244 +++++++++++++++++ .../master_policy_permissions_list.json | 43 + .../master_policy_permissions_list.yaml | 25 + .../meta_parent_policy_compiler.rb | 1 + .../validated_policy_templates.yaml | 1 + 8 files changed, 1898 insertions(+) create mode 100644 cost/aws/cloudtrail_read_logging/CHANGELOG.md create mode 100644 cost/aws/cloudtrail_read_logging/README.md create mode 100644 cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt create mode 100644 cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt diff --git a/cost/aws/cloudtrail_read_logging/CHANGELOG.md b/cost/aws/cloudtrail_read_logging/CHANGELOG.md new file mode 100644 index 0000000000..341687ee97 --- /dev/null +++ b/cost/aws/cloudtrail_read_logging/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## v0.1.0 + +- Initial Release diff --git a/cost/aws/cloudtrail_read_logging/README.md b/cost/aws/cloudtrail_read_logging/README.md new file mode 100644 index 0000000000..97a9fa17e2 --- /dev/null +++ b/cost/aws/cloudtrail_read_logging/README.md @@ -0,0 +1,62 @@ +# AWS CloudTrails With Read Logging Enabled + +## What It Does + +This policy template reports any AWS CloudTrail trails that log read actions. Logging read actions can greatly increase storage costs in some cases. Optionally, this report can be emailed and read logging can be disabled. + +## Input Parameters + +- *Email Addresses* - Email addresses of the recipients you wish to notify. +- *Account Number* - The Account number for use with the AWS STS Cross Account Role. Leave blank when using AWS IAM Access key and secret. It only needs to be passed when the desired AWS account is different than the one associated with the Flexera One credential. [More information is available in our documentation.](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1123608) +- *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. +- *Allow/Deny Regions List* - A list of regions to allow or deny for an AWS account. Please enter the regions code if SCP is enabled. See [Available Regions](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions) in AWS; otherwise, the policy may fail on regions that are disabled via SCP. Leave blank to consider all the regions. + +## Policy Actions + +- Sends an email notification. +- Disables read logging after approval. + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +- [**AWS Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1121575) (*provider=aws*) which has the following permissions: + - `sts:GetCallerIdentity` + - `cloudtrail:DescribeTrails` + - `cloudtrail:GetEventSelectors` + - `cloudtrail:PutEventSelectors`* + + \* Only required for taking action; the policy will still function in a read-only capacity without these permissions. + + Example IAM Permission Policy: + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "sts:GetCallerIdentity", + "cloudtrail:DescribeTrails", + "cloudtrail:GetEventSelectors", + "cloudtrail:PutEventSelectors" + ], + "Resource": "*" + } + ] + } + ``` + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `billing_center_viewer` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- AWS + +## Cost + +This Policy Template does not incur any cloud costs. diff --git a/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt b/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt new file mode 100644 index 0000000000..836aecb1da --- /dev/null +++ b/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt @@ -0,0 +1,517 @@ +name "AWS CloudTrails With Read Logging Enabled" +rs_pt_ver 20180301 +type "policy" +short_description "Reports AWS CloudTrail trails that are logging read events. See the [README](https://github.com/flexera-public/policy_templates/tree/master/cost/aws/cloudwatch_read_logging) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +category "Cost" +severity "low" +default_frequency "weekly" +info( + version: "0.1.0", + provider: "AWS", + service: "CloudTrail", + policy_set: "Logging" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_email" do + type "list" + category "Policy Settings" + label "Email Addresses" + description "A list of email addresses to notify." + default [] +end + +parameter "param_aws_account_number" do + type "string" + category "Policy Settings" + label "Account Number" + description "Leave blank; this is for automated use with Meta Policies. See README for more details." + default "" +end + +parameter "param_regions_allow_or_deny" do + type "string" + category "Filters" + label "Allow/Deny Regions" + description "Allow or Deny entered regions. See the README for more details" + allowed_values "Allow", "Deny" + default "Allow" +end + +parameter "param_regions_list" do + type "list" + category "Filters" + label "Allow/Deny Regions List" + description "A list of allowed or denied regions. See the README for more details" + allowed_pattern /^([a-zA-Z-_]+-[a-zA-Z0-9-_]+-[0-9-_]+,*|)+$/ + default [] +end + +parameter "param_automatic_action" do + type "list" + category "Actions" + label "Automatic Actions" + description "When this value is set, this policy will automatically take the selected action(s)" + allowed_values ["Disable Read Logging"] + default [] +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_aws" do + schemes "aws", "aws_sts" + label "AWS" + description "Select the AWS Credential from the list" + tags "provider=aws" + aws_account_number $param_aws_account_number +end + +credentials "auth_flexera" do + schemes "oauth2" + label "Flexera" + description "Select Flexera One OAuth2 credentials" + tags "provider=flexera" +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +# Get applied policy metadata for use later +datasource "ds_applied_policy" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) + header "Api-Version", "1.0" + end +end + +# Get region-specific Flexera API endpoints +datasource "ds_flexera_api_hosts" do + run_script $js_flexera_api_hosts, rs_optima_host +end + +script "js_flexera_api_hosts", type: "javascript" do + parameters "rs_optima_host" + result "result" + code <<-'EOS' + host_table = { + "api.optima.flexeraeng.com": { + flexera: "api.flexera.com", + fsm: "api.fsm.flexeraeng.com" + }, + "api.optima-eu.flexeraeng.com": { + flexera: "api.flexera.eu", + fsm: "api.fsm-eu.flexeraeng.com" + }, + "api.optima-apac.flexeraeng.com": { + flexera: "api.flexera.au", + fsm: "api.fsm-apac.flexeraeng.com" + } + } + + result = host_table[rs_optima_host] +EOS +end + +# Get AWS account info +datasource "ds_cloud_vendor_accounts" do + request do + auth $auth_flexera + host val($ds_flexera_api_hosts, 'flexera') + path join(["/finops-analytics/v1/orgs/", rs_org_id, "/cloud-vendor-accounts"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + collect jmes_path(response, "values[*]") do + field "id", jmes_path(col_item, "aws.accountId") + field "name", jmes_path(col_item, "name") + field "tags", jmes_path(col_item, "tags") + end + end +end + +datasource "ds_get_caller_identity" do + request do + auth $auth_aws + verb "GET" + host "sts.amazonaws.com" + path "/" + query "Action", "GetCallerIdentity" + query "Version", "2011-06-15" + header "User-Agent", "RS Policies" + end + result do + encoding "xml" + collect xpath(response, "//GetCallerIdentityResponse/GetCallerIdentityResult") do + field "account", xpath(col_item, "Account") + end + end +end + +datasource "ds_aws_account" do + run_script $js_aws_account, $ds_cloud_vendor_accounts, $ds_get_caller_identity +end + +script "js_aws_account", type:"javascript" do + parameters "ds_cloud_vendor_accounts", "ds_get_caller_identity" + result "result" + code <<-'EOS' + result = _.find(ds_cloud_vendor_accounts, function(account) { + return account['id'] == ds_get_caller_identity[0]['account'] + }) + + // This is in case the API does not return the relevant account info + if (result == undefined) { + result = { + id: ds_get_caller_identity[0]['account'], + name: "", + tags: {} + } + } +EOS +end + +datasource "ds_trail_list" do + request do + auth $auth_aws + host "cloudtrail.us-east-1.amazonaws.com" + path "/" + query "Action", "DescribeTrails" + header "User-Agent", "RS Policies" + header "Accept", "application/json" + # Header X-Meta-Flexera has no affect on datasource query, but is required for Meta Policies + # Forces `ds_is_deleted` datasource to run first during policy execution + header "Meta-Flexera", val($ds_is_deleted, "path") + end + result do + encoding "json" + collect jmes_path(response, "DescribeTrailsResponse.DescribeTrailsResult.trailList") do + field "name", jmes_path(col_item, "Name") + field "arn", jmes_path(col_item, "TrailARN") + field "region", jmes_path(col_item, "HomeRegion") + field "s3_bucket", jmes_path(col_item, "S3BucketName") + end + end +end + +datasource "ds_trail_list_region_filtered" do + run_script $js_trail_list_region_filtered, $ds_trail_list, $param_regions_list, $param_regions_allow_or_deny +end + +script "js_trail_list_region_filtered", type:"javascript" do + parameters "ds_trail_list", "param_regions_list", "param_regions_allow_or_deny" + result "result" + code <<-EOS + allow_deny_test = { "Allow": true, "Deny": false } + + if (param_regions_list.length > 0) { + result = _.filter(ds_trail_list, function(item) { + return _.contains(param_regions_list, item['region']) == allow_deny_test[param_regions_allow_or_deny] + }) + } else { + result = ds_trail_list + } +EOS +end + +datasource "ds_trail_list_with_selectors" do + iterate $ds_trail_list_region_filtered + request do + auth $auth_aws + verb "POST" + host join(["cloudtrail.", val(iter_item, "region"), ".amazonaws.com"]) + path "/" + header "User-Agent", "RS Policies" + header "X-Amz-Target", "com.amazonaws.cloudtrail.v20131101.CloudTrail_20131101.GetEventSelectors" + header "Content-Type", "application/x-amz-json-1.1" + body_field "TrailName", val(iter_item, "arn") + end + result do + encoding "json" + field "event_selectors", jmes_path(response, "EventSelectors") + field "name", val(iter_item, "name") + field "arn", val(iter_item, "arn") + field "region", val(iter_item, "region") + field "s3_bucket", val(iter_item, "s3_bucket") + end +end + +datasource "ds_trails_incident" do + run_script $js_trails_incident, $ds_trail_list_with_selectors, $ds_aws_account, $ds_applied_policy +end + +script "js_trails_incident", type:"javascript" do + parameters "ds_trail_list_with_selectors", "ds_aws_account", "ds_applied_policy" + result "result" + code <<-EOS + result = [] + + _.each(ds_trail_list_with_selectors, function(trail) { + has_selectors = typeof(trail['event_selectors']) == 'object' + logging_read = false + logging_write = false + logging_all = false + event_selectors = [] + fixed_selectors = [] + + if (has_selectors) { + event_selectors = trail['event_selectors'] + selector_types = _.pluck(event_selectors, 'ReadWriteType') + logging_all = _.contains(selector_types, 'All') + logging_read = _.contains(selector_types, 'ReadOnly') || logging_all + logging_write = _.contains(selector_types, 'WriteOnly') || logging_all + + _.each(event_selectors, function(selector) { + if (selector['ReadWriteType'] == 'All' || selector['ReadWriteType'] == 'WriteOnly') { + fixed_selectors.push({ + "DataResources": selector['DataResources'], + "ExcludeManagementEventSources": selector['ExcludeManagementEventSources'], + "IncludeManagementEvents": selector['IncludeManagementEvents'], + "ReadWriteType": "WriteOnly" + }) + } + }) + } + + if (logging_read) { + result.push({ + accountID: ds_aws_account['id'], + accountName: ds_aws_account['name'], + name: trail['name'], + id: trail['arn'], + region: trail['region'], + has_selectors: has_selectors, + logging_read: logging_read, + logging_write: logging_write, + logging_all: logging_all, + event_selectors: JSON.stringify(event_selectors), + fixed_selectors: JSON.stringify(fixed_selectors), + fixed_selectors_object: fixed_selectors, + policy_name: ds_applied_policy['name'] + }) + } + }) +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_trails_incident" do + validate_each $ds_trails_incident do + summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} AWS CloudTrails With Read Logging Enabled Found" + check logic_or($ds_parent_policy_terminated, eq(val(item, "id"), "")) + escalate $esc_email + escalate $esc_disable_read_logging + export do + resource_level true + field "accountID" do + label "Account ID" + end + field "accountName" do + label "Account Name" + end + field "name" do + label "Name" + end + field "id" do + label "ARN" + end + field "region" do + label "Region" + end + field "logging_read" do + label "Read Logging" + end + field "logging_write" do + label "Write Logging" + end + field "has_selectors" do + label "Has Event Selectors?" + end + field "event_selectors" do + label "Current Event Selectors" + end + field "fixed_selectors" do + label "Recommended Event Selectors" + end + field "fixed_selectors_object" do + label "Recommended Event Selectors (Object)" + end + end + end +end + +############################################################################### +# Escalations +############################################################################### + +escalation "esc_email" do + automatic true + label "Send Email" + description "Send incident email" + email $param_email +end + +escalation "esc_disable_read_logging" do + automatic contains($param_automatic_action, "Disable Read Logging") + label "Disable Read Logging" + description "Approval to disable read logging on all selected CloudTrails" + run "disable_read_logging_on_trails", data +end + +############################################################################### +# Cloud Workflow +############################################################################### + +define disable_read_logging_on_trails($data) return $all_responses do + $$all_responses = [] + + foreach $clb in $data do + sub on_error: handle_error() do + call disable_read_logging_on_trail($trail) retrieve $response + end + end + + if inspect($$errors) != "null" + raise join($$errors, "\n") + end +end + +define disable_read_logging_on_trail($trail) return $response do + $host = "cloudtrail." + $trail["region"] + ".amazonaws.com" + $href = "/" + $url = $host + $href + task_label("POST " + $url) + + $response = http_request( + auth: $$auth_aws, + https: true, + verb: "post", + host: $host, + href: $href, + body: { + "TrailName": $trail["name"], + "EventSelectors": $trail["fixed_selectors_object"] + } + ) + + task_label("POST AWS CloudTrail response: " + $trail["name"] + " " + to_json($response)) + $$all_responses << to_json({"req": "POST " + $url, "resp": $response}) + + if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 + raise "Unexpected response from POST AWS CloudTrail: "+ $trail["name"] + " " + to_json($response) + else + task_label("POST AWS CloudTrail successful: " + $trail["name"]) + end +end + +define handle_error() do + if !$$errors + $$errors = [] + end + $$errors << $_error["type"] + ": " + $_error["message"] + # We check for errors at the end, and raise them all together + # Skip errors handled by this definition + $_error_behavior = "skip" +end + +############################################################################### +# Meta Policy [alpha] +# Not intended to be modified or used by policy developers +############################################################################### + +# If the meta_parent_policy_id is not set it will evaluate to an empty string and we will look for the policy itself, +# if it is set we will look for the parent policy. +datasource "ds_get_policy" do + request do + auth $auth_flexera + host rs_governance_host + ignore_status [404] + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", switch(ne(meta_parent_policy_id,""), meta_parent_policy_id, policy_id) ]) + header "Api-Version", "1.0" + end + result do + encoding "json" + field "id", jmes_path(response, "id") + end +end + +datasource "ds_parent_policy_terminated" do + run_script $js_decide_if_self_terminate, $ds_get_policy, policy_id, meta_parent_policy_id +end + +# If the policy was applied by a meta_parent_policy we confirm it exists if it doesn't we confirm we are deleting +# This information is used in two places: +# - determining whether or not we make a delete call +# - determining if we should create an incident (we don't want to create an incident on the run where we terminate) +script "js_decide_if_self_terminate", type: "javascript" do + parameters "found", "self_policy_id", "meta_parent_policy_id" + result "result" + code <<-EOS + var result + if (meta_parent_policy_id != "" && found.id == undefined) { + result = true + } else { + result = false + } + EOS +end + +# Two potentials ways to set this up: +# - this way and make a unneeded 'get' request when not deleting +# - make the delete request an interate and have it iterate over an empty array when not deleting and an array with one item when deleting +script "js_make_terminate_request", type: "javascript" do + parameters "should_delete", "policy_id", "rs_project_id", "rs_governance_host" + result "request" + code <<-EOS + + var request = { + auth: 'auth_flexera', + host: rs_governance_host, + path: "/api/governance/projects/" + rs_project_id + "/applied_policies/" + policy_id, + headers: { + "API-Version": "1.0", + "Content-Type":"application/json" + }, + } + + if (should_delete) { + request.verb = 'DELETE' + } + EOS +end + +datasource "ds_terminate_self" do + request do + run_script $js_make_terminate_request, $ds_parent_policy_terminated, policy_id, rs_project_id, rs_governance_host + end +end + +datasource "ds_is_deleted" do + run_script $js_check_deleted, $ds_terminate_self +end + +# This is just a way to have the check delete request connect to the farthest leaf from policy. +# We want the delete check to the first thing the policy does to avoid the policy erroring before it can decide whether or not it needs to self terminate +# Example a customer deletes a credential and then terminates the parent policy. We still want the children to self terminate +# The only way I could see this not happening is if the user who applied the parent_meta_policy was offboarded or lost policy access, the policies who are impersonating the user +# would not have access to self-terminate +# It may be useful for the backend to enable a mass terminate at some point for all meta_child_policies associated with an id. +script "js_check_deleted", type: "javascript" do + parameters "response" + result "result" + code <<-EOS + result = {"path":"/"} + EOS +end diff --git a/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt b/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt new file mode 100644 index 0000000000..8374c348f7 --- /dev/null +++ b/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt @@ -0,0 +1,1244 @@ +name "Meta Parent: AWS CloudTrails With Read Logging Enabled" +rs_pt_ver 20180301 +type "policy" +short_description "**NOTE: Meta policies are an alpha feature. Please consult the [README](https://github.com/flexera-public/policy_templates/blob/master/README_META_POLICIES.md) before use.** Applies and manages \"child\" [AWS CloudTrails With Read Logging Enabled](https://github.com/flexera-public/policy_templates/tree/master/cost/aws/cloudtrail_read_logging) Policies." +severity "low" +category "Meta" +default_frequency "15 minutes" +info( + provider: "AWS", + version: "0.1.0", # 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 +) + +############################################################################## +# Parameters +############################################################################## + +## Meta Parent Parameters +## These are params specific to the meta parent policy. +parameter "param_combined_incident_email" do + type "list" + label "Email addresses for combined incident" + description "A list of email addresses to notify with the consolidated child policy incident." + default [] +end + +parameter "param_dimension_filter_includes" do + type "list" + label "Dimension Include Filters" + description <<-EOS + Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **INCLUDE** and be applied to. + Use = to match the entire value and =~ to match a substring contained in the value. + During each run this policy will select AWS Accounts who match **all** the filters defined and apply a child policy for each. + If no include filters are provided, then all AWS Accounts are included by default. + Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). + EOS + default [] +end + +parameter "param_dimension_filter_excludes" do + type "list" + label "Dimension Exclude Filters" + description <<-EOS + Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **EXCLUDE** and *not* have policy applied to. + Use = to match the entire value and =~ to match a substring contained in the value. + During each run this policy will select AWS Accounts who match **all** the filters defined here and excludes them from results. + Can be used to exclude specific AWS Accounts [`vendor_account=123456789012`] + Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). + EOS + default [] +end + +parameter "param_policy_schedule" do + type "string" + label "Child Policy Schedule" + description "The interval at which the child policy checks for conditions and generates incidents." + default "weekly" + allowed_values "daily", "weekly", "monthly" +end + +parameter "param_template_source" do + type "string" + label "Child Policy Template Source" + description "By default, will use the \"AWS CloudTrails With Read Logging Enabled\" Policy Template from Catalog. Optionally, you can use the \"AWS CloudTrails With Read Logging Enabled\" Policy Template uploaded in the current Flexera Project." + default "Published Catalog Template" + allowed_values "Published Catalog Template", "Uploaded Template" +end + +## Child Policy Parameters +parameter "param_regions_allow_or_deny" do + type "string" + category "Filters" + label "Allow/Deny Regions" + description "Allow or Deny entered regions. See the README for more details" + allowed_values "Allow", "Deny" + default "Allow" +end + +parameter "param_regions_list" do + type "list" + category "Filters" + label "Allow/Deny Regions List" + description "A list of allowed or denied regions. See the README for more details" + allowed_pattern /^([a-zA-Z-_]+-[a-zA-Z0-9-_]+-[0-9-_]+,*|)+$/ + default [] +end + +parameter "param_automatic_action" do + type "list" + category "Actions" + label "Automatic Actions" + description "When this value is set, this policy will automatically take the selected action(s)" + allowed_values ["Disable Read Logging"] + default [] +end + +############################################################################### +# Authentication +############################################################################### +credentials "auth_aws" do + schemes "aws", "aws_sts" + label "AWS" + description "Select the AWS Credential from the list" + tags "provider=aws" + aws_account_number $param_aws_account_number +end + +credentials "auth_flexera" do + schemes "oauth2" + label "Flexera" + description "Select Flexera One OAuth2 credentials" + tags "provider=flexera" +end + +############################################################################### +# Datasources +############################################################################### + +# Get Applied Parent Policy Details +datasource "ds_self_policy_information" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) + header "Api-Version", "1.0" + end + result do + encoding "json" + field "name", jmes_path(response, "name") + field "creator_id", jmes_path(response, "created_by.id") + field "credentials", jmes_path(response, "credentials") + field "options", jmes_path(response, "options") + end +end + +datasource "ds_child_policy_options" do + run_script $js_child_policy_options, $ds_self_policy_information +end + +script "js_child_policy_options", type: "javascript" do + parameters "ds_self_policy_information" + result "options" + code <<-EOS + // Filter Options that are not appropriate for Child Policy + var options = _.map(ds_self_policy_information.options, function(option){ + // param_combined_incident_email, param_dimension_filter_includes, param_dimension_filter_excludes, param_policy_schedule are exclusion to Meta Parent Policy Parameters + if (!_.contains(["param_combined_incident_email", "param_dimension_filter_includes", "param_dimension_filter_excludes", "param_policy_schedule", "param_template_source"], option.name)) { + return { "name": option.name, "value": option.value }; + } + }); + // Explicitly add param_email which is disabled/does not exist in meta parent policy + options.push({ + "name": "param_email", + "value": [] + }); + EOS +end + +datasource "ds_child_policy_options_map" do + run_script $js_child_policy_options_map, $ds_child_policy_options +end + +script "js_child_policy_options_map", type: "javascript" do + parameters "ds_child_policy_options" + result "options" + code <<-EOS + function format_options_keyvalue(options) { + var options_keyvalue_map = {}; + _.each(options, function(option) { + options_keyvalue_map[option.name] = option.value; + }); + return options_keyvalue_map; + } + var options = format_options_keyvalue(ds_child_policy_options) + EOS +end + +datasource "ds_format_self" do + run_script $js_format_self, $ds_self_policy_information, $ds_child_policy_options_map +end + +script "js_format_self", type: "javascript" do + parameters "ds_self_policy_information", "ds_child_policy_options_map" + result "formatted" + code <<-EOS + var formatted = { + "name": ds_self_policy_information["name"], + "creator_id": ds_self_policy_information["creator_id"], + "credentials": ds_self_policy_information["credentials"], + "options": ds_child_policy_options_map + }; + EOS +end + + +# Get Pulished Policy Details +datasource "ds_published_child_policy_information" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/orgs/", rs_org_id, "/published_templates"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + # Select the published policy that is published by "support@flexera.com" and matches the name of the child policy template + collect jq(response, '.items[] | select(.name == "AWS CloudTrails With Read Logging Enabled" and .created_by.email == "support@flexera.com")' ) do + field "name", jmes_path(col_item, "name") + field "href", jmes_path(col_item, "href") + field "short_description", jmes_path(col_item, "short_description") + end + end +end + +# Get Uploaded Policy Details +datasource "ds_project_child_policy_information" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/policy_templates"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + # Select the uploaded policy that matches the name of the child policy template + collect jq(response, '.items[] | select(.name == "AWS CloudTrails With Read Logging Enabled")' ) do + field "name", jmes_path(col_item, "name") + field "href", jmes_path(col_item, "href") + field "short_description", jmes_path(col_item, "short_description") + end + end +end + +datasource "ds_get_billing_centers" do + request do + auth $auth_flexera + host rs_optima_host + path join(["/analytics/orgs/",rs_org_id,"/billing_centers"]) + header "Api-Version", "1.0" + header "User-Agent", "RS Policies" + query "view", "allocation_table" + ignore_status [403] + end + result do + encoding "json" + # Select the Billing Centers that have "parent_id" undefined or "" (i.e. top-level Billing Centers) + collect jq(response, '.[] | select(.parent_id == null)' ) do + field "href", jq(col_item,".href") + field "id", jq(col_item,".id") + field "name", jq(col_item,".name") + field "parent_id", jq(col_item,".parent_id") + end + end +end + +script "js_make_billing_center_request", type: "javascript" do + parameters "rs_org_id", "rs_optima_host", "billing_centers_unformatted", "param_dimension_filter_includes", "param_dimension_filter_excludes" + result "request" + code <<-EOS + + billing_centers_formatted = [] + + for (x=0; x< billing_centers_unformatted.length; x++) { + billing_centers_formatted.push(billing_centers_unformatted[x]["id"]) + } + + finish = new Date() + finishFormatted = finish.toJSON().split("T")[0] + start = new Date() + start.setDate(start.getDate() - 30) + startFormatted = start.toJSON().split("T")[0] + + // Default dimensions and filter expressions required for meta parent policy + var dimensions = ["vendor_account", "vendor_account_name"]; + var filter_expressions = [ + { dimension: "vendor", type: "equal", value: "AWS" } + ] + + // Append to default dimensions and filter expressions using parent policy params + _.each(param_dimension_filter_includes, function (v) { + // split key=value string + if (v.indexOf('=~') == -1) { + var split = v.split("="); + var type = "equal" + } else { + var split = v.split("=~"); + var type = "substring" + } + + var k = split[0]; + var v = split[1]; + + // append to lists + dimensions.push(k); + + if (type == "equal") { + filter_expressions.push({ dimension: k, type: "equal", value: v }); + } else { + filter_expressions.push({ dimension: k, type: "substring", substring: v }); + } + }); + + // Append to filter expressions using exclude policy params + _.each(param_dimension_filter_excludes, function (v) { + // split key=value string + if (v.indexOf('=~') == -1) { + var split = v.split("="); + var type = "equal" + } else { + var split = v.split("=~"); + var type = "substring" + } + + var k = split[0]; + var v = split[1]; + + // append to lists + dimensions.push(k); + + if (type == "equal") { + filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "equal", "value": v } }); + } else { + filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "substring", "substring": v } }); + } + }); + + // Produces a duplicate-free version of the array + dimensions = _.uniq(dimensions); + + var body = { + "dimensions": dimensions, + "granularity":"day", + "start_at": startFormatted, + "end_at": finishFormatted, + "metrics":["cost_amortized_unblended_adj"], + "billing_center_ids": billing_centers_formatted, + "filter": + { + "type": "and", + "expressions": filter_expressions + }, + "summarized": true + } + var request = { + auth: 'auth_flexera', + host: rs_optima_host, + scheme: 'https', + verb: 'POST', + path: "/bill-analysis/orgs/"+ rs_org_id + "/costs/aggregated", + headers: { + "API-Version": "1.0", + "Content-Type":"application/json" + }, + body: JSON.stringify(body) + } + EOS +end + +# Get the AWS acounts +datasource "ds_get_aws_accounts" do + request do + run_script $js_make_billing_center_request, rs_org_id, rs_optima_host, $ds_get_billing_centers, $param_dimension_filter_includes, $param_dimension_filter_excludes + end + result do + encoding "json" + collect jmes_path(response,"rows[*]") do + field "aws_account_id", jmes_path(col_item,"dimensions.vendor_account") + field "aws_account_name", jmes_path(col_item,"dimensions.vendor_account_name") + end + end +end + +# Get Child policies +datasource "ds_get_existing_policies" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies"]) + header "Api-Version", "1.0" + query "meta_parent_policy_id", policy_id + end + result do + collect jq(response, '.items[]?') do + field "name", jq(col_item, ".name") + field "applied_policy_id", jq(col_item, ".id") + field "options", jq(col_item, ".options") + field "updated_at", jq(col_item, ".updated_at") + field "status", jq(col_item, ".status") + end + end +end + +# Get Child policies incidents +datasource "ds_get_existing_policies_incidents" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/incidents"]) + header "Api-Version", "1.0" + query "meta_parent_policy_id", policy_id + query "state", "triggered" + end + result do + collect jq(response, '.items[]?') do + field "incident_id", jq(col_item, ".id") + field "applied_policy_id", jq(col_item, ".applied_policy.id") + field "summary", jq(col_item, ".summary") + field "state", jq(col_item, ".state") + field "violation_data_count", jq(col_item, ".violation_data_count") + field "updated_at", jq(col_item, ".updated_at") + field "meta_parent_policy_id", jq(col_item, ".meta_parent_policy_id") + end + end +end + +datasource "ds_format_incidents" do + run_script $js_format_existing_policies_incidents, $ds_get_existing_policies_incidents +end + +script "js_format_existing_policies_incidents", type: "javascript" do + parameters "unformatted" + result "formatted" + code <<-EOS + formatted={} + + _.each(unformatted, function(incident) { + if (formatted[incident['applied_policy_id']] == undefined) { + formatted[incident['applied_policy_id']] = [] + } + + formatted[incident['applied_policy_id']].push(incident) + }) +EOS +end + +datasource "ds_format_existing_policies" do + run_script $js_format_existing_policies, $ds_get_existing_policies, $ds_format_incidents +end + +# format +# duplicates logic should compare updated at +# we can validate update here when destructring the existing policy options, don't need updated at +# format options +script "js_format_existing_policies", type: "javascript" do + parameters "ds_get_existing_policies", "ds_format_incidents" + result "result" + code <<-EOS + function format_options_keyvalue(options) { + var options_keyvalue_map = {}; + _.each(options, function(option) { + options_keyvalue_map[option.name] = option.value; + }); + return options_keyvalue_map; + } + + result = {} + formatted = {} + duplicates = [] + // tracking holds all existing policies and later can be used to determine if existing policies should be deleted [i.e. if cloud account was removed] + tracking = {} + + for (x=0; x newDate) { + duplicates.push({ + "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], + "applied_policy_name":ds_get_existing_policies[x]["name"], + "status":ds_get_existing_policies[x]["status"], + "updated_at":ds_get_existing_policies[x]["updated_at"], + "incident": incident, + "incident2": incident2 + }) + } else { + duplicates.push({ + "applied_policy_id":current["applied_policy_id"], + "applied_policy_name":current["applied_policy_name"], + "status":current["status"], + "updated_at":current["updated_at"], + "incident": current["incident"], + "incident2": current["incident2"] + }) + formatted[aws_account_id] = { + "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], + "applied_policy_name":ds_get_existing_policies[x]["name"], + "status":ds_get_existing_policies[x]["status"], + "updated_at":ds_get_existing_policies[x]["updated_at"], + "incident": incident, + "incident2": incident2, + "options": options + } + + } + } + } + + result.formatted=formatted + result.duplicates=duplicates + result.tracking=tracking + EOS +end + +datasource "ds_take_in_parameters" do + run_script $js_take_in_parameters, $ds_get_aws_accounts, $ds_format_self, first($ds_published_child_policy_information), first($ds_project_child_policy_information), $ds_format_existing_policies, $ds_child_policy_options, $ds_child_policy_options_map, $param_template_source, $param_policy_schedule, policy_id, f1_app_host, rs_org_id, rs_project_id +end + +# hardcode template href with id from catalog +# catalog policies show in customer's published templates with their org id +# "template_href": "/api/governance/orgs/" + rs_org_id + "/published_templates/62618616e3dff80001572bf0" +# update logic: the only reason we're going to update the child policies for is changes to options +# and only some options, email is always blank and aws_account_id is tied to the idenity of each policy, so: new account creation, removal of account: termination +# param_automatic_action is a list with only one action, unless the person is applying using an API and putting the same value multiple times this should either be a length of 0 or 1 +# param_log_to_cm_audit_entries is a String of Yes or No +# param_exclude_tags and param_allowed_regions are arrays. I'm doing an update on the order changing but the values remaining the same. +# If we only want to do an update on the values changing we could sort before doing the equality check. +script "js_take_in_parameters", type: "javascript" do + parameters "ds_get_aws_accounts", "ds_format_self", "ds_published_child_policy_information", "ds_project_child_policy_information", "ds_format_existing_policies", "ds_child_policy_options", "ds_child_policy_options_map", "param_template_source", "param_policy_schedule", "meta_parent_policy_id", "f1_app_host", "rs_org_id", "rs_project_id" + result "grid_and_cwf" + code <<-EOS + + // Set Child Policy Information based on param_template_source value + if (param_template_source == "Published Catalog Template") { + child_policy_information = ds_published_child_policy_information + } else { + child_policy_information = ds_project_child_policy_information + } + + max_actions = 50; + + grid_and_cwf={grid:[], to_create:[], to_update:[], to_delete:[], parent_policy:ds_format_self}; + + should_keep = ds_format_existing_policies.tracking; + + // Construct UI URL prefixes for policy template summary + ui_url_prefix = "https://" + f1_app_host + "/orgs/" + rs_org_id; + applied_policy_url_prefix = ui_url_prefix + "/automation/applied-policies/projects/" + rs_project_id + "?noIndex=1&policyId="; + incident_url_prefix = ui_url_prefix + "/automation/incidents/projects/" + rs_project_id + "?noIndex=1&incidentId="; + + function add_to_grid(ep, action) { + policy_status={ + "id": ep["applied_policy_id"], + "policy_name": ep["applied_policy_name"] + '||' + applied_policy_url_prefix + ep["applied_policy_id"], + "meta_policy_status": action, + "policy_status": ep["status"], + "policy_last_update": ep["updated_at"], + }; + + if (ep.incident != null && ep.incident != undefined) { + // Remove policy name from summary when applicable + summary_parts = ep.incident.summary.split(':') + summary = summary_parts[summary_parts.length - 1].trim() + + policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident.incident_id; + policy_status["incident_state"] = ep.incident.state; + policy_status["incident_violation_data_count"] = ep.incident.violation_data_count; + policy_status["incident_last_update"] = ep.incident.updated_at; + } + + if (ep.incident2 != null && ep.incident2 != undefined) { + // Remove policy name from summary when applicable + summary_parts = ep.incident2.summary.split(':') + summary = summary_parts[summary_parts.length - 1].trim() + + policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident2.incident_id; + policy_status["incident_state"] = ep.incident2.state; + policy_status["incident2_violation_data_count"] = ep.incident2.violation_data_count; + policy_status["incident2_last_update"] = ep.incident2.updated_at; + } + + grid_and_cwf.grid.push(policy_status); + } + + for (x=0; x -1) { + _.each(incident["violation_data"], function(violation) { + violation["incident_id"] = incident["id"]; + result.push(violation); + }); + } + }); +EOS +end + + +# Escalation for Disable Read Logging +escalation "esc_disable_read_logging" do + automatic false # Do not automatically action from meta parent. the child will handle automatic escalations if param is set + label "Disable Read Logging" + description "Approval to disable read logging on all selected CloudTrails" + + # Run declaration should go at end, after any parameters that may exist + run "esc_disable_read_logging", data, rs_governance_host, rs_project_id +end +define esc_disable_read_logging($data, $governance_host, $rs_project_id) do + $actions_options = [] + call child_run_action($data, $governance_host, $rs_project_id, "Disable Read Logging", $action_options) +end + + +# Summary and a conditional incident which will show up if any policy is being applied, updated or deleted. +# Minimum of 1 incident, max of four +# Could swap the summary to only showing running +# Could also just have one incident and use meta_status to determine which escalation happens +policy "policy_scheduled_report" do + # Consolidated Incident Check(s) + # Consolidated incident for AWS CloudTrails With Read Logging Enabled Found + validate $ds_trails_incident_combined_incidents do + summary_template "Consolidated Incident: {{ len data }} AWS CloudTrails With Read Logging Enabled Found" + escalate $esc_email + escalate $esc_disable_read_logging + check eq(size(data), 0) + export do + resource_level true + field "accountID" do + label "Account ID" + end + field "accountName" do + label "Account Name" + end + field "name" do + label "Name" + end + field "id" do + label "ARN" + end + field "region" do + label "Region" + end + field "logging_read" do + label "Read Logging" + end + field "logging_write" do + label "Write Logging" + end + field "has_selectors" do + label "Has Event Selectors?" + end + field "event_selectors" do + label "Current Event Selectors" + end + field "fixed_selectors" do + label "Recommended Event Selectors" + end + field "fixed_selectors_object" do + label "Recommend + field "incident_id" do + label "Child Incident ID" + end + end + end + + # Status Incident Check + validate $ds_take_in_parameters do + summary_template "{{ data.parent_policy.name }}: Status of Child Policies" + detail_template <<-EOS +The current status of Child Policies for **{{ data.parent_policy.name }}**: + +Total Child Applied Policies: {{ len data.grid }} +EOS + check false # always trigger this status incident + export "grid" do + resource_level true + field "id" do + label "Applied Policy ID" + end + field "policy_name" do + label "Applied Policy Name" + format "link-external" + end + field "meta_policy_status" do + label "Meta Child Policy Status" + end + field "policy_status" do + label "Policy Status" + end + field "policy_last_update" do + label "Policy Last Update" + end + field "incident_summary" do + label "Incident Summary" + format "link-external" + end + field "incident_state" do + label "Incident State" + end + field "incident_violation_data_count" do + label "Incident Violation Count" + end + field "incident_last_update" do + label "Incident Last Update" + end + field "incident2_summary" do + label "Incident 2 Summary" + format "link-external" + end + field "incident2_state" do + label "Incident 2 State" + end + field "incident2_violation_data_count" do + label "Incident 2 Violation Count" + end + field "incident2_last_update" do + label "Incident 2 Last Update" + end + end + end + + # Create Child Policies Incident Check + validate $ds_to_create do + summary_template "Policies being created" + detail_template <<-EOS + Policies Being Created: + + | Applied Policy | + | --------------- | + {{ range data -}} + | {{ .name }} | + {{ end -}} + EOS + escalate $create_policies + check eq(size(data),0) + end + + # Update Child Policies Incident Check + validate $ds_to_update do + summary_template "Policies being updated" + detail_template <<-EOS + Policies Being Updated: + + | Applied Policy | + | --------------- | + {{ range data -}} + | {{ .name }} | + {{ end -}} + EOS + escalate $update_policies + check eq(size(data),0) + end + + # Delete Child Policies Incident Check + validate $ds_to_delete do + summary_template "Policies being deleted" + detail_template <<-EOS + Policies being Deleted: + + | Applied Policy | + | --------------- | + {{ range data -}} + | {{ .name }} | + {{ end -}} + EOS + escalate $delete_policies + check eq(size(data),0) + end +end + +# Begin Shared Functions for Child Actions from Consolidated Incident +define groupByIncidentID($data) return $incidents do + # Empty hash to store incidents is incident_id + $incidents = {} + + task_label("Grouping items by Incident ID") + $index = 1 + foreach $item in $data do + task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))) + if !$incidents[$item["incident_id"]] + #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". New Incident: "+$item["incident_id"]) + $incidents[$item["incident_id"]] = {"id": $item["incident_id"], "resource_ids": []} + end + #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". Appending Resource: "+$item["id"]) + # Append resource id to the list for the incident + $incidents[$item["incident_id"]]["resource_ids"] = $incidents[$item["incident_id"]]["resource_ids"] + [$item["id"]] + end +end + +define child_run_action($data, $governance_host, $rs_project_id, $action_label, $action_options) do + # Empty global array for log strings, helpful for debugging + $$debug = [] + + # Group Resources by Incident ID + # This reduces the number of requests made to the Flexera API + call groupByIncidentID($data) retrieve $incidents + $$debug_incidents = to_json($incidents) + + call runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) + + # If we encountered any errors, use `raise` to mark the CWF process as errored + if inspect($$errors) != "null" + raise join($$errors,"\n") + end + + # If we made it here, all actions completed successfully + # Celebrate Success! + task_label("All \""+$action_label+"\" actions completed successfully!") +end + +define runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) do + foreach $id in keys($incidents) do + sub on_error: handle_error() do + $incident = $incidents[$id] + task_label("Triggering action \""+$action_label+"\" on "+size($incident["resource_ids"])+" count resources via incident "+$incident["id"]) + $request = { + auth: $$auth_flexera, + verb: "get", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"]]), + headers: { "Api-Version": "1.0" }, + query_strings: { "view": "extended" } + } + $response = http_request($request) + $$debug << to_json({ + "request": $request, + "response": $response + }) + $action_id = "" + foreach $action in $response["body"]["available_actions"] do + # If we have not already found the action id, and the label matches, set the action id + # The first check is to prevent looking through the entire list if we already have the id + if $action["label"] == $action_label + $action_id = $action["id"] + end + end + if $action_id == "" + raise "Could not find action id for \""+$action_label+"\" response="+to_json($response) + end + # Now we are reach to trigger the action + $request = { + auth: $$auth_flexera, + verb: "post", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"],"/actions/", $action_id,"/run_action"]), + headers: { "Api-Version": "1.0" }, + body: { "options":[{ "name": "ids", "value": $incident["resource_ids"] }] } + } + # If the action has parameters, add them to the request body + if type($action_options) == "array" && size($action_options) > 0 + $request["body"]["options"] = $request["body"]["options"] + $action_options + end + $response = http_request($request) + $$debug << to_json({ + "request": $request, + "response": $response + }) + # Get the action status from response header + $action_location = $response["headers"]["Location"] + + # Setup some variables for the wait loop + $action_status = "" + $loop_count = 0 + $loop_endtime = now() + (3600*2) # 2 hours from now + # [ queued, aborted, pending, running, completed, failed, denied ] + while ($action_status !~ /^(aborted|completed|failed|denied)/) && (now() <= $loop_endtime) do + # Using Loop Count to slowly increment the sleep time + # This is to prevent the loop from hammering our APIs + $loop_count = $loop_count + 1 + task_label("action_status=\""+$action_status+"\" Sleeping for "+to_s($loop_count)+" seconds") + sleep($loop_count) + task_label("action_status=\""+$action_status+"\" Getting action status") + $request = { + auth: $$auth_flexera, + verb: "get", + https: true, + host: $governance_host, + href: $action_location, + headers: { "Api-Version": "1.0" }, + query_strings: { "view": "extended" } + } + $response = http_request($request) + $$debug << to_json({ + "request": $request, + "response": $response + }) + $action_status = $response["body"]["status"] + end + if ($action_status != "completed") + # Check if we are out of time first + if (now() > $loop_endtime) + raise "action_status=\""+$action_status+"\" Action did not complete in time. Aborting to prevent endless loop. action_status_json="+to_json($response) + else + # If not, then it was aborted, failed or denied + raise "action_status=\""+$action_status+"\" Action did not complete as expected. action_status_json="+to_json($response) + end + end + # If we made it here, the action completed successfully + task_label("action_status=\""+$action_status+"\" Action completed successfully") + end + end +end +# End Shared Functions for Child Actions from Consolidated Incident + +# CWF function to handle errors +define handle_error() do + if !$$errors + $$errors = [] + end + $$errors << $_error["type"] + ": " + $_error["message"] + # We check for errors at the end, and raise them all together + # Skip errors handled by this definition + $_error_behavior = "skip" +end + +# Used only for emailing the combined child incident if so desired +escalation "esc_email" do + automatic true + label "Send Email" + description "Send incident email" + email $param_combined_incident_email +end + +escalation "create_policies" do + run "create_applied_policies", data, rs_governance_host, rs_project_id +end + +# if name !=null +define create_applied_policies($data, $governance_host, $rs_project_id) return $responses do + $responses = [] + $$debug = [] + $item_index = 0 + $item_total = size($data) + foreach $item in $data do + $item_index = $item_index + 1 + $status = to_s("("+$item_index+"/"+$item_total+")") + task_label($status+" Creating Applied Policy with Options: " + to_json($item["options"])) + $response = http_request( + auth: $$auth_flexera, + verb: "post", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies"]), + headers: { "Api-Version": "1.0" }, + body: { + "name": $item["name"], + "description": $item["description"], + "template_href": $item["template_href"], + "frequency": $item["frequency"], + "options": $item["options"], + "credentials": $item["credentials"], + "meta_parent_policy_id": $item["meta_parent_policy_id"] + } + ) + $responses << $response + $$debug << to_json({ + "response": $response, + "item": $item, + "governance_host": $governance_host + }) + end +end + +escalation "update_policies" do + run "update_applied_policies", data, rs_governance_host, rs_project_id +end + +define update_applied_policies($data, $governance_host, $rs_project_id) return $responses do + $responses = [] + $$debug = [] + $item_index = 0 + $item_total = size($data) + foreach $item in $data do + $item_index = $item_index + 1 + $status = to_s("("+$item_index+"/"+$item_total+")") + task_label($status+" Updating Applied Policy with Options: " + to_json($item["options"])) + $response = http_request( + auth: $$auth_flexera, + verb: "patch", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["applied_policy_id"]]), + headers: { "Api-Version": "1.0" }, + body: { + "options": $item["options"] + } + ) + $responses << $response + $$debug << to_json({ + "response": $response, + "item": $item, + "governance_host": $governance_host + }) + end +end + +escalation "delete_policies" do + run "delete_applied_policies", data, rs_governance_host, rs_project_id +end + +define delete_applied_policies($data, $governance_host, $rs_project_id) return $responses do + $responses = [] + $$debug = [] + $item_index = 0 + $item_total = size($data) + foreach $item in $data do + $item_index = $item_index + 1 + $status = to_s("("+$item_index+"/"+$item_total+")") + task_label($status+" Deleting Applied Policy: " + $item["id"]) + $response = http_request( + auth: $$auth_flexera, + verb: "delete", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["id"]]), + headers: { "Api-Version": "1.0" } + ) + $responses << $response + $$debug << to_json({ + "response": $response, + "item": $item, + "governance_host": $governance_host + }) + end +end diff --git a/data/policy_permissions_list/master_policy_permissions_list.json b/data/policy_permissions_list/master_policy_permissions_list.json index 5983f009d7..4fb440b601 100644 --- a/data/policy_permissions_list/master_policy_permissions_list.json +++ b/data/policy_permissions_list/master_policy_permissions_list.json @@ -1381,6 +1381,49 @@ } ] }, + { + "id": "./cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt", + "name": "AWS CloudTrails With Read Logging Enabled", + "version": "0.1.0", + "providers": [ + { + "name": "aws", + "permissions": [ + { + "name": "sts:GetCallerIdentity", + "read_only": true, + "required": true + }, + { + "name": "cloudtrail:DescribeTrails", + "read_only": true, + "required": true + }, + { + "name": "cloudtrail:GetEventSelectors", + "read_only": true, + "required": true + }, + { + "name": "cloudtrail:PutEventSelectors", + "read_only": false, + "required": false, + "description": "Only required for taking action; the policy will still function in a read-only capacity without these permissions." + } + ] + }, + { + "name": "flexera", + "permissions": [ + { + "name": "billing_center_viewer", + "read_only": true, + "required": true + } + ] + } + ] + }, { "id": "./cost/aws/eks_without_spot/aws_eks_without_spot.pt", "name": "AWS EKS Clusters Without Spot Instances", diff --git a/data/policy_permissions_list/master_policy_permissions_list.yaml b/data/policy_permissions_list/master_policy_permissions_list.yaml index c64e8fa28d..6372bec248 100644 --- a/data/policy_permissions_list/master_policy_permissions_list.yaml +++ b/data/policy_permissions_list/master_policy_permissions_list.yaml @@ -797,6 +797,31 @@ - name: billing_center_viewer read_only: true required: true +- id: "./cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt" + name: AWS CloudTrails With Read Logging Enabled + version: 0.1.0 + :providers: + - :name: aws + :permissions: + - name: sts:GetCallerIdentity + read_only: true + required: true + - name: cloudtrail:DescribeTrails + read_only: true + required: true + - name: cloudtrail:GetEventSelectors + read_only: true + required: true + - name: cloudtrail:PutEventSelectors + read_only: false + required: false + description: Only required for taking action; the policy will still function + in a read-only capacity without these permissions. + - :name: flexera + :permissions: + - name: billing_center_viewer + read_only: true + required: true - id: "./cost/aws/eks_without_spot/aws_eks_without_spot.pt" name: AWS EKS Clusters Without Spot Instances version: 0.1.0 diff --git a/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb b/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb index 98efaadfc3..3b55d42155 100644 --- a/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb +++ b/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb @@ -15,6 +15,7 @@ "../../compliance/aws/rds_backup/aws_rds_backup.pt", "../../compliance/aws/untagged_resources/aws_untagged_resources.pt", "../../cost/aws/burstable_ec2_instances/aws_burstable_ec2_instances.pt", + "../../cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt", "../../cost/aws/eks_without_spot/aws_eks_without_spot.pt", "../../cost/aws/gp3_volume_upgrade/aws_upgrade_to_gp3_volume.pt", "../../cost/aws/idle_compute_instances/idle_compute_instances.pt", diff --git a/tools/policy_master_permission_generation/validated_policy_templates.yaml b/tools/policy_master_permission_generation/validated_policy_templates.yaml index e089f8c74d..b0b2c84082 100644 --- a/tools/policy_master_permission_generation/validated_policy_templates.yaml +++ b/tools/policy_master_permission_generation/validated_policy_templates.yaml @@ -16,6 +16,7 @@ validated_policy_templates: - "./compliance/aws/untagged_resources/aws_untagged_resources.pt" - "./cost/aws/burstable_ec2_instances/aws_burstable_ec2_instances.pt" - "./cost/aws/cheaper_regions/aws_cheaper_regions.pt" +- "./cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt" - "./cost/aws/eks_without_spot/aws_eks_without_spot.pt" - "./cost/aws/extended_support/aws_extended_support.pt" - "./cost/aws/gp3_volume_upgrade/aws_upgrade_to_gp3_volume.pt" From 3b1c72e896e63148ec329e6a15523c9af0a2aea7 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 9 Aug 2024 13:25:55 -0500 Subject: [PATCH 04/23] fix --- cost/aws/cloudtrail_read_logging/CHANGELOG.md | 5 - cost/aws/cloudtrail_read_logging/README.md | 62 - .../aws_cloudtrail_read_logging.pt | 517 ------- ...aws_cloudtrail_read_logging_meta_parent.pt | 1244 ----------------- .../meta_parent_policy_compiler.rb | 1 - .../validated_policy_templates.yaml | 1 - 6 files changed, 1830 deletions(-) delete mode 100644 cost/aws/cloudtrail_read_logging/CHANGELOG.md delete mode 100644 cost/aws/cloudtrail_read_logging/README.md delete mode 100644 cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt delete mode 100644 cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt diff --git a/cost/aws/cloudtrail_read_logging/CHANGELOG.md b/cost/aws/cloudtrail_read_logging/CHANGELOG.md deleted file mode 100644 index 341687ee97..0000000000 --- a/cost/aws/cloudtrail_read_logging/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Changelog - -## v0.1.0 - -- Initial Release diff --git a/cost/aws/cloudtrail_read_logging/README.md b/cost/aws/cloudtrail_read_logging/README.md deleted file mode 100644 index 97a9fa17e2..0000000000 --- a/cost/aws/cloudtrail_read_logging/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# AWS CloudTrails With Read Logging Enabled - -## What It Does - -This policy template reports any AWS CloudTrail trails that log read actions. Logging read actions can greatly increase storage costs in some cases. Optionally, this report can be emailed and read logging can be disabled. - -## Input Parameters - -- *Email Addresses* - Email addresses of the recipients you wish to notify. -- *Account Number* - The Account number for use with the AWS STS Cross Account Role. Leave blank when using AWS IAM Access key and secret. It only needs to be passed when the desired AWS account is different than the one associated with the Flexera One credential. [More information is available in our documentation.](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1123608) -- *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. -- *Allow/Deny Regions List* - A list of regions to allow or deny for an AWS account. Please enter the regions code if SCP is enabled. See [Available Regions](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions) in AWS; otherwise, the policy may fail on regions that are disabled via SCP. Leave blank to consider all the regions. - -## Policy Actions - -- Sends an email notification. -- Disables read logging after approval. - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -- [**AWS Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1121575) (*provider=aws*) which has the following permissions: - - `sts:GetCallerIdentity` - - `cloudtrail:DescribeTrails` - - `cloudtrail:GetEventSelectors` - - `cloudtrail:PutEventSelectors`* - - \* Only required for taking action; the policy will still function in a read-only capacity without these permissions. - - Example IAM Permission Policy: - - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "sts:GetCallerIdentity", - "cloudtrail:DescribeTrails", - "cloudtrail:GetEventSelectors", - "cloudtrail:PutEventSelectors" - ], - "Resource": "*" - } - ] - } - ``` - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `billing_center_viewer` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- AWS - -## Cost - -This Policy Template does not incur any cloud costs. diff --git a/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt b/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt deleted file mode 100644 index 836aecb1da..0000000000 --- a/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt +++ /dev/null @@ -1,517 +0,0 @@ -name "AWS CloudTrails With Read Logging Enabled" -rs_pt_ver 20180301 -type "policy" -short_description "Reports AWS CloudTrail trails that are logging read events. See the [README](https://github.com/flexera-public/policy_templates/tree/master/cost/aws/cloudwatch_read_logging) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -category "Cost" -severity "low" -default_frequency "weekly" -info( - version: "0.1.0", - provider: "AWS", - service: "CloudTrail", - policy_set: "Logging" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_email" do - type "list" - category "Policy Settings" - label "Email Addresses" - description "A list of email addresses to notify." - default [] -end - -parameter "param_aws_account_number" do - type "string" - category "Policy Settings" - label "Account Number" - description "Leave blank; this is for automated use with Meta Policies. See README for more details." - default "" -end - -parameter "param_regions_allow_or_deny" do - type "string" - category "Filters" - label "Allow/Deny Regions" - description "Allow or Deny entered regions. See the README for more details" - allowed_values "Allow", "Deny" - default "Allow" -end - -parameter "param_regions_list" do - type "list" - category "Filters" - label "Allow/Deny Regions List" - description "A list of allowed or denied regions. See the README for more details" - allowed_pattern /^([a-zA-Z-_]+-[a-zA-Z0-9-_]+-[0-9-_]+,*|)+$/ - default [] -end - -parameter "param_automatic_action" do - type "list" - category "Actions" - label "Automatic Actions" - description "When this value is set, this policy will automatically take the selected action(s)" - allowed_values ["Disable Read Logging"] - default [] -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_aws" do - schemes "aws", "aws_sts" - label "AWS" - description "Select the AWS Credential from the list" - tags "provider=aws" - aws_account_number $param_aws_account_number -end - -credentials "auth_flexera" do - schemes "oauth2" - label "Flexera" - description "Select Flexera One OAuth2 credentials" - tags "provider=flexera" -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -# Get applied policy metadata for use later -datasource "ds_applied_policy" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) - header "Api-Version", "1.0" - end -end - -# Get region-specific Flexera API endpoints -datasource "ds_flexera_api_hosts" do - run_script $js_flexera_api_hosts, rs_optima_host -end - -script "js_flexera_api_hosts", type: "javascript" do - parameters "rs_optima_host" - result "result" - code <<-'EOS' - host_table = { - "api.optima.flexeraeng.com": { - flexera: "api.flexera.com", - fsm: "api.fsm.flexeraeng.com" - }, - "api.optima-eu.flexeraeng.com": { - flexera: "api.flexera.eu", - fsm: "api.fsm-eu.flexeraeng.com" - }, - "api.optima-apac.flexeraeng.com": { - flexera: "api.flexera.au", - fsm: "api.fsm-apac.flexeraeng.com" - } - } - - result = host_table[rs_optima_host] -EOS -end - -# Get AWS account info -datasource "ds_cloud_vendor_accounts" do - request do - auth $auth_flexera - host val($ds_flexera_api_hosts, 'flexera') - path join(["/finops-analytics/v1/orgs/", rs_org_id, "/cloud-vendor-accounts"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - collect jmes_path(response, "values[*]") do - field "id", jmes_path(col_item, "aws.accountId") - field "name", jmes_path(col_item, "name") - field "tags", jmes_path(col_item, "tags") - end - end -end - -datasource "ds_get_caller_identity" do - request do - auth $auth_aws - verb "GET" - host "sts.amazonaws.com" - path "/" - query "Action", "GetCallerIdentity" - query "Version", "2011-06-15" - header "User-Agent", "RS Policies" - end - result do - encoding "xml" - collect xpath(response, "//GetCallerIdentityResponse/GetCallerIdentityResult") do - field "account", xpath(col_item, "Account") - end - end -end - -datasource "ds_aws_account" do - run_script $js_aws_account, $ds_cloud_vendor_accounts, $ds_get_caller_identity -end - -script "js_aws_account", type:"javascript" do - parameters "ds_cloud_vendor_accounts", "ds_get_caller_identity" - result "result" - code <<-'EOS' - result = _.find(ds_cloud_vendor_accounts, function(account) { - return account['id'] == ds_get_caller_identity[0]['account'] - }) - - // This is in case the API does not return the relevant account info - if (result == undefined) { - result = { - id: ds_get_caller_identity[0]['account'], - name: "", - tags: {} - } - } -EOS -end - -datasource "ds_trail_list" do - request do - auth $auth_aws - host "cloudtrail.us-east-1.amazonaws.com" - path "/" - query "Action", "DescribeTrails" - header "User-Agent", "RS Policies" - header "Accept", "application/json" - # Header X-Meta-Flexera has no affect on datasource query, but is required for Meta Policies - # Forces `ds_is_deleted` datasource to run first during policy execution - header "Meta-Flexera", val($ds_is_deleted, "path") - end - result do - encoding "json" - collect jmes_path(response, "DescribeTrailsResponse.DescribeTrailsResult.trailList") do - field "name", jmes_path(col_item, "Name") - field "arn", jmes_path(col_item, "TrailARN") - field "region", jmes_path(col_item, "HomeRegion") - field "s3_bucket", jmes_path(col_item, "S3BucketName") - end - end -end - -datasource "ds_trail_list_region_filtered" do - run_script $js_trail_list_region_filtered, $ds_trail_list, $param_regions_list, $param_regions_allow_or_deny -end - -script "js_trail_list_region_filtered", type:"javascript" do - parameters "ds_trail_list", "param_regions_list", "param_regions_allow_or_deny" - result "result" - code <<-EOS - allow_deny_test = { "Allow": true, "Deny": false } - - if (param_regions_list.length > 0) { - result = _.filter(ds_trail_list, function(item) { - return _.contains(param_regions_list, item['region']) == allow_deny_test[param_regions_allow_or_deny] - }) - } else { - result = ds_trail_list - } -EOS -end - -datasource "ds_trail_list_with_selectors" do - iterate $ds_trail_list_region_filtered - request do - auth $auth_aws - verb "POST" - host join(["cloudtrail.", val(iter_item, "region"), ".amazonaws.com"]) - path "/" - header "User-Agent", "RS Policies" - header "X-Amz-Target", "com.amazonaws.cloudtrail.v20131101.CloudTrail_20131101.GetEventSelectors" - header "Content-Type", "application/x-amz-json-1.1" - body_field "TrailName", val(iter_item, "arn") - end - result do - encoding "json" - field "event_selectors", jmes_path(response, "EventSelectors") - field "name", val(iter_item, "name") - field "arn", val(iter_item, "arn") - field "region", val(iter_item, "region") - field "s3_bucket", val(iter_item, "s3_bucket") - end -end - -datasource "ds_trails_incident" do - run_script $js_trails_incident, $ds_trail_list_with_selectors, $ds_aws_account, $ds_applied_policy -end - -script "js_trails_incident", type:"javascript" do - parameters "ds_trail_list_with_selectors", "ds_aws_account", "ds_applied_policy" - result "result" - code <<-EOS - result = [] - - _.each(ds_trail_list_with_selectors, function(trail) { - has_selectors = typeof(trail['event_selectors']) == 'object' - logging_read = false - logging_write = false - logging_all = false - event_selectors = [] - fixed_selectors = [] - - if (has_selectors) { - event_selectors = trail['event_selectors'] - selector_types = _.pluck(event_selectors, 'ReadWriteType') - logging_all = _.contains(selector_types, 'All') - logging_read = _.contains(selector_types, 'ReadOnly') || logging_all - logging_write = _.contains(selector_types, 'WriteOnly') || logging_all - - _.each(event_selectors, function(selector) { - if (selector['ReadWriteType'] == 'All' || selector['ReadWriteType'] == 'WriteOnly') { - fixed_selectors.push({ - "DataResources": selector['DataResources'], - "ExcludeManagementEventSources": selector['ExcludeManagementEventSources'], - "IncludeManagementEvents": selector['IncludeManagementEvents'], - "ReadWriteType": "WriteOnly" - }) - } - }) - } - - if (logging_read) { - result.push({ - accountID: ds_aws_account['id'], - accountName: ds_aws_account['name'], - name: trail['name'], - id: trail['arn'], - region: trail['region'], - has_selectors: has_selectors, - logging_read: logging_read, - logging_write: logging_write, - logging_all: logging_all, - event_selectors: JSON.stringify(event_selectors), - fixed_selectors: JSON.stringify(fixed_selectors), - fixed_selectors_object: fixed_selectors, - policy_name: ds_applied_policy['name'] - }) - } - }) -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_trails_incident" do - validate_each $ds_trails_incident do - summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} AWS CloudTrails With Read Logging Enabled Found" - check logic_or($ds_parent_policy_terminated, eq(val(item, "id"), "")) - escalate $esc_email - escalate $esc_disable_read_logging - export do - resource_level true - field "accountID" do - label "Account ID" - end - field "accountName" do - label "Account Name" - end - field "name" do - label "Name" - end - field "id" do - label "ARN" - end - field "region" do - label "Region" - end - field "logging_read" do - label "Read Logging" - end - field "logging_write" do - label "Write Logging" - end - field "has_selectors" do - label "Has Event Selectors?" - end - field "event_selectors" do - label "Current Event Selectors" - end - field "fixed_selectors" do - label "Recommended Event Selectors" - end - field "fixed_selectors_object" do - label "Recommended Event Selectors (Object)" - end - end - end -end - -############################################################################### -# Escalations -############################################################################### - -escalation "esc_email" do - automatic true - label "Send Email" - description "Send incident email" - email $param_email -end - -escalation "esc_disable_read_logging" do - automatic contains($param_automatic_action, "Disable Read Logging") - label "Disable Read Logging" - description "Approval to disable read logging on all selected CloudTrails" - run "disable_read_logging_on_trails", data -end - -############################################################################### -# Cloud Workflow -############################################################################### - -define disable_read_logging_on_trails($data) return $all_responses do - $$all_responses = [] - - foreach $clb in $data do - sub on_error: handle_error() do - call disable_read_logging_on_trail($trail) retrieve $response - end - end - - if inspect($$errors) != "null" - raise join($$errors, "\n") - end -end - -define disable_read_logging_on_trail($trail) return $response do - $host = "cloudtrail." + $trail["region"] + ".amazonaws.com" - $href = "/" - $url = $host + $href - task_label("POST " + $url) - - $response = http_request( - auth: $$auth_aws, - https: true, - verb: "post", - host: $host, - href: $href, - body: { - "TrailName": $trail["name"], - "EventSelectors": $trail["fixed_selectors_object"] - } - ) - - task_label("POST AWS CloudTrail response: " + $trail["name"] + " " + to_json($response)) - $$all_responses << to_json({"req": "POST " + $url, "resp": $response}) - - if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 - raise "Unexpected response from POST AWS CloudTrail: "+ $trail["name"] + " " + to_json($response) - else - task_label("POST AWS CloudTrail successful: " + $trail["name"]) - end -end - -define handle_error() do - if !$$errors - $$errors = [] - end - $$errors << $_error["type"] + ": " + $_error["message"] - # We check for errors at the end, and raise them all together - # Skip errors handled by this definition - $_error_behavior = "skip" -end - -############################################################################### -# Meta Policy [alpha] -# Not intended to be modified or used by policy developers -############################################################################### - -# If the meta_parent_policy_id is not set it will evaluate to an empty string and we will look for the policy itself, -# if it is set we will look for the parent policy. -datasource "ds_get_policy" do - request do - auth $auth_flexera - host rs_governance_host - ignore_status [404] - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", switch(ne(meta_parent_policy_id,""), meta_parent_policy_id, policy_id) ]) - header "Api-Version", "1.0" - end - result do - encoding "json" - field "id", jmes_path(response, "id") - end -end - -datasource "ds_parent_policy_terminated" do - run_script $js_decide_if_self_terminate, $ds_get_policy, policy_id, meta_parent_policy_id -end - -# If the policy was applied by a meta_parent_policy we confirm it exists if it doesn't we confirm we are deleting -# This information is used in two places: -# - determining whether or not we make a delete call -# - determining if we should create an incident (we don't want to create an incident on the run where we terminate) -script "js_decide_if_self_terminate", type: "javascript" do - parameters "found", "self_policy_id", "meta_parent_policy_id" - result "result" - code <<-EOS - var result - if (meta_parent_policy_id != "" && found.id == undefined) { - result = true - } else { - result = false - } - EOS -end - -# Two potentials ways to set this up: -# - this way and make a unneeded 'get' request when not deleting -# - make the delete request an interate and have it iterate over an empty array when not deleting and an array with one item when deleting -script "js_make_terminate_request", type: "javascript" do - parameters "should_delete", "policy_id", "rs_project_id", "rs_governance_host" - result "request" - code <<-EOS - - var request = { - auth: 'auth_flexera', - host: rs_governance_host, - path: "/api/governance/projects/" + rs_project_id + "/applied_policies/" + policy_id, - headers: { - "API-Version": "1.0", - "Content-Type":"application/json" - }, - } - - if (should_delete) { - request.verb = 'DELETE' - } - EOS -end - -datasource "ds_terminate_self" do - request do - run_script $js_make_terminate_request, $ds_parent_policy_terminated, policy_id, rs_project_id, rs_governance_host - end -end - -datasource "ds_is_deleted" do - run_script $js_check_deleted, $ds_terminate_self -end - -# This is just a way to have the check delete request connect to the farthest leaf from policy. -# We want the delete check to the first thing the policy does to avoid the policy erroring before it can decide whether or not it needs to self terminate -# Example a customer deletes a credential and then terminates the parent policy. We still want the children to self terminate -# The only way I could see this not happening is if the user who applied the parent_meta_policy was offboarded or lost policy access, the policies who are impersonating the user -# would not have access to self-terminate -# It may be useful for the backend to enable a mass terminate at some point for all meta_child_policies associated with an id. -script "js_check_deleted", type: "javascript" do - parameters "response" - result "result" - code <<-EOS - result = {"path":"/"} - EOS -end diff --git a/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt b/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt deleted file mode 100644 index 8374c348f7..0000000000 --- a/cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging_meta_parent.pt +++ /dev/null @@ -1,1244 +0,0 @@ -name "Meta Parent: AWS CloudTrails With Read Logging Enabled" -rs_pt_ver 20180301 -type "policy" -short_description "**NOTE: Meta policies are an alpha feature. Please consult the [README](https://github.com/flexera-public/policy_templates/blob/master/README_META_POLICIES.md) before use.** Applies and manages \"child\" [AWS CloudTrails With Read Logging Enabled](https://github.com/flexera-public/policy_templates/tree/master/cost/aws/cloudtrail_read_logging) Policies." -severity "low" -category "Meta" -default_frequency "15 minutes" -info( - provider: "AWS", - version: "0.1.0", # 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 -) - -############################################################################## -# Parameters -############################################################################## - -## Meta Parent Parameters -## These are params specific to the meta parent policy. -parameter "param_combined_incident_email" do - type "list" - label "Email addresses for combined incident" - description "A list of email addresses to notify with the consolidated child policy incident." - default [] -end - -parameter "param_dimension_filter_includes" do - type "list" - label "Dimension Include Filters" - description <<-EOS - Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **INCLUDE** and be applied to. - Use = to match the entire value and =~ to match a substring contained in the value. - During each run this policy will select AWS Accounts who match **all** the filters defined and apply a child policy for each. - If no include filters are provided, then all AWS Accounts are included by default. - Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). - EOS - default [] -end - -parameter "param_dimension_filter_excludes" do - type "list" - label "Dimension Exclude Filters" - description <<-EOS - Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **EXCLUDE** and *not* have policy applied to. - Use = to match the entire value and =~ to match a substring contained in the value. - During each run this policy will select AWS Accounts who match **all** the filters defined here and excludes them from results. - Can be used to exclude specific AWS Accounts [`vendor_account=123456789012`] - Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). - EOS - default [] -end - -parameter "param_policy_schedule" do - type "string" - label "Child Policy Schedule" - description "The interval at which the child policy checks for conditions and generates incidents." - default "weekly" - allowed_values "daily", "weekly", "monthly" -end - -parameter "param_template_source" do - type "string" - label "Child Policy Template Source" - description "By default, will use the \"AWS CloudTrails With Read Logging Enabled\" Policy Template from Catalog. Optionally, you can use the \"AWS CloudTrails With Read Logging Enabled\" Policy Template uploaded in the current Flexera Project." - default "Published Catalog Template" - allowed_values "Published Catalog Template", "Uploaded Template" -end - -## Child Policy Parameters -parameter "param_regions_allow_or_deny" do - type "string" - category "Filters" - label "Allow/Deny Regions" - description "Allow or Deny entered regions. See the README for more details" - allowed_values "Allow", "Deny" - default "Allow" -end - -parameter "param_regions_list" do - type "list" - category "Filters" - label "Allow/Deny Regions List" - description "A list of allowed or denied regions. See the README for more details" - allowed_pattern /^([a-zA-Z-_]+-[a-zA-Z0-9-_]+-[0-9-_]+,*|)+$/ - default [] -end - -parameter "param_automatic_action" do - type "list" - category "Actions" - label "Automatic Actions" - description "When this value is set, this policy will automatically take the selected action(s)" - allowed_values ["Disable Read Logging"] - default [] -end - -############################################################################### -# Authentication -############################################################################### -credentials "auth_aws" do - schemes "aws", "aws_sts" - label "AWS" - description "Select the AWS Credential from the list" - tags "provider=aws" - aws_account_number $param_aws_account_number -end - -credentials "auth_flexera" do - schemes "oauth2" - label "Flexera" - description "Select Flexera One OAuth2 credentials" - tags "provider=flexera" -end - -############################################################################### -# Datasources -############################################################################### - -# Get Applied Parent Policy Details -datasource "ds_self_policy_information" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) - header "Api-Version", "1.0" - end - result do - encoding "json" - field "name", jmes_path(response, "name") - field "creator_id", jmes_path(response, "created_by.id") - field "credentials", jmes_path(response, "credentials") - field "options", jmes_path(response, "options") - end -end - -datasource "ds_child_policy_options" do - run_script $js_child_policy_options, $ds_self_policy_information -end - -script "js_child_policy_options", type: "javascript" do - parameters "ds_self_policy_information" - result "options" - code <<-EOS - // Filter Options that are not appropriate for Child Policy - var options = _.map(ds_self_policy_information.options, function(option){ - // param_combined_incident_email, param_dimension_filter_includes, param_dimension_filter_excludes, param_policy_schedule are exclusion to Meta Parent Policy Parameters - if (!_.contains(["param_combined_incident_email", "param_dimension_filter_includes", "param_dimension_filter_excludes", "param_policy_schedule", "param_template_source"], option.name)) { - return { "name": option.name, "value": option.value }; - } - }); - // Explicitly add param_email which is disabled/does not exist in meta parent policy - options.push({ - "name": "param_email", - "value": [] - }); - EOS -end - -datasource "ds_child_policy_options_map" do - run_script $js_child_policy_options_map, $ds_child_policy_options -end - -script "js_child_policy_options_map", type: "javascript" do - parameters "ds_child_policy_options" - result "options" - code <<-EOS - function format_options_keyvalue(options) { - var options_keyvalue_map = {}; - _.each(options, function(option) { - options_keyvalue_map[option.name] = option.value; - }); - return options_keyvalue_map; - } - var options = format_options_keyvalue(ds_child_policy_options) - EOS -end - -datasource "ds_format_self" do - run_script $js_format_self, $ds_self_policy_information, $ds_child_policy_options_map -end - -script "js_format_self", type: "javascript" do - parameters "ds_self_policy_information", "ds_child_policy_options_map" - result "formatted" - code <<-EOS - var formatted = { - "name": ds_self_policy_information["name"], - "creator_id": ds_self_policy_information["creator_id"], - "credentials": ds_self_policy_information["credentials"], - "options": ds_child_policy_options_map - }; - EOS -end - - -# Get Pulished Policy Details -datasource "ds_published_child_policy_information" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/orgs/", rs_org_id, "/published_templates"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - # Select the published policy that is published by "support@flexera.com" and matches the name of the child policy template - collect jq(response, '.items[] | select(.name == "AWS CloudTrails With Read Logging Enabled" and .created_by.email == "support@flexera.com")' ) do - field "name", jmes_path(col_item, "name") - field "href", jmes_path(col_item, "href") - field "short_description", jmes_path(col_item, "short_description") - end - end -end - -# Get Uploaded Policy Details -datasource "ds_project_child_policy_information" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/policy_templates"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - # Select the uploaded policy that matches the name of the child policy template - collect jq(response, '.items[] | select(.name == "AWS CloudTrails With Read Logging Enabled")' ) do - field "name", jmes_path(col_item, "name") - field "href", jmes_path(col_item, "href") - field "short_description", jmes_path(col_item, "short_description") - end - end -end - -datasource "ds_get_billing_centers" do - request do - auth $auth_flexera - host rs_optima_host - path join(["/analytics/orgs/",rs_org_id,"/billing_centers"]) - header "Api-Version", "1.0" - header "User-Agent", "RS Policies" - query "view", "allocation_table" - ignore_status [403] - end - result do - encoding "json" - # Select the Billing Centers that have "parent_id" undefined or "" (i.e. top-level Billing Centers) - collect jq(response, '.[] | select(.parent_id == null)' ) do - field "href", jq(col_item,".href") - field "id", jq(col_item,".id") - field "name", jq(col_item,".name") - field "parent_id", jq(col_item,".parent_id") - end - end -end - -script "js_make_billing_center_request", type: "javascript" do - parameters "rs_org_id", "rs_optima_host", "billing_centers_unformatted", "param_dimension_filter_includes", "param_dimension_filter_excludes" - result "request" - code <<-EOS - - billing_centers_formatted = [] - - for (x=0; x< billing_centers_unformatted.length; x++) { - billing_centers_formatted.push(billing_centers_unformatted[x]["id"]) - } - - finish = new Date() - finishFormatted = finish.toJSON().split("T")[0] - start = new Date() - start.setDate(start.getDate() - 30) - startFormatted = start.toJSON().split("T")[0] - - // Default dimensions and filter expressions required for meta parent policy - var dimensions = ["vendor_account", "vendor_account_name"]; - var filter_expressions = [ - { dimension: "vendor", type: "equal", value: "AWS" } - ] - - // Append to default dimensions and filter expressions using parent policy params - _.each(param_dimension_filter_includes, function (v) { - // split key=value string - if (v.indexOf('=~') == -1) { - var split = v.split("="); - var type = "equal" - } else { - var split = v.split("=~"); - var type = "substring" - } - - var k = split[0]; - var v = split[1]; - - // append to lists - dimensions.push(k); - - if (type == "equal") { - filter_expressions.push({ dimension: k, type: "equal", value: v }); - } else { - filter_expressions.push({ dimension: k, type: "substring", substring: v }); - } - }); - - // Append to filter expressions using exclude policy params - _.each(param_dimension_filter_excludes, function (v) { - // split key=value string - if (v.indexOf('=~') == -1) { - var split = v.split("="); - var type = "equal" - } else { - var split = v.split("=~"); - var type = "substring" - } - - var k = split[0]; - var v = split[1]; - - // append to lists - dimensions.push(k); - - if (type == "equal") { - filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "equal", "value": v } }); - } else { - filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "substring", "substring": v } }); - } - }); - - // Produces a duplicate-free version of the array - dimensions = _.uniq(dimensions); - - var body = { - "dimensions": dimensions, - "granularity":"day", - "start_at": startFormatted, - "end_at": finishFormatted, - "metrics":["cost_amortized_unblended_adj"], - "billing_center_ids": billing_centers_formatted, - "filter": - { - "type": "and", - "expressions": filter_expressions - }, - "summarized": true - } - var request = { - auth: 'auth_flexera', - host: rs_optima_host, - scheme: 'https', - verb: 'POST', - path: "/bill-analysis/orgs/"+ rs_org_id + "/costs/aggregated", - headers: { - "API-Version": "1.0", - "Content-Type":"application/json" - }, - body: JSON.stringify(body) - } - EOS -end - -# Get the AWS acounts -datasource "ds_get_aws_accounts" do - request do - run_script $js_make_billing_center_request, rs_org_id, rs_optima_host, $ds_get_billing_centers, $param_dimension_filter_includes, $param_dimension_filter_excludes - end - result do - encoding "json" - collect jmes_path(response,"rows[*]") do - field "aws_account_id", jmes_path(col_item,"dimensions.vendor_account") - field "aws_account_name", jmes_path(col_item,"dimensions.vendor_account_name") - end - end -end - -# Get Child policies -datasource "ds_get_existing_policies" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies"]) - header "Api-Version", "1.0" - query "meta_parent_policy_id", policy_id - end - result do - collect jq(response, '.items[]?') do - field "name", jq(col_item, ".name") - field "applied_policy_id", jq(col_item, ".id") - field "options", jq(col_item, ".options") - field "updated_at", jq(col_item, ".updated_at") - field "status", jq(col_item, ".status") - end - end -end - -# Get Child policies incidents -datasource "ds_get_existing_policies_incidents" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/incidents"]) - header "Api-Version", "1.0" - query "meta_parent_policy_id", policy_id - query "state", "triggered" - end - result do - collect jq(response, '.items[]?') do - field "incident_id", jq(col_item, ".id") - field "applied_policy_id", jq(col_item, ".applied_policy.id") - field "summary", jq(col_item, ".summary") - field "state", jq(col_item, ".state") - field "violation_data_count", jq(col_item, ".violation_data_count") - field "updated_at", jq(col_item, ".updated_at") - field "meta_parent_policy_id", jq(col_item, ".meta_parent_policy_id") - end - end -end - -datasource "ds_format_incidents" do - run_script $js_format_existing_policies_incidents, $ds_get_existing_policies_incidents -end - -script "js_format_existing_policies_incidents", type: "javascript" do - parameters "unformatted" - result "formatted" - code <<-EOS - formatted={} - - _.each(unformatted, function(incident) { - if (formatted[incident['applied_policy_id']] == undefined) { - formatted[incident['applied_policy_id']] = [] - } - - formatted[incident['applied_policy_id']].push(incident) - }) -EOS -end - -datasource "ds_format_existing_policies" do - run_script $js_format_existing_policies, $ds_get_existing_policies, $ds_format_incidents -end - -# format -# duplicates logic should compare updated at -# we can validate update here when destructring the existing policy options, don't need updated at -# format options -script "js_format_existing_policies", type: "javascript" do - parameters "ds_get_existing_policies", "ds_format_incidents" - result "result" - code <<-EOS - function format_options_keyvalue(options) { - var options_keyvalue_map = {}; - _.each(options, function(option) { - options_keyvalue_map[option.name] = option.value; - }); - return options_keyvalue_map; - } - - result = {} - formatted = {} - duplicates = [] - // tracking holds all existing policies and later can be used to determine if existing policies should be deleted [i.e. if cloud account was removed] - tracking = {} - - for (x=0; x newDate) { - duplicates.push({ - "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], - "applied_policy_name":ds_get_existing_policies[x]["name"], - "status":ds_get_existing_policies[x]["status"], - "updated_at":ds_get_existing_policies[x]["updated_at"], - "incident": incident, - "incident2": incident2 - }) - } else { - duplicates.push({ - "applied_policy_id":current["applied_policy_id"], - "applied_policy_name":current["applied_policy_name"], - "status":current["status"], - "updated_at":current["updated_at"], - "incident": current["incident"], - "incident2": current["incident2"] - }) - formatted[aws_account_id] = { - "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], - "applied_policy_name":ds_get_existing_policies[x]["name"], - "status":ds_get_existing_policies[x]["status"], - "updated_at":ds_get_existing_policies[x]["updated_at"], - "incident": incident, - "incident2": incident2, - "options": options - } - - } - } - } - - result.formatted=formatted - result.duplicates=duplicates - result.tracking=tracking - EOS -end - -datasource "ds_take_in_parameters" do - run_script $js_take_in_parameters, $ds_get_aws_accounts, $ds_format_self, first($ds_published_child_policy_information), first($ds_project_child_policy_information), $ds_format_existing_policies, $ds_child_policy_options, $ds_child_policy_options_map, $param_template_source, $param_policy_schedule, policy_id, f1_app_host, rs_org_id, rs_project_id -end - -# hardcode template href with id from catalog -# catalog policies show in customer's published templates with their org id -# "template_href": "/api/governance/orgs/" + rs_org_id + "/published_templates/62618616e3dff80001572bf0" -# update logic: the only reason we're going to update the child policies for is changes to options -# and only some options, email is always blank and aws_account_id is tied to the idenity of each policy, so: new account creation, removal of account: termination -# param_automatic_action is a list with only one action, unless the person is applying using an API and putting the same value multiple times this should either be a length of 0 or 1 -# param_log_to_cm_audit_entries is a String of Yes or No -# param_exclude_tags and param_allowed_regions are arrays. I'm doing an update on the order changing but the values remaining the same. -# If we only want to do an update on the values changing we could sort before doing the equality check. -script "js_take_in_parameters", type: "javascript" do - parameters "ds_get_aws_accounts", "ds_format_self", "ds_published_child_policy_information", "ds_project_child_policy_information", "ds_format_existing_policies", "ds_child_policy_options", "ds_child_policy_options_map", "param_template_source", "param_policy_schedule", "meta_parent_policy_id", "f1_app_host", "rs_org_id", "rs_project_id" - result "grid_and_cwf" - code <<-EOS - - // Set Child Policy Information based on param_template_source value - if (param_template_source == "Published Catalog Template") { - child_policy_information = ds_published_child_policy_information - } else { - child_policy_information = ds_project_child_policy_information - } - - max_actions = 50; - - grid_and_cwf={grid:[], to_create:[], to_update:[], to_delete:[], parent_policy:ds_format_self}; - - should_keep = ds_format_existing_policies.tracking; - - // Construct UI URL prefixes for policy template summary - ui_url_prefix = "https://" + f1_app_host + "/orgs/" + rs_org_id; - applied_policy_url_prefix = ui_url_prefix + "/automation/applied-policies/projects/" + rs_project_id + "?noIndex=1&policyId="; - incident_url_prefix = ui_url_prefix + "/automation/incidents/projects/" + rs_project_id + "?noIndex=1&incidentId="; - - function add_to_grid(ep, action) { - policy_status={ - "id": ep["applied_policy_id"], - "policy_name": ep["applied_policy_name"] + '||' + applied_policy_url_prefix + ep["applied_policy_id"], - "meta_policy_status": action, - "policy_status": ep["status"], - "policy_last_update": ep["updated_at"], - }; - - if (ep.incident != null && ep.incident != undefined) { - // Remove policy name from summary when applicable - summary_parts = ep.incident.summary.split(':') - summary = summary_parts[summary_parts.length - 1].trim() - - policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident.incident_id; - policy_status["incident_state"] = ep.incident.state; - policy_status["incident_violation_data_count"] = ep.incident.violation_data_count; - policy_status["incident_last_update"] = ep.incident.updated_at; - } - - if (ep.incident2 != null && ep.incident2 != undefined) { - // Remove policy name from summary when applicable - summary_parts = ep.incident2.summary.split(':') - summary = summary_parts[summary_parts.length - 1].trim() - - policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident2.incident_id; - policy_status["incident_state"] = ep.incident2.state; - policy_status["incident2_violation_data_count"] = ep.incident2.violation_data_count; - policy_status["incident2_last_update"] = ep.incident2.updated_at; - } - - grid_and_cwf.grid.push(policy_status); - } - - for (x=0; x -1) { - _.each(incident["violation_data"], function(violation) { - violation["incident_id"] = incident["id"]; - result.push(violation); - }); - } - }); -EOS -end - - -# Escalation for Disable Read Logging -escalation "esc_disable_read_logging" do - automatic false # Do not automatically action from meta parent. the child will handle automatic escalations if param is set - label "Disable Read Logging" - description "Approval to disable read logging on all selected CloudTrails" - - # Run declaration should go at end, after any parameters that may exist - run "esc_disable_read_logging", data, rs_governance_host, rs_project_id -end -define esc_disable_read_logging($data, $governance_host, $rs_project_id) do - $actions_options = [] - call child_run_action($data, $governance_host, $rs_project_id, "Disable Read Logging", $action_options) -end - - -# Summary and a conditional incident which will show up if any policy is being applied, updated or deleted. -# Minimum of 1 incident, max of four -# Could swap the summary to only showing running -# Could also just have one incident and use meta_status to determine which escalation happens -policy "policy_scheduled_report" do - # Consolidated Incident Check(s) - # Consolidated incident for AWS CloudTrails With Read Logging Enabled Found - validate $ds_trails_incident_combined_incidents do - summary_template "Consolidated Incident: {{ len data }} AWS CloudTrails With Read Logging Enabled Found" - escalate $esc_email - escalate $esc_disable_read_logging - check eq(size(data), 0) - export do - resource_level true - field "accountID" do - label "Account ID" - end - field "accountName" do - label "Account Name" - end - field "name" do - label "Name" - end - field "id" do - label "ARN" - end - field "region" do - label "Region" - end - field "logging_read" do - label "Read Logging" - end - field "logging_write" do - label "Write Logging" - end - field "has_selectors" do - label "Has Event Selectors?" - end - field "event_selectors" do - label "Current Event Selectors" - end - field "fixed_selectors" do - label "Recommended Event Selectors" - end - field "fixed_selectors_object" do - label "Recommend - field "incident_id" do - label "Child Incident ID" - end - end - end - - # Status Incident Check - validate $ds_take_in_parameters do - summary_template "{{ data.parent_policy.name }}: Status of Child Policies" - detail_template <<-EOS -The current status of Child Policies for **{{ data.parent_policy.name }}**: - -Total Child Applied Policies: {{ len data.grid }} -EOS - check false # always trigger this status incident - export "grid" do - resource_level true - field "id" do - label "Applied Policy ID" - end - field "policy_name" do - label "Applied Policy Name" - format "link-external" - end - field "meta_policy_status" do - label "Meta Child Policy Status" - end - field "policy_status" do - label "Policy Status" - end - field "policy_last_update" do - label "Policy Last Update" - end - field "incident_summary" do - label "Incident Summary" - format "link-external" - end - field "incident_state" do - label "Incident State" - end - field "incident_violation_data_count" do - label "Incident Violation Count" - end - field "incident_last_update" do - label "Incident Last Update" - end - field "incident2_summary" do - label "Incident 2 Summary" - format "link-external" - end - field "incident2_state" do - label "Incident 2 State" - end - field "incident2_violation_data_count" do - label "Incident 2 Violation Count" - end - field "incident2_last_update" do - label "Incident 2 Last Update" - end - end - end - - # Create Child Policies Incident Check - validate $ds_to_create do - summary_template "Policies being created" - detail_template <<-EOS - Policies Being Created: - - | Applied Policy | - | --------------- | - {{ range data -}} - | {{ .name }} | - {{ end -}} - EOS - escalate $create_policies - check eq(size(data),0) - end - - # Update Child Policies Incident Check - validate $ds_to_update do - summary_template "Policies being updated" - detail_template <<-EOS - Policies Being Updated: - - | Applied Policy | - | --------------- | - {{ range data -}} - | {{ .name }} | - {{ end -}} - EOS - escalate $update_policies - check eq(size(data),0) - end - - # Delete Child Policies Incident Check - validate $ds_to_delete do - summary_template "Policies being deleted" - detail_template <<-EOS - Policies being Deleted: - - | Applied Policy | - | --------------- | - {{ range data -}} - | {{ .name }} | - {{ end -}} - EOS - escalate $delete_policies - check eq(size(data),0) - end -end - -# Begin Shared Functions for Child Actions from Consolidated Incident -define groupByIncidentID($data) return $incidents do - # Empty hash to store incidents is incident_id - $incidents = {} - - task_label("Grouping items by Incident ID") - $index = 1 - foreach $item in $data do - task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))) - if !$incidents[$item["incident_id"]] - #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". New Incident: "+$item["incident_id"]) - $incidents[$item["incident_id"]] = {"id": $item["incident_id"], "resource_ids": []} - end - #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". Appending Resource: "+$item["id"]) - # Append resource id to the list for the incident - $incidents[$item["incident_id"]]["resource_ids"] = $incidents[$item["incident_id"]]["resource_ids"] + [$item["id"]] - end -end - -define child_run_action($data, $governance_host, $rs_project_id, $action_label, $action_options) do - # Empty global array for log strings, helpful for debugging - $$debug = [] - - # Group Resources by Incident ID - # This reduces the number of requests made to the Flexera API - call groupByIncidentID($data) retrieve $incidents - $$debug_incidents = to_json($incidents) - - call runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) - - # If we encountered any errors, use `raise` to mark the CWF process as errored - if inspect($$errors) != "null" - raise join($$errors,"\n") - end - - # If we made it here, all actions completed successfully - # Celebrate Success! - task_label("All \""+$action_label+"\" actions completed successfully!") -end - -define runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) do - foreach $id in keys($incidents) do - sub on_error: handle_error() do - $incident = $incidents[$id] - task_label("Triggering action \""+$action_label+"\" on "+size($incident["resource_ids"])+" count resources via incident "+$incident["id"]) - $request = { - auth: $$auth_flexera, - verb: "get", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"]]), - headers: { "Api-Version": "1.0" }, - query_strings: { "view": "extended" } - } - $response = http_request($request) - $$debug << to_json({ - "request": $request, - "response": $response - }) - $action_id = "" - foreach $action in $response["body"]["available_actions"] do - # If we have not already found the action id, and the label matches, set the action id - # The first check is to prevent looking through the entire list if we already have the id - if $action["label"] == $action_label - $action_id = $action["id"] - end - end - if $action_id == "" - raise "Could not find action id for \""+$action_label+"\" response="+to_json($response) - end - # Now we are reach to trigger the action - $request = { - auth: $$auth_flexera, - verb: "post", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"],"/actions/", $action_id,"/run_action"]), - headers: { "Api-Version": "1.0" }, - body: { "options":[{ "name": "ids", "value": $incident["resource_ids"] }] } - } - # If the action has parameters, add them to the request body - if type($action_options) == "array" && size($action_options) > 0 - $request["body"]["options"] = $request["body"]["options"] + $action_options - end - $response = http_request($request) - $$debug << to_json({ - "request": $request, - "response": $response - }) - # Get the action status from response header - $action_location = $response["headers"]["Location"] - - # Setup some variables for the wait loop - $action_status = "" - $loop_count = 0 - $loop_endtime = now() + (3600*2) # 2 hours from now - # [ queued, aborted, pending, running, completed, failed, denied ] - while ($action_status !~ /^(aborted|completed|failed|denied)/) && (now() <= $loop_endtime) do - # Using Loop Count to slowly increment the sleep time - # This is to prevent the loop from hammering our APIs - $loop_count = $loop_count + 1 - task_label("action_status=\""+$action_status+"\" Sleeping for "+to_s($loop_count)+" seconds") - sleep($loop_count) - task_label("action_status=\""+$action_status+"\" Getting action status") - $request = { - auth: $$auth_flexera, - verb: "get", - https: true, - host: $governance_host, - href: $action_location, - headers: { "Api-Version": "1.0" }, - query_strings: { "view": "extended" } - } - $response = http_request($request) - $$debug << to_json({ - "request": $request, - "response": $response - }) - $action_status = $response["body"]["status"] - end - if ($action_status != "completed") - # Check if we are out of time first - if (now() > $loop_endtime) - raise "action_status=\""+$action_status+"\" Action did not complete in time. Aborting to prevent endless loop. action_status_json="+to_json($response) - else - # If not, then it was aborted, failed or denied - raise "action_status=\""+$action_status+"\" Action did not complete as expected. action_status_json="+to_json($response) - end - end - # If we made it here, the action completed successfully - task_label("action_status=\""+$action_status+"\" Action completed successfully") - end - end -end -# End Shared Functions for Child Actions from Consolidated Incident - -# CWF function to handle errors -define handle_error() do - if !$$errors - $$errors = [] - end - $$errors << $_error["type"] + ": " + $_error["message"] - # We check for errors at the end, and raise them all together - # Skip errors handled by this definition - $_error_behavior = "skip" -end - -# Used only for emailing the combined child incident if so desired -escalation "esc_email" do - automatic true - label "Send Email" - description "Send incident email" - email $param_combined_incident_email -end - -escalation "create_policies" do - run "create_applied_policies", data, rs_governance_host, rs_project_id -end - -# if name !=null -define create_applied_policies($data, $governance_host, $rs_project_id) return $responses do - $responses = [] - $$debug = [] - $item_index = 0 - $item_total = size($data) - foreach $item in $data do - $item_index = $item_index + 1 - $status = to_s("("+$item_index+"/"+$item_total+")") - task_label($status+" Creating Applied Policy with Options: " + to_json($item["options"])) - $response = http_request( - auth: $$auth_flexera, - verb: "post", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies"]), - headers: { "Api-Version": "1.0" }, - body: { - "name": $item["name"], - "description": $item["description"], - "template_href": $item["template_href"], - "frequency": $item["frequency"], - "options": $item["options"], - "credentials": $item["credentials"], - "meta_parent_policy_id": $item["meta_parent_policy_id"] - } - ) - $responses << $response - $$debug << to_json({ - "response": $response, - "item": $item, - "governance_host": $governance_host - }) - end -end - -escalation "update_policies" do - run "update_applied_policies", data, rs_governance_host, rs_project_id -end - -define update_applied_policies($data, $governance_host, $rs_project_id) return $responses do - $responses = [] - $$debug = [] - $item_index = 0 - $item_total = size($data) - foreach $item in $data do - $item_index = $item_index + 1 - $status = to_s("("+$item_index+"/"+$item_total+")") - task_label($status+" Updating Applied Policy with Options: " + to_json($item["options"])) - $response = http_request( - auth: $$auth_flexera, - verb: "patch", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["applied_policy_id"]]), - headers: { "Api-Version": "1.0" }, - body: { - "options": $item["options"] - } - ) - $responses << $response - $$debug << to_json({ - "response": $response, - "item": $item, - "governance_host": $governance_host - }) - end -end - -escalation "delete_policies" do - run "delete_applied_policies", data, rs_governance_host, rs_project_id -end - -define delete_applied_policies($data, $governance_host, $rs_project_id) return $responses do - $responses = [] - $$debug = [] - $item_index = 0 - $item_total = size($data) - foreach $item in $data do - $item_index = $item_index + 1 - $status = to_s("("+$item_index+"/"+$item_total+")") - task_label($status+" Deleting Applied Policy: " + $item["id"]) - $response = http_request( - auth: $$auth_flexera, - verb: "delete", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["id"]]), - headers: { "Api-Version": "1.0" } - ) - $responses << $response - $$debug << to_json({ - "response": $response, - "item": $item, - "governance_host": $governance_host - }) - end -end diff --git a/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb b/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb index 3b55d42155..98efaadfc3 100644 --- a/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb +++ b/tools/meta_parent_policy_compiler/meta_parent_policy_compiler.rb @@ -15,7 +15,6 @@ "../../compliance/aws/rds_backup/aws_rds_backup.pt", "../../compliance/aws/untagged_resources/aws_untagged_resources.pt", "../../cost/aws/burstable_ec2_instances/aws_burstable_ec2_instances.pt", - "../../cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt", "../../cost/aws/eks_without_spot/aws_eks_without_spot.pt", "../../cost/aws/gp3_volume_upgrade/aws_upgrade_to_gp3_volume.pt", "../../cost/aws/idle_compute_instances/idle_compute_instances.pt", diff --git a/tools/policy_master_permission_generation/validated_policy_templates.yaml b/tools/policy_master_permission_generation/validated_policy_templates.yaml index b0b2c84082..e089f8c74d 100644 --- a/tools/policy_master_permission_generation/validated_policy_templates.yaml +++ b/tools/policy_master_permission_generation/validated_policy_templates.yaml @@ -16,7 +16,6 @@ validated_policy_templates: - "./compliance/aws/untagged_resources/aws_untagged_resources.pt" - "./cost/aws/burstable_ec2_instances/aws_burstable_ec2_instances.pt" - "./cost/aws/cheaper_regions/aws_cheaper_regions.pt" -- "./cost/aws/cloudtrail_read_logging/aws_cloudtrail_read_logging.pt" - "./cost/aws/eks_without_spot/aws_eks_without_spot.pt" - "./cost/aws/extended_support/aws_extended_support.pt" - "./cost/aws/gp3_volume_upgrade/aws_upgrade_to_gp3_volume.pt" From 6ddd523b0aa88e12512326757e551139d90bd3ff Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Tue, 13 Aug 2024 13:17:26 -0500 Subject: [PATCH 05/23] update --- automation/aws/aws_rbd_from_tag/CHANGELOG.md | 4 ++ .../aws/aws_rbd_from_tag/aws_rbd_from_tag.pt | 6 +- .../azure/azure_rbd_from_rg_tag/CHANGELOG.md | 4 ++ .../azure_rbd_from_rg_tag.pt | 60 ++++++++++--------- .../azure/azure_rbd_from_tag/CHANGELOG.md | 4 ++ .../azure_rbd_from_tag/azure_rbd_from_tag.pt | 22 +++---- .../google/google_rbd_from_label/CHANGELOG.md | 4 ++ .../google_rbd_from_label.pt | 22 +++---- 8 files changed, 75 insertions(+), 51 deletions(-) diff --git a/automation/aws/aws_rbd_from_tag/CHANGELOG.md b/automation/aws/aws_rbd_from_tag/CHANGELOG.md index 896755351a..827c354577 100644 --- a/automation/aws/aws_rbd_from_tag/CHANGELOG.md +++ b/automation/aws/aws_rbd_from_tag/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v2.3.1 + +- Fixed issue that would sometimes cause execution to fail if an account had no tag keys + ## v2.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt b/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt index a9fb5298a8..55b1055285 100644 --- a/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt +++ b/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "2.3.0", + version: "2.3.1", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -158,8 +158,8 @@ script "js_rbds", type: "javascript" do rules = [] _.each(accounts, function(account) { - if (typeof(account['id']) == 'string' && account['id'] != '') { - if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { + if (typeof(account['id']) == 'string' && account['id'] != '' && typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { if (account['tags'][tag_key].trim() != '') { value = account['tags'][tag_key].trim() if (param_normalize_case == "Yes") { value = value.toLowerCase() } diff --git a/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md index 6f6921bda4..722e5324ad 100644 --- a/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md +++ b/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v1.3.1 + +- Fixed issue that would sometimes cause execution to fail if an account had no tag keys + ## v1.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt b/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt index cb49e01ac7..6373bd8a39 100644 --- a/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt +++ b/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "1.3.0", + version: "1.3.1", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -291,33 +291,35 @@ script "js_rbds", type: "javascript" do rules = [] _.each(rgs, function(rg) { - if (rg['tags'][tag_key] != undefined && rg['tags'][tag_key] != null) { - if (rg['tags'][tag_key].trim() != '') { - value = rg['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { - type: "and", - expressions: [ - { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim() }, - { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } - ] - }, - value: { text: value } - }) - - if (rg['name'].trim() != rg['name'].trim().toLowerCase()) { + if (typeof(rg['tags']) == 'object') { + if (typeof(rg['tags'][tag_key]) == 'string') { + if (rg['tags'][tag_key].trim() != '') { + value = rg['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + rules.push({ condition: { type: "and", expressions: [ - { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim().toLowerCase() }, + { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim() }, { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } ] }, value: { text: value } }) + + if (rg['name'].trim() != rg['name'].trim().toLowerCase()) { + rules.push({ + condition: { + type: "and", + expressions: [ + { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim().toLowerCase() }, + { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } + ] + }, + value: { text: value } + }) + } } } } @@ -325,15 +327,17 @@ script "js_rbds", type: "javascript" do if (param_subscription_fallback == "Yes") { _.each(accounts, function(account) { - if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) + if (typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) + } } } }) diff --git a/automation/azure/azure_rbd_from_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_tag/CHANGELOG.md index 6f6921bda4..722e5324ad 100644 --- a/automation/azure/azure_rbd_from_tag/CHANGELOG.md +++ b/automation/azure/azure_rbd_from_tag/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v1.3.1 + +- Fixed issue that would sometimes cause execution to fail if an account had no tag keys + ## v1.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt b/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt index 31447edb97..467c1700d0 100644 --- a/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt +++ b/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "1.3.0", + version: "1.3.1", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -228,15 +228,17 @@ script "js_rbds", type: "javascript" do rules = [] _.each(accounts, function(account) { - if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) + if (typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) + } } } }) diff --git a/automation/google/google_rbd_from_label/CHANGELOG.md b/automation/google/google_rbd_from_label/CHANGELOG.md index 9eb4c138e2..831a79310a 100644 --- a/automation/google/google_rbd_from_label/CHANGELOG.md +++ b/automation/google/google_rbd_from_label/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v1.3.1 + +- Fixed issue that would sometimes cause execution to fail if an account had no tag keys + ## v1.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/google/google_rbd_from_label/google_rbd_from_label.pt b/automation/google/google_rbd_from_label/google_rbd_from_label.pt index e80fb5b5a8..93be95a9b0 100644 --- a/automation/google/google_rbd_from_label/google_rbd_from_label.pt +++ b/automation/google/google_rbd_from_label/google_rbd_from_label.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "1.3.0", + version: "1.3.1", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -215,15 +215,17 @@ script "js_rbds", type: "javascript" do rules = [] _.each(accounts, function(account) { - if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) + if (typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) + } } } }) From 6ae60c32b3c6eb6de1327c4c252bd2579fa3a059 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Tue, 13 Aug 2024 13:23:23 -0500 Subject: [PATCH 06/23] fix --- automation/aws/aws_rbd_from_tag/CHANGELOG.md | 4 -- .../aws/aws_rbd_from_tag/aws_rbd_from_tag.pt | 6 +- .../azure/azure_rbd_from_rg_tag/CHANGELOG.md | 4 -- .../azure_rbd_from_rg_tag.pt | 60 +++++++++---------- .../azure/azure_rbd_from_tag/CHANGELOG.md | 4 -- .../azure_rbd_from_tag/azure_rbd_from_tag.pt | 22 ++++--- .../google/google_rbd_from_label/CHANGELOG.md | 4 -- .../google_rbd_from_label.pt | 22 ++++--- 8 files changed, 51 insertions(+), 75 deletions(-) diff --git a/automation/aws/aws_rbd_from_tag/CHANGELOG.md b/automation/aws/aws_rbd_from_tag/CHANGELOG.md index 827c354577..896755351a 100644 --- a/automation/aws/aws_rbd_from_tag/CHANGELOG.md +++ b/automation/aws/aws_rbd_from_tag/CHANGELOG.md @@ -1,9 +1,5 @@ # Changelog -## v2.3.1 - -- Fixed issue that would sometimes cause execution to fail if an account had no tag keys - ## v2.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt b/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt index 55b1055285..a9fb5298a8 100644 --- a/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt +++ b/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "2.3.1", + version: "2.3.0", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -158,8 +158,8 @@ script "js_rbds", type: "javascript" do rules = [] _.each(accounts, function(account) { - if (typeof(account['id']) == 'string' && account['id'] != '' && typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { + if (typeof(account['id']) == 'string' && account['id'] != '') { + if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { if (account['tags'][tag_key].trim() != '') { value = account['tags'][tag_key].trim() if (param_normalize_case == "Yes") { value = value.toLowerCase() } diff --git a/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md index 722e5324ad..6f6921bda4 100644 --- a/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md +++ b/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md @@ -1,9 +1,5 @@ # Changelog -## v1.3.1 - -- Fixed issue that would sometimes cause execution to fail if an account had no tag keys - ## v1.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt b/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt index 6373bd8a39..cb49e01ac7 100644 --- a/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt +++ b/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "1.3.1", + version: "1.3.0", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -291,35 +291,33 @@ script "js_rbds", type: "javascript" do rules = [] _.each(rgs, function(rg) { - if (typeof(rg['tags']) == 'object') { - if (typeof(rg['tags'][tag_key]) == 'string') { - if (rg['tags'][tag_key].trim() != '') { - value = rg['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - + if (rg['tags'][tag_key] != undefined && rg['tags'][tag_key] != null) { + if (rg['tags'][tag_key].trim() != '') { + value = rg['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { + type: "and", + expressions: [ + { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim() }, + { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } + ] + }, + value: { text: value } + }) + + if (rg['name'].trim() != rg['name'].trim().toLowerCase()) { rules.push({ condition: { type: "and", expressions: [ - { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim() }, + { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim().toLowerCase() }, { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } ] }, value: { text: value } }) - - if (rg['name'].trim() != rg['name'].trim().toLowerCase()) { - rules.push({ - condition: { - type: "and", - expressions: [ - { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim().toLowerCase() }, - { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } - ] - }, - value: { text: value } - }) - } } } } @@ -327,17 +325,15 @@ script "js_rbds", type: "javascript" do if (param_subscription_fallback == "Yes") { _.each(accounts, function(account) { - if (typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) - } + if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) } } }) diff --git a/automation/azure/azure_rbd_from_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_tag/CHANGELOG.md index 722e5324ad..6f6921bda4 100644 --- a/automation/azure/azure_rbd_from_tag/CHANGELOG.md +++ b/automation/azure/azure_rbd_from_tag/CHANGELOG.md @@ -1,9 +1,5 @@ # Changelog -## v1.3.1 - -- Fixed issue that would sometimes cause execution to fail if an account had no tag keys - ## v1.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt b/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt index 467c1700d0..31447edb97 100644 --- a/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt +++ b/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "1.3.1", + version: "1.3.0", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -228,17 +228,15 @@ script "js_rbds", type: "javascript" do rules = [] _.each(accounts, function(account) { - if (typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) - } + if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) } } }) diff --git a/automation/google/google_rbd_from_label/CHANGELOG.md b/automation/google/google_rbd_from_label/CHANGELOG.md index 831a79310a..9eb4c138e2 100644 --- a/automation/google/google_rbd_from_label/CHANGELOG.md +++ b/automation/google/google_rbd_from_label/CHANGELOG.md @@ -1,9 +1,5 @@ # Changelog -## v1.3.1 - -- Fixed issue that would sometimes cause execution to fail if an account had no tag keys - ## v1.3.0 - Added option to retain original casing of tag values instead of normalizing them all to lowercase diff --git a/automation/google/google_rbd_from_label/google_rbd_from_label.pt b/automation/google/google_rbd_from_label/google_rbd_from_label.pt index 93be95a9b0..e80fb5b5a8 100644 --- a/automation/google/google_rbd_from_label/google_rbd_from_label.pt +++ b/automation/google/google_rbd_from_label/google_rbd_from_label.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "daily" info( - version: "1.3.1", + version: "1.3.0", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -215,17 +215,15 @@ script "js_rbds", type: "javascript" do rules = [] _.each(accounts, function(account) { - if (typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) - } + if (account['tags'][tag_key] != undefined && account['tags'][tag_key] != null) { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) } } }) From f510611e07e6d0b209aae11a985b2e191cffa671 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Tue, 8 Oct 2024 03:08:27 -0500 Subject: [PATCH 07/23] update --- .spellignore | 29 +++++++++++++++++++ automation/aws/aws_missing_regions/README.md | 2 +- automation/aws/aws_rbd_from_tag/README.md | 2 +- .../azure_missing_subscriptions/CHANGELOG.md | 4 +++ .../azure_missing_subscriptions/README.md | 2 +- .../azure_missing_subscriptions.pt | 4 +-- .../azure/azure_rbd_from_rg_tag/README.md | 2 +- automation/azure/azure_rbd_from_tag/README.md | 2 +- .../delete_all_billing_centers/CHANGELOG.md | 4 +++ .../delete_all_billing_centers/README.md | 10 ++++++- .../delete_all_billing_centers.pt | 4 +-- .../outdated_applied_policies/README.md | 2 +- .../google/google_rbd_from_label/README.md | 2 +- 13 files changed, 57 insertions(+), 12 deletions(-) diff --git a/.spellignore b/.spellignore index 1c67184d4e..537c65c574 100644 --- a/.spellignore +++ b/.spellignore @@ -585,3 +585,32 @@ ByteCount PacketCount balancers backfill +FNMS +CBI +workspace +workspaces +Workspace +Workspaces +OCID +OAuth +oauth +BYOL +GCP +TLS +SSL +Balancer +balancer +LUN +Unmanaged +unmanaged +Oversized +oversized +AMI +actioning +actioned +VPN +VPNs +Dataset +dataset +Datasets +datasets diff --git a/automation/aws/aws_missing_regions/README.md b/automation/aws/aws_missing_regions/README.md index 22893aed73..4aa17c94e2 100644 --- a/automation/aws/aws_missing_regions/README.md +++ b/automation/aws/aws_missing_regions/README.md @@ -59,4 +59,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not incur any cloud costs. +This policy template does not incur any cloud costs. diff --git a/automation/aws/aws_rbd_from_tag/README.md b/automation/aws/aws_rbd_from_tag/README.md index 311f531d76..e8ebf29119 100644 --- a/automation/aws/aws_rbd_from_tag/README.md +++ b/automation/aws/aws_rbd_from_tag/README.md @@ -34,4 +34,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not launch any instances, and so does not incur any cloud costs. +This policy template does not incur any cloud costs. diff --git a/automation/azure/azure_missing_subscriptions/CHANGELOG.md b/automation/azure/azure_missing_subscriptions/CHANGELOG.md index 1ad604f8d4..f18747584b 100644 --- a/automation/azure/azure_missing_subscriptions/CHANGELOG.md +++ b/automation/azure/azure_missing_subscriptions/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.1.1 + +- Minor code improvements to conform with current standards. Functionality unchanged. + ## v0.1 - initial release diff --git a/automation/azure/azure_missing_subscriptions/README.md b/automation/azure/azure_missing_subscriptions/README.md index 5f33caf7f3..716d93e8f3 100644 --- a/automation/azure/azure_missing_subscriptions/README.md +++ b/automation/azure/azure_missing_subscriptions/README.md @@ -37,4 +37,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not incur any cloud costs. +This policy template does not incur any cloud costs. diff --git a/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt b/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt index 4cdf0a2821..31fa39c86c 100644 --- a/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt +++ b/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt @@ -7,7 +7,7 @@ severity "low" category "Cost" default_frequency "weekly" info( - version: "0.1", + version: "0.1.1", provider: "Flexera", service: "Optima", policy_set: "Automation", @@ -102,9 +102,9 @@ datasource "ds_billing_centers" do auth $auth_flexera host rs_optima_host path join(["/analytics/orgs/", rs_org_id, "/billing_centers"]) + query "view", "allocation_table" header "Api-Version", "1.0" header "User-Agent", "RS Policies" - query "view", "allocation_table" ignore_status [403] end result do diff --git a/automation/azure/azure_rbd_from_rg_tag/README.md b/automation/azure/azure_rbd_from_rg_tag/README.md index 98ae4beb88..12e7c4928a 100644 --- a/automation/azure/azure_rbd_from_rg_tag/README.md +++ b/automation/azure/azure_rbd_from_rg_tag/README.md @@ -40,4 +40,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not launch any instances, and so does not incur any cloud costs. +This policy template does not incur any cloud costs. diff --git a/automation/azure/azure_rbd_from_tag/README.md b/automation/azure/azure_rbd_from_tag/README.md index 270f1ef5ef..10d38b2d6d 100644 --- a/automation/azure/azure_rbd_from_tag/README.md +++ b/automation/azure/azure_rbd_from_tag/README.md @@ -39,4 +39,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not launch any instances, and so does not incur any cloud costs. +This policy template does not incur any cloud costs. diff --git a/automation/flexera/delete_all_billing_centers/CHANGELOG.md b/automation/flexera/delete_all_billing_centers/CHANGELOG.md index 3a41ea7330..6b508a1e70 100644 --- a/automation/flexera/delete_all_billing_centers/CHANGELOG.md +++ b/automation/flexera/delete_all_billing_centers/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v1.1.1 + +- Minor code improvements to conform with current standards. Functionality unchanged. + ## v1.1 - Updated policy metadata to make it more clear what Flexera service the policy is for diff --git a/automation/flexera/delete_all_billing_centers/README.md b/automation/flexera/delete_all_billing_centers/README.md index 45be0de250..878c9a5917 100644 --- a/automation/flexera/delete_all_billing_centers/README.md +++ b/automation/flexera/delete_all_billing_centers/README.md @@ -13,6 +13,14 @@ This policy deletes all Billing Centers in the Flexera organization it is execut - If this is the policy's second time executing, but for some reason the policy has failed to self-terminate, no action will be taken. - If this is the policy's first time executing, all of the Billing Centers in the Flexera organization are deleted. +## Input Parameters + +This policy template has no input parameters. + +## Policy Actions + +- Delete all Billing Centers + ## Prerequisites This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). @@ -31,4 +39,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not incur any cloud costs. +This policy template does not incur any cloud costs. diff --git a/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt b/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt index c39455a663..2eb4046e2c 100644 --- a/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt +++ b/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt @@ -7,7 +7,7 @@ severity "high" category "Cost" default_frequency "15 minutes" info( - version: "1.1", + version: "1.1.1", provider: "Flexera", service: "Cloud Cost Optimization", policy_set: "Automation", @@ -78,8 +78,8 @@ datasource "ds_self_terminate" do iterate $ds_self_terminate_boolean request do auth $auth_flexera - host rs_governance_host verb "DELETE" + host rs_governance_host path val(iter_item, 'id') header "Api-Version", "1.0" end diff --git a/automation/flexera/outdated_applied_policies/README.md b/automation/flexera/outdated_applied_policies/README.md index 8a91fe0a0d..91be793e28 100644 --- a/automation/flexera/outdated_applied_policies/README.md +++ b/automation/flexera/outdated_applied_policies/README.md @@ -68,4 +68,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not incur any cloud costs. Cloud costs may be incurred by the applied policies that this policy reports on and updates. Please consult the README of each policy for more information. +This policy template does not incur any cloud costs. Cloud costs may be incurred by the applied policies that this policy reports on and updates. Please consult the README of each policy for more information. diff --git a/automation/google/google_rbd_from_label/README.md b/automation/google/google_rbd_from_label/README.md index 16ec257e2c..0f4903041c 100644 --- a/automation/google/google_rbd_from_label/README.md +++ b/automation/google/google_rbd_from_label/README.md @@ -37,4 +37,4 @@ The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automati ## Cost -This Policy Template does not launch any instances, and so does not incur any cloud costs. +This policy template does not incur any cloud costs. From 4af5e375f7e252f3bd0f10acb1f24b944738632f Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Tue, 8 Oct 2024 03:09:57 -0500 Subject: [PATCH 08/23] update --- .../aws/aws_missing_regions/CHANGELOG.md | 9 - automation/aws/aws_missing_regions/README.md | 62 - .../aws_missing_regions.pt | 359 ----- .../aws_missing_regions_meta_parent.pt | 1221 ----------------- automation/aws/aws_rbd_from_tag/CHANGELOG.md | 34 - automation/aws/aws_rbd_from_tag/README.md | 37 - .../aws/aws_rbd_from_tag/aws_rbd_from_tag.pt | 277 ---- .../azure_missing_subscriptions/CHANGELOG.md | 9 - .../azure_missing_subscriptions/README.md | 40 - .../azure_missing_subscriptions.pt | 340 ----- .../azure/azure_rbd_from_rg_tag/CHANGELOG.md | 25 - .../azure/azure_rbd_from_rg_tag/README.md | 43 - .../azure_rbd_from_rg_tag.pt | 418 ------ .../azure/azure_rbd_from_tag/CHANGELOG.md | 25 - automation/azure/azure_rbd_from_tag/README.md | 42 - .../azure_rbd_from_tag/azure_rbd_from_tag.pt | 318 ----- .../delete_all_billing_centers/CHANGELOG.md | 13 - .../delete_all_billing_centers/README.md | 42 - .../delete_all_billing_centers.pt | 233 ---- .../outdated_applied_policies/CHANGELOG.md | 14 - .../outdated_applied_policies/README.md | 71 - .../outdated_applied_policies.pt | 835 ----------- .../google/google_rbd_from_label/CHANGELOG.md | 26 - .../google/google_rbd_from_label/README.md | 40 - .../google_rbd_from_label.pt | 305 ---- 25 files changed, 4838 deletions(-) delete mode 100644 automation/aws/aws_missing_regions/CHANGELOG.md delete mode 100644 automation/aws/aws_missing_regions/README.md delete mode 100644 automation/aws/aws_missing_regions/aws_missing_regions.pt delete mode 100644 automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt delete mode 100644 automation/aws/aws_rbd_from_tag/CHANGELOG.md delete mode 100644 automation/aws/aws_rbd_from_tag/README.md delete mode 100644 automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt delete mode 100644 automation/azure/azure_missing_subscriptions/CHANGELOG.md delete mode 100644 automation/azure/azure_missing_subscriptions/README.md delete mode 100644 automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt delete mode 100644 automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md delete mode 100644 automation/azure/azure_rbd_from_rg_tag/README.md delete mode 100644 automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt delete mode 100644 automation/azure/azure_rbd_from_tag/CHANGELOG.md delete mode 100644 automation/azure/azure_rbd_from_tag/README.md delete mode 100644 automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt delete mode 100644 automation/flexera/delete_all_billing_centers/CHANGELOG.md delete mode 100644 automation/flexera/delete_all_billing_centers/README.md delete mode 100644 automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt delete mode 100644 automation/flexera/outdated_applied_policies/CHANGELOG.md delete mode 100644 automation/flexera/outdated_applied_policies/README.md delete mode 100644 automation/flexera/outdated_applied_policies/outdated_applied_policies.pt delete mode 100644 automation/google/google_rbd_from_label/CHANGELOG.md delete mode 100644 automation/google/google_rbd_from_label/README.md delete mode 100644 automation/google/google_rbd_from_label/google_rbd_from_label.pt diff --git a/automation/aws/aws_missing_regions/CHANGELOG.md b/automation/aws/aws_missing_regions/CHANGELOG.md deleted file mode 100644 index c0e1662927..0000000000 --- a/automation/aws/aws_missing_regions/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# Changelog - -## v0.2.0 - -- Fixed issue with meta policy not working due to missing `Account Number` parameter - -## v0.1 - -- initial release diff --git a/automation/aws/aws_missing_regions/README.md b/automation/aws/aws_missing_regions/README.md deleted file mode 100644 index 4aa17c94e2..0000000000 --- a/automation/aws/aws_missing_regions/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# AWS Missing Regions - -## What It Does - -This policy checks the list of AWS regions returned by an AWS `DescribeRegions` API request and tests each region with an EC2 `DescribeInstances` request to see if the Flexera AWS credential can actually run API requests against that region. An incident is raised and email sent with any regions that are inaccessible. - -__NOTE: Meta Parent policy will only work if both the parent and the child are uploaded to the Flexera org and the "Uploaded Template" option is selected for the `Child Policy Template Source` parameter. This is because the child policy is *not* published in the catalog.__ - -## Input Parameters - -This policy has the following input parameters required when launching the policy. - -- *Email Addresses* - Email addresses of the recipients you wish to notify when new incidents are created. -- *Account Number* - The Account number for use with the AWS STS Cross Account Role. Leave blank when using AWS IAM Access key and secret. It only needs to be passed when the desired AWS account is different than the one associated with the Flexera One credential. [More information is available in our documentation.](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1123608) -- *Region Ignore List* - A list of regions to never include in the results. Leave blank to not filter results - -## Policy Actions - -The following policy actions are taken on any resources found to be out of compliance. - -- Send an email report - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -- [**AWS Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1121575) (*provider=aws*) which has the following permissions: - - `ec2:DescribeRegions` - - `ec2:DescribeInstances` - - `sts:GetCallerIdentity` - - Example IAM Permission Policy: - - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "ec2:DescribeRegions", - "ec2:DescribeInstances", - "sts:GetCallerIdentity" - ], - "Resource": "*" - } - ] - } - ``` - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `billing_center_viewer` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- AWS - -## Cost - -This policy template does not incur any cloud costs. diff --git a/automation/aws/aws_missing_regions/aws_missing_regions.pt b/automation/aws/aws_missing_regions/aws_missing_regions.pt deleted file mode 100644 index 5b41cc8225..0000000000 --- a/automation/aws/aws_missing_regions/aws_missing_regions.pt +++ /dev/null @@ -1,359 +0,0 @@ -name "AWS Missing Regions" -rs_pt_ver 20180301 -type "policy" -short_description "Reports any AWS regions that are enabled but the policy engine is not able to access. [README](https://github.com/flexera-public/policy_templates/tree/master/automation/aws/aws_missing_regions/) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "low" -category "Cost" -default_frequency "weekly" -info( - version: "0.2.0", - provider: "Flexera", - service: "Optima", - policy_set: "Automation", - publish: "false" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_email" do - type "list" - category "Policy Settings" - label "Email Addresses" - description "A list of email addresses to notify." - default [] -end - -parameter "param_aws_account_number" do - type "string" - category "Policy Settings" - label "Account Number" - description "Leave blank; this is for automated use with Meta Policies. See README for more details." - default "" -end - -parameter "param_region_list" do - type "list" - category "Filters" - label "Region Ignore List" - description "A list of regions to never include in the results. Leave blank to not filter results." - default [] -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_aws" do - schemes "aws", "aws_sts" - label "AWS" - description "Select the AWS Credential from the list" - tags "provider=aws" - aws_account_number $param_aws_account_number -end - -credentials "auth_flexera" do - schemes "oauth2" - label "Flexera" - description "Select Flexera One OAuth2 credentials" - tags "provider=flexera" -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -# Get applied policy metadata for use later -datasource "ds_applied_policy" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) - header "Api-Version", "1.0" - end -end - -# Get region-specific Flexera API endpoints -datasource "ds_flexera_api_hosts" do - run_script $js_flexera_api_hosts, rs_optima_host -end - -script "js_flexera_api_hosts", type: "javascript" do - parameters "rs_optima_host" - result "result" - code <<-EOS - host_table = { - "api.optima.flexeraeng.com": { - flexera: "api.flexera.com", - fsm: "api.fsm.flexeraeng.com" - }, - "api.optima-eu.flexeraeng.com": { - flexera: "api.flexera.eu", - fsm: "api.fsm-eu.flexeraeng.com" - }, - "api.optima-apac.flexeraeng.com": { - flexera: "api.flexera.au", - fsm: "api.fsm-apac.flexeraeng.com" - } - } - - result = host_table[rs_optima_host] -EOS -end - -# Get AWS account info -datasource "ds_cloud_vendor_accounts" do - request do - auth $auth_flexera - host val($ds_flexera_api_hosts, 'flexera') - path join(["/finops-analytics/v1/orgs/", rs_org_id, "/cloud-vendor-accounts"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - collect jmes_path(response, "values[*]") do - field "id", jmes_path(col_item, "aws.accountId") - field "name", jmes_path(col_item, "name") - field "tags", jmes_path(col_item, "tags") - end - end -end - -datasource "ds_get_caller_identity" do - request do - auth $auth_aws - verb "GET" - host "sts.amazonaws.com" - path "/" - query "Action", "GetCallerIdentity" - query "Version", "2011-06-15" - header "User-Agent", "RS Policies" - end - result do - encoding "xml" - collect xpath(response, "//GetCallerIdentityResponse/GetCallerIdentityResult") do - field "account", xpath(col_item, "Account") - end - end -end - -datasource "ds_aws_account" do - run_script $js_aws_account, $ds_cloud_vendor_accounts, $ds_get_caller_identity -end - -script "js_aws_account", type:"javascript" do - parameters "ds_cloud_vendor_accounts", "ds_get_caller_identity" - result "result" - code <<-EOS - result = _.find(ds_cloud_vendor_accounts, function(account) { - return account['id'] == ds_get_caller_identity[0]['account'] - }) - - // This is in case the API does not return the relevant account info - if (result == undefined) { - result = { - id: ds_get_caller_identity[0]['account'], - name: "", - tags: {} - } - } -EOS -end - -datasource "ds_regions" do - request do - auth $auth_aws - verb "GET" - host "ec2.amazonaws.com" - path "/" - query "Action", "DescribeRegions" - query "Version", "2016-11-15" - query "Filter.1.Name", "opt-in-status" - query "Filter.1.Value.1", "opt-in-not-required" - query "Filter.1.Value.2", "opted-in" - # Header X-Meta-Flexera has no affect on datasource query, but is required for Meta Policies - # Forces `ds_is_deleted` datasource to run first during policy execution - header "Meta-Flexera", val($ds_is_deleted, "path") - end - result do - encoding "xml" - collect xpath(response, "//DescribeRegionsResponse/regionInfo/item", "array") do - field "region", xpath(col_item, "regionName") - end - end -end - -# Make a general API call to list EC2 instances to test functionality -datasource "ds_instance_sets" do - iterate $ds_regions - request do - auth $auth_aws - host join(['ec2.', val(iter_item, 'region'), '.amazonaws.com']) - path '/' - query 'Action', 'DescribeInstances' - query 'Version', '2016-11-15' - header 'User-Agent', 'RS Policies' - header 'Content-Type', 'text/xml' - ignore_status [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410] - end - result do - encoding "xml" - field "region", val(iter_item, "region") - end -end - -datasource "ds_missing_regions" do - run_script $js_missing_regions, $ds_regions, $ds_instance_sets, $ds_aws_account, $ds_applied_policy, $param_region_list -end - -script "js_missing_regions", type: "javascript" do - parameters "ds_regions", "ds_instance_sets", "ds_aws_account", "ds_applied_policy", "param_region_list" - result "result" - code <<-'EOS' - result = [] - - enabled_regions = _.uniq(_.pluck(ds_regions, 'region')) - found_regions = _.uniq(_.pluck(ds_instance_sets, 'region')) - - _.each(enabled_regions, function(region) { - if (!_.contains(found_regions, region) && !_.contains(param_region_list, region)) { - result.push({ - "accountID": ds_aws_account['id'], - "accountName": ds_aws_account['name'], - "region": region, - "policy_name": ds_applied_policy['name'] - }) - } - }) - - result = _.sortBy(result, 'region') - result = _.sortBy(result, 'accountID') -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_missing_regions" do - validate_each $ds_missing_regions do - summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} AWS Missing Regions Detected" - check logic_or($ds_parent_policy_terminated, eq(val(item, "accountID"), "")) - escalate $esc_email - export do - resource_level false - field "accountID" do - label "Account ID" - end - field "accountName" do - label "Account Name" - end - field "region" do - label "Region" - end - end - end -end - -############################################################################### -# Escalations -############################################################################### - -escalation "esc_email" do - automatic true - label "Send Email" - description "Send incident email" - email $param_email -end - -############################################################################### -# Meta Policy [alpha] -# Not intended to be modified or used by policy developers -############################################################################### - -# If the meta_parent_policy_id is not set it will evaluate to an empty string and we will look for the policy itself, -# if it is set we will look for the parent policy. -datasource "ds_get_policy" do - request do - auth $auth_flexera - host rs_governance_host - ignore_status [404] - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", switch(ne(meta_parent_policy_id, ""), meta_parent_policy_id, policy_id) ]) - header "Api-Version", "1.0" - end - result do - encoding "json" - field "id", jmes_path(response, "id") - end -end - -datasource "ds_parent_policy_terminated" do - run_script $js_decide_if_self_terminate, $ds_get_policy, policy_id, meta_parent_policy_id -end - -# If the policy was applied by a meta_parent_policy we confirm it exists if it doesn't we confirm we are deleting -# This information is used in two places: -# - determining whether or not we make a delete call -# - determining if we should create an incident (we don't want to create an incident on the run where we terminate) -script "js_decide_if_self_terminate", type: "javascript" do - parameters "found", "self_policy_id", "meta_parent_policy_id" - result "result" - code <<-EOS - var result - if (meta_parent_policy_id != "" && found.id == undefined) { - result = true - } else { - result = false - } - EOS -end - -# Two potentials ways to set this up: -# - this way and make a unneeded 'get' request when not deleting -# - make the delete request an interate and have it iterate over an empty array when not deleting and an array with one item when deleting -script "js_make_terminate_request", type: "javascript" do - parameters "should_delete", "policy_id", "rs_project_id", "rs_governance_host" - result "request" - code <<-EOS - - var request = { - auth: 'auth_flexera', - host: rs_governance_host, - path: "/api/governance/projects/" + rs_project_id + "/applied_policies/" + policy_id, - headers: { - "API-Version": "1.0", - "Content-Type":"application/json" - }, - } - - if (should_delete) { - request.verb = 'DELETE' - } - EOS -end - -datasource "ds_terminate_self" do - request do - run_script $js_make_terminate_request, $ds_parent_policy_terminated, policy_id, rs_project_id, rs_governance_host - end -end - -datasource "ds_is_deleted" do - run_script $js_check_deleted, $ds_terminate_self -end - -# This is just a way to have the check delete request connect to the farthest leaf from policy. -# We want the delete check to the first thing the policy does to avoid the policy erroring before it can decide whether or not it needs to self terminate -# Example a customer deletes a credential and then terminates the parent policy. We still want the children to self terminate -# The only way I could see this not happening is if the user who applied the parent_meta_policy was offboarded or lost policy access, the policies who are impersonating the user -# would not have access to self-terminate -# It may be useful for the backend to enable a mass terminate at some point for all meta_child_policies associated with an id. -script "js_check_deleted", type: "javascript" do - parameters "response" - result "result" - code <<-EOS - result = {"path":"/"} - EOS -end diff --git a/automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt b/automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt deleted file mode 100644 index dbe5d526b0..0000000000 --- a/automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt +++ /dev/null @@ -1,1221 +0,0 @@ -name "Meta Parent: AWS Missing Regions" -rs_pt_ver 20180301 -type "policy" -short_description "**NOTE: Meta policies are an alpha feature. Please consult the [README](https://github.com/flexera-public/policy_templates/blob/master/README_META_POLICIES.md) before use.** Applies and manages \"child\" [AWS Missing Regions](https://github.com/flexera-public/policy_templates/tree/master/automation/aws/aws_missing_regions) Policies." -severity "low" -category "Meta" -default_frequency "15 minutes" -info( - provider: "AWS", - version: "0.2.0", # 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", - deprecated: "false" -) - -############################################################################## -# Parameters -############################################################################## - -## Meta Parent Parameters -## These are params specific to the meta parent policy. -parameter "param_combined_incident_email" do - type "list" - label "Email addresses for combined incident" - description "A list of email addresses to notify with the consolidated child policy incident." - default [] -end - -parameter "param_dimension_filter_includes" do - type "list" - label "Dimension Include Filters" - description <<-EOS - Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **INCLUDE** and be applied to. - Use = to match the entire value and =~ to match a substring contained in the value. - During each run this policy will select AWS Accounts who match **all** the filters defined and apply a child policy for each. - If no include filters are provided, then all AWS Accounts are included by default. - Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). - EOS - default [] -end - -parameter "param_dimension_filter_excludes" do - type "list" - label "Dimension Exclude Filters" - description <<-EOS - Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **EXCLUDE** and *not* have policy applied to. - Use = to match the entire value and =~ to match a substring contained in the value. - During each run this policy will select AWS Accounts who match **all** the filters defined here and excludes them from results. - Can be used to exclude specific AWS Accounts [`vendor_account=123456789012`] - Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). - EOS - default [] -end - -parameter "param_policy_schedule" do - type "string" - label "Child Policy Schedule" - description "The interval at which the child policy checks for conditions and generates incidents." - default "weekly" - allowed_values "daily", "weekly", "monthly" -end - -parameter "param_template_source" do - type "string" - label "Child Policy Template Source" - description "By default, will use the \"AWS Missing Regions\" Policy Template from Catalog. Optionally, you can use the \"AWS Missing Regions\" Policy Template uploaded in the current Flexera Project." - default "Published Catalog Template" - allowed_values "Published Catalog Template", "Uploaded Template" -end - -## Child Policy Parameters -parameter "param_region_list" do - type "list" - category "Filters" - label "Region Ignore List" - description "A list of regions to never include in the results. Leave blank to not filter results." - default [] -end - -############################################################################### -# Authentication -############################################################################### -credentials "auth_aws" do - schemes "aws", "aws_sts" - label "AWS" - description "Select the AWS Credential from the list" - tags "provider=aws" - aws_account_number $param_aws_account_number -end - -credentials "auth_flexera" do - schemes "oauth2" - label "Flexera" - description "Select Flexera One OAuth2 credentials" - tags "provider=flexera" -end - -############################################################################### -# Datasources -############################################################################### - -# Get Applied Parent Policy Details -datasource "ds_self_policy_information" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) - header "Api-Version", "1.0" - end - result do - encoding "json" - field "name", jmes_path(response, "name") - field "creator_id", jmes_path(response, "created_by.id") - field "credentials", jmes_path(response, "credentials") - field "options", jmes_path(response, "options") - end -end - -datasource "ds_child_policy_options" do - run_script $js_child_policy_options, $ds_self_policy_information -end - -script "js_child_policy_options", type: "javascript" do - parameters "ds_self_policy_information" - result "options" - code <<-EOS - // Filter Options that are not appropriate for Child Policy - var options = _.map(ds_self_policy_information.options, function(option){ - // param_combined_incident_email, param_dimension_filter_includes, param_dimension_filter_excludes, param_policy_schedule are exclusion to Meta Parent Policy Parameters - if (!_.contains(["param_combined_incident_email", "param_dimension_filter_includes", "param_dimension_filter_excludes", "param_policy_schedule", "param_template_source"], option.name)) { - return { "name": option.name, "value": option.value }; - } - }); - // Explicitly add param_email which is disabled/does not exist in meta parent policy - options.push({ - "name": "param_email", - "value": [] - }); - EOS -end - -datasource "ds_child_policy_options_map" do - run_script $js_child_policy_options_map, $ds_child_policy_options -end - -script "js_child_policy_options_map", type: "javascript" do - parameters "ds_child_policy_options" - result "options" - code <<-EOS - function format_options_keyvalue(options) { - var options_keyvalue_map = {}; - _.each(options, function(option) { - options_keyvalue_map[option.name] = option.value; - }); - return options_keyvalue_map; - } - var options = format_options_keyvalue(ds_child_policy_options) - EOS -end - -datasource "ds_format_self" do - run_script $js_format_self, $ds_self_policy_information, $ds_child_policy_options_map -end - -script "js_format_self", type: "javascript" do - parameters "ds_self_policy_information", "ds_child_policy_options_map" - result "formatted" - code <<-EOS - var formatted = { - "name": ds_self_policy_information["name"], - "creator_id": ds_self_policy_information["creator_id"], - "credentials": ds_self_policy_information["credentials"], - "options": ds_child_policy_options_map - }; - EOS -end - -# Get Pulished Policy Details -datasource "ds_get_published_child_policy_information" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/orgs/", rs_org_id, "/published_templates"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - collect jmes_path(response, "items[*]") do - field "name", jmes_path(col_item, "name") - field "created_by", jmes_path(col_item, "created_by.email") - field "href", jmes_path(col_item, "href") - field "short_description", jmes_path(col_item, "short_description") - end - end -end - -# Select the published policy that is published by "support@flexera.com" and matches the name of the child policy template -datasource "ds_published_child_policy_information" do - run_script $js_published_child_policy_information, $ds_get_published_child_policy_information -end - -script "js_published_child_policy_information", type: "javascript" do - parameters "ds_get_published_child_policy_information" - result "result" - code <<-EOS - result = _.filter(ds_get_published_child_policy_information, function(item) { - return item['name'] == "AWS Missing Regions" && item['created_by'] == "support@flexera.com" - }) -EOS -end - -# Get Uploaded Policy Details -datasource "ds_get_project_child_policy_information" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/policy_templates"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - collect jmes_path(response, "items[*]") do - field "name", jmes_path(col_item, "name") - field "href", jmes_path(col_item, "href") - field "short_description", jmes_path(col_item, "short_description") - end - end -end - -# Select the uploaded policy that matches the name of the child policy template -datasource "ds_project_child_policy_information" do - run_script $js_project_child_policy_information, $ds_get_project_child_policy_information -end - -script "js_project_child_policy_information", type: "javascript" do - parameters "ds_get_project_child_policy_information" - result "result" - code <<-EOS - result = _.filter(ds_get_project_child_policy_information, function(item) { - return item['name'] == "AWS Missing Regions" - }) -EOS -end - -datasource "ds_get_billing_centers" do - request do - auth $auth_flexera - host rs_optima_host - path join(["/analytics/orgs/",rs_org_id,"/billing_centers"]) - header "Api-Version", "1.0" - header "User-Agent", "RS Policies" - query "view", "allocation_table" - ignore_status [403] - end - result do - encoding "json" - # Select the Billing Centers that have "parent_id" undefined or "" (i.e. top-level Billing Centers) - collect jq(response, '.[] | select(.parent_id == null)' ) do - field "href", jq(col_item,".href") - field "id", jq(col_item,".id") - field "name", jq(col_item,".name") - field "parent_id", jq(col_item,".parent_id") - end - end -end - -script "js_make_billing_center_request", type: "javascript" do - parameters "rs_org_id", "rs_optima_host", "billing_centers_unformatted", "param_dimension_filter_includes", "param_dimension_filter_excludes" - result "request" - code <<-EOS - - billing_centers_formatted = [] - - for (x=0; x< billing_centers_unformatted.length; x++) { - billing_centers_formatted.push(billing_centers_unformatted[x]["id"]) - } - - finish = new Date() - finishFormatted = finish.toJSON().split("T")[0] - start = new Date() - start.setDate(start.getDate() - 30) - startFormatted = start.toJSON().split("T")[0] - - // Default dimensions and filter expressions required for meta parent policy - var dimensions = ["vendor_account", "vendor_account_name"]; - var filter_expressions = [ - { dimension: "vendor", type: "equal", value: "AWS" } - ] - - // Append to default dimensions and filter expressions using parent policy params - _.each(param_dimension_filter_includes, function (v) { - // split key=value string - if (v.indexOf('=~') == -1) { - var split = v.split("="); - var type = "equal" - } else { - var split = v.split("=~"); - var type = "substring" - } - - var k = split[0]; - var v = split[1]; - - // append to lists - dimensions.push(k); - - if (type == "equal") { - filter_expressions.push({ dimension: k, type: "equal", value: v }); - } else { - filter_expressions.push({ dimension: k, type: "substring", substring: v }); - } - }); - - // Append to filter expressions using exclude policy params - _.each(param_dimension_filter_excludes, function (v) { - // split key=value string - if (v.indexOf('=~') == -1) { - var split = v.split("="); - var type = "equal" - } else { - var split = v.split("=~"); - var type = "substring" - } - - var k = split[0]; - var v = split[1]; - - // append to lists - dimensions.push(k); - - if (type == "equal") { - filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "equal", "value": v } }); - } else { - filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "substring", "substring": v } }); - } - }); - - // Produces a duplicate-free version of the array - dimensions = _.uniq(dimensions); - - var body = { - "dimensions": dimensions, - "granularity":"day", - "start_at": startFormatted, - "end_at": finishFormatted, - "metrics":["cost_amortized_unblended_adj"], - "billing_center_ids": billing_centers_formatted, - "filter": - { - "type": "and", - "expressions": filter_expressions - }, - "summarized": true - } - var request = { - auth: 'auth_flexera', - host: rs_optima_host, - scheme: 'https', - verb: 'POST', - path: "/bill-analysis/orgs/"+ rs_org_id + "/costs/aggregated", - headers: { - "API-Version": "1.0", - "Content-Type":"application/json" - }, - body: JSON.stringify(body) - } - EOS -end - -# Get the AWS acounts -datasource "ds_get_aws_accounts" do - request do - run_script $js_make_billing_center_request, rs_org_id, rs_optima_host, $ds_get_billing_centers, $param_dimension_filter_includes, $param_dimension_filter_excludes - end - result do - encoding "json" - collect jmes_path(response,"rows[*]") do - field "aws_account_id", jmes_path(col_item,"dimensions.vendor_account") - field "aws_account_name", jmes_path(col_item,"dimensions.vendor_account_name") - end - end -end - -# Get Child policies -datasource "ds_get_existing_policies" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies"]) - header "Api-Version", "1.0" - query "meta_parent_policy_id", policy_id - end - result do - encoding "json" - collect jmes_path(response, "items[*]") do - field "name", jmes_path(col_item, "name") - field "applied_policy_id", jmes_path(col_item, "id") - field "options", jmes_path(col_item, "options") - field "updated_at", jmes_path(col_item, "updated_at") - field "status", jmes_path(col_item, "status") - end - end -end - -# Get Child policies incidents -datasource "ds_get_existing_policies_incidents" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/incidents"]) - header "Api-Version", "1.0" - query "meta_parent_policy_id", policy_id - query "state", "triggered" - end - result do - encoding "json" - collect jmes_path(response, "items[*]") do - field "incident_id", jmes_path(col_item, "id") - field "applied_policy_id", jmes_path(col_item, "applied_policy.id") - field "summary", jmes_path(col_item, "summary") - field "state", jmes_path(col_item, "state") - field "violation_data_count", jmes_path(col_item, "violation_data_count") - field "updated_at", jmes_path(col_item, "updated_at") - field "meta_parent_policy_id", jmes_path(col_item, "meta_parent_policy_id") - end - end -end - -datasource "ds_format_incidents" do - run_script $js_format_existing_policies_incidents, $ds_get_existing_policies_incidents -end - -script "js_format_existing_policies_incidents", type: "javascript" do - parameters "unformatted" - result "formatted" - code <<-EOS - formatted={} - - _.each(unformatted, function(incident) { - if (formatted[incident['applied_policy_id']] == undefined) { - formatted[incident['applied_policy_id']] = [] - } - - formatted[incident['applied_policy_id']].push(incident) - }) -EOS -end - -datasource "ds_format_existing_policies" do - run_script $js_format_existing_policies, $ds_get_existing_policies, $ds_format_incidents -end - -# format -# duplicates logic should compare updated at -# we can validate update here when destructring the existing policy options, don't need updated at -# format options -script "js_format_existing_policies", type: "javascript" do - parameters "ds_get_existing_policies", "ds_format_incidents" - result "result" - code <<-EOS - function format_options_keyvalue(options) { - var options_keyvalue_map = {}; - _.each(options, function(option) { - options_keyvalue_map[option.name] = option.value; - }); - return options_keyvalue_map; - } - - result = {} - formatted = {} - duplicates = [] - // tracking holds all existing policies and later can be used to determine if existing policies should be deleted [i.e. if cloud account was removed] - tracking = {} - - for (x=0; x newDate) { - duplicates.push({ - "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], - "applied_policy_name":ds_get_existing_policies[x]["name"], - "status":ds_get_existing_policies[x]["status"], - "updated_at":ds_get_existing_policies[x]["updated_at"], - "incident": incident, - "incident2": incident2 - }) - } else { - duplicates.push({ - "applied_policy_id":current["applied_policy_id"], - "applied_policy_name":current["applied_policy_name"], - "status":current["status"], - "updated_at":current["updated_at"], - "incident": current["incident"], - "incident2": current["incident2"] - }) - formatted[aws_account_id] = { - "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], - "applied_policy_name":ds_get_existing_policies[x]["name"], - "status":ds_get_existing_policies[x]["status"], - "updated_at":ds_get_existing_policies[x]["updated_at"], - "incident": incident, - "incident2": incident2, - "options": options - } - - } - } - } - - result.formatted=formatted - result.duplicates=duplicates - result.tracking=tracking - EOS -end - -datasource "ds_take_in_parameters" do - run_script $js_take_in_parameters, $ds_get_aws_accounts, $ds_format_self, first($ds_published_child_policy_information), first($ds_project_child_policy_information), $ds_format_existing_policies, $ds_child_policy_options, $ds_child_policy_options_map, $param_template_source, $param_policy_schedule, policy_id, f1_app_host, rs_org_id, rs_project_id -end - -# hardcode template href with id from catalog -# catalog policies show in customer's published templates with their org id -# "template_href": "/api/governance/orgs/" + rs_org_id + "/published_templates/62618616e3dff80001572bf0" -# update logic: the only reason we're going to update the child policies for is changes to options -# and only some options, email is always blank and aws_account_id is tied to the idenity of each policy, so: new account creation, removal of account: termination -# param_automatic_action is a list with only one action, unless the person is applying using an API and putting the same value multiple times this should either be a length of 0 or 1 -# param_log_to_cm_audit_entries is a String of Yes or No -# param_exclude_tags and param_allowed_regions are arrays. I'm doing an update on the order changing but the values remaining the same. -# If we only want to do an update on the values changing we could sort before doing the equality check. -script "js_take_in_parameters", type: "javascript" do - parameters "ds_get_aws_accounts", "ds_format_self", "ds_published_child_policy_information", "ds_project_child_policy_information", "ds_format_existing_policies", "ds_child_policy_options", "ds_child_policy_options_map", "param_template_source", "param_policy_schedule", "meta_parent_policy_id", "f1_app_host", "rs_org_id", "rs_project_id" - result "grid_and_cwf" - code <<-EOS - - // Set Child Policy Information based on param_template_source value - if (param_template_source == "Published Catalog Template") { - child_policy_information = ds_published_child_policy_information - } else { - child_policy_information = ds_project_child_policy_information - } - - max_actions = 50; - - grid_and_cwf={grid:[], to_create:[], to_update:[], to_delete:[], parent_policy:ds_format_self}; - - should_keep = ds_format_existing_policies.tracking; - - // Construct UI URL prefixes for policy template summary - ui_url_prefix = "https://" + f1_app_host + "/orgs/" + rs_org_id; - applied_policy_url_prefix = ui_url_prefix + "/automation/applied-policies/projects/" + rs_project_id + "?noIndex=1&policyId="; - incident_url_prefix = ui_url_prefix + "/automation/incidents/projects/" + rs_project_id + "?noIndex=1&incidentId="; - - function add_to_grid(ep, action) { - policy_status={ - "id": ep["applied_policy_id"], - "policy_name": ep["applied_policy_name"] + '||' + applied_policy_url_prefix + ep["applied_policy_id"], - "meta_policy_status": action, - "policy_status": ep["status"], - "policy_last_update": ep["updated_at"], - }; - - if (ep.incident != null && ep.incident != undefined) { - // Remove policy name from summary when applicable - summary_parts = ep.incident.summary.split(':') - summary = summary_parts[summary_parts.length - 1].trim() - - policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident.incident_id; - policy_status["incident_state"] = ep.incident.state; - policy_status["incident_violation_data_count"] = ep.incident.violation_data_count; - policy_status["incident_last_update"] = ep.incident.updated_at; - } - - if (ep.incident2 != null && ep.incident2 != undefined) { - // Remove policy name from summary when applicable - summary_parts = ep.incident2.summary.split(':') - summary = summary_parts[summary_parts.length - 1].trim() - - policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident2.incident_id; - policy_status["incident_state"] = ep.incident2.state; - policy_status["incident2_violation_data_count"] = ep.incident2.violation_data_count; - policy_status["incident2_last_update"] = ep.incident2.updated_at; - } - - grid_and_cwf.grid.push(policy_status); - } - - for (x=0; x -1) { - _.each(incident["violation_data"], function(violation) { - violation["incident_id"] = incident["id"]; - result.push(violation); - }); - } - }); -EOS -end - - - - -# Summary and a conditional incident which will show up if any policy is being applied, updated or deleted. -# Minimum of 1 incident, max of four -# Could swap the summary to only showing running -# Could also just have one incident and use meta_status to determine which escalation happens -policy "policy_scheduled_report" do - # Consolidated Incident Check(s) - # Consolidated incident for AWS Missing Regions Detected - validate $ds_missing_regions_combined_incidents do - summary_template "Consolidated Incident: {{ len data }} AWS Missing Regions Detected" - escalate $esc_email - - check eq(size(data), 0) - export do - resource_level false - field "accountID" do - label "Account ID" - end - field "accountName" do - label "Account Name" - end - field "region" do - label "Region" - end - field "incident_id" do - label "Child Incident ID" - end - end - end - - # Status Incident Check - validate $ds_take_in_parameters do - summary_template "{{ data.parent_policy.name }}: Status of Child Policies" - detail_template <<-EOS -The current status of Child Policies for **{{ data.parent_policy.name }}**: - -Total Child Applied Policies: {{ len data.grid }} -EOS - check false # always trigger this status incident - export "grid" do - resource_level true - field "id" do - label "Applied Policy ID" - end - field "policy_name" do - label "Applied Policy Name" - format "link-external" - end - field "meta_policy_status" do - label "Meta Child Policy Status" - end - field "policy_status" do - label "Policy Status" - end - field "policy_last_update" do - label "Policy Last Update" - end - field "incident_summary" do - label "Incident Summary" - format "link-external" - end - field "incident_state" do - label "Incident State" - end - field "incident_violation_data_count" do - label "Incident Violation Count" - end - field "incident_last_update" do - label "Incident Last Update" - end - field "incident2_summary" do - label "Incident 2 Summary" - format "link-external" - end - field "incident2_state" do - label "Incident 2 State" - end - field "incident2_violation_data_count" do - label "Incident 2 Violation Count" - end - field "incident2_last_update" do - label "Incident 2 Last Update" - end - end - end - - # Create Child Policies Incident Check - validate $ds_to_create do - summary_template "Policies being created" - detail_template <<-EOS - Policies Being Created: - - | Applied Policy | - | --------------- | - {{ range data -}} - | {{ .name }} | - {{ end -}} - EOS - escalate $create_policies - check eq(size(data),0) - end - - # Update Child Policies Incident Check - validate $ds_to_update do - summary_template "Policies being updated" - detail_template <<-EOS - Policies Being Updated: - - | Applied Policy | - | --------------- | - {{ range data -}} - | {{ .name }} | - {{ end -}} - EOS - escalate $update_policies - check eq(size(data),0) - end - - # Delete Child Policies Incident Check - validate $ds_to_delete do - summary_template "Policies being deleted" - detail_template <<-EOS - Policies being Deleted: - - | Applied Policy | - | --------------- | - {{ range data -}} - | {{ .name }} | - {{ end -}} - EOS - escalate $delete_policies - check eq(size(data),0) - end -end - -# Begin Shared Functions for Child Actions from Consolidated Incident -define groupByIncidentID($data) return $incidents do - # Empty hash to store incidents is incident_id - $incidents = {} - - task_label("Grouping items by Incident ID") - $index = 1 - foreach $item in $data do - task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))) - if !$incidents[$item["incident_id"]] - #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". New Incident: "+$item["incident_id"]) - $incidents[$item["incident_id"]] = {"id": $item["incident_id"], "resource_ids": []} - end - #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". Appending Resource: "+$item["id"]) - # Append resource id to the list for the incident - $incidents[$item["incident_id"]]["resource_ids"] = $incidents[$item["incident_id"]]["resource_ids"] + [$item["id"]] - end -end - -define child_run_action($data, $governance_host, $rs_project_id, $action_label, $action_options) do - # Empty global array for log strings, helpful for debugging - $$debug = [] - - # Group Resources by Incident ID - # This reduces the number of requests made to the Flexera API - call groupByIncidentID($data) retrieve $incidents - $$debug_incidents = to_json($incidents) - - call runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) - - # If we encountered any errors, use `raise` to mark the CWF process as errored - if inspect($$errors) != "null" - raise join($$errors,"\n") - end - - # If we made it here, all actions completed successfully - # Celebrate Success! - task_label("All \""+$action_label+"\" actions completed successfully!") -end - -define runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) do - foreach $id in keys($incidents) do - sub on_error: handle_error() do - $incident = $incidents[$id] - task_label("Triggering action \""+$action_label+"\" on "+size($incident["resource_ids"])+" count resources via incident "+$incident["id"]) - $request = { - auth: $$auth_flexera, - verb: "get", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"]]), - headers: { "Api-Version": "1.0" }, - query_strings: { "view": "extended" } - } - $response = http_request($request) - $$debug << to_json({ - "request": $request, - "response": $response - }) - $action_id = "" - foreach $action in $response["body"]["available_actions"] do - # If we have not already found the action id, and the label matches, set the action id - # The first check is to prevent looking through the entire list if we already have the id - if $action["label"] == $action_label - $action_id = $action["id"] - end - end - if $action_id == "" - raise "Could not find action id for \""+$action_label+"\" response="+to_json($response) - end - # Now we are reach to trigger the action - $request = { - auth: $$auth_flexera, - verb: "post", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"],"/actions/", $action_id,"/run_action"]), - headers: { "Api-Version": "1.0" }, - body: { "options":[{ "name": "ids", "value": $incident["resource_ids"] }] } - } - # If the action has parameters, add them to the request body - if type($action_options) == "array" && size($action_options) > 0 - $request["body"]["options"] = $request["body"]["options"] + $action_options - end - $response = http_request($request) - $$debug << to_json({ - "request": $request, - "response": $response - }) - # Get the action status from response header - $action_location = $response["headers"]["Location"] - - # Setup some variables for the wait loop - $action_status = "" - $loop_count = 0 - $loop_endtime = now() + (3600*2) # 2 hours from now - # [ queued, aborted, pending, running, completed, failed, denied ] - while ($action_status !~ /^(aborted|completed|failed|denied)/) && (now() <= $loop_endtime) do - # Using Loop Count to slowly increment the sleep time - # This is to prevent the loop from hammering our APIs - $loop_count = $loop_count + 1 - task_label("action_status=\""+$action_status+"\" Sleeping for "+to_s($loop_count)+" seconds") - sleep($loop_count) - task_label("action_status=\""+$action_status+"\" Getting action status") - $request = { - auth: $$auth_flexera, - verb: "get", - https: true, - host: $governance_host, - href: $action_location, - headers: { "Api-Version": "1.0" }, - query_strings: { "view": "extended" } - } - $response = http_request($request) - $$debug << to_json({ - "request": $request, - "response": $response - }) - $action_status = $response["body"]["status"] - end - if ($action_status != "completed") - # Check if we are out of time first - if (now() > $loop_endtime) - raise "action_status=\""+$action_status+"\" Action did not complete in time. Aborting to prevent endless loop. action_status_json="+to_json($response) - else - # If not, then it was aborted, failed or denied - raise "action_status=\""+$action_status+"\" Action did not complete as expected. action_status_json="+to_json($response) - end - end - # If we made it here, the action completed successfully - task_label("action_status=\""+$action_status+"\" Action completed successfully") - end - end -end -# End Shared Functions for Child Actions from Consolidated Incident - -# CWF function to handle errors -define handle_error() do - if !$$errors - $$errors = [] - end - $$errors << $_error["type"] + ": " + $_error["message"] - # We check for errors at the end, and raise them all together - # Skip errors handled by this definition - $_error_behavior = "skip" -end - -# Used only for emailing the combined child incident if so desired -escalation "esc_email" do - automatic true - label "Send Email" - description "Send incident email" - email $param_combined_incident_email -end - -escalation "create_policies" do - run "create_applied_policies", data, rs_governance_host, rs_project_id -end - -# if name !=null -define create_applied_policies($data, $governance_host, $rs_project_id) return $responses do - $responses = [] - $$debug = [] - $item_index = 0 - $item_total = size($data) - foreach $item in $data do - $item_index = $item_index + 1 - $status = to_s("("+$item_index+"/"+$item_total+")") - task_label($status+" Creating Applied Policy with Options: " + to_json($item["options"])) - $response = http_request( - auth: $$auth_flexera, - verb: "post", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies"]), - headers: { "Api-Version": "1.0" }, - body: { - "name": $item["name"], - "description": $item["description"], - "template_href": $item["template_href"], - "frequency": $item["frequency"], - "options": $item["options"], - "credentials": $item["credentials"], - "meta_parent_policy_id": $item["meta_parent_policy_id"] - } - ) - $responses << $response - $$debug << to_json({ - "response": $response, - "item": $item, - "governance_host": $governance_host - }) - end -end - -escalation "update_policies" do - run "update_applied_policies", data, rs_governance_host, rs_project_id -end - -define update_applied_policies($data, $governance_host, $rs_project_id) return $responses do - $responses = [] - $$debug = [] - $item_index = 0 - $item_total = size($data) - foreach $item in $data do - $item_index = $item_index + 1 - $status = to_s("("+$item_index+"/"+$item_total+")") - task_label($status+" Updating Applied Policy with Options: " + to_json($item["options"])) - $response = http_request( - auth: $$auth_flexera, - verb: "patch", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["applied_policy_id"]]), - headers: { "Api-Version": "1.0" }, - body: { - "options": $item["options"] - } - ) - $responses << $response - $$debug << to_json({ - "response": $response, - "item": $item, - "governance_host": $governance_host - }) - end -end - -escalation "delete_policies" do - run "delete_applied_policies", data, rs_governance_host, rs_project_id -end - -define delete_applied_policies($data, $governance_host, $rs_project_id) return $responses do - $responses = [] - $$debug = [] - $item_index = 0 - $item_total = size($data) - foreach $item in $data do - $item_index = $item_index + 1 - $status = to_s("("+$item_index+"/"+$item_total+")") - task_label($status+" Deleting Applied Policy: " + $item["id"]) - $response = http_request( - auth: $$auth_flexera, - verb: "delete", - https: true, - host: $governance_host, - href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["id"]]), - headers: { "Api-Version": "1.0" } - ) - $responses << $response - $$debug << to_json({ - "response": $response, - "item": $item, - "governance_host": $governance_host - }) - end -end diff --git a/automation/aws/aws_rbd_from_tag/CHANGELOG.md b/automation/aws/aws_rbd_from_tag/CHANGELOG.md deleted file mode 100644 index 97fd6e9145..0000000000 --- a/automation/aws/aws_rbd_from_tag/CHANGELOG.md +++ /dev/null @@ -1,34 +0,0 @@ -# Changelog - -## v2.3.2 - -- Fixed issue where tag keys that were not lowercase would not be properly detected and used - -## v2.3.1 - -- Fixed issue that would sometimes cause execution to fail if an AWS Account had no tag keys - -## v2.3.0 - -- Added option to retain original casing of tag values instead of normalizing them all to lowercase - -## v2.2.1 - -- Updated policy template to use newer API endpoints. Functionality is unchanged. - -## v2.2 - -- added ability to specify names for the newly created dimensions - -## v2.1 - -- Corrected API issue when executing policy in APAC - -## v2.0 - -- Removed requirement for AWS credential -- Internal API is now used to gather AWS account and tag information - -## v1.0 - -- initial release diff --git a/automation/aws/aws_rbd_from_tag/README.md b/automation/aws/aws_rbd_from_tag/README.md deleted file mode 100644 index e8ebf29119..0000000000 --- a/automation/aws/aws_rbd_from_tag/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# AWS Rule-Based Dimension From Account Tags - -## What It Does - -This policy creates and updates custom Rule-Based Dimensions that surface the specified AWS Account tag keys in the Flexera One platform. This allows costs to be sliced by the values of the tag keys in question. - -## Input Parameters - -This policy has the following input parameters required when launching the policy. - -- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. -- *Tag Keys* - A list of AWS Account tag keys to create custom Rule-Based Dimensions for. -- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the `Tag Keys` field. Dimension names will be derived from tag keys directly if this list is left empty. -- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. - -## Policy Actions - -- Create/update rule-based dimensions - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `observer` - - `billing_center_viewer` - - `rule_based_dimensions_manager` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- AWS - -## Cost - -This policy template does not incur any cloud costs. diff --git a/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt b/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt deleted file mode 100644 index 55aeb43074..0000000000 --- a/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt +++ /dev/null @@ -1,277 +0,0 @@ -name "AWS Rule-Based Dimension From Account Tags" -rs_pt_ver 20180301 -type "policy" -short_description "Creates and/or updates individual Rule-Based Dimensions based on AWS Account tags. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/aws/aws_rbd_from_tag) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "low" -category "Cost" -default_frequency "daily" -info( - version: "2.3.2", - provider: "Flexera", - service: "Optima", - policy_set: "Automation", - publish: "false" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_tag_list" do - type "list" - category "Policy Settings" - label "Tag Keys" - description "A list of AWS account tag keys to build Rule-Based Dimensions from" - # No default value, user input required -end - -parameter "param_name_list" do - type "list" - category "Policy Settings" - label "Dimension Names" - description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the 'Tag Keys' field. Dimension names will be derived from tag keys directly if this list is left empty." - default [] -end - -parameter "param_effective_date" do - type "string" - category "Policy Settings" - label "Effective Date" - description "Year/month you want rules to start applying in YYYY-MM format" - default "2010-01" -end - -parameter "param_normalize_case" do - type "string" - category "Policy Settings" - label "Lowercase Values" - description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." - allowed_values "Yes", "No" - default "Yes" -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_flexera" do - schemes "oauth2" - label "flexera" - description "Select FlexeraOne OAuth2 credential." - tags "provider=flexera" -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -# Get region-specific Flexera API endpoints -datasource "ds_flexera_api_hosts" do - run_script $js_flexera_api_hosts, rs_optima_host -end - -script "js_flexera_api_hosts", type: "javascript" do - parameters "rs_optima_host" - result "result" - code <<-EOS - host_table = { - "api.optima.flexeraeng.com": { - flexera: "api.flexera.com", - fsm: "api.fsm.flexeraeng.com" - }, - "api.optima-eu.flexeraeng.com": { - flexera: "api.flexera.eu", - fsm: "api.fsm-eu.flexeraeng.com" - }, - "api.optima-apac.flexeraeng.com": { - flexera: "api.flexera.au", - fsm: "api.fsm-apac.flexeraeng.com" - } - } - - result = host_table[rs_optima_host] -EOS -end - -# Get AWS account info -datasource "ds_cloud_vendor_accounts" do - request do - auth $auth_flexera - host val($ds_flexera_api_hosts, 'flexera') - path join(["/finops-analytics/v1/orgs/", rs_org_id, "/cloud-vendor-accounts"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - collect jmes_path(response, "values[*]") do - field "id", jmes_path(col_item, "aws.accountId") - field "name", jmes_path(col_item, "name") - field "tags", jmes_path(col_item, "tags") - end - end -end - -datasource "ds_cloud_vendor_accounts_normalized" do - run_script $js_cloud_vendor_accounts_normalized, $ds_cloud_vendor_accounts -end - -script "js_cloud_vendor_accounts_normalized", type: "javascript" do - parameters "accounts" - result "result" - code <<-'EOS' - result = [] - - _.each(accounts, function(account) { - tags = {} - - if (account['tags'] != null && account['tags'] != undefined) { - _.each(Object.keys(account['tags']), function(key) { - normalized_key = key.toLowerCase().trim() - tags[normalized_key] = account['tags'][key] - }) - } - - result.push({ - id: account['id'], - name: account['name'], - tags: tags - }) - }) -EOS -end - -datasource "ds_existing_rbds" do - request do - auth $auth_flexera - host rs_optima_host - path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) - header "Api-Version", "1.0" - header "content-type", "application/json" - end - result do - encoding "json" - collect jmes_path(response, "rule_based_dimensions") do - field "id", jmes_path(col_item, "id") - field "name", jmes_path(col_item, "name") - field "dated_rules", jmes_path(col_item, "dated_rules") - end - end -end - -datasource "ds_rbds" do - run_script $js_rbds, $ds_cloud_vendor_accounts_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_normalize_case -end - -script "js_rbds", type: "javascript" do - parameters "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_normalize_case" - result "result" - code <<-'EOS' - result = [] - - rbd_id_list = _.pluck(existing_rbds, 'id') - - _.each(param_tag_list, function(tag, index) { - rbd_name = tag.replace('.', ' ').replace('-', ' ') - rbd_name = rbd_name.replace(/\W/g, " ").trim() - - // Use user-specified name instead of user provided one - if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } - - rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() - - tag_key = tag.toLowerCase().trim() - verb = "POST" - if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } - - rules = [] - - _.each(accounts, function(account) { - if (typeof(account['id']) == 'string' && account['id'] != '' && typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) - } - } - } - }) - - if (rules.length > 0) { - result.push({ - id: rbd_id, - name: rbd_name, - verb: verb, - effective_at: param_effective_date, - rules: rules - }) - } - }) -EOS -end - -datasource "ds_create_rbds" do - iterate $ds_rbds - request do - run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id - end - result do - encoding "text" - end -end - -script "js_create_rbds", type: "javascript" do - parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: verb, - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), - body_fields: { name: name } - } -EOS -end - -datasource "ds_apply_rbds" do - iterate $ds_rbds - request do - # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does - run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id - end - result do - encoding "text" - end -end - -script "js_apply_rbds", type: "javascript" do - parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: "PUT", - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), - body_fields: { rules: rules } - } -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_rbds" do - validate $ds_apply_rbds do - summary_template "RBDs Generated & Applied" - detail_template "" - check eq(0, 0) - end -end diff --git a/automation/azure/azure_missing_subscriptions/CHANGELOG.md b/automation/azure/azure_missing_subscriptions/CHANGELOG.md deleted file mode 100644 index f18747584b..0000000000 --- a/automation/azure/azure_missing_subscriptions/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# Changelog - -## v0.1.1 - -- Minor code improvements to conform with current standards. Functionality unchanged. - -## v0.1 - -- initial release diff --git a/automation/azure/azure_missing_subscriptions/README.md b/automation/azure/azure_missing_subscriptions/README.md deleted file mode 100644 index 716d93e8f3..0000000000 --- a/automation/azure/azure_missing_subscriptions/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Azure Missing Subscriptions - -## What It Does - -This policy checks the stored Flexera CCO billing data for Azure from 3 days ago to obtain a list of Azure Subscriptions that we have billing data for and compares that to the list of Azure Subscriptions returned by the Azure Resource Manager API. An incident is raised and email sent containing any subscriptions present in Flexera CCO but not returned by the Azure Resource Manager API, as well as subscriptions returned by the Azure Resource Manager API but not present in Flexera CCO. The user can select which of those two reports they'd like to produce. - -## Input Parameters - -This policy has the following input parameters required when launching the policy. - -- *Email Addresses* - Email addresses of the recipients you wish to notify when new incidents are created. -- *Azure Endpoint* - The endpoint to send Azure API requests to. Recommended to leave this at default unless using this policy with Azure China. -- *Report Selection* - Whether to report Subscriptions missing in the Azure API but present in CCO data, the opposite, or both. -- *Subscriptions Ignore List* - A list of Subscription IDs/names to never include in the results. Leave blank to not filter results - -## Policy Actions - -The following policy actions are taken on any resources found to be out of compliance. - -- Send an email report - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -- [**Azure Resource Manager Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_109256743_1124668) (*provider=azure_rm*) which has the following permissions: - - `Microsoft.Resources/subscriptions/read` - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `billing_center_viewer` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- Azure - -## Cost - -This policy template does not incur any cloud costs. diff --git a/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt b/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt deleted file mode 100644 index 31fa39c86c..0000000000 --- a/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt +++ /dev/null @@ -1,340 +0,0 @@ -name "Azure Missing Subscriptions" -rs_pt_ver 20180301 -type "policy" -short_description "Reports any Azure Subscriptions present in Flexera One that are not accessible via the Azure Resource Manager automation credential. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/azure/azure_missing_subscriptions) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "low" -category "Cost" -default_frequency "weekly" -info( - version: "0.1.1", - provider: "Flexera", - service: "Optima", - policy_set: "Automation", - publish: "false" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_email" do - type "list" - category "Policy Settings" - label "Email Addresses" - description "A list of email addresses to notify." - default [] -end - -parameter "param_azure_endpoint" do - type "string" - category "Policy Settings" - label "Azure Endpoint" - description "Select the API endpoint to use for Azure. Use default value of management.azure.com unless using Azure China." - allowed_values "management.azure.com", "management.chinacloudapi.cn" - default "management.azure.com" -end - -parameter "param_report_selection" do - type "string" - category "Policy Settings" - label "Report Selection" - description "Whether to report Subscriptions missing in the Azure API but present in CCO data, the opposite, or both." - allowed_values "Missing in Azure API", "Missing in CCO", "Both" - default "Missing in Azure API" -end - -parameter "param_subscriptions_list" do - type "list" - category "Filters" - label "Subscriptions Ignore List" - description "A list of Subscription IDs/names to never include in the results. Leave blank to not filter results." - default [] -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_azure" do - schemes "oauth2" - label "Azure" - description "Select the Azure Resource Manager Credential from the list." - tags "provider=azure_rm" -end - -credentials "auth_flexera" do - schemes "oauth2" - label "Flexera" - description "Select Flexera One OAuth2 credentials" - tags "provider=flexera" -end - -############################################################################### -# Pagination -############################################################################### - -pagination "pagination_azure" do - get_page_marker do - body_path "nextLink" - end - set_page_marker do - uri true - end -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -# Get applied policy metadata for use later -datasource "ds_applied_policy" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) - header "Api-Version", "1.0" - end -end - -datasource "ds_billing_centers" do - request do - auth $auth_flexera - host rs_optima_host - path join(["/analytics/orgs/", rs_org_id, "/billing_centers"]) - query "view", "allocation_table" - header "Api-Version", "1.0" - header "User-Agent", "RS Policies" - ignore_status [403] - end - result do - encoding "json" - collect jmes_path(response, "[*]") do - field "href", jmes_path(col_item, "href") - field "id", jmes_path(col_item, "id") - field "name", jmes_path(col_item, "name") - field "parent_id", jmes_path(col_item, "parent_id") - end - end -end - -# Gather top level billing center IDs for when we pull cost data -datasource "ds_top_level_bcs" do - run_script $js_top_level_bcs, $ds_billing_centers -end - -script "js_top_level_bcs", type: "javascript" do - parameters "ds_billing_centers" - result "result" - code <<-EOS - filtered_bcs = _.filter(ds_billing_centers, function(bc) { - return bc['parent_id'] == null || bc['parent_id'] == undefined - }) - - result = _.compact(_.pluck(filtered_bcs, 'id')) -EOS -end - -datasource "ds_flexera_cco_data" do - request do - run_script $js_flexera_cco_data, $ds_top_level_bcs, rs_org_id, rs_optima_host - end - result do - encoding "json" - collect jmes_path(response, "rows[*]") do - field "bill_source", jmes_path(col_item, "dimensions.bill_source") - field "vendor_account", jmes_path(col_item, "dimensions.vendor_account") - field "vendor_account_name", jmes_path(col_item, "dimensions.vendor_account_name") - end - end -end - -script "js_flexera_cco_data", type: "javascript" do - parameters "ds_top_level_bcs", "rs_org_id", "rs_optima_host" - result "request" - code <<-EOS - end_date = new Date() - end_date.setDate(end_date.getDate() - 2) - end_date = end_date.toISOString().split('T')[0] - - start_date = new Date() - start_date.setDate(start_date.getDate() - 3) - start_date = start_date.toISOString().split('T')[0] - - var request = { - auth: "auth_flexera", - host: rs_optima_host, - verb: "POST", - path: "/bill-analysis/orgs/" + rs_org_id + "/costs/aggregated", - body_fields: { - dimensions: ["bill_source", "vendor_account", "vendor_account_name"], - granularity: "day", - start_at: start_date, - end_at: end_date, - metrics: ["cost_amortized_unblended_adj"], - billing_center_ids: ds_top_level_bcs, - limit: 100000, - filter: { - "type": "or", - "expressions": [ - { "dimension": "vendor", "type": "equal", "value": "Azure" }, - { "dimension": "vendor", "type": "equal", "value": "azure" }, - { "dimension": "vendor", "type": "equal", "value": "Microsoft Azure" }, - { "dimension": "vendor", "type": "equal", "value": "microsoft azure" } - ] - } - }, - headers: { - 'User-Agent': "RS Policies", - 'Api-Version': "1.0" - }, - ignore_status: [400] - } -EOS -end - -datasource "ds_azure_subscriptions" do - request do - auth $auth_azure - pagination $pagination_azure - host $param_azure_endpoint - path "/subscriptions/" - query "api-version","2020-01-01" - header "User-Agent", "RS Policies" - # Ignore status 400, 403, and 404 which can be returned in certain (legacy) types of Azure Subscriptions - ignore_status [400, 403, 404] - end - result do - encoding "json" - collect jmes_path(response, "value[*]") do - field "id", jmes_path(col_item, "subscriptionId") - field "name", jmes_path(col_item, "displayName") - field "state", jmes_path(col_item, "state") - end - end -end - -datasource "ds_missing_subscriptions_api" do - run_script $js_missing_subscriptions_api, $ds_flexera_cco_data, $ds_azure_subscriptions, $ds_applied_policy, $param_subscriptions_list, $param_report_selection -end - -script "js_missing_subscriptions_api", type: "javascript" do - parameters "ds_flexera_cco_data", "ds_azure_subscriptions", "ds_applied_policy", "param_subscriptions_list", "param_report_selection" - result "result" - code <<-'EOS' - result = [] - - if (param_report_selection != 'Missing in CCO') { - automation_ids = _.map(ds_azure_subscriptions, function(sub) { - return sub['id'].toLowerCase().trim() - }) - - missing_subs = _.reject(ds_flexera_cco_data, function(sub) { - return _.contains(automation_ids, sub['vendor_account'].toLowerCase().trim()) - }) - - result = _.map(missing_subs, function(sub) { - return { - accountID: sub['vendor_account'].toLowerCase().trim(), - accountName: sub['vendor_account_name'], - bill_source: sub['bill_source'], - policy_name: ds_applied_policy['name'] - } - }) - - // Remove filtered results - result = _.reject(result, function(sub) { - return _.contains(param_subscriptions_list, sub['accountID']) || _.contains(param_subscriptions_list, sub['accountName']) - }) - - result = _.sortBy(result, 'accountID') - result = _.sortBy(result, 'bill_source') - } -EOS -end - -datasource "ds_missing_subscriptions_cco" do - run_script $js_missing_subscriptions_cco, $ds_flexera_cco_data, $ds_azure_subscriptions, $ds_applied_policy, $param_subscriptions_list, $param_report_selection -end - -script "js_missing_subscriptions_cco", type: "javascript" do - parameters "ds_flexera_cco_data", "ds_azure_subscriptions", "ds_applied_policy", "param_subscriptions_list", "param_report_selection" - result "result" - code <<-'EOS' - result = [] - - if (param_report_selection != 'Missing in Azure API') { - cco_ids = _.map(ds_flexera_cco_data, function(sub) { - return sub['vendor_account'].toLowerCase().trim() - }) - - missing_subs = _.reject(ds_azure_subscriptions, function(sub) { - return _.contains(cco_ids, sub['id'].toLowerCase().trim()) - }) - - result = _.map(missing_subs, function(sub) { - return { - accountID: sub['id'].toLowerCase().trim(), - accountName: sub['name'], - policy_name: ds_applied_policy['name'] - } - }) - - // Remove filtered results - result = _.reject(result, function(sub) { - return _.contains(param_subscriptions_list, sub['accountID']) || _.contains(param_subscriptions_list, sub['accountName']) - }) - - result = _.sortBy(result, 'accountID') - } -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_missing_subscriptions" do - validate_each $ds_missing_subscriptions_api do - summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} Azure API Missing Subscriptions" - check eq(val(item, "accountID"), "") - escalate $esc_email - export do - resource_level false - field "accountID" do - label "Subscription ID" - end - field "accountName" do - label "Subscription Name" - end - field "bill_source" do - label "Bill Connection" - end - end - end - validate_each $ds_missing_subscriptions_cco do - summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} Azure CCO Missing Subscriptions" - check eq(val(item, "accountID"), "") - escalate $esc_email - export do - resource_level false - field "accountID" do - label "Subscription ID" - end - field "accountName" do - label "Subscription Name" - end - end - end -end - -############################################################################### -# Escalations -############################################################################### - -escalation "esc_email" do - automatic true - label "Send Email" - description "Send incident email" - email $param_email -end diff --git a/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md deleted file mode 100644 index 9a2c4ba2ad..0000000000 --- a/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md +++ /dev/null @@ -1,25 +0,0 @@ -# Changelog - -## v1.3.1 - -- Fixed issue that would sometimes cause execution to fail if an Azure Subscription or Resource Group had no tag keys - -## v1.3.0 - -- Added option to retain original casing of tag values instead of normalizing them all to lowercase - -## v1.2.1 - -- Updated policy template to use newer API endpoints. Functionality is unchanged. - -## v1.2 - -- Fixed error where policy would fail completely when trying to access resources credential does not have access to. Policy will now simply skip these resources. - -## v1.1 - -- added ability to specify names for the newly created dimensions - -## v1.0 - -- initial release diff --git a/automation/azure/azure_rbd_from_rg_tag/README.md b/automation/azure/azure_rbd_from_rg_tag/README.md deleted file mode 100644 index 12e7c4928a..0000000000 --- a/automation/azure/azure_rbd_from_rg_tag/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Azure Rule-Based Dimension From Resource Group Tags - -## What It Does - -This policy creates and updates custom Rule-Based Dimensions that surface the specified Azure Resource Group tag keys in the Flexera One platform. This allows costs to be sliced by the values of the tag keys in question. - -## Input Parameters - -This policy has the following input parameters required when launching the policy. - -- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. -- *Tag Keys* - A list of Azure Resource Group tag keys to create custom Rule-Based Dimensions for. -- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the `Tag Keys` field. Dimension names will be derived from tag keys directly if this list is left empty. -- *Subscription Fallback Rules* - Whether or not to create rules for Subscription tags as a fallback for untagged Resource Groups. These rules have the lowest priority; rules created for Resource Group tags will always take precedence. -- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. - -## Policy Actions - -- Create/update rule-based dimensions - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -- [**Azure Resource Manager Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_109256743_1124668) (*provider=azure_rm*) which has the following permissions: - - `Microsoft.Resources/subscriptions/resources/read` - - `Microsoft.Resources/subscriptions/providers/read` - - `Microsoft.Resources/tags/read` - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `observer` - - `billing_center_viewer` - - `rule_based_dimensions_manager` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- Azure - -## Cost - -This policy template does not incur any cloud costs. diff --git a/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt b/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt deleted file mode 100644 index 6373bd8a39..0000000000 --- a/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt +++ /dev/null @@ -1,418 +0,0 @@ -name "Azure Rule-Based Dimension From Resource Group Tags" -rs_pt_ver 20180301 -type "policy" -short_description "Creates and/or updates individual Rule-Based Dimensions based on Azure Resource Group tags. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/azure/azure_rbd_from_rg_tag) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "low" -category "Cost" -default_frequency "daily" -info( - version: "1.3.1", - provider: "Flexera", - service: "Optima", - policy_set: "Automation", - publish: "false" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_tag_list" do - type "list" - category "Policy Settings" - label "Tag Keys" - description "A list of Azure account tag keys to build Rule-Based Dimensions from" - # No default value, user input required -end - -parameter "param_name_list" do - type "list" - category "Policy Settings" - label "Dimension Names" - description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the 'Tag Keys' field. Dimension names will be derived from tag keys directly if this list is left empty." - default [] -end - -parameter "param_effective_date" do - type "string" - category "Policy Settings" - label "Effective Date" - description "Year/month you want rules to start applying in YYYY-MM format" - default "2010-01" -end - -parameter "param_subscription_fallback" do - type "string" - category "Policy Settings" - label "Subscription Fallback Rules" - description "Whether or not to create rules for Subscription tags as a fallback for untagged Resource Groups." - allowed_values "Yes", "No" - default "No" -end - -parameter "param_normalize_case" do - type "string" - category "Policy Settings" - label "Lowercase Values" - description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." - allowed_values "Yes", "No" - default "Yes" -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_azure" do - schemes "oauth2" - label "Azure" - description "Select the Azure Resource Manager Credential from the list." - tags "provider=azure_rm" -end - -credentials "auth_flexera" do - schemes "oauth2" - label "flexera" - description "Select FlexeraOne OAuth2 credential." - tags "provider=flexera" -end - -############################################################################### -# Pagination -############################################################################### - -pagination "pagination_azure" do - get_page_marker do - body_path "nextLink" - end - set_page_marker do - uri true - end -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -# Get region-specific Flexera API endpoints -datasource "ds_flexera_api_hosts" do - run_script $js_flexera_api_hosts, rs_optima_host -end - -script "js_flexera_api_hosts", type: "javascript" do - parameters "rs_optima_host" - result "result" - code <<-EOS - host_table = { - "api.optima.flexeraeng.com": { - flexera: "api.flexera.com", - fsm: "api.fsm.flexeraeng.com" - }, - "api.optima-eu.flexeraeng.com": { - flexera: "api.flexera.eu", - fsm: "api.fsm-eu.flexeraeng.com" - }, - "api.optima-apac.flexeraeng.com": { - flexera: "api.flexera.au", - fsm: "api.fsm-apac.flexeraeng.com" - } - } - - result = host_table[rs_optima_host] -EOS -end - -datasource "ds_existing_rbds" do - request do - auth $auth_flexera - host rs_optima_host - path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) - header "Api-Version", "1.0" - header "content-type", "application/json" - end - result do - encoding "json" - collect jmes_path(response, "rule_based_dimensions") do - field "id", jmes_path(col_item, "id") - field "name", jmes_path(col_item, "name") - field "dated_rules", jmes_path(col_item, "dated_rules") - end - end -end - -datasource "ds_azure_subscriptions" do - request do - auth $auth_azure - pagination $pagination_azure - host "management.azure.com" - path "/subscriptions/" - query "api-version", "2018-06-01" - header "User-Agent", "RS Policies" - # Ignore status 400, 403, and 404 which can be returned in certain (legacy) types of Azure Subscriptions - ignore_status [400, 403, 404] - end - result do - encoding "json" - collect jmes_path(response, "value[*]") do - field "id", jmes_path(col_item, "subscriptionId") - field "name", jmes_path(col_item, "displayName") - end - end -end - -datasource "ds_azure_subscriptions_with_tags" do - iterate $ds_azure_subscriptions - request do - auth $auth_azure - pagination $pagination_azure - host "management.azure.com" - path join(["/subscriptions/", val(iter_item, "id"), "/providers/Microsoft.Resources/tags/default"]) - query "api-version", "2021-04-01" - header "User-Agent", "RS Policies" - ignore_status [400, 403, 404] - end - result do - encoding "json" - field "id", val(iter_item, "id") - field "name", val(iter_item, "name") - field "tags", jmes_path(response, "properties.tags") - end -end - -datasource "ds_azure_subscriptions_normalized" do - run_script $js_azure_subscriptions_normalized, $ds_azure_subscriptions_with_tags -end - -script "js_azure_subscriptions_normalized", type: "javascript" do - parameters "accounts" - result "result" - code <<-'EOS' - result = [] - - _.each(accounts, function(account) { - tags = {} - - if (account['tags'] != null && account['tags'] != undefined) { - _.each(Object.keys(account['tags']), function(key) { - normalized_key = key.toLowerCase().trim() - tags[normalized_key] = account['tags'][key] - }) - } - - result.push({ - id: account['id'], - name: account['name'], - tags: tags - }) - }) -EOS -end - -datasource "ds_azure_resource_groups" do - iterate $ds_azure_subscriptions - request do - auth $auth_azure - pagination $pagination_azure - host "management.azure.com" - path join(["/subscriptions/", val(iter_item, "id"), "/resourcegroups"]) - query "api-version", "2021-04-01" - header "User-Agent", "RS Policies" - ignore_status [400, 403, 404] - end - result do - encoding "json" - collect jmes_path(response, "value[*]") do - field "subscriptionId", val(iter_item, "id") - field "subscriptionName", val(iter_item, "name") - field "id", jmes_path(col_item, "id") - field "name", jmes_path(col_item, "name") - field "tags", jmes_path(col_item, "tags") - end - end -end - -datasource "ds_azure_resource_groups_normalized" do - run_script $js_azure_resource_groups_normalized, $ds_azure_resource_groups -end - -script "js_azure_resource_groups_normalized", type: "javascript" do - parameters "rgs" - result "result" - code <<-'EOS' - result = [] - - _.each(rgs, function(rg) { - tags = {} - - if (rg['tags'] != null && rg['tags'] != undefined) { - _.each(Object.keys(rg['tags']), function(key) { - normalized_key = key.toLowerCase().trim() - tags[normalized_key] = rg['tags'][key] - }) - } - - result.push({ - subscriptionId: rg['subscriptionId'], - subscriptionName: rg['subscriptionName'], - id: rg['id'], - name: rg['name'], - tags: tags - }) - }) -EOS -end - -datasource "ds_rbds" do - run_script $js_rbds, $ds_azure_resource_groups_normalized, $ds_azure_subscriptions_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_subscription_fallback, $param_normalize_case -end - -script "js_rbds", type: "javascript" do - parameters "rgs", "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_subscription_fallback", "param_normalize_case" - result "result" - code <<-'EOS' - result = [] - - rbd_id_list = _.pluck(existing_rbds, 'id') - - _.each(param_tag_list, function(tag, index) { - rbd_name = tag.replace('.', ' ').replace('-', ' ') - rbd_name = rbd_name.replace(/\W/g, " ").trim() - - // Use user-specified name instead of user provided one - if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } - - rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() - - tag_key = tag.toLowerCase().trim() - verb = "POST" - if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } - - rules = [] - - _.each(rgs, function(rg) { - if (typeof(rg['tags']) == 'object') { - if (typeof(rg['tags'][tag_key]) == 'string') { - if (rg['tags'][tag_key].trim() != '') { - value = rg['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { - type: "and", - expressions: [ - { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim() }, - { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } - ] - }, - value: { text: value } - }) - - if (rg['name'].trim() != rg['name'].trim().toLowerCase()) { - rules.push({ - condition: { - type: "and", - expressions: [ - { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim().toLowerCase() }, - { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } - ] - }, - value: { text: value } - }) - } - } - } - } - }) - - if (param_subscription_fallback == "Yes") { - _.each(accounts, function(account) { - if (typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) - } - } - } - }) - } - - if (rules.length > 0) { - result.push({ - id: rbd_id, - name: rbd_name, - verb: verb, - effective_at: param_effective_date, - rules: rules - }) - } - }) -EOS -end - -datasource "ds_create_rbds" do - iterate $ds_rbds - request do - run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id - end - result do - encoding "text" - end -end - -script "js_create_rbds", type: "javascript" do - parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: verb, - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), - body_fields: { name: name } - } -EOS -end - -datasource "ds_apply_rbds" do - iterate $ds_rbds - request do - # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does - run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id - end - result do - encoding "text" - end -end - -script "js_apply_rbds", type: "javascript" do - parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: "PUT", - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), - body_fields: { rules: rules } - } -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_rbds" do - validate $ds_apply_rbds do - summary_template "RBDs Generated & Applied" - detail_template "" - check eq(0, 0) - end -end diff --git a/automation/azure/azure_rbd_from_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_tag/CHANGELOG.md deleted file mode 100644 index b2354a4856..0000000000 --- a/automation/azure/azure_rbd_from_tag/CHANGELOG.md +++ /dev/null @@ -1,25 +0,0 @@ -# Changelog - -## v1.3.1 - -- Fixed issue that would sometimes cause execution to fail if an Azure Subscription had no tag keys - -## v1.3.0 - -- Added option to retain original casing of tag values instead of normalizing them all to lowercase - -## v1.2.1 - -- Updated policy template to use newer API endpoints. Functionality is unchanged. - -## v1.2 - -- Fixed error where policy would fail completely when trying to access resources credential does not have access to. Policy will now simply skip these resources. - -## v1.1 - -- added ability to specify names for the newly created dimensions - -## v1.0 - -- initial release diff --git a/automation/azure/azure_rbd_from_tag/README.md b/automation/azure/azure_rbd_from_tag/README.md deleted file mode 100644 index 10d38b2d6d..0000000000 --- a/automation/azure/azure_rbd_from_tag/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Azure Rule-Based Dimension From Subscription Tags - -## What It Does - -This policy creates and updates custom Rule-Based Dimensions that surface the specified Azure Subscription tag keys in the Flexera One platform. This allows costs to be sliced by the values of the tag keys in question. - -## Input Parameters - -This policy has the following input parameters required when launching the policy. - -- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. -- *Tag Keys* - A list of Azure Subscription tag keys to create custom Rule-Based Dimensions for. -- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the `Tag Keys` field. Dimension names will be derived from tag keys directly if this list is left empty. -- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. - -## Policy Actions - -- Create/update rule-based dimensions - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -- [**Azure Resource Manager Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_109256743_1124668) (*provider=azure_rm*) which has the following permissions: - - `Microsoft.Resources/subscriptions/resources/read` - - `Microsoft.Resources/subscriptions/providers/read` - - `Microsoft.Resources/tags/read` - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `observer` - - `billing_center_viewer` - - `rule_based_dimensions_manager` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- Azure - -## Cost - -This policy template does not incur any cloud costs. diff --git a/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt b/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt deleted file mode 100644 index 467c1700d0..0000000000 --- a/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt +++ /dev/null @@ -1,318 +0,0 @@ -name "Azure Rule-Based Dimension From Subscription Tags" -rs_pt_ver 20180301 -type "policy" -short_description "Creates and/or updates individual Rule-Based Dimensions based on Azure Subscription tags. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/azure/azure_rbd_from_tag) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "low" -category "Cost" -default_frequency "daily" -info( - version: "1.3.1", - provider: "Flexera", - service: "Optima", - policy_set: "Automation", - publish: "false" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_tag_list" do - type "list" - category "Policy Settings" - label "Tag Keys" - description "A list of Azure account tag keys to build Rule-Based Dimensions from" - # No default value, user input required -end - -parameter "param_name_list" do - type "list" - category "Policy Settings" - label "Dimension Names" - description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the 'Tag Keys' field. Dimension names will be derived from tag keys directly if this list is left empty." - default [] -end - -parameter "param_effective_date" do - type "string" - category "Policy Settings" - label "Effective Date" - description "Year/month you want rules to start applying in YYYY-MM format" - default "2010-01" -end - -parameter "param_normalize_case" do - type "string" - category "Policy Settings" - label "Lowercase Values" - description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." - allowed_values "Yes", "No" - default "Yes" -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_azure" do - schemes "oauth2" - label "Azure" - description "Select the Azure Resource Manager Credential from the list." - tags "provider=azure_rm" -end - -credentials "auth_flexera" do - schemes "oauth2" - label "flexera" - description "Select FlexeraOne OAuth2 credential." - tags "provider=flexera" -end - -############################################################################### -# Pagination -############################################################################### - -pagination "pagination_azure" do - get_page_marker do - body_path "nextLink" - end - set_page_marker do - uri true - end -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -# Get region-specific Flexera API endpoints -datasource "ds_flexera_api_hosts" do - run_script $js_flexera_api_hosts, rs_optima_host -end - -script "js_flexera_api_hosts", type: "javascript" do - parameters "rs_optima_host" - result "result" - code <<-EOS - host_table = { - "api.optima.flexeraeng.com": { - flexera: "api.flexera.com", - fsm: "api.fsm.flexeraeng.com" - }, - "api.optima-eu.flexeraeng.com": { - flexera: "api.flexera.eu", - fsm: "api.fsm-eu.flexeraeng.com" - }, - "api.optima-apac.flexeraeng.com": { - flexera: "api.flexera.au", - fsm: "api.fsm-apac.flexeraeng.com" - } - } - - result = host_table[rs_optima_host] -EOS -end - -datasource "ds_existing_rbds" do - request do - auth $auth_flexera - host rs_optima_host - path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) - header "Api-Version", "1.0" - header "content-type", "application/json" - end - result do - encoding "json" - collect jmes_path(response, "rule_based_dimensions") do - field "id", jmes_path(col_item, "id") - field "name", jmes_path(col_item, "name") - field "dated_rules", jmes_path(col_item, "dated_rules") - end - end -end - -datasource "ds_azure_subscriptions_without_tags" do - request do - auth $auth_azure - pagination $pagination_azure - host "management.azure.com" - path "/subscriptions/" - query "api-version", "2018-06-01" - header "User-Agent", "RS Policies" - # Ignore status 400, 403, and 404 which can be returned in certain (legacy) types of Azure Subscriptions - ignore_status [400, 403, 404] - end - result do - encoding "json" - collect jmes_path(response, "value[*]") do - field "id", jmes_path(col_item, "subscriptionId") - field "name", jmes_path(col_item, "displayName") - end - end -end - -datasource "ds_azure_subscriptions" do - iterate $ds_azure_subscriptions_without_tags - request do - auth $auth_azure - pagination $pagination_azure - host "management.azure.com" - path join(["/subscriptions/", val(iter_item, "id"), "/providers/Microsoft.Resources/tags/default"]) - query "api-version", "2021-04-01" - header "User-Agent", "RS Policies" - ignore_status [400, 403, 404] - end - result do - encoding "json" - field "id", val(iter_item, "id") - field "name", val(iter_item, "name") - field "tags", jmes_path(response, "properties.tags") - end -end - -datasource "ds_azure_subscriptions_normalized" do - run_script $js_azure_subscriptions_normalized, $ds_azure_subscriptions -end - -script "js_azure_subscriptions_normalized", type: "javascript" do - parameters "accounts" - result "result" - code <<-'EOS' - result = [] - - _.each(accounts, function(account) { - tags = {} - - if (account['tags'] != null && account['tags'] != undefined) { - _.each(Object.keys(account['tags']), function(key) { - normalized_key = key.toLowerCase().trim() - tags[normalized_key] = account['tags'][key] - }) - } - - result.push({ - id: account['id'], - name: account['name'], - tags: tags - }) - }) -EOS -end - -datasource "ds_rbds" do - run_script $js_rbds, $ds_azure_subscriptions_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_normalize_case -end - -script "js_rbds", type: "javascript" do - parameters "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_normalize_case" - result "result" - code <<-'EOS' - result = [] - - rbd_id_list = _.pluck(existing_rbds, 'id') - - _.each(param_tag_list, function(tag, index) { - rbd_name = tag.replace('.', ' ').replace('-', ' ') - rbd_name = rbd_name.replace(/\W/g, " ").trim() - - // Use user-specified name instead of user provided one - if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } - - rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() - - tag_key = tag.toLowerCase().trim() - verb = "POST" - if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } - - rules = [] - - _.each(accounts, function(account) { - if (typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) - } - } - } - }) - - if (rules.length > 0) { - result.push({ - id: rbd_id, - name: rbd_name, - verb: verb, - effective_at: param_effective_date, - rules: rules - }) - } - }) -EOS -end - -datasource "ds_create_rbds" do - iterate $ds_rbds - request do - run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id - end - result do - encoding "text" - end -end - -script "js_create_rbds", type: "javascript" do - parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: verb, - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), - body_fields: { name: name } - } -EOS -end - -datasource "ds_apply_rbds" do - iterate $ds_rbds - request do - # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does - run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id - end - result do - encoding "text" - end -end - -script "js_apply_rbds", type: "javascript" do - parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: "PUT", - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), - body_fields: { rules: rules } - } -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_rbds" do - validate $ds_apply_rbds do - summary_template "RBDs Generated & Applied" - detail_template "" - check eq(0, 0) - end -end diff --git a/automation/flexera/delete_all_billing_centers/CHANGELOG.md b/automation/flexera/delete_all_billing_centers/CHANGELOG.md deleted file mode 100644 index 6b508a1e70..0000000000 --- a/automation/flexera/delete_all_billing_centers/CHANGELOG.md +++ /dev/null @@ -1,13 +0,0 @@ -# Changelog - -## v1.1.1 - -- Minor code improvements to conform with current standards. Functionality unchanged. - -## v1.1 - -- Updated policy metadata to make it more clear what Flexera service the policy is for - -## v1.0 - -- initial release diff --git a/automation/flexera/delete_all_billing_centers/README.md b/automation/flexera/delete_all_billing_centers/README.md deleted file mode 100644 index 878c9a5917..0000000000 --- a/automation/flexera/delete_all_billing_centers/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Flexera CCO Delete All Billing Centers - -## What It Does - -This policy deletes all Billing Centers in the Flexera organization it is executed within. The policy will automatically self-terminate the second time it runs to avoid accidental future deletion of Billing Centers. - -## How It Works - -- During execution, the policy determines if this is the second time it has run since it was applied by comparing the applied policy's `created_at` date/time with the current date/time. If the difference between the two is greater than 1 minute, it is assumed the policy is running a second time. -- If this is the policy's second time running, the policy self-terminates before completing execution as a failsafe in case the user has forgotten to terminate the policy after usage. -- An incident is always raised, with the `Self Terminate` field in the incident table being true if this is the policy's second time executing since it was applied. -- Cloud Workflow is automatically kicked off. - - If this is the policy's second time executing, but for some reason the policy has failed to self-terminate, no action will be taken. - - If this is the policy's first time executing, all of the Billing Centers in the Flexera organization are deleted. - -## Input Parameters - -This policy template has no input parameters. - -## Policy Actions - -- Delete all Billing Centers - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -### Credential configuration - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `billing_center_admin` - - `policy_manager` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- Flexera - -## Cost - -This policy template does not incur any cloud costs. diff --git a/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt b/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt deleted file mode 100644 index 2eb4046e2c..0000000000 --- a/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt +++ /dev/null @@ -1,233 +0,0 @@ -name "Flexera CCO Delete All Billing Centers" -rs_pt_ver 20180301 -type "policy" -short_description "Deletes all Billing Centers in the Flexera organization. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/flexera/delete_all_billing_centers) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "high" -category "Cost" -default_frequency "15 minutes" -info( - version: "1.1.1", - provider: "Flexera", - service: "Cloud Cost Optimization", - policy_set: "Automation", - publish: "false" -) - -############################################################################### -# Parameters -############################################################################### - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_flexera" do - schemes "oauth2" - label "Flexera" - description "Select FlexeraOne OAuth2 credential." - tags "provider=flexera" -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -datasource "ds_applied_policy" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) - header "Api-Version", "1.0" - end -end - -datasource "ds_second_execution" do - run_script $js_second_execution, $ds_applied_policy -end - -script "js_second_execution", type: "javascript" do - parameters "ds_applied_policy" - result "result" - code <<-'EOS' - result = [{ id: ds_applied_policy['href'], terminate: false }] - - now = new Date() - created_at = new Date(ds_applied_policy['created_at']) - - // If applied policy was created over 1 minute ago, assume this is the second time it is running - if (now - created_at > 60000) { result[0]['terminate'] = true } -EOS -end - -datasource "ds_self_terminate_boolean" do - run_script $js_self_terminate_boolean, $ds_second_execution -end - -script "js_self_terminate_boolean", type: "javascript" do - parameters "ds_second_execution" - result "result" - code <<-'EOS' - result = [] - - if (ds_second_execution[0]['terminate']) { result = ds_second_execution } -EOS -end - -datasource "ds_self_terminate" do - iterate $ds_self_terminate_boolean - request do - auth $auth_flexera - verb "DELETE" - host rs_governance_host - path val(iter_item, 'id') - header "Api-Version", "1.0" - end -end - -datasource "ds_incident" do - run_script $js_incident, $ds_second_execution, $ds_self_terminate -end - -script "js_incident", type: "javascript" do - parameters "ds_second_execution", "ds_self_terminate" - result "result" - code <<-'EOS' - result = ds_second_execution -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_delete_bcs" do - validate_each $ds_incident do - summary_template "Deleting Billing Centers" - check eq(0, 1) - escalate $esc_delete_billing_centers - export do - resource_level true - field "id" do - label "Policy HREF" - end - field "terminate" do - label "Self Terminate" - end - end - end -end - -############################################################################### -# Escalations -############################################################################### - -escalation "esc_delete_billing_centers" do - automatic true - label "Delete Billing Centers" - description "Approval to delete all billing centers" - run "delete_billing_centers", data, rs_org_id, rs_optima_host -end - -############################################################################### -# Cloud Workflow -############################################################################### - -define delete_billing_centers($data, $rs_org_id, $rs_optima_host) return $all_responses do - $$all_responses = [] - - # Policy will only run if it isn't self-terminating - if $data[0]["terminate"] == false - call list_childless_billing_centers($rs_org_id, $rs_optima_host) retrieve $billing_centers - - while size($billing_centers) > 0 do - foreach $billing_center in $billing_centers do - sub on_error: handle_error() do - call delete_billing_center($billing_center, $rs_org_id, $rs_optima_host) retrieve $delete_response - end - end - - sleep(10) - - call list_childless_billing_centers($rs_org_id, $rs_optima_host) retrieve $billing_centers - end - end -end - -define list_childless_billing_centers($rs_org_id, $rs_optima_host) return $billing_centers do - $billing_centers = [] - - task_label("Listing All Billing Centers") - - $response = http_request( - auth: $$auth_flexera, - https: true, - verb: "get", - href: "/analytics/orgs/" + $rs_org_id + "/billing_centers", - host: $rs_optima_host, - headers: { - "Api-Version": "1.0", - "User-Agent": "RS Policies" - } - ) - - task_label("Listing All Billing Centers response: " + to_json($response)) - $$all_responses << to_json({"req": "GET /billing_centers", "resp": $response}) - - if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 - raise "Unexpected response Listing All Billing Centers: " + to_json($response) - else - task_label("Listing All Billing Centers successful") - - $parent_ids = [] - - foreach $item in $response["body"] do - if $item["name"] != "Unallocated" && $item["parent_id"] != null && $item["parent_id"] != "" - $parent_ids << $item["parent_id"] - end - end - - foreach $item in $response["body"] do - if $item["name"] != "Unallocated" && contains?($parent_ids, [ $item["id"] ]) == false - $billing_centers << $item - end - end - end -end - -define delete_billing_center($billing_center, $rs_org_id, $rs_optima_host) return $response do - $bc_label = $billing_center["name"] + " (" + $billing_center["id"] + ")" - - task_label("Delete Billing Center: " + $bc_label) - - $response = http_request( - auth: $$auth_flexera, - https: true, - verb: "delete", - href: "/analytics/orgs/" + $rs_org_id + "/billing_centers/" + $billing_center["id"], - host: $rs_optima_host, - headers: { - "Api-Version": "1.0", - "User-Agent": "RS Policies" - } - ) - - task_label("Delete Billing Center response: " + $bc_label + " " + to_json($response)) - $$all_responses << to_json({"req": "DELETE /billing_centers/" + $billing_center["id"], "resp": $response}) - - if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 - raise "Unexpected response Deleting Billing Centers: " + $bc_label + " " + to_json($response) - else - task_label("Delete Billing Center successful: " + $bc_label) - end -end - -define handle_error() do - if !$$errors - $$errors = [] - end - $$errors << $_error["type"] + ": " + $_error["message"] - # We check for errors at the end, and raise them all together - # Skip errors handled by this definition - $_error_behavior = "skip" -end diff --git a/automation/flexera/outdated_applied_policies/CHANGELOG.md b/automation/flexera/outdated_applied_policies/CHANGELOG.md deleted file mode 100644 index 85a84d011f..0000000000 --- a/automation/flexera/outdated_applied_policies/CHANGELOG.md +++ /dev/null @@ -1,14 +0,0 @@ -# Changelog - -## v0.2.0 - -- Policy template now reports both outdated and deprecated policy templates with a parameter to choose which -- Automatic updates for policy templates with a major version change is now supported via parameter - -## v0.1.1 - -- Minor fix to wording in resulting incident detail - -## v0.1 - -- initial release diff --git a/automation/flexera/outdated_applied_policies/README.md b/automation/flexera/outdated_applied_policies/README.md deleted file mode 100644 index 91be793e28..0000000000 --- a/automation/flexera/outdated_applied_policies/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# Flexera Automation Outdated Applied Policies - -## What It Does - -This policy template checks all applied policies for the following: - -- Whether the policy template is an older version than the current version in the policy catalog. -- Whether the policy template has been deprecated. - -The following policy types will always be ignored and not reported on by this policy: - -- This policy itself. -- Policies applied from a source other than the Flexera Automation Catalog. -- Organization-specific policies published to that organization's own catalog. -- Flexera policies present in the [policy-templates Github Repository](https://github.com/flexera-public/policy_templates) but not published in the Flexera Automation Catalog, such as meta policies and other misc. utility policies. -- Policy aggregates applied across multiple projects. Aggregates applied only to the project this policy is applied in will still be included in the results and are actionable. - -## How It Works - -The list of outdated policies is generated as follows: - -- The list of applied policies are obtained using the [Flexera Policy API](https://reference.rightscale.com/governance-policies/). -- The list of catalog policies are obtained using the [Active Policy List JSON file](https://github.com/flexera-public/policy_templates/blob/master/data/active_policy_list/active_policy_list.json) in the [policy-templates Github Repository](https://github.com/flexera-public/policy_templates). -- The list of applied policies is filtered for just those applied policies that were applied from a catalog policy and whose version number does not match the version number in the catalog. - -The list of deprecated policies is generated as follows: - -- The list of applied policies are obtained using the [Flexera Policy API](https://reference.rightscale.com/governance-policies/). -- The list of catalog policies are obtained using the [Active Policy List JSON file](https://github.com/flexera-public/policy_templates/blob/master/data/active_policy_list/active_policy_list.json) in the [policy-templates Github Repository](https://github.com/flexera-public/policy_templates). -- The list of applied policies is filtered for just those applied policies marked as deprecated in the [Active Policy List JSON file](https://github.com/flexera-public/policy_templates/blob/master/data/active_policy_list/active_policy_list.json). - -Updating an outdated policy is done as follows: - -- The [major version](https://semver.org/) of the applied policy is compared to the catalog policy. If the major version has changed, and the `Allow Automated Major Version Updates` parameter is set to "Do Not Allow", an error is raised indicating that the update should be done manually. This is because a major version change usually involves major changes in functionality and input parameters that would require the user to intelligently determine how to apply the updated policy. -- If the major version has not changed, or the `Allow Automated Major Version Updates` parameter is set to "Allow", the catalog policy is applied with the exact same configuration and settings as the existing applied policy. -- If the above action was successful, the existing applied policy is deleted. If the above action failed, an error is raised and the existing applied policy remains in place so that the user can manually update as needed. - -## Input Parameters - -- *Email Addresses* - A list of email addresses to notify. -- *Policy Ignore List* - A list of applied policy names and/or IDs to ignore and not report on. Leave blank to assess all applied policies. -- *Policy Templates To Report* - Whether to report outdated policy templates, deprecated policy templates, or both. Separate incidents will be raised/emailed if both are selected and found. -- *Allow Automated Major Version Updates* - Whether to allow actions to automatically update outdated policy templates when there's been a major version change. This is not recommended in most cases. -- *Automatic Actions* - When this value is set, this policy will automatically take the selected action(s). - -## Policy Actions - -- Send an email report -- Update applied policy to the newest version after approval - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -### Credential Configuration - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `policy_viewer` - - `policy_manager`* - - \* Only required for taking action (updating applied policies); the policy will still function in a read-only capacity without these permissions. - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- Flexera - -## Cost - -This policy template does not incur any cloud costs. Cloud costs may be incurred by the applied policies that this policy reports on and updates. Please consult the README of each policy for more information. diff --git a/automation/flexera/outdated_applied_policies/outdated_applied_policies.pt b/automation/flexera/outdated_applied_policies/outdated_applied_policies.pt deleted file mode 100644 index 367dee8444..0000000000 --- a/automation/flexera/outdated_applied_policies/outdated_applied_policies.pt +++ /dev/null @@ -1,835 +0,0 @@ -name "Flexera Automation Outdated Applied Policies" -rs_pt_ver 20180301 -type "policy" -short_description "Reports any applied policies in Flexera Automation that are not using the latest version of that policy from the catalog and, optionally, updates them. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/flexera/outdated_applied_policies) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "low" -category "Operational" -default_frequency "weekly" -info( - version: "0.2.0", - provider: "Flexera", - service: "Automation", - policy_set: "Automation" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_email" do - type "list" - category "Policy Settings" - label "Email Addresses" - description "A list of email addresses to notify." - default [] -end - -parameter "param_ignore_list" do - type "list" - category "Filters" - label "Policy Ignore List" - description "A list of applied policy names and/or IDs to ignore and not report on. Leave blank to assess all applied policies." - default [] -end - -parameter "param_report_filter" do - type "string" - category "Filters" - label "Policy Templates To Report" - description "Whether to report outdated policy templates, deprecated policy templates, or both. Separate incidents will be raised/emailed if both are selected and found." - allowed_values "Both", "Report Outdated Only", "Report Deprecated Only" - default "Both" -end - -parameter "param_allow_major" do - type "string" - category "Actions" - label "Allow Automated Major Version Updates" - description "Whether to allow actions to automatically update outdated policy templates when there's been a major version change. This is not recommended in most cases." - allowed_values "Allow", "Do Not Allow" - default "Do Not Allow" -end - -parameter "param_automatic_action" do - type "list" - category "Actions" - label "Automatic Actions" - description "When this value is set, this policy will automatically take the selected action(s)" - allowed_values ["Update Applied Policies"] - default [] -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_flexera" do - schemes "oauth2" - label "Flexera" - description "Select Flexera One OAuth2 credentials" - tags "provider=flexera" -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -datasource "ds_self_policy" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) - header "Api-Version", "1.0" - end -end - -datasource "ds_applied_policies" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/projects/", rs_project_id, "/applied_policies"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - collect jmes_path(response, "items[*]") do - field "id", jmes_path(col_item, "id") - field "href", jmes_path(col_item, "href") - field "name", jmes_path(col_item, "name") - field "description", jmes_path(col_item, "description") - field "category", jmes_path(col_item, "category") - field "created_at", jmes_path(col_item, "created_at") - field "created_by", jmes_path(col_item, "created_by.email") - field "frequency", jmes_path(col_item, "frequency") - field "category", jmes_path(col_item, "category") - field "credentials", jmes_path(col_item, "credentials") - field "options", jmes_path(col_item, "options") - field "severity", jmes_path(col_item, "severity") - field "skip_approvals", jmes_path(col_item, "skip_approvals") - field "scope", jmes_path(col_item, "scope") - field "dry_run", jmes_path(col_item, "dry_run") - field "log_level", jmes_path(col_item, "log_level") - field "version", jmes_path(col_item, "info.version") - field "policy_template", jmes_path(col_item, "policy_template") - field "published_template", jmes_path(col_item, "published_template") - end - end -end - -datasource "ds_policy_aggregates" do - request do - auth $auth_flexera - host rs_governance_host - path join(["/api/governance/orgs/", rs_org_id, "/policy_aggregates"]) - header "Api-Version", "1.0" - end - result do - encoding "json" - collect jmes_path(response, "items[*]") do - field "id", jmes_path(col_item, "id") - field "href", jmes_path(col_item, "href") - field "name", jmes_path(col_item, "name") - field "description", jmes_path(col_item, "description") - field "category", jmes_path(col_item, "category") - field "created_at", jmes_path(col_item, "created_at") - field "created_by", jmes_path(col_item, "created_by.email") - field "frequency", jmes_path(col_item, "frequency") - field "category", jmes_path(col_item, "category") - field "credentials", jmes_path(col_item, "credentials") - field "options", jmes_path(col_item, "options") - field "severity", jmes_path(col_item, "severity") - field "skip_approvals", jmes_path(col_item, "skip_approvals") - field "dry_run", jmes_path(col_item, "dry_run") - field "running_project_ids", jmes_path(col_item, "running_project_ids") - field "published_template", jmes_path(col_item, "published_template") - end - end -end - -datasource "ds_catalog_policies" do - request do - verb "GET" - host "raw.githubusercontent.com" - path "/flexera-public/policy_templates/master/data/active_policy_list/active_policy_list.json" - header "User-Agent", "RS Policies" - end - result do - encoding "json" - collect jmes_path(response, "policies[*]") do - field "name", jmes_path(col_item, "name") - field "file_name", jmes_path(col_item, "file_name") - field "version", jmes_path(col_item, "version") - field "change_log", jmes_path(col_item, "change_log") - field "description", jmes_path(col_item, "description") - field "category", jmes_path(col_item, "category") - field "severity", jmes_path(col_item, "severity") - field "readme", jmes_path(col_item, "readme") - field "provider", jmes_path(col_item, "provider") - field "service", jmes_path(col_item, "service") - field "policy_set", jmes_path(col_item, "policy_set") - field "recommendation_type", jmes_path(col_item, "recommendation_type") - field "updated_at", jmes_path(col_item, "updated_at") - field "generally_recommended", jmes_path(col_item, "generally_recommended") - field "deprecated", jmes_path(col_item, "deprecated") - end - end -end - -datasource "ds_outdated_policies" do - run_script $js_outdated_policies, $ds_applied_policies, $ds_catalog_policies, $ds_policy_aggregates, $ds_self_policy, $param_ignore_list, $param_report_filter, rs_org_id, rs_project_id, policy_id, rs_optima_host -end - -script "js_outdated_policies", type: "javascript" do - parameters "ds_applied_policies", "ds_catalog_policies", "ds_policy_aggregates", "ds_self_policy", "param_ignore_list", "param_report_filter", "rs_org_id", "rs_project_id", "policy_id", "rs_optima_host" - result "result" - code <<-'EOS' - tld_table = { - "api.optima.flexeraeng.com": "app.flexera.com", - "api.optima-eu.flexeraeng.com": "app.flexera.eu", - "api.optima-apac.flexeraeng.com": "app.flexera.au" - } - - tld = tld_table[rs_optima_host] - - aggregate_object = {} - - _.each(ds_policy_aggregates, function(agg) { - if (typeof(agg['running_project_ids']) == 'object') { - if (agg['running_project_ids'].length == 1 && agg['running_project_ids'][0] == rs_project_id) { - aggregate_object[agg['name']] = agg['href'] - } - } - }) - - catalog_object = {} - - _.each(ds_catalog_policies, function(policy) { - catalog_object[policy['name']] = policy - }) - - filtered_policies = _.reject(ds_applied_policies, function(policy) { - reject_policy = false - - // Exclude this policy to avoid the policy trying to terminate itself if the user actions on it - if (policy['id'] == policy_id) { - reject_policy = true - } - - // Exclude policies on the user-provided ignore list - ignore_list = _.map(param_ignore_list, function(item) { return item.toLowerCase().trim() }) - - if (!reject_policy && (_.contains(ignore_list, policy['name'].toLowerCase()) || _.contains(ignore_list, policy['id'].toLowerCase()))) { - reject_policy = true - } - - // Exclude policies that were not applied from the catalog - if (!reject_policy && policy['published_template'] == null) { - reject_policy = true - } else if (!reject_policy) { - // Exclude policies where we did not find a corresponding entry in the active policy list - if (catalog_object[policy['published_template']['name']] == undefined) { - reject_policy = true - } - - // Exclude policies applied from a catalog other than the Flexera one - if (!reject_policy && policy['published_template']['updated_by']['email'] != 'support@flexera.com') { - reject_policy = true - } - } - - // Exclude all policies if the user opted not to report on outdated policies - if (!reject_policy && param_report_filter == "Report Deprecated Only") { - reject_policy = true - } - - return reject_policy - }) - - combined_data = _.map(filtered_policies, function(policy) { - catalog_policy = catalog_object[policy['published_template']['name']] - policy_url = "https://" + tld + "/orgs/" + rs_org_id + "/automation/applied-policies/projects/" + rs_project_id + "?policyId=" + policy['id'] - - rec_verb = "Update" - - if (policy['version'].split('.')[0] != catalog_policy['version'].split('.')[0]) { - rec_verb = "Manually update" - } - - recommendationDetails = [ - rec_verb, " applied policy ", policy['name'], " (", policy['id'], ") ", - "from version ", policy['version'], " to version ", catalog_policy['version'] - ].join('') - - href = null - - if (policy['scope'] == 'org' && typeof(aggregate_object[policy['name']]) == 'string') { - href = aggregate_object[policy['name']] - } - - if (policy['scope'] != 'org') { - href = policy['href'] - } - - update_body = { - credentials: policy['credentials'], - description: policy['description'], - dry_run: policy['dry_run'], - frequency: policy['frequency'], - log_level: policy['log_level'], - name: policy['name'], - options: policy['options'], - severity: policy['severity'], - skip_approvals: policy['skip_approvals'], - template_href: policy['published_template']['href'] - } - - catalog_recommendation_type = "" - - if (typeof(catalog_policy['recommendation_type']) == 'string') { - catalog_recommendation_type = catalog_policy['recommendation_type'] - } - - boolean_table = { "true": "True", "false": "False" } - - catalog_url = "https://github.com/flexera-public/policy_templates/tree/master/" + catalog_policy['readme'] - - return { - id: policy['id'], - name: policy['name'] + "||" + policy_url, - name_without_link: policy['name'], - description: policy['description'], - category: policy['category'], - created_at: policy['created_at'], - created_by: policy['created_by'], - frequency: policy['frequency'], - version: policy['version'], - credentials: policy['credentials'], - options: policy['options'], - severity: policy['severity'], - skip_approvals: policy['skip_approvals'], - scope: policy['scope'], - dry_run: policy['dry_run'], - log_level: policy['log_level'], - catalog_id: policy['published_template']['id'], - catalog_href: policy['published_template']['href'], - catalog_name: catalog_policy['name'] + "||" + catalog_url, - catalog_file_name: catalog_policy['file_name'], - catalog_version: catalog_policy['version'], - catalog_change_log: catalog_policy['change_log'], - catalog_description: catalog_policy['description'], - catalog_category: catalog_policy['category'], - catalog_severity: catalog_policy['severity'], - catalog_readme: catalog_policy['readme'], - catalog_provider: catalog_policy['provider'], - catalog_service: catalog_policy['service'], - catalog_policy_set: catalog_policy['policy_set'], - catalog_recommendation_type: catalog_recommendation_type, - catalog_updated_at: catalog_policy['updated_at'], - catalog_generally_recommended: boolean_table[catalog_policy['generally_recommended'].toString()], - catalog_deprecated: boolean_table[catalog_policy['deprecated'].toString()], - self_policy_name: ds_self_policy['name'], - href: href, - update_body: update_body, - recommendationDetails: recommendationDetails, - message: '' - } - }) - - result = _.filter(combined_data, function(policy) { - return policy['version'] != policy['catalog_version'] && typeof(policy['catalog_version']) == 'string' && policy['href'] != null - }) - - if (result.length > 0) { - total_applied_policies = ds_applied_policies.length.toString() - total_outdated = result.length.toString() - outdated_percentage = (total_outdated / total_applied_policies * 100).toFixed(2).toString() + '%' - - pol_noun = "policies" - if (total_applied_policies == 1) { pol_noun = "policy" } - - pol_verb = "are outdated" - if (total_outdated == 1) { pol_verb = "is outdated" } - - pol_action = "recommended to be replaced with the latest version from the Catalog" - - message = [ - "Out of ", total_applied_policies, " ", pol_noun, " analyzed, ", - total_outdated, " (", outdated_percentage, - ") ", pol_verb, " and ", pol_action, ".\n\n" - ].join('') - - settings = "No policies were filtered from this report.\n\n" - - if (param_ignore_list.length > 0) { - settings = "The following policies were filtered from this report: " + param_ignore_list.join(', ') + "\n\n" - } - - disclaimer = "Filtering can be adjusted by editing the applied policy and changing the appropriate parameters." - - result[0]['message'] = message + settings + disclaimer - } -EOS -end - -datasource "ds_deprecated_policies" do - run_script $js_deprecated_policies, $ds_applied_policies, $ds_catalog_policies, $ds_policy_aggregates, $ds_self_policy, $param_ignore_list, $param_report_filter, rs_org_id, rs_project_id, policy_id, rs_optima_host -end - -script "js_deprecated_policies", type: "javascript" do - parameters "ds_applied_policies", "ds_catalog_policies", "ds_policy_aggregates", "ds_self_policy", "param_ignore_list", "param_report_filter", "rs_org_id", "rs_project_id", "policy_id", "rs_optima_host" - result "result" - code <<-'EOS' - tld_table = { - "api.optima.flexeraeng.com": "app.flexera.com", - "api.optima-eu.flexeraeng.com": "app.flexera.eu", - "api.optima-apac.flexeraeng.com": "app.flexera.au" - } - - tld = tld_table[rs_optima_host] - - aggregate_object = {} - - _.each(ds_policy_aggregates, function(agg) { - if (typeof(agg['running_project_ids']) == 'object') { - if (agg['running_project_ids'].length == 1 && agg['running_project_ids'][0] == rs_project_id) { - aggregate_object[agg['name']] = agg['href'] - } - } - }) - - catalog_object = {} - - _.each(ds_catalog_policies, function(policy) { - catalog_object[policy['name']] = policy - }) - - filtered_policies = _.reject(ds_applied_policies, function(policy) { - reject_policy = false - - // Exclude this policy to avoid the policy trying to terminate itself if the user actions on it - if (policy['id'] == policy_id) { - reject_policy = true - } - - // Exclude policies on the user-provided ignore list - ignore_list = _.map(param_ignore_list, function(item) { return item.toLowerCase().trim() }) - - if (!reject_policy && (_.contains(ignore_list, policy['name'].toLowerCase()) || _.contains(ignore_list, policy['id'].toLowerCase()))) { - reject_policy = true - } - - // Exclude policies that were not applied from the catalog - if (!reject_policy && policy['published_template'] == null) { - reject_policy = true - } else if (!reject_policy) { - // Exclude policies where we did not find a corresponding entry in the active policy list - if (catalog_object[policy['published_template']['name']] == undefined) { - reject_policy = true - } - - // Exclude policies applied from a catalog other than the Flexera one - if (!reject_policy && policy['published_template']['updated_by']['email'] != 'support@flexera.com') { - reject_policy = true - } - } - - // Exclude all policies if the user opted not to report on deprecated policies - if (!reject_policy && param_report_filter == "Report Outdated Only") { - reject_policy = true - } - - // Exclude non-deprecated policies - if (!reject_policy && !catalog_object[policy['published_template']['name']]['deprecated']) { - reject_policy = true - } - - return reject_policy - }) - - result = _.map(filtered_policies, function(policy) { - catalog_policy = catalog_object[policy['published_template']['name']] - policy_url = "https://" + tld + "/orgs/" + rs_org_id + "/automation/applied-policies/projects/" + rs_project_id + "?policyId=" + policy['id'] - - recommendationDetails = [ - "Terminate applied policy ", policy['name'], " (", policy['id'], ")" - ].join('') - - href = null - - if (policy['scope'] == 'org' && typeof(aggregate_object[policy['name']]) == 'string') { - href = aggregate_object[policy['name']] - } - - if (policy['scope'] != 'org') { - href = policy['href'] - } - - update_body = { - credentials: policy['credentials'], - description: policy['description'], - dry_run: policy['dry_run'], - frequency: policy['frequency'], - log_level: policy['log_level'], - name: policy['name'], - options: policy['options'], - severity: policy['severity'], - skip_approvals: policy['skip_approvals'], - template_href: policy['published_template']['href'] - } - - catalog_recommendation_type = "" - - if (typeof(catalog_policy['recommendation_type']) == 'string') { - catalog_recommendation_type = catalog_policy['recommendation_type'] - } - - boolean_table = { "true": "True", "false": "False" } - - catalog_url = "https://github.com/flexera-public/policy_templates/tree/master/" + catalog_policy['readme'] - - return { - id: policy['id'], - name: policy['name'] + "||" + policy_url, - name_without_link: policy['name'], - description: policy['description'], - category: policy['category'], - created_at: policy['created_at'], - created_by: policy['created_by'], - frequency: policy['frequency'], - version: policy['version'], - credentials: policy['credentials'], - options: policy['options'], - severity: policy['severity'], - skip_approvals: policy['skip_approvals'], - scope: policy['scope'], - dry_run: policy['dry_run'], - log_level: policy['log_level'], - catalog_id: policy['published_template']['id'], - catalog_href: policy['published_template']['href'], - catalog_name: catalog_policy['name'] + "||" + catalog_url, - catalog_file_name: catalog_policy['file_name'], - catalog_version: catalog_policy['version'], - catalog_change_log: catalog_policy['change_log'], - catalog_description: catalog_policy['description'], - catalog_category: catalog_policy['category'], - catalog_severity: catalog_policy['severity'], - catalog_readme: catalog_policy['readme'], - catalog_provider: catalog_policy['provider'], - catalog_service: catalog_policy['service'], - catalog_policy_set: catalog_policy['policy_set'], - catalog_recommendation_type: catalog_recommendation_type, - catalog_updated_at: catalog_policy['updated_at'], - catalog_generally_recommended: boolean_table[catalog_policy['generally_recommended'].toString()], - catalog_deprecated: boolean_table[catalog_policy['deprecated'].toString()], - self_policy_name: ds_self_policy['name'], - href: href, - update_body: update_body, - recommendationDetails: recommendationDetails, - message: '' - } - }) - - if (result.length > 0) { - total_applied_policies = ds_applied_policies.length.toString() - total_deprecated = result.length.toString() - deprecated_percentage = (total_deprecated / total_applied_policies * 100).toFixed(2).toString() + '%' - - pol_noun = "policies" - if (total_applied_policies == 1) { pol_noun = "policy" } - - pol_verb = "are deprecated" - if (total_deprecated == 1) { pol_verb = "is deprecated" } - - pol_action = [ - "recommended for termination. ", - "Please consult the policy template README for information on what policy template to use instead. ", - "The README can be accessed by clicking on the link in the 'Catalog Policy Name' field" - ].join('') - - message = [ - "Out of ", total_applied_policies, " ", pol_noun, " analyzed, ", - total_deprecated, " (", deprecated_percentage, - ") ", pol_verb, " and ", pol_action, ".\n\n" - ].join('') - - settings = "No policies were filtered from this report.\n\n" - - if (param_ignore_list.length > 0) { - settings = "The following policies were filtered from this report: " + param_ignore_list.join(', ') + "\n\n" - } - - disclaimer = "Filtering can be adjusted by editing the applied policy and changing the appropriate parameters." - - result[0]['message'] = message + settings + disclaimer - } -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_outdated_policies" do - validate_each $ds_outdated_policies do - summary_template "{{ with index data 0 }}{{ .self_policy_name }}{{ end }}: {{ len data }} Outdated Policies Found" - detail_template "{{ with index data 0 }}{{ .message }}{{ end }}" - check eq(val(item, "id"), "") - escalate $esc_email - escalate $esc_update_policies - export do - resource_level true - field "name" do - label "Applied Policy Name" - format "link-external" - end - field "recommendationDetails" do - label "Recommendation" - end - field "created_at" do - label "Date Applied" - end - field "catalog_updated_at" do - label "Date Catalog Updated" - end - field "catalog_deprecated" do - label "Deprecated" - end - field "version" do - label "Applied Policy Version" - end - field "catalog_version" do - label "Catalog Policy Version" - end - field "catalog_id" do - label "Catalog Policy ID" - end - field "catalog_name" do - label "Catalog Policy Name" - format "link-external" - end - field "catalog_href" do - label "Catalog Policy HREF" - end - field "id" do - label "Applied Policy ID" - end - field "href" do - label "Applied Policy HREF" - end - field "description" do - label "Applied Policy Description" - end - field "frequency" do - label "Applied Policy Frequency" - end - field "severity" do - label "Applied Policy Severity" - end - field "skip_approvals" do - label "Applied Policy Skip Approvals" - end - field "scope" do - label "Applied Policy Scope" - end - field "dry_run" do - label "Applied Policy Dry Run" - end - field "log_level" do - label "Applied Policy Log Level" - end - field "name_without_link" do - label "Applied Policy Name (Unlinked)" - end - field "update_body" do - label "Applied Policy Details" - end - end - end - validate_each $ds_deprecated_policies do - summary_template "{{ with index data 0 }}{{ .self_policy_name }}{{ end }}: {{ len data }} Deprecated Policies Found" - detail_template "{{ with index data 0 }}{{ .message }}{{ end }}" - check eq(val(item, "id"), "") - escalate $esc_email - export do - resource_level true - field "name" do - label "Applied Policy Name" - format "link-external" - end - field "recommendationDetails" do - label "Recommendation" - end - field "created_at" do - label "Date Applied" - end - field "catalog_updated_at" do - label "Date Catalog Updated" - end - field "catalog_deprecated" do - label "Deprecated" - end - field "version" do - label "Applied Policy Version" - end - field "catalog_version" do - label "Catalog Policy Version" - end - field "catalog_id" do - label "Catalog Policy ID" - end - field "catalog_name" do - label "Catalog Policy Name" - format "link-external" - end - field "catalog_href" do - label "Catalog Policy HREF" - end - field "id" do - label "Applied Policy ID" - end - field "href" do - label "Applied Policy HREF" - end - field "description" do - label "Applied Policy Description" - end - field "frequency" do - label "Applied Policy Frequency" - end - field "severity" do - label "Applied Policy Severity" - end - field "skip_approvals" do - label "Applied Policy Skip Approvals" - end - field "scope" do - label "Applied Policy Scope" - end - field "dry_run" do - label "Applied Policy Dry Run" - end - field "log_level" do - label "Applied Policy Log Level" - end - field "name_without_link" do - label "Applied Policy Name (Unlinked)" - end - field "update_body" do - label "Applied Policy Details" - end - end - end -end - -############################################################################### -# Escalations -############################################################################### - -escalation "esc_email" do - automatic true - label "Send Email" - description "Send incident email" - email $param_email -end - -escalation "esc_update_policies" do - automatic contains($param_automatic_action, "Update Applied Policies") - label "Update Applied Policies" - description "Approval to update all selected applied policies to the latest version" - run "update_policies", data, $param_allow_major, rs_governance_host, rs_project_id -end - -############################################################################### -# Cloud Workflow -############################################################################### - -define update_policies($data, $param_allow_major, $rs_governance_host, $rs_project_id) return $all_responses do - $$all_responses = [] - - foreach $policy in $data do - sub on_error: handle_error() do - - if split($policy['version'], '.')[0] == split($policy['catalog_version'], '.')[0] || $param_allow_major == "Allow" - call apply_policy($policy, $rs_governance_host, $rs_project_id) retrieve $apply_response, $code - - if $code == 204 || $code == 202 || $code == 200 - call delete_policy($policy, $rs_governance_host) retrieve $delete_response - end - else - $policy_name = $policy["name_without_link"] + " (" + $policy["id"] + ")" - raise "Applied Policy " + $policy_name + " was not updated due to a major version change. Please update manually." - end - end - end - - if inspect($$errors) != "null" - raise join($$errors, "\n") - end -end - -define apply_policy($policy, $rs_governance_host, $rs_project_id) return $response, $code do - $host = $rs_governance_host - $href = "/api/governance/projects/" + $rs_project_id + "/applied_policies" - $url = $host + $href - task_label("POST " + $url) - - $response = http_request( - auth: $$auth_flexera, - host: $host, - href: $href, - https: true, - verb: "post", - headers: { "Api-Version": "1.0" }, - body: $policy["update_body"] - ) - - $code = $response["code"] - $policy_name = $policy["catalog_name"] + " (" + $policy["catalog_id"] + ")" - - task_label("Apply Catalog Policy response: " + $policy_name + " " + to_json($response)) - $$all_responses << to_json({"req": "POST " + $url, "resp": $response}) - - if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 - raise "Unexpected response applying Catalog Policy: " + $policy_name + " " + to_json($response) - else - task_label("Apply Catalog Policy successful: " + $policy_name) - end -end - -define delete_policy($policy, $rs_governance_host) return $response do - $host = $rs_governance_host - $href = $policy['href'] - $url = $host + $href - task_label("DELETE " + $url) - - $response = http_request( - auth: $$auth_flexera, - host: $host, - href: $href, - https: true, - verb: "delete", - headers: { "Api-Version": "1.0" } - ) - - $policy_name = $policy["name_without_link"] + " (" + $policy["id"] + ")" - - task_label("Delete Applied Policy response: " + $policy_name + " " + to_json($response)) - $$all_responses << to_json({"req": "POST " + $url, "resp": $response}) - - if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 - raise "Unexpected response deleting Applied Policy: " + $policy_name + " " + to_json($response) - else - task_label("Delete Applied Policy successful: " + $policy_name) - end -end - -define handle_error() do - if !$$errors - $$errors = [] - end - $$errors << $_error["type"] + ": " + $_error["message"] - # We check for errors at the end, and raise them all together - # Skip errors handled by this definition - $_error_behavior = "skip" -end diff --git a/automation/google/google_rbd_from_label/CHANGELOG.md b/automation/google/google_rbd_from_label/CHANGELOG.md deleted file mode 100644 index 26beb076b9..0000000000 --- a/automation/google/google_rbd_from_label/CHANGELOG.md +++ /dev/null @@ -1,26 +0,0 @@ -# Changelog - -## v1.3.1 - -- Fixed issue that would sometimes cause execution to fail if a Google Project had no label keys - -## v1.3.0 - -- Added option to retain original casing of tag values instead of normalizing them all to lowercase - -## v1.2.1 - -- Updated policy template to use newer API endpoints. Functionality is unchanged. - -## v1.2 - -- fixed link to README in policy description - -## v1.1 - -- added ability to specify names for the newly created dimensions -- fixed issue where labels were incorrectly referred to as tags in parameter name - -## v1.0 - -- initial release diff --git a/automation/google/google_rbd_from_label/README.md b/automation/google/google_rbd_from_label/README.md deleted file mode 100644 index 0f4903041c..0000000000 --- a/automation/google/google_rbd_from_label/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Google Rule-Based Dimension From Project Labels - -## What It Does - -This policy creates and updates custom Rule-Based Dimensions that surface the specified Google Project label keys in the Flexera One platform. This allows costs to be sliced by the values of the label keys in question. - -## Input Parameters - -This policy has the following input parameters required when launching the policy. - -- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. -- *Label Keys* - A list of Google Project label keys to create custom Rule-Based Dimensions for. -- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the label keys in the `Label Keys` field. Dimension names will be derived from label keys directly if this list is left empty. -- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. - -## Policy Actions - -- Create/update rule-based dimensions - -## Prerequisites - -This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). - -- [**Google Cloud Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_4083446696_1121577) (*provider=gce*) which has the following: - - `resourcemanager.projects.get` - -- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: - - `observer` - - `billing_center_viewer` - - `rule_based_dimensions_manager` - -The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. - -## Supported Clouds - -- Google - -## Cost - -This policy template does not incur any cloud costs. diff --git a/automation/google/google_rbd_from_label/google_rbd_from_label.pt b/automation/google/google_rbd_from_label/google_rbd_from_label.pt deleted file mode 100644 index 93be95a9b0..0000000000 --- a/automation/google/google_rbd_from_label/google_rbd_from_label.pt +++ /dev/null @@ -1,305 +0,0 @@ -name "Google Rule-Based Dimension From Project Labels" -rs_pt_ver 20180301 -type "policy" -short_description "Creates and/or updates individual Rule-Based Dimensions based on Google Project labels. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/google/google_rbd_from_label) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." -long_description "" -severity "low" -category "Cost" -default_frequency "daily" -info( - version: "1.3.1", - provider: "Flexera", - service: "Optima", - policy_set: "Automation", - publish: "false" -) - -############################################################################### -# Parameters -############################################################################### - -parameter "param_tag_list" do - type "list" - category "Policy Settings" - label "Label Keys" - description "A list of Google account label keys to build Rule-Based Dimensions from" - # No default value, user input required -end - -parameter "param_name_list" do - type "list" - category "Policy Settings" - label "Dimension Names" - description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the label keys in the 'Label Keys' field. Dimension names will be derived from label keys directly if this list is left empty." - default [] -end - -parameter "param_effective_date" do - type "string" - category "Policy Settings" - label "Effective Date" - description "Year/month you want rules to start applying in YYYY-MM format" - default "2010-01" -end - -parameter "param_normalize_case" do - type "string" - category "Policy Settings" - label "Lowercase Values" - description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." - allowed_values "Yes", "No" - default "Yes" -end - -############################################################################### -# Authentication -############################################################################### - -credentials "auth_google" do - schemes "oauth2" - label "Google" - description "Select the Google Cloud Credential from the list." - tags "provider=gce" -end - -credentials "auth_flexera" do - schemes "oauth2" - label "flexera" - description "Select FlexeraOne OAuth2 credential." - tags "provider=flexera" -end - -############################################################################### -# Pagination -############################################################################### - -pagination "pagination_google" do - get_page_marker do - body_path "nextPageToken" - end - set_page_marker do - query "pageToken" - end -end - -############################################################################### -# Datasources & Scripts -############################################################################### - -# Get region-specific Flexera API endpoints -datasource "ds_flexera_api_hosts" do - run_script $js_flexera_api_hosts, rs_optima_host -end - -script "js_flexera_api_hosts", type: "javascript" do - parameters "rs_optima_host" - result "result" - code <<-EOS - host_table = { - "api.optima.flexeraeng.com": { - flexera: "api.flexera.com", - fsm: "api.fsm.flexeraeng.com" - }, - "api.optima-eu.flexeraeng.com": { - flexera: "api.flexera.eu", - fsm: "api.fsm-eu.flexeraeng.com" - }, - "api.optima-apac.flexeraeng.com": { - flexera: "api.flexera.au", - fsm: "api.fsm-apac.flexeraeng.com" - } - } - - result = host_table[rs_optima_host] -EOS -end - -datasource "ds_existing_rbds" do - request do - auth $auth_flexera - host rs_optima_host - path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) - header "Api-Version", "1.0" - header "content-type", "application/json" - end - result do - encoding "json" - collect jmes_path(response, "rule_based_dimensions") do - field "id", jmes_path(col_item, "id") - field "name", jmes_path(col_item, "name") - field "dated_rules", jmes_path(col_item, "dated_rules") - end - end -end - -datasource "ds_google_projects" do - request do - auth $auth_google - pagination $pagination_google - host "cloudresourcemanager.googleapis.com" - path "/v1/projects/" - query "filter", "lifecycleState=ACTIVE" - end - result do - encoding "json" - collect jmes_path(response, "projects[*]") do - field "id", jmes_path(col_item, "projectId") - field "number", jmes_path(col_item, "projectNumber") - field "name", jmes_path(col_item, "name") - field "parent", jmes_path(col_item, "parent") - field "createTime", jmes_path(col_item, "createTime") - field "lifecycleState", jmes_path(col_item, "lifecycleState") - field "tags", jmes_path(col_item, "labels") - end - end -end - -datasource "ds_google_projects_normalized" do - run_script $js_google_projects_normalized, $ds_google_projects -end - -script "js_google_projects_normalized", type: "javascript" do - parameters "accounts" - result "result" - code <<-'EOS' - result = [] - - _.each(accounts, function(account) { - tags = {} - - if (account['tags'] != null && account['tags'] != undefined) { - _.each(Object.keys(account['tags']), function(key) { - normalized_key = key.toLowerCase().trim() - tags[normalized_key] = account['tags'][key] - }) - } - - result.push({ - id: account['id'], - number: account['number'], - name: account['name'], - parent: account['parent'], - createTime: account['createTime'], - lifecycleState: account['lifecycleState'], - tags: tags - }) - }) -EOS -end - -datasource "ds_rbds" do - run_script $js_rbds, $ds_google_projects_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_normalize_case -end - -script "js_rbds", type: "javascript" do - parameters "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_normalize_case" - result "result" - code <<-'EOS' - result = [] - - rbd_id_list = _.pluck(existing_rbds, 'id') - - _.each(param_tag_list, function(tag, index) { - rbd_name = tag.replace('.', ' ').replace('-', ' ') - rbd_name = rbd_name.replace(/\W/g, " ").trim() - - // Use user-specified name instead of user provided one - if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } - - rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() - - tag_key = tag.toLowerCase().trim() - verb = "POST" - if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } - - rules = [] - - _.each(accounts, function(account) { - if (typeof(account['tags']) == 'object') { - if (typeof(account['tags'][tag_key]) == 'string') { - if (account['tags'][tag_key].trim() != '') { - value = account['tags'][tag_key].trim() - if (param_normalize_case == "Yes") { value = value.toLowerCase() } - - rules.push({ - condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, - value: { text: value } - }) - } - } - } - }) - - if (rules.length > 0) { - result.push({ - id: rbd_id, - name: rbd_name, - verb: verb, - effective_at: param_effective_date, - rules: rules - }) - } - }) -EOS -end - -datasource "ds_create_rbds" do - iterate $ds_rbds - request do - run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id - end - result do - encoding "text" - end -end - -script "js_create_rbds", type: "javascript" do - parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: verb, - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), - body_fields: { name: name } - } -EOS -end - -datasource "ds_apply_rbds" do - iterate $ds_rbds - request do - # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does - run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id - end - result do - encoding "text" - end -end - -script "js_apply_rbds", type: "javascript" do - parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" - result "request" - code <<-EOS - var request = { - auth: "auth_flexera", - verb: "PUT", - host: api_host, - path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), - body_fields: { rules: rules } - } -EOS -end - -############################################################################### -# Policy -############################################################################### - -policy "pol_rbds" do - validate $ds_apply_rbds do - summary_template "RBDs Generated & Applied" - detail_template "" - check eq(0, 0) - end -end From 27997df5715b53c313c23f00d22d91d325831249 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Tue, 8 Oct 2024 03:11:11 -0500 Subject: [PATCH 09/23] update --- .spellignore | 29 - .../aws/aws_missing_regions/CHANGELOG.md | 9 + automation/aws/aws_missing_regions/README.md | 62 + .../aws_missing_regions.pt | 359 +++++ .../aws_missing_regions_meta_parent.pt | 1221 +++++++++++++++++ automation/aws/aws_rbd_from_tag/CHANGELOG.md | 34 + automation/aws/aws_rbd_from_tag/README.md | 37 + .../aws/aws_rbd_from_tag/aws_rbd_from_tag.pt | 277 ++++ .../azure_missing_subscriptions/CHANGELOG.md | 5 + .../azure_missing_subscriptions/README.md | 40 + .../azure_missing_subscriptions.pt | 340 +++++ .../azure/azure_rbd_from_rg_tag/CHANGELOG.md | 25 + .../azure/azure_rbd_from_rg_tag/README.md | 43 + .../azure_rbd_from_rg_tag.pt | 418 ++++++ .../azure/azure_rbd_from_tag/CHANGELOG.md | 25 + automation/azure/azure_rbd_from_tag/README.md | 42 + .../azure_rbd_from_tag/azure_rbd_from_tag.pt | 318 +++++ .../delete_all_billing_centers/CHANGELOG.md | 9 + .../delete_all_billing_centers/README.md | 34 + .../delete_all_billing_centers.pt | 233 ++++ .../outdated_applied_policies/CHANGELOG.md | 14 + .../outdated_applied_policies/README.md | 71 + .../outdated_applied_policies.pt | 835 +++++++++++ .../google/google_rbd_from_label/CHANGELOG.md | 26 + .../google/google_rbd_from_label/README.md | 40 + .../google_rbd_from_label.pt | 305 ++++ 26 files changed, 4822 insertions(+), 29 deletions(-) create mode 100644 automation/aws/aws_missing_regions/CHANGELOG.md create mode 100644 automation/aws/aws_missing_regions/README.md create mode 100644 automation/aws/aws_missing_regions/aws_missing_regions.pt create mode 100644 automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt create mode 100644 automation/aws/aws_rbd_from_tag/CHANGELOG.md create mode 100644 automation/aws/aws_rbd_from_tag/README.md create mode 100644 automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt create mode 100644 automation/azure/azure_missing_subscriptions/CHANGELOG.md create mode 100644 automation/azure/azure_missing_subscriptions/README.md create mode 100644 automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt create mode 100644 automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md create mode 100644 automation/azure/azure_rbd_from_rg_tag/README.md create mode 100644 automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt create mode 100644 automation/azure/azure_rbd_from_tag/CHANGELOG.md create mode 100644 automation/azure/azure_rbd_from_tag/README.md create mode 100644 automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt create mode 100644 automation/flexera/delete_all_billing_centers/CHANGELOG.md create mode 100644 automation/flexera/delete_all_billing_centers/README.md create mode 100644 automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt create mode 100644 automation/flexera/outdated_applied_policies/CHANGELOG.md create mode 100644 automation/flexera/outdated_applied_policies/README.md create mode 100644 automation/flexera/outdated_applied_policies/outdated_applied_policies.pt create mode 100644 automation/google/google_rbd_from_label/CHANGELOG.md create mode 100644 automation/google/google_rbd_from_label/README.md create mode 100644 automation/google/google_rbd_from_label/google_rbd_from_label.pt diff --git a/.spellignore b/.spellignore index 537c65c574..1c67184d4e 100644 --- a/.spellignore +++ b/.spellignore @@ -585,32 +585,3 @@ ByteCount PacketCount balancers backfill -FNMS -CBI -workspace -workspaces -Workspace -Workspaces -OCID -OAuth -oauth -BYOL -GCP -TLS -SSL -Balancer -balancer -LUN -Unmanaged -unmanaged -Oversized -oversized -AMI -actioning -actioned -VPN -VPNs -Dataset -dataset -Datasets -datasets diff --git a/automation/aws/aws_missing_regions/CHANGELOG.md b/automation/aws/aws_missing_regions/CHANGELOG.md new file mode 100644 index 0000000000..c0e1662927 --- /dev/null +++ b/automation/aws/aws_missing_regions/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## v0.2.0 + +- Fixed issue with meta policy not working due to missing `Account Number` parameter + +## v0.1 + +- initial release diff --git a/automation/aws/aws_missing_regions/README.md b/automation/aws/aws_missing_regions/README.md new file mode 100644 index 0000000000..22893aed73 --- /dev/null +++ b/automation/aws/aws_missing_regions/README.md @@ -0,0 +1,62 @@ +# AWS Missing Regions + +## What It Does + +This policy checks the list of AWS regions returned by an AWS `DescribeRegions` API request and tests each region with an EC2 `DescribeInstances` request to see if the Flexera AWS credential can actually run API requests against that region. An incident is raised and email sent with any regions that are inaccessible. + +__NOTE: Meta Parent policy will only work if both the parent and the child are uploaded to the Flexera org and the "Uploaded Template" option is selected for the `Child Policy Template Source` parameter. This is because the child policy is *not* published in the catalog.__ + +## Input Parameters + +This policy has the following input parameters required when launching the policy. + +- *Email Addresses* - Email addresses of the recipients you wish to notify when new incidents are created. +- *Account Number* - The Account number for use with the AWS STS Cross Account Role. Leave blank when using AWS IAM Access key and secret. It only needs to be passed when the desired AWS account is different than the one associated with the Flexera One credential. [More information is available in our documentation.](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1123608) +- *Region Ignore List* - A list of regions to never include in the results. Leave blank to not filter results + +## Policy Actions + +The following policy actions are taken on any resources found to be out of compliance. + +- Send an email report + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +- [**AWS Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_1982464505_1121575) (*provider=aws*) which has the following permissions: + - `ec2:DescribeRegions` + - `ec2:DescribeInstances` + - `sts:GetCallerIdentity` + + Example IAM Permission Policy: + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeRegions", + "ec2:DescribeInstances", + "sts:GetCallerIdentity" + ], + "Resource": "*" + } + ] + } + ``` + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `billing_center_viewer` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- AWS + +## Cost + +This Policy Template does not incur any cloud costs. diff --git a/automation/aws/aws_missing_regions/aws_missing_regions.pt b/automation/aws/aws_missing_regions/aws_missing_regions.pt new file mode 100644 index 0000000000..5b41cc8225 --- /dev/null +++ b/automation/aws/aws_missing_regions/aws_missing_regions.pt @@ -0,0 +1,359 @@ +name "AWS Missing Regions" +rs_pt_ver 20180301 +type "policy" +short_description "Reports any AWS regions that are enabled but the policy engine is not able to access. [README](https://github.com/flexera-public/policy_templates/tree/master/automation/aws/aws_missing_regions/) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "low" +category "Cost" +default_frequency "weekly" +info( + version: "0.2.0", + provider: "Flexera", + service: "Optima", + policy_set: "Automation", + publish: "false" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_email" do + type "list" + category "Policy Settings" + label "Email Addresses" + description "A list of email addresses to notify." + default [] +end + +parameter "param_aws_account_number" do + type "string" + category "Policy Settings" + label "Account Number" + description "Leave blank; this is for automated use with Meta Policies. See README for more details." + default "" +end + +parameter "param_region_list" do + type "list" + category "Filters" + label "Region Ignore List" + description "A list of regions to never include in the results. Leave blank to not filter results." + default [] +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_aws" do + schemes "aws", "aws_sts" + label "AWS" + description "Select the AWS Credential from the list" + tags "provider=aws" + aws_account_number $param_aws_account_number +end + +credentials "auth_flexera" do + schemes "oauth2" + label "Flexera" + description "Select Flexera One OAuth2 credentials" + tags "provider=flexera" +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +# Get applied policy metadata for use later +datasource "ds_applied_policy" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) + header "Api-Version", "1.0" + end +end + +# Get region-specific Flexera API endpoints +datasource "ds_flexera_api_hosts" do + run_script $js_flexera_api_hosts, rs_optima_host +end + +script "js_flexera_api_hosts", type: "javascript" do + parameters "rs_optima_host" + result "result" + code <<-EOS + host_table = { + "api.optima.flexeraeng.com": { + flexera: "api.flexera.com", + fsm: "api.fsm.flexeraeng.com" + }, + "api.optima-eu.flexeraeng.com": { + flexera: "api.flexera.eu", + fsm: "api.fsm-eu.flexeraeng.com" + }, + "api.optima-apac.flexeraeng.com": { + flexera: "api.flexera.au", + fsm: "api.fsm-apac.flexeraeng.com" + } + } + + result = host_table[rs_optima_host] +EOS +end + +# Get AWS account info +datasource "ds_cloud_vendor_accounts" do + request do + auth $auth_flexera + host val($ds_flexera_api_hosts, 'flexera') + path join(["/finops-analytics/v1/orgs/", rs_org_id, "/cloud-vendor-accounts"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + collect jmes_path(response, "values[*]") do + field "id", jmes_path(col_item, "aws.accountId") + field "name", jmes_path(col_item, "name") + field "tags", jmes_path(col_item, "tags") + end + end +end + +datasource "ds_get_caller_identity" do + request do + auth $auth_aws + verb "GET" + host "sts.amazonaws.com" + path "/" + query "Action", "GetCallerIdentity" + query "Version", "2011-06-15" + header "User-Agent", "RS Policies" + end + result do + encoding "xml" + collect xpath(response, "//GetCallerIdentityResponse/GetCallerIdentityResult") do + field "account", xpath(col_item, "Account") + end + end +end + +datasource "ds_aws_account" do + run_script $js_aws_account, $ds_cloud_vendor_accounts, $ds_get_caller_identity +end + +script "js_aws_account", type:"javascript" do + parameters "ds_cloud_vendor_accounts", "ds_get_caller_identity" + result "result" + code <<-EOS + result = _.find(ds_cloud_vendor_accounts, function(account) { + return account['id'] == ds_get_caller_identity[0]['account'] + }) + + // This is in case the API does not return the relevant account info + if (result == undefined) { + result = { + id: ds_get_caller_identity[0]['account'], + name: "", + tags: {} + } + } +EOS +end + +datasource "ds_regions" do + request do + auth $auth_aws + verb "GET" + host "ec2.amazonaws.com" + path "/" + query "Action", "DescribeRegions" + query "Version", "2016-11-15" + query "Filter.1.Name", "opt-in-status" + query "Filter.1.Value.1", "opt-in-not-required" + query "Filter.1.Value.2", "opted-in" + # Header X-Meta-Flexera has no affect on datasource query, but is required for Meta Policies + # Forces `ds_is_deleted` datasource to run first during policy execution + header "Meta-Flexera", val($ds_is_deleted, "path") + end + result do + encoding "xml" + collect xpath(response, "//DescribeRegionsResponse/regionInfo/item", "array") do + field "region", xpath(col_item, "regionName") + end + end +end + +# Make a general API call to list EC2 instances to test functionality +datasource "ds_instance_sets" do + iterate $ds_regions + request do + auth $auth_aws + host join(['ec2.', val(iter_item, 'region'), '.amazonaws.com']) + path '/' + query 'Action', 'DescribeInstances' + query 'Version', '2016-11-15' + header 'User-Agent', 'RS Policies' + header 'Content-Type', 'text/xml' + ignore_status [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410] + end + result do + encoding "xml" + field "region", val(iter_item, "region") + end +end + +datasource "ds_missing_regions" do + run_script $js_missing_regions, $ds_regions, $ds_instance_sets, $ds_aws_account, $ds_applied_policy, $param_region_list +end + +script "js_missing_regions", type: "javascript" do + parameters "ds_regions", "ds_instance_sets", "ds_aws_account", "ds_applied_policy", "param_region_list" + result "result" + code <<-'EOS' + result = [] + + enabled_regions = _.uniq(_.pluck(ds_regions, 'region')) + found_regions = _.uniq(_.pluck(ds_instance_sets, 'region')) + + _.each(enabled_regions, function(region) { + if (!_.contains(found_regions, region) && !_.contains(param_region_list, region)) { + result.push({ + "accountID": ds_aws_account['id'], + "accountName": ds_aws_account['name'], + "region": region, + "policy_name": ds_applied_policy['name'] + }) + } + }) + + result = _.sortBy(result, 'region') + result = _.sortBy(result, 'accountID') +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_missing_regions" do + validate_each $ds_missing_regions do + summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} AWS Missing Regions Detected" + check logic_or($ds_parent_policy_terminated, eq(val(item, "accountID"), "")) + escalate $esc_email + export do + resource_level false + field "accountID" do + label "Account ID" + end + field "accountName" do + label "Account Name" + end + field "region" do + label "Region" + end + end + end +end + +############################################################################### +# Escalations +############################################################################### + +escalation "esc_email" do + automatic true + label "Send Email" + description "Send incident email" + email $param_email +end + +############################################################################### +# Meta Policy [alpha] +# Not intended to be modified or used by policy developers +############################################################################### + +# If the meta_parent_policy_id is not set it will evaluate to an empty string and we will look for the policy itself, +# if it is set we will look for the parent policy. +datasource "ds_get_policy" do + request do + auth $auth_flexera + host rs_governance_host + ignore_status [404] + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", switch(ne(meta_parent_policy_id, ""), meta_parent_policy_id, policy_id) ]) + header "Api-Version", "1.0" + end + result do + encoding "json" + field "id", jmes_path(response, "id") + end +end + +datasource "ds_parent_policy_terminated" do + run_script $js_decide_if_self_terminate, $ds_get_policy, policy_id, meta_parent_policy_id +end + +# If the policy was applied by a meta_parent_policy we confirm it exists if it doesn't we confirm we are deleting +# This information is used in two places: +# - determining whether or not we make a delete call +# - determining if we should create an incident (we don't want to create an incident on the run where we terminate) +script "js_decide_if_self_terminate", type: "javascript" do + parameters "found", "self_policy_id", "meta_parent_policy_id" + result "result" + code <<-EOS + var result + if (meta_parent_policy_id != "" && found.id == undefined) { + result = true + } else { + result = false + } + EOS +end + +# Two potentials ways to set this up: +# - this way and make a unneeded 'get' request when not deleting +# - make the delete request an interate and have it iterate over an empty array when not deleting and an array with one item when deleting +script "js_make_terminate_request", type: "javascript" do + parameters "should_delete", "policy_id", "rs_project_id", "rs_governance_host" + result "request" + code <<-EOS + + var request = { + auth: 'auth_flexera', + host: rs_governance_host, + path: "/api/governance/projects/" + rs_project_id + "/applied_policies/" + policy_id, + headers: { + "API-Version": "1.0", + "Content-Type":"application/json" + }, + } + + if (should_delete) { + request.verb = 'DELETE' + } + EOS +end + +datasource "ds_terminate_self" do + request do + run_script $js_make_terminate_request, $ds_parent_policy_terminated, policy_id, rs_project_id, rs_governance_host + end +end + +datasource "ds_is_deleted" do + run_script $js_check_deleted, $ds_terminate_self +end + +# This is just a way to have the check delete request connect to the farthest leaf from policy. +# We want the delete check to the first thing the policy does to avoid the policy erroring before it can decide whether or not it needs to self terminate +# Example a customer deletes a credential and then terminates the parent policy. We still want the children to self terminate +# The only way I could see this not happening is if the user who applied the parent_meta_policy was offboarded or lost policy access, the policies who are impersonating the user +# would not have access to self-terminate +# It may be useful for the backend to enable a mass terminate at some point for all meta_child_policies associated with an id. +script "js_check_deleted", type: "javascript" do + parameters "response" + result "result" + code <<-EOS + result = {"path":"/"} + EOS +end diff --git a/automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt b/automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt new file mode 100644 index 0000000000..dbe5d526b0 --- /dev/null +++ b/automation/aws/aws_missing_regions/aws_missing_regions_meta_parent.pt @@ -0,0 +1,1221 @@ +name "Meta Parent: AWS Missing Regions" +rs_pt_ver 20180301 +type "policy" +short_description "**NOTE: Meta policies are an alpha feature. Please consult the [README](https://github.com/flexera-public/policy_templates/blob/master/README_META_POLICIES.md) before use.** Applies and manages \"child\" [AWS Missing Regions](https://github.com/flexera-public/policy_templates/tree/master/automation/aws/aws_missing_regions) Policies." +severity "low" +category "Meta" +default_frequency "15 minutes" +info( + provider: "AWS", + version: "0.2.0", # 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", + deprecated: "false" +) + +############################################################################## +# Parameters +############################################################################## + +## Meta Parent Parameters +## These are params specific to the meta parent policy. +parameter "param_combined_incident_email" do + type "list" + label "Email addresses for combined incident" + description "A list of email addresses to notify with the consolidated child policy incident." + default [] +end + +parameter "param_dimension_filter_includes" do + type "list" + label "Dimension Include Filters" + description <<-EOS + Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **INCLUDE** and be applied to. + Use = to match the entire value and =~ to match a substring contained in the value. + During each run this policy will select AWS Accounts who match **all** the filters defined and apply a child policy for each. + If no include filters are provided, then all AWS Accounts are included by default. + Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). + EOS + default [] +end + +parameter "param_dimension_filter_excludes" do + type "list" + label "Dimension Exclude Filters" + description <<-EOS + Filters [`dimension_name=dimension_value` and `dimension_name=~dimension_value` pairs] to determine which AWS Accounts returned by the Flexera Bill Analysis API to **EXCLUDE** and *not* have policy applied to. + Use = to match the entire value and =~ to match a substring contained in the value. + During each run this policy will select AWS Accounts who match **all** the filters defined here and excludes them from results. + Can be used to exclude specific AWS Accounts [`vendor_account=123456789012`] + Most of the dimensions in Flexera can be used [default dimensions, custom tag dimensions, rule-based dimensions]. Full list of available dimensions documented in the [Bill Analysis API Docs](https://reference.rightscale.com/bill_analysis/). + EOS + default [] +end + +parameter "param_policy_schedule" do + type "string" + label "Child Policy Schedule" + description "The interval at which the child policy checks for conditions and generates incidents." + default "weekly" + allowed_values "daily", "weekly", "monthly" +end + +parameter "param_template_source" do + type "string" + label "Child Policy Template Source" + description "By default, will use the \"AWS Missing Regions\" Policy Template from Catalog. Optionally, you can use the \"AWS Missing Regions\" Policy Template uploaded in the current Flexera Project." + default "Published Catalog Template" + allowed_values "Published Catalog Template", "Uploaded Template" +end + +## Child Policy Parameters +parameter "param_region_list" do + type "list" + category "Filters" + label "Region Ignore List" + description "A list of regions to never include in the results. Leave blank to not filter results." + default [] +end + +############################################################################### +# Authentication +############################################################################### +credentials "auth_aws" do + schemes "aws", "aws_sts" + label "AWS" + description "Select the AWS Credential from the list" + tags "provider=aws" + aws_account_number $param_aws_account_number +end + +credentials "auth_flexera" do + schemes "oauth2" + label "Flexera" + description "Select Flexera One OAuth2 credentials" + tags "provider=flexera" +end + +############################################################################### +# Datasources +############################################################################### + +# Get Applied Parent Policy Details +datasource "ds_self_policy_information" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) + header "Api-Version", "1.0" + end + result do + encoding "json" + field "name", jmes_path(response, "name") + field "creator_id", jmes_path(response, "created_by.id") + field "credentials", jmes_path(response, "credentials") + field "options", jmes_path(response, "options") + end +end + +datasource "ds_child_policy_options" do + run_script $js_child_policy_options, $ds_self_policy_information +end + +script "js_child_policy_options", type: "javascript" do + parameters "ds_self_policy_information" + result "options" + code <<-EOS + // Filter Options that are not appropriate for Child Policy + var options = _.map(ds_self_policy_information.options, function(option){ + // param_combined_incident_email, param_dimension_filter_includes, param_dimension_filter_excludes, param_policy_schedule are exclusion to Meta Parent Policy Parameters + if (!_.contains(["param_combined_incident_email", "param_dimension_filter_includes", "param_dimension_filter_excludes", "param_policy_schedule", "param_template_source"], option.name)) { + return { "name": option.name, "value": option.value }; + } + }); + // Explicitly add param_email which is disabled/does not exist in meta parent policy + options.push({ + "name": "param_email", + "value": [] + }); + EOS +end + +datasource "ds_child_policy_options_map" do + run_script $js_child_policy_options_map, $ds_child_policy_options +end + +script "js_child_policy_options_map", type: "javascript" do + parameters "ds_child_policy_options" + result "options" + code <<-EOS + function format_options_keyvalue(options) { + var options_keyvalue_map = {}; + _.each(options, function(option) { + options_keyvalue_map[option.name] = option.value; + }); + return options_keyvalue_map; + } + var options = format_options_keyvalue(ds_child_policy_options) + EOS +end + +datasource "ds_format_self" do + run_script $js_format_self, $ds_self_policy_information, $ds_child_policy_options_map +end + +script "js_format_self", type: "javascript" do + parameters "ds_self_policy_information", "ds_child_policy_options_map" + result "formatted" + code <<-EOS + var formatted = { + "name": ds_self_policy_information["name"], + "creator_id": ds_self_policy_information["creator_id"], + "credentials": ds_self_policy_information["credentials"], + "options": ds_child_policy_options_map + }; + EOS +end + +# Get Pulished Policy Details +datasource "ds_get_published_child_policy_information" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/orgs/", rs_org_id, "/published_templates"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + collect jmes_path(response, "items[*]") do + field "name", jmes_path(col_item, "name") + field "created_by", jmes_path(col_item, "created_by.email") + field "href", jmes_path(col_item, "href") + field "short_description", jmes_path(col_item, "short_description") + end + end +end + +# Select the published policy that is published by "support@flexera.com" and matches the name of the child policy template +datasource "ds_published_child_policy_information" do + run_script $js_published_child_policy_information, $ds_get_published_child_policy_information +end + +script "js_published_child_policy_information", type: "javascript" do + parameters "ds_get_published_child_policy_information" + result "result" + code <<-EOS + result = _.filter(ds_get_published_child_policy_information, function(item) { + return item['name'] == "AWS Missing Regions" && item['created_by'] == "support@flexera.com" + }) +EOS +end + +# Get Uploaded Policy Details +datasource "ds_get_project_child_policy_information" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/policy_templates"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + collect jmes_path(response, "items[*]") do + field "name", jmes_path(col_item, "name") + field "href", jmes_path(col_item, "href") + field "short_description", jmes_path(col_item, "short_description") + end + end +end + +# Select the uploaded policy that matches the name of the child policy template +datasource "ds_project_child_policy_information" do + run_script $js_project_child_policy_information, $ds_get_project_child_policy_information +end + +script "js_project_child_policy_information", type: "javascript" do + parameters "ds_get_project_child_policy_information" + result "result" + code <<-EOS + result = _.filter(ds_get_project_child_policy_information, function(item) { + return item['name'] == "AWS Missing Regions" + }) +EOS +end + +datasource "ds_get_billing_centers" do + request do + auth $auth_flexera + host rs_optima_host + path join(["/analytics/orgs/",rs_org_id,"/billing_centers"]) + header "Api-Version", "1.0" + header "User-Agent", "RS Policies" + query "view", "allocation_table" + ignore_status [403] + end + result do + encoding "json" + # Select the Billing Centers that have "parent_id" undefined or "" (i.e. top-level Billing Centers) + collect jq(response, '.[] | select(.parent_id == null)' ) do + field "href", jq(col_item,".href") + field "id", jq(col_item,".id") + field "name", jq(col_item,".name") + field "parent_id", jq(col_item,".parent_id") + end + end +end + +script "js_make_billing_center_request", type: "javascript" do + parameters "rs_org_id", "rs_optima_host", "billing_centers_unformatted", "param_dimension_filter_includes", "param_dimension_filter_excludes" + result "request" + code <<-EOS + + billing_centers_formatted = [] + + for (x=0; x< billing_centers_unformatted.length; x++) { + billing_centers_formatted.push(billing_centers_unformatted[x]["id"]) + } + + finish = new Date() + finishFormatted = finish.toJSON().split("T")[0] + start = new Date() + start.setDate(start.getDate() - 30) + startFormatted = start.toJSON().split("T")[0] + + // Default dimensions and filter expressions required for meta parent policy + var dimensions = ["vendor_account", "vendor_account_name"]; + var filter_expressions = [ + { dimension: "vendor", type: "equal", value: "AWS" } + ] + + // Append to default dimensions and filter expressions using parent policy params + _.each(param_dimension_filter_includes, function (v) { + // split key=value string + if (v.indexOf('=~') == -1) { + var split = v.split("="); + var type = "equal" + } else { + var split = v.split("=~"); + var type = "substring" + } + + var k = split[0]; + var v = split[1]; + + // append to lists + dimensions.push(k); + + if (type == "equal") { + filter_expressions.push({ dimension: k, type: "equal", value: v }); + } else { + filter_expressions.push({ dimension: k, type: "substring", substring: v }); + } + }); + + // Append to filter expressions using exclude policy params + _.each(param_dimension_filter_excludes, function (v) { + // split key=value string + if (v.indexOf('=~') == -1) { + var split = v.split("="); + var type = "equal" + } else { + var split = v.split("=~"); + var type = "substring" + } + + var k = split[0]; + var v = split[1]; + + // append to lists + dimensions.push(k); + + if (type == "equal") { + filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "equal", "value": v } }); + } else { + filter_expressions.push({ "type": "not", "expression": { "dimension": k, "type": "substring", "substring": v } }); + } + }); + + // Produces a duplicate-free version of the array + dimensions = _.uniq(dimensions); + + var body = { + "dimensions": dimensions, + "granularity":"day", + "start_at": startFormatted, + "end_at": finishFormatted, + "metrics":["cost_amortized_unblended_adj"], + "billing_center_ids": billing_centers_formatted, + "filter": + { + "type": "and", + "expressions": filter_expressions + }, + "summarized": true + } + var request = { + auth: 'auth_flexera', + host: rs_optima_host, + scheme: 'https', + verb: 'POST', + path: "/bill-analysis/orgs/"+ rs_org_id + "/costs/aggregated", + headers: { + "API-Version": "1.0", + "Content-Type":"application/json" + }, + body: JSON.stringify(body) + } + EOS +end + +# Get the AWS acounts +datasource "ds_get_aws_accounts" do + request do + run_script $js_make_billing_center_request, rs_org_id, rs_optima_host, $ds_get_billing_centers, $param_dimension_filter_includes, $param_dimension_filter_excludes + end + result do + encoding "json" + collect jmes_path(response,"rows[*]") do + field "aws_account_id", jmes_path(col_item,"dimensions.vendor_account") + field "aws_account_name", jmes_path(col_item,"dimensions.vendor_account_name") + end + end +end + +# Get Child policies +datasource "ds_get_existing_policies" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies"]) + header "Api-Version", "1.0" + query "meta_parent_policy_id", policy_id + end + result do + encoding "json" + collect jmes_path(response, "items[*]") do + field "name", jmes_path(col_item, "name") + field "applied_policy_id", jmes_path(col_item, "id") + field "options", jmes_path(col_item, "options") + field "updated_at", jmes_path(col_item, "updated_at") + field "status", jmes_path(col_item, "status") + end + end +end + +# Get Child policies incidents +datasource "ds_get_existing_policies_incidents" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/incidents"]) + header "Api-Version", "1.0" + query "meta_parent_policy_id", policy_id + query "state", "triggered" + end + result do + encoding "json" + collect jmes_path(response, "items[*]") do + field "incident_id", jmes_path(col_item, "id") + field "applied_policy_id", jmes_path(col_item, "applied_policy.id") + field "summary", jmes_path(col_item, "summary") + field "state", jmes_path(col_item, "state") + field "violation_data_count", jmes_path(col_item, "violation_data_count") + field "updated_at", jmes_path(col_item, "updated_at") + field "meta_parent_policy_id", jmes_path(col_item, "meta_parent_policy_id") + end + end +end + +datasource "ds_format_incidents" do + run_script $js_format_existing_policies_incidents, $ds_get_existing_policies_incidents +end + +script "js_format_existing_policies_incidents", type: "javascript" do + parameters "unformatted" + result "formatted" + code <<-EOS + formatted={} + + _.each(unformatted, function(incident) { + if (formatted[incident['applied_policy_id']] == undefined) { + formatted[incident['applied_policy_id']] = [] + } + + formatted[incident['applied_policy_id']].push(incident) + }) +EOS +end + +datasource "ds_format_existing_policies" do + run_script $js_format_existing_policies, $ds_get_existing_policies, $ds_format_incidents +end + +# format +# duplicates logic should compare updated at +# we can validate update here when destructring the existing policy options, don't need updated at +# format options +script "js_format_existing_policies", type: "javascript" do + parameters "ds_get_existing_policies", "ds_format_incidents" + result "result" + code <<-EOS + function format_options_keyvalue(options) { + var options_keyvalue_map = {}; + _.each(options, function(option) { + options_keyvalue_map[option.name] = option.value; + }); + return options_keyvalue_map; + } + + result = {} + formatted = {} + duplicates = [] + // tracking holds all existing policies and later can be used to determine if existing policies should be deleted [i.e. if cloud account was removed] + tracking = {} + + for (x=0; x newDate) { + duplicates.push({ + "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], + "applied_policy_name":ds_get_existing_policies[x]["name"], + "status":ds_get_existing_policies[x]["status"], + "updated_at":ds_get_existing_policies[x]["updated_at"], + "incident": incident, + "incident2": incident2 + }) + } else { + duplicates.push({ + "applied_policy_id":current["applied_policy_id"], + "applied_policy_name":current["applied_policy_name"], + "status":current["status"], + "updated_at":current["updated_at"], + "incident": current["incident"], + "incident2": current["incident2"] + }) + formatted[aws_account_id] = { + "applied_policy_id":ds_get_existing_policies[x]["applied_policy_id"], + "applied_policy_name":ds_get_existing_policies[x]["name"], + "status":ds_get_existing_policies[x]["status"], + "updated_at":ds_get_existing_policies[x]["updated_at"], + "incident": incident, + "incident2": incident2, + "options": options + } + + } + } + } + + result.formatted=formatted + result.duplicates=duplicates + result.tracking=tracking + EOS +end + +datasource "ds_take_in_parameters" do + run_script $js_take_in_parameters, $ds_get_aws_accounts, $ds_format_self, first($ds_published_child_policy_information), first($ds_project_child_policy_information), $ds_format_existing_policies, $ds_child_policy_options, $ds_child_policy_options_map, $param_template_source, $param_policy_schedule, policy_id, f1_app_host, rs_org_id, rs_project_id +end + +# hardcode template href with id from catalog +# catalog policies show in customer's published templates with their org id +# "template_href": "/api/governance/orgs/" + rs_org_id + "/published_templates/62618616e3dff80001572bf0" +# update logic: the only reason we're going to update the child policies for is changes to options +# and only some options, email is always blank and aws_account_id is tied to the idenity of each policy, so: new account creation, removal of account: termination +# param_automatic_action is a list with only one action, unless the person is applying using an API and putting the same value multiple times this should either be a length of 0 or 1 +# param_log_to_cm_audit_entries is a String of Yes or No +# param_exclude_tags and param_allowed_regions are arrays. I'm doing an update on the order changing but the values remaining the same. +# If we only want to do an update on the values changing we could sort before doing the equality check. +script "js_take_in_parameters", type: "javascript" do + parameters "ds_get_aws_accounts", "ds_format_self", "ds_published_child_policy_information", "ds_project_child_policy_information", "ds_format_existing_policies", "ds_child_policy_options", "ds_child_policy_options_map", "param_template_source", "param_policy_schedule", "meta_parent_policy_id", "f1_app_host", "rs_org_id", "rs_project_id" + result "grid_and_cwf" + code <<-EOS + + // Set Child Policy Information based on param_template_source value + if (param_template_source == "Published Catalog Template") { + child_policy_information = ds_published_child_policy_information + } else { + child_policy_information = ds_project_child_policy_information + } + + max_actions = 50; + + grid_and_cwf={grid:[], to_create:[], to_update:[], to_delete:[], parent_policy:ds_format_self}; + + should_keep = ds_format_existing_policies.tracking; + + // Construct UI URL prefixes for policy template summary + ui_url_prefix = "https://" + f1_app_host + "/orgs/" + rs_org_id; + applied_policy_url_prefix = ui_url_prefix + "/automation/applied-policies/projects/" + rs_project_id + "?noIndex=1&policyId="; + incident_url_prefix = ui_url_prefix + "/automation/incidents/projects/" + rs_project_id + "?noIndex=1&incidentId="; + + function add_to_grid(ep, action) { + policy_status={ + "id": ep["applied_policy_id"], + "policy_name": ep["applied_policy_name"] + '||' + applied_policy_url_prefix + ep["applied_policy_id"], + "meta_policy_status": action, + "policy_status": ep["status"], + "policy_last_update": ep["updated_at"], + }; + + if (ep.incident != null && ep.incident != undefined) { + // Remove policy name from summary when applicable + summary_parts = ep.incident.summary.split(':') + summary = summary_parts[summary_parts.length - 1].trim() + + policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident.incident_id; + policy_status["incident_state"] = ep.incident.state; + policy_status["incident_violation_data_count"] = ep.incident.violation_data_count; + policy_status["incident_last_update"] = ep.incident.updated_at; + } + + if (ep.incident2 != null && ep.incident2 != undefined) { + // Remove policy name from summary when applicable + summary_parts = ep.incident2.summary.split(':') + summary = summary_parts[summary_parts.length - 1].trim() + + policy_status["incident_summary"] = summary + '||' + incident_url_prefix + ep.incident2.incident_id; + policy_status["incident_state"] = ep.incident2.state; + policy_status["incident2_violation_data_count"] = ep.incident2.violation_data_count; + policy_status["incident2_last_update"] = ep.incident2.updated_at; + } + + grid_and_cwf.grid.push(policy_status); + } + + for (x=0; x -1) { + _.each(incident["violation_data"], function(violation) { + violation["incident_id"] = incident["id"]; + result.push(violation); + }); + } + }); +EOS +end + + + + +# Summary and a conditional incident which will show up if any policy is being applied, updated or deleted. +# Minimum of 1 incident, max of four +# Could swap the summary to only showing running +# Could also just have one incident and use meta_status to determine which escalation happens +policy "policy_scheduled_report" do + # Consolidated Incident Check(s) + # Consolidated incident for AWS Missing Regions Detected + validate $ds_missing_regions_combined_incidents do + summary_template "Consolidated Incident: {{ len data }} AWS Missing Regions Detected" + escalate $esc_email + + check eq(size(data), 0) + export do + resource_level false + field "accountID" do + label "Account ID" + end + field "accountName" do + label "Account Name" + end + field "region" do + label "Region" + end + field "incident_id" do + label "Child Incident ID" + end + end + end + + # Status Incident Check + validate $ds_take_in_parameters do + summary_template "{{ data.parent_policy.name }}: Status of Child Policies" + detail_template <<-EOS +The current status of Child Policies for **{{ data.parent_policy.name }}**: + +Total Child Applied Policies: {{ len data.grid }} +EOS + check false # always trigger this status incident + export "grid" do + resource_level true + field "id" do + label "Applied Policy ID" + end + field "policy_name" do + label "Applied Policy Name" + format "link-external" + end + field "meta_policy_status" do + label "Meta Child Policy Status" + end + field "policy_status" do + label "Policy Status" + end + field "policy_last_update" do + label "Policy Last Update" + end + field "incident_summary" do + label "Incident Summary" + format "link-external" + end + field "incident_state" do + label "Incident State" + end + field "incident_violation_data_count" do + label "Incident Violation Count" + end + field "incident_last_update" do + label "Incident Last Update" + end + field "incident2_summary" do + label "Incident 2 Summary" + format "link-external" + end + field "incident2_state" do + label "Incident 2 State" + end + field "incident2_violation_data_count" do + label "Incident 2 Violation Count" + end + field "incident2_last_update" do + label "Incident 2 Last Update" + end + end + end + + # Create Child Policies Incident Check + validate $ds_to_create do + summary_template "Policies being created" + detail_template <<-EOS + Policies Being Created: + + | Applied Policy | + | --------------- | + {{ range data -}} + | {{ .name }} | + {{ end -}} + EOS + escalate $create_policies + check eq(size(data),0) + end + + # Update Child Policies Incident Check + validate $ds_to_update do + summary_template "Policies being updated" + detail_template <<-EOS + Policies Being Updated: + + | Applied Policy | + | --------------- | + {{ range data -}} + | {{ .name }} | + {{ end -}} + EOS + escalate $update_policies + check eq(size(data),0) + end + + # Delete Child Policies Incident Check + validate $ds_to_delete do + summary_template "Policies being deleted" + detail_template <<-EOS + Policies being Deleted: + + | Applied Policy | + | --------------- | + {{ range data -}} + | {{ .name }} | + {{ end -}} + EOS + escalate $delete_policies + check eq(size(data),0) + end +end + +# Begin Shared Functions for Child Actions from Consolidated Incident +define groupByIncidentID($data) return $incidents do + # Empty hash to store incidents is incident_id + $incidents = {} + + task_label("Grouping items by Incident ID") + $index = 1 + foreach $item in $data do + task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))) + if !$incidents[$item["incident_id"]] + #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". New Incident: "+$item["incident_id"]) + $incidents[$item["incident_id"]] = {"id": $item["incident_id"], "resource_ids": []} + end + #task_label("Grouping items by Incident ID. "+to_s($index)+"/"+to_s(size($data))". Appending Resource: "+$item["id"]) + # Append resource id to the list for the incident + $incidents[$item["incident_id"]]["resource_ids"] = $incidents[$item["incident_id"]]["resource_ids"] + [$item["id"]] + end +end + +define child_run_action($data, $governance_host, $rs_project_id, $action_label, $action_options) do + # Empty global array for log strings, helpful for debugging + $$debug = [] + + # Group Resources by Incident ID + # This reduces the number of requests made to the Flexera API + call groupByIncidentID($data) retrieve $incidents + $$debug_incidents = to_json($incidents) + + call runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) + + # If we encountered any errors, use `raise` to mark the CWF process as errored + if inspect($$errors) != "null" + raise join($$errors,"\n") + end + + # If we made it here, all actions completed successfully + # Celebrate Success! + task_label("All \""+$action_label+"\" actions completed successfully!") +end + +define runActions($incidents, $action_label, $governance_host, $rs_project_id, $action_options) do + foreach $id in keys($incidents) do + sub on_error: handle_error() do + $incident = $incidents[$id] + task_label("Triggering action \""+$action_label+"\" on "+size($incident["resource_ids"])+" count resources via incident "+$incident["id"]) + $request = { + auth: $$auth_flexera, + verb: "get", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"]]), + headers: { "Api-Version": "1.0" }, + query_strings: { "view": "extended" } + } + $response = http_request($request) + $$debug << to_json({ + "request": $request, + "response": $response + }) + $action_id = "" + foreach $action in $response["body"]["available_actions"] do + # If we have not already found the action id, and the label matches, set the action id + # The first check is to prevent looking through the entire list if we already have the id + if $action["label"] == $action_label + $action_id = $action["id"] + end + end + if $action_id == "" + raise "Could not find action id for \""+$action_label+"\" response="+to_json($response) + end + # Now we are reach to trigger the action + $request = { + auth: $$auth_flexera, + verb: "post", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/incidents/", $incident["id"],"/actions/", $action_id,"/run_action"]), + headers: { "Api-Version": "1.0" }, + body: { "options":[{ "name": "ids", "value": $incident["resource_ids"] }] } + } + # If the action has parameters, add them to the request body + if type($action_options) == "array" && size($action_options) > 0 + $request["body"]["options"] = $request["body"]["options"] + $action_options + end + $response = http_request($request) + $$debug << to_json({ + "request": $request, + "response": $response + }) + # Get the action status from response header + $action_location = $response["headers"]["Location"] + + # Setup some variables for the wait loop + $action_status = "" + $loop_count = 0 + $loop_endtime = now() + (3600*2) # 2 hours from now + # [ queued, aborted, pending, running, completed, failed, denied ] + while ($action_status !~ /^(aborted|completed|failed|denied)/) && (now() <= $loop_endtime) do + # Using Loop Count to slowly increment the sleep time + # This is to prevent the loop from hammering our APIs + $loop_count = $loop_count + 1 + task_label("action_status=\""+$action_status+"\" Sleeping for "+to_s($loop_count)+" seconds") + sleep($loop_count) + task_label("action_status=\""+$action_status+"\" Getting action status") + $request = { + auth: $$auth_flexera, + verb: "get", + https: true, + host: $governance_host, + href: $action_location, + headers: { "Api-Version": "1.0" }, + query_strings: { "view": "extended" } + } + $response = http_request($request) + $$debug << to_json({ + "request": $request, + "response": $response + }) + $action_status = $response["body"]["status"] + end + if ($action_status != "completed") + # Check if we are out of time first + if (now() > $loop_endtime) + raise "action_status=\""+$action_status+"\" Action did not complete in time. Aborting to prevent endless loop. action_status_json="+to_json($response) + else + # If not, then it was aborted, failed or denied + raise "action_status=\""+$action_status+"\" Action did not complete as expected. action_status_json="+to_json($response) + end + end + # If we made it here, the action completed successfully + task_label("action_status=\""+$action_status+"\" Action completed successfully") + end + end +end +# End Shared Functions for Child Actions from Consolidated Incident + +# CWF function to handle errors +define handle_error() do + if !$$errors + $$errors = [] + end + $$errors << $_error["type"] + ": " + $_error["message"] + # We check for errors at the end, and raise them all together + # Skip errors handled by this definition + $_error_behavior = "skip" +end + +# Used only for emailing the combined child incident if so desired +escalation "esc_email" do + automatic true + label "Send Email" + description "Send incident email" + email $param_combined_incident_email +end + +escalation "create_policies" do + run "create_applied_policies", data, rs_governance_host, rs_project_id +end + +# if name !=null +define create_applied_policies($data, $governance_host, $rs_project_id) return $responses do + $responses = [] + $$debug = [] + $item_index = 0 + $item_total = size($data) + foreach $item in $data do + $item_index = $item_index + 1 + $status = to_s("("+$item_index+"/"+$item_total+")") + task_label($status+" Creating Applied Policy with Options: " + to_json($item["options"])) + $response = http_request( + auth: $$auth_flexera, + verb: "post", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies"]), + headers: { "Api-Version": "1.0" }, + body: { + "name": $item["name"], + "description": $item["description"], + "template_href": $item["template_href"], + "frequency": $item["frequency"], + "options": $item["options"], + "credentials": $item["credentials"], + "meta_parent_policy_id": $item["meta_parent_policy_id"] + } + ) + $responses << $response + $$debug << to_json({ + "response": $response, + "item": $item, + "governance_host": $governance_host + }) + end +end + +escalation "update_policies" do + run "update_applied_policies", data, rs_governance_host, rs_project_id +end + +define update_applied_policies($data, $governance_host, $rs_project_id) return $responses do + $responses = [] + $$debug = [] + $item_index = 0 + $item_total = size($data) + foreach $item in $data do + $item_index = $item_index + 1 + $status = to_s("("+$item_index+"/"+$item_total+")") + task_label($status+" Updating Applied Policy with Options: " + to_json($item["options"])) + $response = http_request( + auth: $$auth_flexera, + verb: "patch", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["applied_policy_id"]]), + headers: { "Api-Version": "1.0" }, + body: { + "options": $item["options"] + } + ) + $responses << $response + $$debug << to_json({ + "response": $response, + "item": $item, + "governance_host": $governance_host + }) + end +end + +escalation "delete_policies" do + run "delete_applied_policies", data, rs_governance_host, rs_project_id +end + +define delete_applied_policies($data, $governance_host, $rs_project_id) return $responses do + $responses = [] + $$debug = [] + $item_index = 0 + $item_total = size($data) + foreach $item in $data do + $item_index = $item_index + 1 + $status = to_s("("+$item_index+"/"+$item_total+")") + task_label($status+" Deleting Applied Policy: " + $item["id"]) + $response = http_request( + auth: $$auth_flexera, + verb: "delete", + https: true, + host: $governance_host, + href: join(["/api/governance/projects/", $rs_project_id, "/applied_policies/", $item["id"]]), + headers: { "Api-Version": "1.0" } + ) + $responses << $response + $$debug << to_json({ + "response": $response, + "item": $item, + "governance_host": $governance_host + }) + end +end diff --git a/automation/aws/aws_rbd_from_tag/CHANGELOG.md b/automation/aws/aws_rbd_from_tag/CHANGELOG.md new file mode 100644 index 0000000000..97fd6e9145 --- /dev/null +++ b/automation/aws/aws_rbd_from_tag/CHANGELOG.md @@ -0,0 +1,34 @@ +# Changelog + +## v2.3.2 + +- Fixed issue where tag keys that were not lowercase would not be properly detected and used + +## v2.3.1 + +- Fixed issue that would sometimes cause execution to fail if an AWS Account had no tag keys + +## v2.3.0 + +- Added option to retain original casing of tag values instead of normalizing them all to lowercase + +## v2.2.1 + +- Updated policy template to use newer API endpoints. Functionality is unchanged. + +## v2.2 + +- added ability to specify names for the newly created dimensions + +## v2.1 + +- Corrected API issue when executing policy in APAC + +## v2.0 + +- Removed requirement for AWS credential +- Internal API is now used to gather AWS account and tag information + +## v1.0 + +- initial release diff --git a/automation/aws/aws_rbd_from_tag/README.md b/automation/aws/aws_rbd_from_tag/README.md new file mode 100644 index 0000000000..311f531d76 --- /dev/null +++ b/automation/aws/aws_rbd_from_tag/README.md @@ -0,0 +1,37 @@ +# AWS Rule-Based Dimension From Account Tags + +## What It Does + +This policy creates and updates custom Rule-Based Dimensions that surface the specified AWS Account tag keys in the Flexera One platform. This allows costs to be sliced by the values of the tag keys in question. + +## Input Parameters + +This policy has the following input parameters required when launching the policy. + +- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. +- *Tag Keys* - A list of AWS Account tag keys to create custom Rule-Based Dimensions for. +- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the `Tag Keys` field. Dimension names will be derived from tag keys directly if this list is left empty. +- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. + +## Policy Actions + +- Create/update rule-based dimensions + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `observer` + - `billing_center_viewer` + - `rule_based_dimensions_manager` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- AWS + +## Cost + +This Policy Template does not launch any instances, and so does not incur any cloud costs. diff --git a/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt b/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt new file mode 100644 index 0000000000..55aeb43074 --- /dev/null +++ b/automation/aws/aws_rbd_from_tag/aws_rbd_from_tag.pt @@ -0,0 +1,277 @@ +name "AWS Rule-Based Dimension From Account Tags" +rs_pt_ver 20180301 +type "policy" +short_description "Creates and/or updates individual Rule-Based Dimensions based on AWS Account tags. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/aws/aws_rbd_from_tag) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "low" +category "Cost" +default_frequency "daily" +info( + version: "2.3.2", + provider: "Flexera", + service: "Optima", + policy_set: "Automation", + publish: "false" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_tag_list" do + type "list" + category "Policy Settings" + label "Tag Keys" + description "A list of AWS account tag keys to build Rule-Based Dimensions from" + # No default value, user input required +end + +parameter "param_name_list" do + type "list" + category "Policy Settings" + label "Dimension Names" + description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the 'Tag Keys' field. Dimension names will be derived from tag keys directly if this list is left empty." + default [] +end + +parameter "param_effective_date" do + type "string" + category "Policy Settings" + label "Effective Date" + description "Year/month you want rules to start applying in YYYY-MM format" + default "2010-01" +end + +parameter "param_normalize_case" do + type "string" + category "Policy Settings" + label "Lowercase Values" + description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." + allowed_values "Yes", "No" + default "Yes" +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_flexera" do + schemes "oauth2" + label "flexera" + description "Select FlexeraOne OAuth2 credential." + tags "provider=flexera" +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +# Get region-specific Flexera API endpoints +datasource "ds_flexera_api_hosts" do + run_script $js_flexera_api_hosts, rs_optima_host +end + +script "js_flexera_api_hosts", type: "javascript" do + parameters "rs_optima_host" + result "result" + code <<-EOS + host_table = { + "api.optima.flexeraeng.com": { + flexera: "api.flexera.com", + fsm: "api.fsm.flexeraeng.com" + }, + "api.optima-eu.flexeraeng.com": { + flexera: "api.flexera.eu", + fsm: "api.fsm-eu.flexeraeng.com" + }, + "api.optima-apac.flexeraeng.com": { + flexera: "api.flexera.au", + fsm: "api.fsm-apac.flexeraeng.com" + } + } + + result = host_table[rs_optima_host] +EOS +end + +# Get AWS account info +datasource "ds_cloud_vendor_accounts" do + request do + auth $auth_flexera + host val($ds_flexera_api_hosts, 'flexera') + path join(["/finops-analytics/v1/orgs/", rs_org_id, "/cloud-vendor-accounts"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + collect jmes_path(response, "values[*]") do + field "id", jmes_path(col_item, "aws.accountId") + field "name", jmes_path(col_item, "name") + field "tags", jmes_path(col_item, "tags") + end + end +end + +datasource "ds_cloud_vendor_accounts_normalized" do + run_script $js_cloud_vendor_accounts_normalized, $ds_cloud_vendor_accounts +end + +script "js_cloud_vendor_accounts_normalized", type: "javascript" do + parameters "accounts" + result "result" + code <<-'EOS' + result = [] + + _.each(accounts, function(account) { + tags = {} + + if (account['tags'] != null && account['tags'] != undefined) { + _.each(Object.keys(account['tags']), function(key) { + normalized_key = key.toLowerCase().trim() + tags[normalized_key] = account['tags'][key] + }) + } + + result.push({ + id: account['id'], + name: account['name'], + tags: tags + }) + }) +EOS +end + +datasource "ds_existing_rbds" do + request do + auth $auth_flexera + host rs_optima_host + path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) + header "Api-Version", "1.0" + header "content-type", "application/json" + end + result do + encoding "json" + collect jmes_path(response, "rule_based_dimensions") do + field "id", jmes_path(col_item, "id") + field "name", jmes_path(col_item, "name") + field "dated_rules", jmes_path(col_item, "dated_rules") + end + end +end + +datasource "ds_rbds" do + run_script $js_rbds, $ds_cloud_vendor_accounts_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_normalize_case +end + +script "js_rbds", type: "javascript" do + parameters "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_normalize_case" + result "result" + code <<-'EOS' + result = [] + + rbd_id_list = _.pluck(existing_rbds, 'id') + + _.each(param_tag_list, function(tag, index) { + rbd_name = tag.replace('.', ' ').replace('-', ' ') + rbd_name = rbd_name.replace(/\W/g, " ").trim() + + // Use user-specified name instead of user provided one + if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } + + rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() + + tag_key = tag.toLowerCase().trim() + verb = "POST" + if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } + + rules = [] + + _.each(accounts, function(account) { + if (typeof(account['id']) == 'string' && account['id'] != '' && typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) + } + } + } + }) + + if (rules.length > 0) { + result.push({ + id: rbd_id, + name: rbd_name, + verb: verb, + effective_at: param_effective_date, + rules: rules + }) + } + }) +EOS +end + +datasource "ds_create_rbds" do + iterate $ds_rbds + request do + run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id + end + result do + encoding "text" + end +end + +script "js_create_rbds", type: "javascript" do + parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: verb, + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), + body_fields: { name: name } + } +EOS +end + +datasource "ds_apply_rbds" do + iterate $ds_rbds + request do + # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does + run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id + end + result do + encoding "text" + end +end + +script "js_apply_rbds", type: "javascript" do + parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: "PUT", + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), + body_fields: { rules: rules } + } +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_rbds" do + validate $ds_apply_rbds do + summary_template "RBDs Generated & Applied" + detail_template "" + check eq(0, 0) + end +end diff --git a/automation/azure/azure_missing_subscriptions/CHANGELOG.md b/automation/azure/azure_missing_subscriptions/CHANGELOG.md new file mode 100644 index 0000000000..1ad604f8d4 --- /dev/null +++ b/automation/azure/azure_missing_subscriptions/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## v0.1 + +- initial release diff --git a/automation/azure/azure_missing_subscriptions/README.md b/automation/azure/azure_missing_subscriptions/README.md new file mode 100644 index 0000000000..5f33caf7f3 --- /dev/null +++ b/automation/azure/azure_missing_subscriptions/README.md @@ -0,0 +1,40 @@ +# Azure Missing Subscriptions + +## What It Does + +This policy checks the stored Flexera CCO billing data for Azure from 3 days ago to obtain a list of Azure Subscriptions that we have billing data for and compares that to the list of Azure Subscriptions returned by the Azure Resource Manager API. An incident is raised and email sent containing any subscriptions present in Flexera CCO but not returned by the Azure Resource Manager API, as well as subscriptions returned by the Azure Resource Manager API but not present in Flexera CCO. The user can select which of those two reports they'd like to produce. + +## Input Parameters + +This policy has the following input parameters required when launching the policy. + +- *Email Addresses* - Email addresses of the recipients you wish to notify when new incidents are created. +- *Azure Endpoint* - The endpoint to send Azure API requests to. Recommended to leave this at default unless using this policy with Azure China. +- *Report Selection* - Whether to report Subscriptions missing in the Azure API but present in CCO data, the opposite, or both. +- *Subscriptions Ignore List* - A list of Subscription IDs/names to never include in the results. Leave blank to not filter results + +## Policy Actions + +The following policy actions are taken on any resources found to be out of compliance. + +- Send an email report + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +- [**Azure Resource Manager Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_109256743_1124668) (*provider=azure_rm*) which has the following permissions: + - `Microsoft.Resources/subscriptions/read` + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `billing_center_viewer` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- Azure + +## Cost + +This Policy Template does not incur any cloud costs. diff --git a/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt b/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt new file mode 100644 index 0000000000..4cdf0a2821 --- /dev/null +++ b/automation/azure/azure_missing_subscriptions/azure_missing_subscriptions.pt @@ -0,0 +1,340 @@ +name "Azure Missing Subscriptions" +rs_pt_ver 20180301 +type "policy" +short_description "Reports any Azure Subscriptions present in Flexera One that are not accessible via the Azure Resource Manager automation credential. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/azure/azure_missing_subscriptions) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "low" +category "Cost" +default_frequency "weekly" +info( + version: "0.1", + provider: "Flexera", + service: "Optima", + policy_set: "Automation", + publish: "false" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_email" do + type "list" + category "Policy Settings" + label "Email Addresses" + description "A list of email addresses to notify." + default [] +end + +parameter "param_azure_endpoint" do + type "string" + category "Policy Settings" + label "Azure Endpoint" + description "Select the API endpoint to use for Azure. Use default value of management.azure.com unless using Azure China." + allowed_values "management.azure.com", "management.chinacloudapi.cn" + default "management.azure.com" +end + +parameter "param_report_selection" do + type "string" + category "Policy Settings" + label "Report Selection" + description "Whether to report Subscriptions missing in the Azure API but present in CCO data, the opposite, or both." + allowed_values "Missing in Azure API", "Missing in CCO", "Both" + default "Missing in Azure API" +end + +parameter "param_subscriptions_list" do + type "list" + category "Filters" + label "Subscriptions Ignore List" + description "A list of Subscription IDs/names to never include in the results. Leave blank to not filter results." + default [] +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_azure" do + schemes "oauth2" + label "Azure" + description "Select the Azure Resource Manager Credential from the list." + tags "provider=azure_rm" +end + +credentials "auth_flexera" do + schemes "oauth2" + label "Flexera" + description "Select Flexera One OAuth2 credentials" + tags "provider=flexera" +end + +############################################################################### +# Pagination +############################################################################### + +pagination "pagination_azure" do + get_page_marker do + body_path "nextLink" + end + set_page_marker do + uri true + end +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +# Get applied policy metadata for use later +datasource "ds_applied_policy" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) + header "Api-Version", "1.0" + end +end + +datasource "ds_billing_centers" do + request do + auth $auth_flexera + host rs_optima_host + path join(["/analytics/orgs/", rs_org_id, "/billing_centers"]) + header "Api-Version", "1.0" + header "User-Agent", "RS Policies" + query "view", "allocation_table" + ignore_status [403] + end + result do + encoding "json" + collect jmes_path(response, "[*]") do + field "href", jmes_path(col_item, "href") + field "id", jmes_path(col_item, "id") + field "name", jmes_path(col_item, "name") + field "parent_id", jmes_path(col_item, "parent_id") + end + end +end + +# Gather top level billing center IDs for when we pull cost data +datasource "ds_top_level_bcs" do + run_script $js_top_level_bcs, $ds_billing_centers +end + +script "js_top_level_bcs", type: "javascript" do + parameters "ds_billing_centers" + result "result" + code <<-EOS + filtered_bcs = _.filter(ds_billing_centers, function(bc) { + return bc['parent_id'] == null || bc['parent_id'] == undefined + }) + + result = _.compact(_.pluck(filtered_bcs, 'id')) +EOS +end + +datasource "ds_flexera_cco_data" do + request do + run_script $js_flexera_cco_data, $ds_top_level_bcs, rs_org_id, rs_optima_host + end + result do + encoding "json" + collect jmes_path(response, "rows[*]") do + field "bill_source", jmes_path(col_item, "dimensions.bill_source") + field "vendor_account", jmes_path(col_item, "dimensions.vendor_account") + field "vendor_account_name", jmes_path(col_item, "dimensions.vendor_account_name") + end + end +end + +script "js_flexera_cco_data", type: "javascript" do + parameters "ds_top_level_bcs", "rs_org_id", "rs_optima_host" + result "request" + code <<-EOS + end_date = new Date() + end_date.setDate(end_date.getDate() - 2) + end_date = end_date.toISOString().split('T')[0] + + start_date = new Date() + start_date.setDate(start_date.getDate() - 3) + start_date = start_date.toISOString().split('T')[0] + + var request = { + auth: "auth_flexera", + host: rs_optima_host, + verb: "POST", + path: "/bill-analysis/orgs/" + rs_org_id + "/costs/aggregated", + body_fields: { + dimensions: ["bill_source", "vendor_account", "vendor_account_name"], + granularity: "day", + start_at: start_date, + end_at: end_date, + metrics: ["cost_amortized_unblended_adj"], + billing_center_ids: ds_top_level_bcs, + limit: 100000, + filter: { + "type": "or", + "expressions": [ + { "dimension": "vendor", "type": "equal", "value": "Azure" }, + { "dimension": "vendor", "type": "equal", "value": "azure" }, + { "dimension": "vendor", "type": "equal", "value": "Microsoft Azure" }, + { "dimension": "vendor", "type": "equal", "value": "microsoft azure" } + ] + } + }, + headers: { + 'User-Agent': "RS Policies", + 'Api-Version': "1.0" + }, + ignore_status: [400] + } +EOS +end + +datasource "ds_azure_subscriptions" do + request do + auth $auth_azure + pagination $pagination_azure + host $param_azure_endpoint + path "/subscriptions/" + query "api-version","2020-01-01" + header "User-Agent", "RS Policies" + # Ignore status 400, 403, and 404 which can be returned in certain (legacy) types of Azure Subscriptions + ignore_status [400, 403, 404] + end + result do + encoding "json" + collect jmes_path(response, "value[*]") do + field "id", jmes_path(col_item, "subscriptionId") + field "name", jmes_path(col_item, "displayName") + field "state", jmes_path(col_item, "state") + end + end +end + +datasource "ds_missing_subscriptions_api" do + run_script $js_missing_subscriptions_api, $ds_flexera_cco_data, $ds_azure_subscriptions, $ds_applied_policy, $param_subscriptions_list, $param_report_selection +end + +script "js_missing_subscriptions_api", type: "javascript" do + parameters "ds_flexera_cco_data", "ds_azure_subscriptions", "ds_applied_policy", "param_subscriptions_list", "param_report_selection" + result "result" + code <<-'EOS' + result = [] + + if (param_report_selection != 'Missing in CCO') { + automation_ids = _.map(ds_azure_subscriptions, function(sub) { + return sub['id'].toLowerCase().trim() + }) + + missing_subs = _.reject(ds_flexera_cco_data, function(sub) { + return _.contains(automation_ids, sub['vendor_account'].toLowerCase().trim()) + }) + + result = _.map(missing_subs, function(sub) { + return { + accountID: sub['vendor_account'].toLowerCase().trim(), + accountName: sub['vendor_account_name'], + bill_source: sub['bill_source'], + policy_name: ds_applied_policy['name'] + } + }) + + // Remove filtered results + result = _.reject(result, function(sub) { + return _.contains(param_subscriptions_list, sub['accountID']) || _.contains(param_subscriptions_list, sub['accountName']) + }) + + result = _.sortBy(result, 'accountID') + result = _.sortBy(result, 'bill_source') + } +EOS +end + +datasource "ds_missing_subscriptions_cco" do + run_script $js_missing_subscriptions_cco, $ds_flexera_cco_data, $ds_azure_subscriptions, $ds_applied_policy, $param_subscriptions_list, $param_report_selection +end + +script "js_missing_subscriptions_cco", type: "javascript" do + parameters "ds_flexera_cco_data", "ds_azure_subscriptions", "ds_applied_policy", "param_subscriptions_list", "param_report_selection" + result "result" + code <<-'EOS' + result = [] + + if (param_report_selection != 'Missing in Azure API') { + cco_ids = _.map(ds_flexera_cco_data, function(sub) { + return sub['vendor_account'].toLowerCase().trim() + }) + + missing_subs = _.reject(ds_azure_subscriptions, function(sub) { + return _.contains(cco_ids, sub['id'].toLowerCase().trim()) + }) + + result = _.map(missing_subs, function(sub) { + return { + accountID: sub['id'].toLowerCase().trim(), + accountName: sub['name'], + policy_name: ds_applied_policy['name'] + } + }) + + // Remove filtered results + result = _.reject(result, function(sub) { + return _.contains(param_subscriptions_list, sub['accountID']) || _.contains(param_subscriptions_list, sub['accountName']) + }) + + result = _.sortBy(result, 'accountID') + } +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_missing_subscriptions" do + validate_each $ds_missing_subscriptions_api do + summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} Azure API Missing Subscriptions" + check eq(val(item, "accountID"), "") + escalate $esc_email + export do + resource_level false + field "accountID" do + label "Subscription ID" + end + field "accountName" do + label "Subscription Name" + end + field "bill_source" do + label "Bill Connection" + end + end + end + validate_each $ds_missing_subscriptions_cco do + summary_template "{{ with index data 0 }}{{ .policy_name }}{{ end }}: {{ len data }} Azure CCO Missing Subscriptions" + check eq(val(item, "accountID"), "") + escalate $esc_email + export do + resource_level false + field "accountID" do + label "Subscription ID" + end + field "accountName" do + label "Subscription Name" + end + end + end +end + +############################################################################### +# Escalations +############################################################################### + +escalation "esc_email" do + automatic true + label "Send Email" + description "Send incident email" + email $param_email +end diff --git a/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md new file mode 100644 index 0000000000..9a2c4ba2ad --- /dev/null +++ b/automation/azure/azure_rbd_from_rg_tag/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +## v1.3.1 + +- Fixed issue that would sometimes cause execution to fail if an Azure Subscription or Resource Group had no tag keys + +## v1.3.0 + +- Added option to retain original casing of tag values instead of normalizing them all to lowercase + +## v1.2.1 + +- Updated policy template to use newer API endpoints. Functionality is unchanged. + +## v1.2 + +- Fixed error where policy would fail completely when trying to access resources credential does not have access to. Policy will now simply skip these resources. + +## v1.1 + +- added ability to specify names for the newly created dimensions + +## v1.0 + +- initial release diff --git a/automation/azure/azure_rbd_from_rg_tag/README.md b/automation/azure/azure_rbd_from_rg_tag/README.md new file mode 100644 index 0000000000..98ae4beb88 --- /dev/null +++ b/automation/azure/azure_rbd_from_rg_tag/README.md @@ -0,0 +1,43 @@ +# Azure Rule-Based Dimension From Resource Group Tags + +## What It Does + +This policy creates and updates custom Rule-Based Dimensions that surface the specified Azure Resource Group tag keys in the Flexera One platform. This allows costs to be sliced by the values of the tag keys in question. + +## Input Parameters + +This policy has the following input parameters required when launching the policy. + +- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. +- *Tag Keys* - A list of Azure Resource Group tag keys to create custom Rule-Based Dimensions for. +- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the `Tag Keys` field. Dimension names will be derived from tag keys directly if this list is left empty. +- *Subscription Fallback Rules* - Whether or not to create rules for Subscription tags as a fallback for untagged Resource Groups. These rules have the lowest priority; rules created for Resource Group tags will always take precedence. +- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. + +## Policy Actions + +- Create/update rule-based dimensions + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +- [**Azure Resource Manager Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_109256743_1124668) (*provider=azure_rm*) which has the following permissions: + - `Microsoft.Resources/subscriptions/resources/read` + - `Microsoft.Resources/subscriptions/providers/read` + - `Microsoft.Resources/tags/read` + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `observer` + - `billing_center_viewer` + - `rule_based_dimensions_manager` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- Azure + +## Cost + +This Policy Template does not launch any instances, and so does not incur any cloud costs. diff --git a/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt b/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt new file mode 100644 index 0000000000..6373bd8a39 --- /dev/null +++ b/automation/azure/azure_rbd_from_rg_tag/azure_rbd_from_rg_tag.pt @@ -0,0 +1,418 @@ +name "Azure Rule-Based Dimension From Resource Group Tags" +rs_pt_ver 20180301 +type "policy" +short_description "Creates and/or updates individual Rule-Based Dimensions based on Azure Resource Group tags. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/azure/azure_rbd_from_rg_tag) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "low" +category "Cost" +default_frequency "daily" +info( + version: "1.3.1", + provider: "Flexera", + service: "Optima", + policy_set: "Automation", + publish: "false" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_tag_list" do + type "list" + category "Policy Settings" + label "Tag Keys" + description "A list of Azure account tag keys to build Rule-Based Dimensions from" + # No default value, user input required +end + +parameter "param_name_list" do + type "list" + category "Policy Settings" + label "Dimension Names" + description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the 'Tag Keys' field. Dimension names will be derived from tag keys directly if this list is left empty." + default [] +end + +parameter "param_effective_date" do + type "string" + category "Policy Settings" + label "Effective Date" + description "Year/month you want rules to start applying in YYYY-MM format" + default "2010-01" +end + +parameter "param_subscription_fallback" do + type "string" + category "Policy Settings" + label "Subscription Fallback Rules" + description "Whether or not to create rules for Subscription tags as a fallback for untagged Resource Groups." + allowed_values "Yes", "No" + default "No" +end + +parameter "param_normalize_case" do + type "string" + category "Policy Settings" + label "Lowercase Values" + description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." + allowed_values "Yes", "No" + default "Yes" +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_azure" do + schemes "oauth2" + label "Azure" + description "Select the Azure Resource Manager Credential from the list." + tags "provider=azure_rm" +end + +credentials "auth_flexera" do + schemes "oauth2" + label "flexera" + description "Select FlexeraOne OAuth2 credential." + tags "provider=flexera" +end + +############################################################################### +# Pagination +############################################################################### + +pagination "pagination_azure" do + get_page_marker do + body_path "nextLink" + end + set_page_marker do + uri true + end +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +# Get region-specific Flexera API endpoints +datasource "ds_flexera_api_hosts" do + run_script $js_flexera_api_hosts, rs_optima_host +end + +script "js_flexera_api_hosts", type: "javascript" do + parameters "rs_optima_host" + result "result" + code <<-EOS + host_table = { + "api.optima.flexeraeng.com": { + flexera: "api.flexera.com", + fsm: "api.fsm.flexeraeng.com" + }, + "api.optima-eu.flexeraeng.com": { + flexera: "api.flexera.eu", + fsm: "api.fsm-eu.flexeraeng.com" + }, + "api.optima-apac.flexeraeng.com": { + flexera: "api.flexera.au", + fsm: "api.fsm-apac.flexeraeng.com" + } + } + + result = host_table[rs_optima_host] +EOS +end + +datasource "ds_existing_rbds" do + request do + auth $auth_flexera + host rs_optima_host + path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) + header "Api-Version", "1.0" + header "content-type", "application/json" + end + result do + encoding "json" + collect jmes_path(response, "rule_based_dimensions") do + field "id", jmes_path(col_item, "id") + field "name", jmes_path(col_item, "name") + field "dated_rules", jmes_path(col_item, "dated_rules") + end + end +end + +datasource "ds_azure_subscriptions" do + request do + auth $auth_azure + pagination $pagination_azure + host "management.azure.com" + path "/subscriptions/" + query "api-version", "2018-06-01" + header "User-Agent", "RS Policies" + # Ignore status 400, 403, and 404 which can be returned in certain (legacy) types of Azure Subscriptions + ignore_status [400, 403, 404] + end + result do + encoding "json" + collect jmes_path(response, "value[*]") do + field "id", jmes_path(col_item, "subscriptionId") + field "name", jmes_path(col_item, "displayName") + end + end +end + +datasource "ds_azure_subscriptions_with_tags" do + iterate $ds_azure_subscriptions + request do + auth $auth_azure + pagination $pagination_azure + host "management.azure.com" + path join(["/subscriptions/", val(iter_item, "id"), "/providers/Microsoft.Resources/tags/default"]) + query "api-version", "2021-04-01" + header "User-Agent", "RS Policies" + ignore_status [400, 403, 404] + end + result do + encoding "json" + field "id", val(iter_item, "id") + field "name", val(iter_item, "name") + field "tags", jmes_path(response, "properties.tags") + end +end + +datasource "ds_azure_subscriptions_normalized" do + run_script $js_azure_subscriptions_normalized, $ds_azure_subscriptions_with_tags +end + +script "js_azure_subscriptions_normalized", type: "javascript" do + parameters "accounts" + result "result" + code <<-'EOS' + result = [] + + _.each(accounts, function(account) { + tags = {} + + if (account['tags'] != null && account['tags'] != undefined) { + _.each(Object.keys(account['tags']), function(key) { + normalized_key = key.toLowerCase().trim() + tags[normalized_key] = account['tags'][key] + }) + } + + result.push({ + id: account['id'], + name: account['name'], + tags: tags + }) + }) +EOS +end + +datasource "ds_azure_resource_groups" do + iterate $ds_azure_subscriptions + request do + auth $auth_azure + pagination $pagination_azure + host "management.azure.com" + path join(["/subscriptions/", val(iter_item, "id"), "/resourcegroups"]) + query "api-version", "2021-04-01" + header "User-Agent", "RS Policies" + ignore_status [400, 403, 404] + end + result do + encoding "json" + collect jmes_path(response, "value[*]") do + field "subscriptionId", val(iter_item, "id") + field "subscriptionName", val(iter_item, "name") + field "id", jmes_path(col_item, "id") + field "name", jmes_path(col_item, "name") + field "tags", jmes_path(col_item, "tags") + end + end +end + +datasource "ds_azure_resource_groups_normalized" do + run_script $js_azure_resource_groups_normalized, $ds_azure_resource_groups +end + +script "js_azure_resource_groups_normalized", type: "javascript" do + parameters "rgs" + result "result" + code <<-'EOS' + result = [] + + _.each(rgs, function(rg) { + tags = {} + + if (rg['tags'] != null && rg['tags'] != undefined) { + _.each(Object.keys(rg['tags']), function(key) { + normalized_key = key.toLowerCase().trim() + tags[normalized_key] = rg['tags'][key] + }) + } + + result.push({ + subscriptionId: rg['subscriptionId'], + subscriptionName: rg['subscriptionName'], + id: rg['id'], + name: rg['name'], + tags: tags + }) + }) +EOS +end + +datasource "ds_rbds" do + run_script $js_rbds, $ds_azure_resource_groups_normalized, $ds_azure_subscriptions_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_subscription_fallback, $param_normalize_case +end + +script "js_rbds", type: "javascript" do + parameters "rgs", "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_subscription_fallback", "param_normalize_case" + result "result" + code <<-'EOS' + result = [] + + rbd_id_list = _.pluck(existing_rbds, 'id') + + _.each(param_tag_list, function(tag, index) { + rbd_name = tag.replace('.', ' ').replace('-', ' ') + rbd_name = rbd_name.replace(/\W/g, " ").trim() + + // Use user-specified name instead of user provided one + if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } + + rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() + + tag_key = tag.toLowerCase().trim() + verb = "POST" + if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } + + rules = [] + + _.each(rgs, function(rg) { + if (typeof(rg['tags']) == 'object') { + if (typeof(rg['tags'][tag_key]) == 'string') { + if (rg['tags'][tag_key].trim() != '') { + value = rg['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { + type: "and", + expressions: [ + { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim() }, + { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } + ] + }, + value: { text: value } + }) + + if (rg['name'].trim() != rg['name'].trim().toLowerCase()) { + rules.push({ + condition: { + type: "and", + expressions: [ + { type: "dimension_equals", dimension: "resource_group", value: rg['name'].trim().toLowerCase() }, + { type: "dimension_equals", dimension: "vendor_account", value: rg['subscriptionId'].trim().toLowerCase() } + ] + }, + value: { text: value } + }) + } + } + } + } + }) + + if (param_subscription_fallback == "Yes") { + _.each(accounts, function(account) { + if (typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) + } + } + } + }) + } + + if (rules.length > 0) { + result.push({ + id: rbd_id, + name: rbd_name, + verb: verb, + effective_at: param_effective_date, + rules: rules + }) + } + }) +EOS +end + +datasource "ds_create_rbds" do + iterate $ds_rbds + request do + run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id + end + result do + encoding "text" + end +end + +script "js_create_rbds", type: "javascript" do + parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: verb, + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), + body_fields: { name: name } + } +EOS +end + +datasource "ds_apply_rbds" do + iterate $ds_rbds + request do + # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does + run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id + end + result do + encoding "text" + end +end + +script "js_apply_rbds", type: "javascript" do + parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: "PUT", + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), + body_fields: { rules: rules } + } +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_rbds" do + validate $ds_apply_rbds do + summary_template "RBDs Generated & Applied" + detail_template "" + check eq(0, 0) + end +end diff --git a/automation/azure/azure_rbd_from_tag/CHANGELOG.md b/automation/azure/azure_rbd_from_tag/CHANGELOG.md new file mode 100644 index 0000000000..b2354a4856 --- /dev/null +++ b/automation/azure/azure_rbd_from_tag/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +## v1.3.1 + +- Fixed issue that would sometimes cause execution to fail if an Azure Subscription had no tag keys + +## v1.3.0 + +- Added option to retain original casing of tag values instead of normalizing them all to lowercase + +## v1.2.1 + +- Updated policy template to use newer API endpoints. Functionality is unchanged. + +## v1.2 + +- Fixed error where policy would fail completely when trying to access resources credential does not have access to. Policy will now simply skip these resources. + +## v1.1 + +- added ability to specify names for the newly created dimensions + +## v1.0 + +- initial release diff --git a/automation/azure/azure_rbd_from_tag/README.md b/automation/azure/azure_rbd_from_tag/README.md new file mode 100644 index 0000000000..270f1ef5ef --- /dev/null +++ b/automation/azure/azure_rbd_from_tag/README.md @@ -0,0 +1,42 @@ +# Azure Rule-Based Dimension From Subscription Tags + +## What It Does + +This policy creates and updates custom Rule-Based Dimensions that surface the specified Azure Subscription tag keys in the Flexera One platform. This allows costs to be sliced by the values of the tag keys in question. + +## Input Parameters + +This policy has the following input parameters required when launching the policy. + +- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. +- *Tag Keys* - A list of Azure Subscription tag keys to create custom Rule-Based Dimensions for. +- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the `Tag Keys` field. Dimension names will be derived from tag keys directly if this list is left empty. +- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. + +## Policy Actions + +- Create/update rule-based dimensions + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +- [**Azure Resource Manager Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_109256743_1124668) (*provider=azure_rm*) which has the following permissions: + - `Microsoft.Resources/subscriptions/resources/read` + - `Microsoft.Resources/subscriptions/providers/read` + - `Microsoft.Resources/tags/read` + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `observer` + - `billing_center_viewer` + - `rule_based_dimensions_manager` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- Azure + +## Cost + +This Policy Template does not launch any instances, and so does not incur any cloud costs. diff --git a/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt b/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt new file mode 100644 index 0000000000..467c1700d0 --- /dev/null +++ b/automation/azure/azure_rbd_from_tag/azure_rbd_from_tag.pt @@ -0,0 +1,318 @@ +name "Azure Rule-Based Dimension From Subscription Tags" +rs_pt_ver 20180301 +type "policy" +short_description "Creates and/or updates individual Rule-Based Dimensions based on Azure Subscription tags. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/azure/azure_rbd_from_tag) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "low" +category "Cost" +default_frequency "daily" +info( + version: "1.3.1", + provider: "Flexera", + service: "Optima", + policy_set: "Automation", + publish: "false" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_tag_list" do + type "list" + category "Policy Settings" + label "Tag Keys" + description "A list of Azure account tag keys to build Rule-Based Dimensions from" + # No default value, user input required +end + +parameter "param_name_list" do + type "list" + category "Policy Settings" + label "Dimension Names" + description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the tag keys in the 'Tag Keys' field. Dimension names will be derived from tag keys directly if this list is left empty." + default [] +end + +parameter "param_effective_date" do + type "string" + category "Policy Settings" + label "Effective Date" + description "Year/month you want rules to start applying in YYYY-MM format" + default "2010-01" +end + +parameter "param_normalize_case" do + type "string" + category "Policy Settings" + label "Lowercase Values" + description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." + allowed_values "Yes", "No" + default "Yes" +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_azure" do + schemes "oauth2" + label "Azure" + description "Select the Azure Resource Manager Credential from the list." + tags "provider=azure_rm" +end + +credentials "auth_flexera" do + schemes "oauth2" + label "flexera" + description "Select FlexeraOne OAuth2 credential." + tags "provider=flexera" +end + +############################################################################### +# Pagination +############################################################################### + +pagination "pagination_azure" do + get_page_marker do + body_path "nextLink" + end + set_page_marker do + uri true + end +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +# Get region-specific Flexera API endpoints +datasource "ds_flexera_api_hosts" do + run_script $js_flexera_api_hosts, rs_optima_host +end + +script "js_flexera_api_hosts", type: "javascript" do + parameters "rs_optima_host" + result "result" + code <<-EOS + host_table = { + "api.optima.flexeraeng.com": { + flexera: "api.flexera.com", + fsm: "api.fsm.flexeraeng.com" + }, + "api.optima-eu.flexeraeng.com": { + flexera: "api.flexera.eu", + fsm: "api.fsm-eu.flexeraeng.com" + }, + "api.optima-apac.flexeraeng.com": { + flexera: "api.flexera.au", + fsm: "api.fsm-apac.flexeraeng.com" + } + } + + result = host_table[rs_optima_host] +EOS +end + +datasource "ds_existing_rbds" do + request do + auth $auth_flexera + host rs_optima_host + path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) + header "Api-Version", "1.0" + header "content-type", "application/json" + end + result do + encoding "json" + collect jmes_path(response, "rule_based_dimensions") do + field "id", jmes_path(col_item, "id") + field "name", jmes_path(col_item, "name") + field "dated_rules", jmes_path(col_item, "dated_rules") + end + end +end + +datasource "ds_azure_subscriptions_without_tags" do + request do + auth $auth_azure + pagination $pagination_azure + host "management.azure.com" + path "/subscriptions/" + query "api-version", "2018-06-01" + header "User-Agent", "RS Policies" + # Ignore status 400, 403, and 404 which can be returned in certain (legacy) types of Azure Subscriptions + ignore_status [400, 403, 404] + end + result do + encoding "json" + collect jmes_path(response, "value[*]") do + field "id", jmes_path(col_item, "subscriptionId") + field "name", jmes_path(col_item, "displayName") + end + end +end + +datasource "ds_azure_subscriptions" do + iterate $ds_azure_subscriptions_without_tags + request do + auth $auth_azure + pagination $pagination_azure + host "management.azure.com" + path join(["/subscriptions/", val(iter_item, "id"), "/providers/Microsoft.Resources/tags/default"]) + query "api-version", "2021-04-01" + header "User-Agent", "RS Policies" + ignore_status [400, 403, 404] + end + result do + encoding "json" + field "id", val(iter_item, "id") + field "name", val(iter_item, "name") + field "tags", jmes_path(response, "properties.tags") + end +end + +datasource "ds_azure_subscriptions_normalized" do + run_script $js_azure_subscriptions_normalized, $ds_azure_subscriptions +end + +script "js_azure_subscriptions_normalized", type: "javascript" do + parameters "accounts" + result "result" + code <<-'EOS' + result = [] + + _.each(accounts, function(account) { + tags = {} + + if (account['tags'] != null && account['tags'] != undefined) { + _.each(Object.keys(account['tags']), function(key) { + normalized_key = key.toLowerCase().trim() + tags[normalized_key] = account['tags'][key] + }) + } + + result.push({ + id: account['id'], + name: account['name'], + tags: tags + }) + }) +EOS +end + +datasource "ds_rbds" do + run_script $js_rbds, $ds_azure_subscriptions_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_normalize_case +end + +script "js_rbds", type: "javascript" do + parameters "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_normalize_case" + result "result" + code <<-'EOS' + result = [] + + rbd_id_list = _.pluck(existing_rbds, 'id') + + _.each(param_tag_list, function(tag, index) { + rbd_name = tag.replace('.', ' ').replace('-', ' ') + rbd_name = rbd_name.replace(/\W/g, " ").trim() + + // Use user-specified name instead of user provided one + if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } + + rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() + + tag_key = tag.toLowerCase().trim() + verb = "POST" + if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } + + rules = [] + + _.each(accounts, function(account) { + if (typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) + } + } + } + }) + + if (rules.length > 0) { + result.push({ + id: rbd_id, + name: rbd_name, + verb: verb, + effective_at: param_effective_date, + rules: rules + }) + } + }) +EOS +end + +datasource "ds_create_rbds" do + iterate $ds_rbds + request do + run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id + end + result do + encoding "text" + end +end + +script "js_create_rbds", type: "javascript" do + parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: verb, + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), + body_fields: { name: name } + } +EOS +end + +datasource "ds_apply_rbds" do + iterate $ds_rbds + request do + # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does + run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id + end + result do + encoding "text" + end +end + +script "js_apply_rbds", type: "javascript" do + parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: "PUT", + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), + body_fields: { rules: rules } + } +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_rbds" do + validate $ds_apply_rbds do + summary_template "RBDs Generated & Applied" + detail_template "" + check eq(0, 0) + end +end diff --git a/automation/flexera/delete_all_billing_centers/CHANGELOG.md b/automation/flexera/delete_all_billing_centers/CHANGELOG.md new file mode 100644 index 0000000000..3a41ea7330 --- /dev/null +++ b/automation/flexera/delete_all_billing_centers/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## v1.1 + +- Updated policy metadata to make it more clear what Flexera service the policy is for + +## v1.0 + +- initial release diff --git a/automation/flexera/delete_all_billing_centers/README.md b/automation/flexera/delete_all_billing_centers/README.md new file mode 100644 index 0000000000..45be0de250 --- /dev/null +++ b/automation/flexera/delete_all_billing_centers/README.md @@ -0,0 +1,34 @@ +# Flexera CCO Delete All Billing Centers + +## What It Does + +This policy deletes all Billing Centers in the Flexera organization it is executed within. The policy will automatically self-terminate the second time it runs to avoid accidental future deletion of Billing Centers. + +## How It Works + +- During execution, the policy determines if this is the second time it has run since it was applied by comparing the applied policy's `created_at` date/time with the current date/time. If the difference between the two is greater than 1 minute, it is assumed the policy is running a second time. +- If this is the policy's second time running, the policy self-terminates before completing execution as a failsafe in case the user has forgotten to terminate the policy after usage. +- An incident is always raised, with the `Self Terminate` field in the incident table being true if this is the policy's second time executing since it was applied. +- Cloud Workflow is automatically kicked off. + - If this is the policy's second time executing, but for some reason the policy has failed to self-terminate, no action will be taken. + - If this is the policy's first time executing, all of the Billing Centers in the Flexera organization are deleted. + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +### Credential configuration + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `billing_center_admin` + - `policy_manager` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- Flexera + +## Cost + +This Policy Template does not incur any cloud costs. diff --git a/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt b/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt new file mode 100644 index 0000000000..c39455a663 --- /dev/null +++ b/automation/flexera/delete_all_billing_centers/delete_all_billing_centers.pt @@ -0,0 +1,233 @@ +name "Flexera CCO Delete All Billing Centers" +rs_pt_ver 20180301 +type "policy" +short_description "Deletes all Billing Centers in the Flexera organization. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/flexera/delete_all_billing_centers) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "high" +category "Cost" +default_frequency "15 minutes" +info( + version: "1.1", + provider: "Flexera", + service: "Cloud Cost Optimization", + policy_set: "Automation", + publish: "false" +) + +############################################################################### +# Parameters +############################################################################### + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_flexera" do + schemes "oauth2" + label "Flexera" + description "Select FlexeraOne OAuth2 credential." + tags "provider=flexera" +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +datasource "ds_applied_policy" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) + header "Api-Version", "1.0" + end +end + +datasource "ds_second_execution" do + run_script $js_second_execution, $ds_applied_policy +end + +script "js_second_execution", type: "javascript" do + parameters "ds_applied_policy" + result "result" + code <<-'EOS' + result = [{ id: ds_applied_policy['href'], terminate: false }] + + now = new Date() + created_at = new Date(ds_applied_policy['created_at']) + + // If applied policy was created over 1 minute ago, assume this is the second time it is running + if (now - created_at > 60000) { result[0]['terminate'] = true } +EOS +end + +datasource "ds_self_terminate_boolean" do + run_script $js_self_terminate_boolean, $ds_second_execution +end + +script "js_self_terminate_boolean", type: "javascript" do + parameters "ds_second_execution" + result "result" + code <<-'EOS' + result = [] + + if (ds_second_execution[0]['terminate']) { result = ds_second_execution } +EOS +end + +datasource "ds_self_terminate" do + iterate $ds_self_terminate_boolean + request do + auth $auth_flexera + host rs_governance_host + verb "DELETE" + path val(iter_item, 'id') + header "Api-Version", "1.0" + end +end + +datasource "ds_incident" do + run_script $js_incident, $ds_second_execution, $ds_self_terminate +end + +script "js_incident", type: "javascript" do + parameters "ds_second_execution", "ds_self_terminate" + result "result" + code <<-'EOS' + result = ds_second_execution +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_delete_bcs" do + validate_each $ds_incident do + summary_template "Deleting Billing Centers" + check eq(0, 1) + escalate $esc_delete_billing_centers + export do + resource_level true + field "id" do + label "Policy HREF" + end + field "terminate" do + label "Self Terminate" + end + end + end +end + +############################################################################### +# Escalations +############################################################################### + +escalation "esc_delete_billing_centers" do + automatic true + label "Delete Billing Centers" + description "Approval to delete all billing centers" + run "delete_billing_centers", data, rs_org_id, rs_optima_host +end + +############################################################################### +# Cloud Workflow +############################################################################### + +define delete_billing_centers($data, $rs_org_id, $rs_optima_host) return $all_responses do + $$all_responses = [] + + # Policy will only run if it isn't self-terminating + if $data[0]["terminate"] == false + call list_childless_billing_centers($rs_org_id, $rs_optima_host) retrieve $billing_centers + + while size($billing_centers) > 0 do + foreach $billing_center in $billing_centers do + sub on_error: handle_error() do + call delete_billing_center($billing_center, $rs_org_id, $rs_optima_host) retrieve $delete_response + end + end + + sleep(10) + + call list_childless_billing_centers($rs_org_id, $rs_optima_host) retrieve $billing_centers + end + end +end + +define list_childless_billing_centers($rs_org_id, $rs_optima_host) return $billing_centers do + $billing_centers = [] + + task_label("Listing All Billing Centers") + + $response = http_request( + auth: $$auth_flexera, + https: true, + verb: "get", + href: "/analytics/orgs/" + $rs_org_id + "/billing_centers", + host: $rs_optima_host, + headers: { + "Api-Version": "1.0", + "User-Agent": "RS Policies" + } + ) + + task_label("Listing All Billing Centers response: " + to_json($response)) + $$all_responses << to_json({"req": "GET /billing_centers", "resp": $response}) + + if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 + raise "Unexpected response Listing All Billing Centers: " + to_json($response) + else + task_label("Listing All Billing Centers successful") + + $parent_ids = [] + + foreach $item in $response["body"] do + if $item["name"] != "Unallocated" && $item["parent_id"] != null && $item["parent_id"] != "" + $parent_ids << $item["parent_id"] + end + end + + foreach $item in $response["body"] do + if $item["name"] != "Unallocated" && contains?($parent_ids, [ $item["id"] ]) == false + $billing_centers << $item + end + end + end +end + +define delete_billing_center($billing_center, $rs_org_id, $rs_optima_host) return $response do + $bc_label = $billing_center["name"] + " (" + $billing_center["id"] + ")" + + task_label("Delete Billing Center: " + $bc_label) + + $response = http_request( + auth: $$auth_flexera, + https: true, + verb: "delete", + href: "/analytics/orgs/" + $rs_org_id + "/billing_centers/" + $billing_center["id"], + host: $rs_optima_host, + headers: { + "Api-Version": "1.0", + "User-Agent": "RS Policies" + } + ) + + task_label("Delete Billing Center response: " + $bc_label + " " + to_json($response)) + $$all_responses << to_json({"req": "DELETE /billing_centers/" + $billing_center["id"], "resp": $response}) + + if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 + raise "Unexpected response Deleting Billing Centers: " + $bc_label + " " + to_json($response) + else + task_label("Delete Billing Center successful: " + $bc_label) + end +end + +define handle_error() do + if !$$errors + $$errors = [] + end + $$errors << $_error["type"] + ": " + $_error["message"] + # We check for errors at the end, and raise them all together + # Skip errors handled by this definition + $_error_behavior = "skip" +end diff --git a/automation/flexera/outdated_applied_policies/CHANGELOG.md b/automation/flexera/outdated_applied_policies/CHANGELOG.md new file mode 100644 index 0000000000..85a84d011f --- /dev/null +++ b/automation/flexera/outdated_applied_policies/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog + +## v0.2.0 + +- Policy template now reports both outdated and deprecated policy templates with a parameter to choose which +- Automatic updates for policy templates with a major version change is now supported via parameter + +## v0.1.1 + +- Minor fix to wording in resulting incident detail + +## v0.1 + +- initial release diff --git a/automation/flexera/outdated_applied_policies/README.md b/automation/flexera/outdated_applied_policies/README.md new file mode 100644 index 0000000000..8a91fe0a0d --- /dev/null +++ b/automation/flexera/outdated_applied_policies/README.md @@ -0,0 +1,71 @@ +# Flexera Automation Outdated Applied Policies + +## What It Does + +This policy template checks all applied policies for the following: + +- Whether the policy template is an older version than the current version in the policy catalog. +- Whether the policy template has been deprecated. + +The following policy types will always be ignored and not reported on by this policy: + +- This policy itself. +- Policies applied from a source other than the Flexera Automation Catalog. +- Organization-specific policies published to that organization's own catalog. +- Flexera policies present in the [policy-templates Github Repository](https://github.com/flexera-public/policy_templates) but not published in the Flexera Automation Catalog, such as meta policies and other misc. utility policies. +- Policy aggregates applied across multiple projects. Aggregates applied only to the project this policy is applied in will still be included in the results and are actionable. + +## How It Works + +The list of outdated policies is generated as follows: + +- The list of applied policies are obtained using the [Flexera Policy API](https://reference.rightscale.com/governance-policies/). +- The list of catalog policies are obtained using the [Active Policy List JSON file](https://github.com/flexera-public/policy_templates/blob/master/data/active_policy_list/active_policy_list.json) in the [policy-templates Github Repository](https://github.com/flexera-public/policy_templates). +- The list of applied policies is filtered for just those applied policies that were applied from a catalog policy and whose version number does not match the version number in the catalog. + +The list of deprecated policies is generated as follows: + +- The list of applied policies are obtained using the [Flexera Policy API](https://reference.rightscale.com/governance-policies/). +- The list of catalog policies are obtained using the [Active Policy List JSON file](https://github.com/flexera-public/policy_templates/blob/master/data/active_policy_list/active_policy_list.json) in the [policy-templates Github Repository](https://github.com/flexera-public/policy_templates). +- The list of applied policies is filtered for just those applied policies marked as deprecated in the [Active Policy List JSON file](https://github.com/flexera-public/policy_templates/blob/master/data/active_policy_list/active_policy_list.json). + +Updating an outdated policy is done as follows: + +- The [major version](https://semver.org/) of the applied policy is compared to the catalog policy. If the major version has changed, and the `Allow Automated Major Version Updates` parameter is set to "Do Not Allow", an error is raised indicating that the update should be done manually. This is because a major version change usually involves major changes in functionality and input parameters that would require the user to intelligently determine how to apply the updated policy. +- If the major version has not changed, or the `Allow Automated Major Version Updates` parameter is set to "Allow", the catalog policy is applied with the exact same configuration and settings as the existing applied policy. +- If the above action was successful, the existing applied policy is deleted. If the above action failed, an error is raised and the existing applied policy remains in place so that the user can manually update as needed. + +## Input Parameters + +- *Email Addresses* - A list of email addresses to notify. +- *Policy Ignore List* - A list of applied policy names and/or IDs to ignore and not report on. Leave blank to assess all applied policies. +- *Policy Templates To Report* - Whether to report outdated policy templates, deprecated policy templates, or both. Separate incidents will be raised/emailed if both are selected and found. +- *Allow Automated Major Version Updates* - Whether to allow actions to automatically update outdated policy templates when there's been a major version change. This is not recommended in most cases. +- *Automatic Actions* - When this value is set, this policy will automatically take the selected action(s). + +## Policy Actions + +- Send an email report +- Update applied policy to the newest version after approval + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +### Credential Configuration + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `policy_viewer` + - `policy_manager`* + + \* Only required for taking action (updating applied policies); the policy will still function in a read-only capacity without these permissions. + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- Flexera + +## Cost + +This Policy Template does not incur any cloud costs. Cloud costs may be incurred by the applied policies that this policy reports on and updates. Please consult the README of each policy for more information. diff --git a/automation/flexera/outdated_applied_policies/outdated_applied_policies.pt b/automation/flexera/outdated_applied_policies/outdated_applied_policies.pt new file mode 100644 index 0000000000..367dee8444 --- /dev/null +++ b/automation/flexera/outdated_applied_policies/outdated_applied_policies.pt @@ -0,0 +1,835 @@ +name "Flexera Automation Outdated Applied Policies" +rs_pt_ver 20180301 +type "policy" +short_description "Reports any applied policies in Flexera Automation that are not using the latest version of that policy from the catalog and, optionally, updates them. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/flexera/outdated_applied_policies) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "low" +category "Operational" +default_frequency "weekly" +info( + version: "0.2.0", + provider: "Flexera", + service: "Automation", + policy_set: "Automation" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_email" do + type "list" + category "Policy Settings" + label "Email Addresses" + description "A list of email addresses to notify." + default [] +end + +parameter "param_ignore_list" do + type "list" + category "Filters" + label "Policy Ignore List" + description "A list of applied policy names and/or IDs to ignore and not report on. Leave blank to assess all applied policies." + default [] +end + +parameter "param_report_filter" do + type "string" + category "Filters" + label "Policy Templates To Report" + description "Whether to report outdated policy templates, deprecated policy templates, or both. Separate incidents will be raised/emailed if both are selected and found." + allowed_values "Both", "Report Outdated Only", "Report Deprecated Only" + default "Both" +end + +parameter "param_allow_major" do + type "string" + category "Actions" + label "Allow Automated Major Version Updates" + description "Whether to allow actions to automatically update outdated policy templates when there's been a major version change. This is not recommended in most cases." + allowed_values "Allow", "Do Not Allow" + default "Do Not Allow" +end + +parameter "param_automatic_action" do + type "list" + category "Actions" + label "Automatic Actions" + description "When this value is set, this policy will automatically take the selected action(s)" + allowed_values ["Update Applied Policies"] + default [] +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_flexera" do + schemes "oauth2" + label "Flexera" + description "Select Flexera One OAuth2 credentials" + tags "provider=flexera" +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +datasource "ds_self_policy" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies/", policy_id]) + header "Api-Version", "1.0" + end +end + +datasource "ds_applied_policies" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/projects/", rs_project_id, "/applied_policies"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + collect jmes_path(response, "items[*]") do + field "id", jmes_path(col_item, "id") + field "href", jmes_path(col_item, "href") + field "name", jmes_path(col_item, "name") + field "description", jmes_path(col_item, "description") + field "category", jmes_path(col_item, "category") + field "created_at", jmes_path(col_item, "created_at") + field "created_by", jmes_path(col_item, "created_by.email") + field "frequency", jmes_path(col_item, "frequency") + field "category", jmes_path(col_item, "category") + field "credentials", jmes_path(col_item, "credentials") + field "options", jmes_path(col_item, "options") + field "severity", jmes_path(col_item, "severity") + field "skip_approvals", jmes_path(col_item, "skip_approvals") + field "scope", jmes_path(col_item, "scope") + field "dry_run", jmes_path(col_item, "dry_run") + field "log_level", jmes_path(col_item, "log_level") + field "version", jmes_path(col_item, "info.version") + field "policy_template", jmes_path(col_item, "policy_template") + field "published_template", jmes_path(col_item, "published_template") + end + end +end + +datasource "ds_policy_aggregates" do + request do + auth $auth_flexera + host rs_governance_host + path join(["/api/governance/orgs/", rs_org_id, "/policy_aggregates"]) + header "Api-Version", "1.0" + end + result do + encoding "json" + collect jmes_path(response, "items[*]") do + field "id", jmes_path(col_item, "id") + field "href", jmes_path(col_item, "href") + field "name", jmes_path(col_item, "name") + field "description", jmes_path(col_item, "description") + field "category", jmes_path(col_item, "category") + field "created_at", jmes_path(col_item, "created_at") + field "created_by", jmes_path(col_item, "created_by.email") + field "frequency", jmes_path(col_item, "frequency") + field "category", jmes_path(col_item, "category") + field "credentials", jmes_path(col_item, "credentials") + field "options", jmes_path(col_item, "options") + field "severity", jmes_path(col_item, "severity") + field "skip_approvals", jmes_path(col_item, "skip_approvals") + field "dry_run", jmes_path(col_item, "dry_run") + field "running_project_ids", jmes_path(col_item, "running_project_ids") + field "published_template", jmes_path(col_item, "published_template") + end + end +end + +datasource "ds_catalog_policies" do + request do + verb "GET" + host "raw.githubusercontent.com" + path "/flexera-public/policy_templates/master/data/active_policy_list/active_policy_list.json" + header "User-Agent", "RS Policies" + end + result do + encoding "json" + collect jmes_path(response, "policies[*]") do + field "name", jmes_path(col_item, "name") + field "file_name", jmes_path(col_item, "file_name") + field "version", jmes_path(col_item, "version") + field "change_log", jmes_path(col_item, "change_log") + field "description", jmes_path(col_item, "description") + field "category", jmes_path(col_item, "category") + field "severity", jmes_path(col_item, "severity") + field "readme", jmes_path(col_item, "readme") + field "provider", jmes_path(col_item, "provider") + field "service", jmes_path(col_item, "service") + field "policy_set", jmes_path(col_item, "policy_set") + field "recommendation_type", jmes_path(col_item, "recommendation_type") + field "updated_at", jmes_path(col_item, "updated_at") + field "generally_recommended", jmes_path(col_item, "generally_recommended") + field "deprecated", jmes_path(col_item, "deprecated") + end + end +end + +datasource "ds_outdated_policies" do + run_script $js_outdated_policies, $ds_applied_policies, $ds_catalog_policies, $ds_policy_aggregates, $ds_self_policy, $param_ignore_list, $param_report_filter, rs_org_id, rs_project_id, policy_id, rs_optima_host +end + +script "js_outdated_policies", type: "javascript" do + parameters "ds_applied_policies", "ds_catalog_policies", "ds_policy_aggregates", "ds_self_policy", "param_ignore_list", "param_report_filter", "rs_org_id", "rs_project_id", "policy_id", "rs_optima_host" + result "result" + code <<-'EOS' + tld_table = { + "api.optima.flexeraeng.com": "app.flexera.com", + "api.optima-eu.flexeraeng.com": "app.flexera.eu", + "api.optima-apac.flexeraeng.com": "app.flexera.au" + } + + tld = tld_table[rs_optima_host] + + aggregate_object = {} + + _.each(ds_policy_aggregates, function(agg) { + if (typeof(agg['running_project_ids']) == 'object') { + if (agg['running_project_ids'].length == 1 && agg['running_project_ids'][0] == rs_project_id) { + aggregate_object[agg['name']] = agg['href'] + } + } + }) + + catalog_object = {} + + _.each(ds_catalog_policies, function(policy) { + catalog_object[policy['name']] = policy + }) + + filtered_policies = _.reject(ds_applied_policies, function(policy) { + reject_policy = false + + // Exclude this policy to avoid the policy trying to terminate itself if the user actions on it + if (policy['id'] == policy_id) { + reject_policy = true + } + + // Exclude policies on the user-provided ignore list + ignore_list = _.map(param_ignore_list, function(item) { return item.toLowerCase().trim() }) + + if (!reject_policy && (_.contains(ignore_list, policy['name'].toLowerCase()) || _.contains(ignore_list, policy['id'].toLowerCase()))) { + reject_policy = true + } + + // Exclude policies that were not applied from the catalog + if (!reject_policy && policy['published_template'] == null) { + reject_policy = true + } else if (!reject_policy) { + // Exclude policies where we did not find a corresponding entry in the active policy list + if (catalog_object[policy['published_template']['name']] == undefined) { + reject_policy = true + } + + // Exclude policies applied from a catalog other than the Flexera one + if (!reject_policy && policy['published_template']['updated_by']['email'] != 'support@flexera.com') { + reject_policy = true + } + } + + // Exclude all policies if the user opted not to report on outdated policies + if (!reject_policy && param_report_filter == "Report Deprecated Only") { + reject_policy = true + } + + return reject_policy + }) + + combined_data = _.map(filtered_policies, function(policy) { + catalog_policy = catalog_object[policy['published_template']['name']] + policy_url = "https://" + tld + "/orgs/" + rs_org_id + "/automation/applied-policies/projects/" + rs_project_id + "?policyId=" + policy['id'] + + rec_verb = "Update" + + if (policy['version'].split('.')[0] != catalog_policy['version'].split('.')[0]) { + rec_verb = "Manually update" + } + + recommendationDetails = [ + rec_verb, " applied policy ", policy['name'], " (", policy['id'], ") ", + "from version ", policy['version'], " to version ", catalog_policy['version'] + ].join('') + + href = null + + if (policy['scope'] == 'org' && typeof(aggregate_object[policy['name']]) == 'string') { + href = aggregate_object[policy['name']] + } + + if (policy['scope'] != 'org') { + href = policy['href'] + } + + update_body = { + credentials: policy['credentials'], + description: policy['description'], + dry_run: policy['dry_run'], + frequency: policy['frequency'], + log_level: policy['log_level'], + name: policy['name'], + options: policy['options'], + severity: policy['severity'], + skip_approvals: policy['skip_approvals'], + template_href: policy['published_template']['href'] + } + + catalog_recommendation_type = "" + + if (typeof(catalog_policy['recommendation_type']) == 'string') { + catalog_recommendation_type = catalog_policy['recommendation_type'] + } + + boolean_table = { "true": "True", "false": "False" } + + catalog_url = "https://github.com/flexera-public/policy_templates/tree/master/" + catalog_policy['readme'] + + return { + id: policy['id'], + name: policy['name'] + "||" + policy_url, + name_without_link: policy['name'], + description: policy['description'], + category: policy['category'], + created_at: policy['created_at'], + created_by: policy['created_by'], + frequency: policy['frequency'], + version: policy['version'], + credentials: policy['credentials'], + options: policy['options'], + severity: policy['severity'], + skip_approvals: policy['skip_approvals'], + scope: policy['scope'], + dry_run: policy['dry_run'], + log_level: policy['log_level'], + catalog_id: policy['published_template']['id'], + catalog_href: policy['published_template']['href'], + catalog_name: catalog_policy['name'] + "||" + catalog_url, + catalog_file_name: catalog_policy['file_name'], + catalog_version: catalog_policy['version'], + catalog_change_log: catalog_policy['change_log'], + catalog_description: catalog_policy['description'], + catalog_category: catalog_policy['category'], + catalog_severity: catalog_policy['severity'], + catalog_readme: catalog_policy['readme'], + catalog_provider: catalog_policy['provider'], + catalog_service: catalog_policy['service'], + catalog_policy_set: catalog_policy['policy_set'], + catalog_recommendation_type: catalog_recommendation_type, + catalog_updated_at: catalog_policy['updated_at'], + catalog_generally_recommended: boolean_table[catalog_policy['generally_recommended'].toString()], + catalog_deprecated: boolean_table[catalog_policy['deprecated'].toString()], + self_policy_name: ds_self_policy['name'], + href: href, + update_body: update_body, + recommendationDetails: recommendationDetails, + message: '' + } + }) + + result = _.filter(combined_data, function(policy) { + return policy['version'] != policy['catalog_version'] && typeof(policy['catalog_version']) == 'string' && policy['href'] != null + }) + + if (result.length > 0) { + total_applied_policies = ds_applied_policies.length.toString() + total_outdated = result.length.toString() + outdated_percentage = (total_outdated / total_applied_policies * 100).toFixed(2).toString() + '%' + + pol_noun = "policies" + if (total_applied_policies == 1) { pol_noun = "policy" } + + pol_verb = "are outdated" + if (total_outdated == 1) { pol_verb = "is outdated" } + + pol_action = "recommended to be replaced with the latest version from the Catalog" + + message = [ + "Out of ", total_applied_policies, " ", pol_noun, " analyzed, ", + total_outdated, " (", outdated_percentage, + ") ", pol_verb, " and ", pol_action, ".\n\n" + ].join('') + + settings = "No policies were filtered from this report.\n\n" + + if (param_ignore_list.length > 0) { + settings = "The following policies were filtered from this report: " + param_ignore_list.join(', ') + "\n\n" + } + + disclaimer = "Filtering can be adjusted by editing the applied policy and changing the appropriate parameters." + + result[0]['message'] = message + settings + disclaimer + } +EOS +end + +datasource "ds_deprecated_policies" do + run_script $js_deprecated_policies, $ds_applied_policies, $ds_catalog_policies, $ds_policy_aggregates, $ds_self_policy, $param_ignore_list, $param_report_filter, rs_org_id, rs_project_id, policy_id, rs_optima_host +end + +script "js_deprecated_policies", type: "javascript" do + parameters "ds_applied_policies", "ds_catalog_policies", "ds_policy_aggregates", "ds_self_policy", "param_ignore_list", "param_report_filter", "rs_org_id", "rs_project_id", "policy_id", "rs_optima_host" + result "result" + code <<-'EOS' + tld_table = { + "api.optima.flexeraeng.com": "app.flexera.com", + "api.optima-eu.flexeraeng.com": "app.flexera.eu", + "api.optima-apac.flexeraeng.com": "app.flexera.au" + } + + tld = tld_table[rs_optima_host] + + aggregate_object = {} + + _.each(ds_policy_aggregates, function(agg) { + if (typeof(agg['running_project_ids']) == 'object') { + if (agg['running_project_ids'].length == 1 && agg['running_project_ids'][0] == rs_project_id) { + aggregate_object[agg['name']] = agg['href'] + } + } + }) + + catalog_object = {} + + _.each(ds_catalog_policies, function(policy) { + catalog_object[policy['name']] = policy + }) + + filtered_policies = _.reject(ds_applied_policies, function(policy) { + reject_policy = false + + // Exclude this policy to avoid the policy trying to terminate itself if the user actions on it + if (policy['id'] == policy_id) { + reject_policy = true + } + + // Exclude policies on the user-provided ignore list + ignore_list = _.map(param_ignore_list, function(item) { return item.toLowerCase().trim() }) + + if (!reject_policy && (_.contains(ignore_list, policy['name'].toLowerCase()) || _.contains(ignore_list, policy['id'].toLowerCase()))) { + reject_policy = true + } + + // Exclude policies that were not applied from the catalog + if (!reject_policy && policy['published_template'] == null) { + reject_policy = true + } else if (!reject_policy) { + // Exclude policies where we did not find a corresponding entry in the active policy list + if (catalog_object[policy['published_template']['name']] == undefined) { + reject_policy = true + } + + // Exclude policies applied from a catalog other than the Flexera one + if (!reject_policy && policy['published_template']['updated_by']['email'] != 'support@flexera.com') { + reject_policy = true + } + } + + // Exclude all policies if the user opted not to report on deprecated policies + if (!reject_policy && param_report_filter == "Report Outdated Only") { + reject_policy = true + } + + // Exclude non-deprecated policies + if (!reject_policy && !catalog_object[policy['published_template']['name']]['deprecated']) { + reject_policy = true + } + + return reject_policy + }) + + result = _.map(filtered_policies, function(policy) { + catalog_policy = catalog_object[policy['published_template']['name']] + policy_url = "https://" + tld + "/orgs/" + rs_org_id + "/automation/applied-policies/projects/" + rs_project_id + "?policyId=" + policy['id'] + + recommendationDetails = [ + "Terminate applied policy ", policy['name'], " (", policy['id'], ")" + ].join('') + + href = null + + if (policy['scope'] == 'org' && typeof(aggregate_object[policy['name']]) == 'string') { + href = aggregate_object[policy['name']] + } + + if (policy['scope'] != 'org') { + href = policy['href'] + } + + update_body = { + credentials: policy['credentials'], + description: policy['description'], + dry_run: policy['dry_run'], + frequency: policy['frequency'], + log_level: policy['log_level'], + name: policy['name'], + options: policy['options'], + severity: policy['severity'], + skip_approvals: policy['skip_approvals'], + template_href: policy['published_template']['href'] + } + + catalog_recommendation_type = "" + + if (typeof(catalog_policy['recommendation_type']) == 'string') { + catalog_recommendation_type = catalog_policy['recommendation_type'] + } + + boolean_table = { "true": "True", "false": "False" } + + catalog_url = "https://github.com/flexera-public/policy_templates/tree/master/" + catalog_policy['readme'] + + return { + id: policy['id'], + name: policy['name'] + "||" + policy_url, + name_without_link: policy['name'], + description: policy['description'], + category: policy['category'], + created_at: policy['created_at'], + created_by: policy['created_by'], + frequency: policy['frequency'], + version: policy['version'], + credentials: policy['credentials'], + options: policy['options'], + severity: policy['severity'], + skip_approvals: policy['skip_approvals'], + scope: policy['scope'], + dry_run: policy['dry_run'], + log_level: policy['log_level'], + catalog_id: policy['published_template']['id'], + catalog_href: policy['published_template']['href'], + catalog_name: catalog_policy['name'] + "||" + catalog_url, + catalog_file_name: catalog_policy['file_name'], + catalog_version: catalog_policy['version'], + catalog_change_log: catalog_policy['change_log'], + catalog_description: catalog_policy['description'], + catalog_category: catalog_policy['category'], + catalog_severity: catalog_policy['severity'], + catalog_readme: catalog_policy['readme'], + catalog_provider: catalog_policy['provider'], + catalog_service: catalog_policy['service'], + catalog_policy_set: catalog_policy['policy_set'], + catalog_recommendation_type: catalog_recommendation_type, + catalog_updated_at: catalog_policy['updated_at'], + catalog_generally_recommended: boolean_table[catalog_policy['generally_recommended'].toString()], + catalog_deprecated: boolean_table[catalog_policy['deprecated'].toString()], + self_policy_name: ds_self_policy['name'], + href: href, + update_body: update_body, + recommendationDetails: recommendationDetails, + message: '' + } + }) + + if (result.length > 0) { + total_applied_policies = ds_applied_policies.length.toString() + total_deprecated = result.length.toString() + deprecated_percentage = (total_deprecated / total_applied_policies * 100).toFixed(2).toString() + '%' + + pol_noun = "policies" + if (total_applied_policies == 1) { pol_noun = "policy" } + + pol_verb = "are deprecated" + if (total_deprecated == 1) { pol_verb = "is deprecated" } + + pol_action = [ + "recommended for termination. ", + "Please consult the policy template README for information on what policy template to use instead. ", + "The README can be accessed by clicking on the link in the 'Catalog Policy Name' field" + ].join('') + + message = [ + "Out of ", total_applied_policies, " ", pol_noun, " analyzed, ", + total_deprecated, " (", deprecated_percentage, + ") ", pol_verb, " and ", pol_action, ".\n\n" + ].join('') + + settings = "No policies were filtered from this report.\n\n" + + if (param_ignore_list.length > 0) { + settings = "The following policies were filtered from this report: " + param_ignore_list.join(', ') + "\n\n" + } + + disclaimer = "Filtering can be adjusted by editing the applied policy and changing the appropriate parameters." + + result[0]['message'] = message + settings + disclaimer + } +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_outdated_policies" do + validate_each $ds_outdated_policies do + summary_template "{{ with index data 0 }}{{ .self_policy_name }}{{ end }}: {{ len data }} Outdated Policies Found" + detail_template "{{ with index data 0 }}{{ .message }}{{ end }}" + check eq(val(item, "id"), "") + escalate $esc_email + escalate $esc_update_policies + export do + resource_level true + field "name" do + label "Applied Policy Name" + format "link-external" + end + field "recommendationDetails" do + label "Recommendation" + end + field "created_at" do + label "Date Applied" + end + field "catalog_updated_at" do + label "Date Catalog Updated" + end + field "catalog_deprecated" do + label "Deprecated" + end + field "version" do + label "Applied Policy Version" + end + field "catalog_version" do + label "Catalog Policy Version" + end + field "catalog_id" do + label "Catalog Policy ID" + end + field "catalog_name" do + label "Catalog Policy Name" + format "link-external" + end + field "catalog_href" do + label "Catalog Policy HREF" + end + field "id" do + label "Applied Policy ID" + end + field "href" do + label "Applied Policy HREF" + end + field "description" do + label "Applied Policy Description" + end + field "frequency" do + label "Applied Policy Frequency" + end + field "severity" do + label "Applied Policy Severity" + end + field "skip_approvals" do + label "Applied Policy Skip Approvals" + end + field "scope" do + label "Applied Policy Scope" + end + field "dry_run" do + label "Applied Policy Dry Run" + end + field "log_level" do + label "Applied Policy Log Level" + end + field "name_without_link" do + label "Applied Policy Name (Unlinked)" + end + field "update_body" do + label "Applied Policy Details" + end + end + end + validate_each $ds_deprecated_policies do + summary_template "{{ with index data 0 }}{{ .self_policy_name }}{{ end }}: {{ len data }} Deprecated Policies Found" + detail_template "{{ with index data 0 }}{{ .message }}{{ end }}" + check eq(val(item, "id"), "") + escalate $esc_email + export do + resource_level true + field "name" do + label "Applied Policy Name" + format "link-external" + end + field "recommendationDetails" do + label "Recommendation" + end + field "created_at" do + label "Date Applied" + end + field "catalog_updated_at" do + label "Date Catalog Updated" + end + field "catalog_deprecated" do + label "Deprecated" + end + field "version" do + label "Applied Policy Version" + end + field "catalog_version" do + label "Catalog Policy Version" + end + field "catalog_id" do + label "Catalog Policy ID" + end + field "catalog_name" do + label "Catalog Policy Name" + format "link-external" + end + field "catalog_href" do + label "Catalog Policy HREF" + end + field "id" do + label "Applied Policy ID" + end + field "href" do + label "Applied Policy HREF" + end + field "description" do + label "Applied Policy Description" + end + field "frequency" do + label "Applied Policy Frequency" + end + field "severity" do + label "Applied Policy Severity" + end + field "skip_approvals" do + label "Applied Policy Skip Approvals" + end + field "scope" do + label "Applied Policy Scope" + end + field "dry_run" do + label "Applied Policy Dry Run" + end + field "log_level" do + label "Applied Policy Log Level" + end + field "name_without_link" do + label "Applied Policy Name (Unlinked)" + end + field "update_body" do + label "Applied Policy Details" + end + end + end +end + +############################################################################### +# Escalations +############################################################################### + +escalation "esc_email" do + automatic true + label "Send Email" + description "Send incident email" + email $param_email +end + +escalation "esc_update_policies" do + automatic contains($param_automatic_action, "Update Applied Policies") + label "Update Applied Policies" + description "Approval to update all selected applied policies to the latest version" + run "update_policies", data, $param_allow_major, rs_governance_host, rs_project_id +end + +############################################################################### +# Cloud Workflow +############################################################################### + +define update_policies($data, $param_allow_major, $rs_governance_host, $rs_project_id) return $all_responses do + $$all_responses = [] + + foreach $policy in $data do + sub on_error: handle_error() do + + if split($policy['version'], '.')[0] == split($policy['catalog_version'], '.')[0] || $param_allow_major == "Allow" + call apply_policy($policy, $rs_governance_host, $rs_project_id) retrieve $apply_response, $code + + if $code == 204 || $code == 202 || $code == 200 + call delete_policy($policy, $rs_governance_host) retrieve $delete_response + end + else + $policy_name = $policy["name_without_link"] + " (" + $policy["id"] + ")" + raise "Applied Policy " + $policy_name + " was not updated due to a major version change. Please update manually." + end + end + end + + if inspect($$errors) != "null" + raise join($$errors, "\n") + end +end + +define apply_policy($policy, $rs_governance_host, $rs_project_id) return $response, $code do + $host = $rs_governance_host + $href = "/api/governance/projects/" + $rs_project_id + "/applied_policies" + $url = $host + $href + task_label("POST " + $url) + + $response = http_request( + auth: $$auth_flexera, + host: $host, + href: $href, + https: true, + verb: "post", + headers: { "Api-Version": "1.0" }, + body: $policy["update_body"] + ) + + $code = $response["code"] + $policy_name = $policy["catalog_name"] + " (" + $policy["catalog_id"] + ")" + + task_label("Apply Catalog Policy response: " + $policy_name + " " + to_json($response)) + $$all_responses << to_json({"req": "POST " + $url, "resp": $response}) + + if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 + raise "Unexpected response applying Catalog Policy: " + $policy_name + " " + to_json($response) + else + task_label("Apply Catalog Policy successful: " + $policy_name) + end +end + +define delete_policy($policy, $rs_governance_host) return $response do + $host = $rs_governance_host + $href = $policy['href'] + $url = $host + $href + task_label("DELETE " + $url) + + $response = http_request( + auth: $$auth_flexera, + host: $host, + href: $href, + https: true, + verb: "delete", + headers: { "Api-Version": "1.0" } + ) + + $policy_name = $policy["name_without_link"] + " (" + $policy["id"] + ")" + + task_label("Delete Applied Policy response: " + $policy_name + " " + to_json($response)) + $$all_responses << to_json({"req": "POST " + $url, "resp": $response}) + + if $response["code"] != 204 && $response["code"] != 202 && $response["code"] != 200 + raise "Unexpected response deleting Applied Policy: " + $policy_name + " " + to_json($response) + else + task_label("Delete Applied Policy successful: " + $policy_name) + end +end + +define handle_error() do + if !$$errors + $$errors = [] + end + $$errors << $_error["type"] + ": " + $_error["message"] + # We check for errors at the end, and raise them all together + # Skip errors handled by this definition + $_error_behavior = "skip" +end diff --git a/automation/google/google_rbd_from_label/CHANGELOG.md b/automation/google/google_rbd_from_label/CHANGELOG.md new file mode 100644 index 0000000000..26beb076b9 --- /dev/null +++ b/automation/google/google_rbd_from_label/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +## v1.3.1 + +- Fixed issue that would sometimes cause execution to fail if a Google Project had no label keys + +## v1.3.0 + +- Added option to retain original casing of tag values instead of normalizing them all to lowercase + +## v1.2.1 + +- Updated policy template to use newer API endpoints. Functionality is unchanged. + +## v1.2 + +- fixed link to README in policy description + +## v1.1 + +- added ability to specify names for the newly created dimensions +- fixed issue where labels were incorrectly referred to as tags in parameter name + +## v1.0 + +- initial release diff --git a/automation/google/google_rbd_from_label/README.md b/automation/google/google_rbd_from_label/README.md new file mode 100644 index 0000000000..16ec257e2c --- /dev/null +++ b/automation/google/google_rbd_from_label/README.md @@ -0,0 +1,40 @@ +# Google Rule-Based Dimension From Project Labels + +## What It Does + +This policy creates and updates custom Rule-Based Dimensions that surface the specified Google Project label keys in the Flexera One platform. This allows costs to be sliced by the values of the label keys in question. + +## Input Parameters + +This policy has the following input parameters required when launching the policy. + +- *Effective Date* - The month and year in YYYY-MM format that you want the rules to apply. This should be left at its default value in most cases to ensure that the rules apply to all costs, including historical costs. +- *Label Keys* - A list of Google Project label keys to create custom Rule-Based Dimensions for. +- *Dimension Names* - A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the label keys in the `Label Keys` field. Dimension names will be derived from label keys directly if this list is left empty. +- *Lowercase Values* - Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail. + +## Policy Actions + +- Create/update rule-based dimensions + +## Prerequisites + +This Policy Template uses [Credentials](https://docs.flexera.com/flexera/EN/Automation/ManagingCredentialsExternal.htm) for authenticating to datasources -- in order to apply this policy you must have a Credential registered in the system that is compatible with this policy. If there are no Credentials listed when you apply the policy, please contact your Flexera Org Admin and ask them to register a Credential that is compatible with this policy. The information below should be consulted when creating the credential(s). + +- [**Google Cloud Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm#automationadmin_4083446696_1121577) (*provider=gce*) which has the following: + - `resourcemanager.projects.get` + +- [**Flexera Credential**](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) (*provider=flexera*) which has the following roles: + - `observer` + - `billing_center_viewer` + - `rule_based_dimensions_manager` + +The [Provider-Specific Credentials](https://docs.flexera.com/flexera/EN/Automation/ProviderCredentials.htm) page in the docs has detailed instructions for setting up Credentials for the most common providers. + +## Supported Clouds + +- Google + +## Cost + +This Policy Template does not launch any instances, and so does not incur any cloud costs. diff --git a/automation/google/google_rbd_from_label/google_rbd_from_label.pt b/automation/google/google_rbd_from_label/google_rbd_from_label.pt new file mode 100644 index 0000000000..93be95a9b0 --- /dev/null +++ b/automation/google/google_rbd_from_label/google_rbd_from_label.pt @@ -0,0 +1,305 @@ +name "Google Rule-Based Dimension From Project Labels" +rs_pt_ver 20180301 +type "policy" +short_description "Creates and/or updates individual Rule-Based Dimensions based on Google Project labels. See the [README](https://github.com/flexera-public/policy_templates/tree/master/automation/google/google_rbd_from_label) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more." +long_description "" +severity "low" +category "Cost" +default_frequency "daily" +info( + version: "1.3.1", + provider: "Flexera", + service: "Optima", + policy_set: "Automation", + publish: "false" +) + +############################################################################### +# Parameters +############################################################################### + +parameter "param_tag_list" do + type "list" + category "Policy Settings" + label "Label Keys" + description "A list of Google account label keys to build Rule-Based Dimensions from" + # No default value, user input required +end + +parameter "param_name_list" do + type "list" + category "Policy Settings" + label "Dimension Names" + description "A list of names to give the Rule-Based Dimensions in the Flexera platform. Enter names in the same order as the label keys in the 'Label Keys' field. Dimension names will be derived from label keys directly if this list is left empty." + default [] +end + +parameter "param_effective_date" do + type "string" + category "Policy Settings" + label "Effective Date" + description "Year/month you want rules to start applying in YYYY-MM format" + default "2010-01" +end + +parameter "param_normalize_case" do + type "string" + category "Policy Settings" + label "Lowercase Values" + description "Whether or not to normalize all values by converting them to lowercase. Note that, if the same value appears multiple times with different casing, and this option is disabled, the rule-based dimension will be rejected and this policy template will fail." + allowed_values "Yes", "No" + default "Yes" +end + +############################################################################### +# Authentication +############################################################################### + +credentials "auth_google" do + schemes "oauth2" + label "Google" + description "Select the Google Cloud Credential from the list." + tags "provider=gce" +end + +credentials "auth_flexera" do + schemes "oauth2" + label "flexera" + description "Select FlexeraOne OAuth2 credential." + tags "provider=flexera" +end + +############################################################################### +# Pagination +############################################################################### + +pagination "pagination_google" do + get_page_marker do + body_path "nextPageToken" + end + set_page_marker do + query "pageToken" + end +end + +############################################################################### +# Datasources & Scripts +############################################################################### + +# Get region-specific Flexera API endpoints +datasource "ds_flexera_api_hosts" do + run_script $js_flexera_api_hosts, rs_optima_host +end + +script "js_flexera_api_hosts", type: "javascript" do + parameters "rs_optima_host" + result "result" + code <<-EOS + host_table = { + "api.optima.flexeraeng.com": { + flexera: "api.flexera.com", + fsm: "api.fsm.flexeraeng.com" + }, + "api.optima-eu.flexeraeng.com": { + flexera: "api.flexera.eu", + fsm: "api.fsm-eu.flexeraeng.com" + }, + "api.optima-apac.flexeraeng.com": { + flexera: "api.flexera.au", + fsm: "api.fsm-apac.flexeraeng.com" + } + } + + result = host_table[rs_optima_host] +EOS +end + +datasource "ds_existing_rbds" do + request do + auth $auth_flexera + host rs_optima_host + path join(["/bill-analysis/orgs/", rs_org_id, "/settings/rule_based_dimensions"]) + header "Api-Version", "1.0" + header "content-type", "application/json" + end + result do + encoding "json" + collect jmes_path(response, "rule_based_dimensions") do + field "id", jmes_path(col_item, "id") + field "name", jmes_path(col_item, "name") + field "dated_rules", jmes_path(col_item, "dated_rules") + end + end +end + +datasource "ds_google_projects" do + request do + auth $auth_google + pagination $pagination_google + host "cloudresourcemanager.googleapis.com" + path "/v1/projects/" + query "filter", "lifecycleState=ACTIVE" + end + result do + encoding "json" + collect jmes_path(response, "projects[*]") do + field "id", jmes_path(col_item, "projectId") + field "number", jmes_path(col_item, "projectNumber") + field "name", jmes_path(col_item, "name") + field "parent", jmes_path(col_item, "parent") + field "createTime", jmes_path(col_item, "createTime") + field "lifecycleState", jmes_path(col_item, "lifecycleState") + field "tags", jmes_path(col_item, "labels") + end + end +end + +datasource "ds_google_projects_normalized" do + run_script $js_google_projects_normalized, $ds_google_projects +end + +script "js_google_projects_normalized", type: "javascript" do + parameters "accounts" + result "result" + code <<-'EOS' + result = [] + + _.each(accounts, function(account) { + tags = {} + + if (account['tags'] != null && account['tags'] != undefined) { + _.each(Object.keys(account['tags']), function(key) { + normalized_key = key.toLowerCase().trim() + tags[normalized_key] = account['tags'][key] + }) + } + + result.push({ + id: account['id'], + number: account['number'], + name: account['name'], + parent: account['parent'], + createTime: account['createTime'], + lifecycleState: account['lifecycleState'], + tags: tags + }) + }) +EOS +end + +datasource "ds_rbds" do + run_script $js_rbds, $ds_google_projects_normalized, $ds_existing_rbds, $param_name_list, $param_tag_list, $param_effective_date, $param_normalize_case +end + +script "js_rbds", type: "javascript" do + parameters "accounts", "existing_rbds", "param_name_list", "param_tag_list", "param_effective_date", "param_normalize_case" + result "result" + code <<-'EOS' + result = [] + + rbd_id_list = _.pluck(existing_rbds, 'id') + + _.each(param_tag_list, function(tag, index) { + rbd_name = tag.replace('.', ' ').replace('-', ' ') + rbd_name = rbd_name.replace(/\W/g, " ").trim() + + // Use user-specified name instead of user provided one + if (param_tag_list.length == param_name_list.length) { rbd_name = param_name_list[index] } + + rbd_id = "rbd_" + rbd_name.toLowerCase().replace(/\s+/g, '').replace(/\W/g, "").replace('.', '').replace('-', '').trim() + + tag_key = tag.toLowerCase().trim() + verb = "POST" + if (_.contains(rbd_id_list, rbd_id)) { verb = "PATCH" } + + rules = [] + + _.each(accounts, function(account) { + if (typeof(account['tags']) == 'object') { + if (typeof(account['tags'][tag_key]) == 'string') { + if (account['tags'][tag_key].trim() != '') { + value = account['tags'][tag_key].trim() + if (param_normalize_case == "Yes") { value = value.toLowerCase() } + + rules.push({ + condition: { type: "dimension_equals", dimension: "vendor_account", value: account['id'] }, + value: { text: value } + }) + } + } + } + }) + + if (rules.length > 0) { + result.push({ + id: rbd_id, + name: rbd_name, + verb: verb, + effective_at: param_effective_date, + rules: rules + }) + } + }) +EOS +end + +datasource "ds_create_rbds" do + iterate $ds_rbds + request do + run_script $js_create_rbds, val(iter_item, "id"), val(iter_item, "verb"), val(iter_item, "name"), val($ds_flexera_api_hosts, "flexera"), rs_org_id + end + result do + encoding "text" + end +end + +script "js_create_rbds", type: "javascript" do + parameters "rbd_id", "verb", "name", "api_host", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: verb, + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id].join(''), + body_fields: { name: name } + } +EOS +end + +datasource "ds_apply_rbds" do + iterate $ds_rbds + request do + # ds_create_rbds is a parameter to ensure that it executes before ds_apply_rbds does + run_script $js_apply_rbds, val(iter_item, "id"), val(iter_item, "effective_at"), val(iter_item, "rules"), val($ds_flexera_api_hosts, "flexera"), $ds_create_rbds, rs_org_id + end + result do + encoding "text" + end +end + +script "js_apply_rbds", type: "javascript" do + parameters "rbd_id", "effective_at", "rules", "api_host", "ds_create_rbds", "rs_org_id" + result "request" + code <<-EOS + var request = { + auth: "auth_flexera", + verb: "PUT", + host: api_host, + path: ["/finops-customizations/v1/orgs/", rs_org_id, "/rule-based-dimensions/", rbd_id, "/rules/", effective_at].join(''), + body_fields: { rules: rules } + } +EOS +end + +############################################################################### +# Policy +############################################################################### + +policy "pol_rbds" do + validate $ds_apply_rbds do + summary_template "RBDs Generated & Applied" + detail_template "" + check eq(0, 0) + end +end From 611278be28ec6efccd5ca16da47948811e8eacab Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 06:29:51 -0600 Subject: [PATCH 10/23] update --- .../aws_cft_generator.template.txt | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 tools/cloudformation-template/aws_cft_generator.template.txt diff --git a/tools/cloudformation-template/aws_cft_generator.template.txt b/tools/cloudformation-template/aws_cft_generator.template.txt new file mode 100644 index 0000000000..4fd2c4dd67 --- /dev/null +++ b/tools/cloudformation-template/aws_cft_generator.template.txt @@ -0,0 +1,158 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" +# Generated by Flexera automation on __PLACEHOLDER_FOR_GENERATION_DATETIME__ +# For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md + +Metadata: + # AWS::CloudFormation::Interface is a metadata key that defines how parameters are grouped and sorted in the AWS CloudFormation console. + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html + AWS::CloudFormation::Interface: + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-parametergroup.html + ParameterGroups: + # ParameterGroup with paramFlexeraOrgId should be first. + # paramFlexeraOrgId only param that is actually required (if Org is on app.flexera.com) + - Label: + default: "Parameters related to your Organization on the Flexera Platform" + Parameters: + - paramFlexeraOrgId + - paramFlexeraZone + - Label: + default: "Parameters related to the IAM Role that is created" + Parameters: + - paramRoleName + - paramRolePath + - Label: + default: "Parameters related to Policy Template permissions on the IAM Role that is created" + Parameters: +__PLACEHOLDER_FOR_PARAMETER_GROUPS__ + # End for each policy template + - paramPermsAttachExistingPolicies + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-parameterlabel.html + ParameterLabels: + paramRoleName: + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-label.html + # The default label that the CloudFormation console uses to name a parameter group or parameter. + default: "IAM Role Name" + paramRolePath: + default: "IAM Role Path" + paramFlexeraOrgId: + default: "Flexera Organization ID" + paramFlexeraZone: + default: "Flexera Zone" +__PLACEHOLDER_FOR_PARAMETER_LABELS__ + # End for each policy template + paramPermsAttachExistingPolicies: + default: "Additional IAM Permission Policies for IAM Role" + +Parameters: + # ParameterGroup: Parameters related to your Organization on the Flexera Platform + paramFlexeraOrgId: + Description: >- + The Organization ID in Flexera which trust will be granted to use the IAM Role that will be created + Type: String + AllowedPattern: "[0-9]+" + MinLength: 1 + ConstraintDescription: Organization ID must be provided and match regex [0-9]+ + paramFlexeraZone: + Description: >- + The Flexera Zone which trust will be granted to. The Organization ID should be located in this Flexera Zone. + Type: String + Default: app.flexera.com + AllowedValues: + - app.flexera.com + - app.flexera.eu + - app.flexera.au + - app.flexeratest.com + + # ParameterGroup: Parameters for the IAM Role that is created + paramRoleName: + Description: Name of the the IAM Role that will be created. If you plan to create more than one IAM Role (i.e. one for each Policy Template, or to trust multiple Orgs) you will need to modify this to prevent naming conflict. + Type: String + Default: FlexeraAutomationAccessRole + # IAM Role Name Max Length is 64chars + MaxLength: 64 + paramRolePath: + Description: Path for the IAM Role that will be created. Generally does not need to be modified. + Type: String + Default: / + + # ParameterGroup: Parameters to define Policy Template permissions on the IAM Role that is created +__PLACEHOLDER_FOR_PARAMETER_GROUP_DEFINITIONS__ + # End for each policy template + paramPermsAttachExistingPolicies: + Description: 'Existing IAM Permission Policies to attach to the IAM Role that will be created. Optional, comma separated list of IAM Policy ARNs -- i.e. arn:aws:iam::aws:policy/ReadOnlyAccess' + Type: String + # AWS Managed Policy ARN: arn:aws:iam::aws:policy/ReadOnlyAccess + # Customer Managed Policy ARN: arn:aws:iam::123456789012:policy/CustomPolicy + AllowedPattern: '^((arn:aws:iam::(\d{12}|aws)?:policy\/[\w+=,.@-]{1,128})(,)?)*$' + ConstraintDescription: 'Malformed IAM Policy ARN. Must match pattern ^((arn:aws:iam::(\d{12}|aws)?:policy\/[\w+=,.@-]{1,128})(,)?)*$' + +Conditions: +__PLACEHOLDER_FOR_CONDITIONS__ + # End for each policy template + ValueProvidedparamPermsAttachExistingPolicies: !Not + - !Equals + - !Ref paramPermsAttachExistingPolicies + - "" + +Mappings: + TrustedRoleMap: + app.flexera.com: + roleArn: "arn:aws:iam::451234325714:role/production_customer_access" + app.flexera.eu: + roleArn: "arn:aws:iam::451234325714:role/production_eu_customer_access" + app.flexera.au: + roleArn: "arn:aws:iam::451234325714:role/production_apac_customer_access" + app.flexeratest.com: + roleArn: "arn:aws:iam::274571843445:role/staging_customer_access" + PermissionMap: + # Begin IAM Permissions Map + # Expect 2 lists for each Policy Template (read and action) +__PLACEHOLDER_FOR_MAPPINGS__ + # End for each policy template + +Resources: + # IAM Role Resource + iamRole: + Type: "AWS::IAM::Role" + Properties: + RoleName: !Ref paramRoleName + Description: !Join + - " " + - - "Allows access from Flexera Platform. This IAM Role and the attached permission policies were created and are managed by CloudFormation Stack:" + - !Ref AWS::StackId + Path: !Ref paramRolePath + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: !FindInMap + - TrustedRoleMap + - !Ref paramFlexeraZone + - roleArn + Action: "sts:AssumeRole" + Condition: + StringEquals: + "sts:ExternalId": !Ref paramFlexeraOrgId + # ManagedPolicyArns value is conditional based on input paramPermsAttachExistingPolicies + ManagedPolicyArns: !If + - ValueProvidedparamPermsAttachExistingPolicies + # If value is provided for paramPermsAttachExistingPolicies, split that comma-separated list into a list object + - !Split [ ",", !Ref paramPermsAttachExistingPolicies ] + # Provide a null value if nothing provided for paramPermsAttachExistingPolicies + - !Ref AWS::NoValue + # Begin IAM Permission Policy Resources + # 1 or 2 Permission Policies per Policy Template (read and action) + # Policy create/attachment is conditional based on parameter input for each policy +__PLACEHOLDER_FOR_RESOURCES__ + # End for each policy template + + # End IAM Permission Policy Resources + +Outputs: + iamRoleArn: + Description: The ARN of the IAM Role that was created + Value: !GetAtt + - iamRole + - Arn From 9f7e1c956faeace126a960b8a9a701456a6c335e Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 06:41:30 -0600 Subject: [PATCH 11/23] update --- .../generate-aws-cloudformation-template.yaml | 8 +-- .../update-aws-cloudformation-template.yaml | 51 +++++++++++++++++++ .../aws_cft_updater.rb | 0 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/update-aws-cloudformation-template.yaml create mode 100644 tools/cloudformation-template/aws_cft_updater.rb diff --git a/.github/workflows/generate-aws-cloudformation-template.yaml b/.github/workflows/generate-aws-cloudformation-template.yaml index 485766ccd7..614a16826b 100644 --- a/.github/workflows/generate-aws-cloudformation-template.yaml +++ b/.github/workflows/generate-aws-cloudformation-template.yaml @@ -31,10 +31,10 @@ jobs: id: cpr uses: peter-evans/create-pull-request@v4 with: - commit-message: "Update AWS CloudFormation Template" - title: "Update AWS CloudFormation Template" - body: "Update AWS CloudFormation Template from GitHub Actions Workflow [${{ github.workflow }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" - branch: "task/update-aws-cloudformation-template" + commit-message: "Generate AWS CloudFormation Template" + title: "Generate AWS CloudFormation Template" + body: "Generate AWS CloudFormation Template from GitHub Actions Workflow [${{ github.workflow }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" + branch: "task/generate-aws-cloudformation-template" delete-branch: true labels: "automation" diff --git a/.github/workflows/update-aws-cloudformation-template.yaml b/.github/workflows/update-aws-cloudformation-template.yaml new file mode 100644 index 0000000000..41078f1ec2 --- /dev/null +++ b/.github/workflows/update-aws-cloudformation-template.yaml @@ -0,0 +1,51 @@ +name: Update Meta Parent Policy Templates + +on: + schedule: + # ┌───────────── minute (0 - 59) + # │ ┌───────────── hour (0 - 23) + # │ │ ┌───────────── day of the month (1 - 31) + # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) + # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) + # │ │ │ │ │ + # │ │ │ │ │ + # │ │ │ │ │ + # * * * * * + # At 01:00 UTC on Sundays + - cron: "0 0 1 * *" + + # Workflow dispatch trigger allows manually running workflow + workflow_dispatch: {} + +jobs: + meta-parent-policy-templates: + name: "Update AWS CloudFormation Template" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Speed up checkout by not fetching history + + - uses: ruby/setup-ruby@v1 + + - name: Update AWS CloudFormation Template + working-directory: tools/cloudformation-template + run: | + ruby aws_cft_updater.rb + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v4 + with: + commit-message: "Update AWS CloudFormation Template" + title: "Update AWS CloudFormation Template" + body: "Update AWS CloudFormation Template from GitHub Actions Workflow [${{ github.workflow }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" + branch: "task/update-aws-cloudformation-template" + delete-branch: true + labels: "automation" + + - name: Check outputs + if: ${{ steps.cpr.outputs.pull-request-number }} + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" diff --git a/tools/cloudformation-template/aws_cft_updater.rb b/tools/cloudformation-template/aws_cft_updater.rb new file mode 100644 index 0000000000..e69de29bb2 From db5d045c2242a09834ee9fe2496c2840b8505e38 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 07:50:44 -0600 Subject: [PATCH 12/23] update --- .../FlexeraAutomationPolicies.template | 4574 ++++++++++++++-- .../aws_cft_updater.rb | 39 + .../FlexeraAutomationPolicies_v0.9.0.template | 4830 +++++++++++++++++ 3 files changed, 9016 insertions(+), 427 deletions(-) create mode 100644 tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template diff --git a/tools/cloudformation-template/FlexeraAutomationPolicies.template b/tools/cloudformation-template/FlexeraAutomationPolicies.template index b4b02d7866..2f4b8b5b50 100644 --- a/tools/cloudformation-template/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/FlexeraAutomationPolicies.template @@ -1,5 +1,7 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" +# Generated by Flexera automation on 2024-12-12T16:59:05Z +# For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: # AWS::CloudFormation::Interface is a metadata key that defines how parameters are grouped and sorted in the AWS CloudFormation console. @@ -22,23 +24,173 @@ Metadata: - Label: default: "Parameters related to Policy Template permissions on the IAM Role that is created" Parameters: - #### For each policy template append: - # - paramPerms - - paramPermsAWSUnusedVolumes - - paramPermsAWSRightsizeEBSVolumes - - paramPermsAWSRightsizeRDSInstances - - paramPermsAWSUnusedIPAddresses - - paramPermsAWSUnusedCLBs + ## All AWS Policy Templates + - paramPermsAllAWSPolicyTemplates + ## AWS Account Credentials + - paramPermsAWSAccountCredentials + ## AWS Accounts Missing Service Control Policies + - paramPermsAWSAccountsMissingServiceControlPolicies + ## AWS Burstable EC2 Instances + - paramPermsAWSBurstableEC2Instances + ## AWS CloudTrail Not Enabled In All Regions + - paramPermsAWSCloudTrailNotEnabledInAllRegions + ## AWS CloudTrail S3 Buckets Without Access Logging + - paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging + ## AWS CloudTrails Not Integrated With CloudWatch + - paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch + ## AWS CloudTrails With Read Logging Enabled + - paramPermsAWSCloudTrailsWithReadLoggingEnabled + ## AWS CloudTrails Without Encrypted Logs + - paramPermsAWSCloudTrailsWithoutEncryptedLogs + ## AWS CloudTrails Without Log File Validation Enabled + - paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled + ## AWS CloudTrails Without Object-level Events Logging Enabled + - paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + - paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled + ## AWS Disallowed Regions + - paramPermsAWSDisallowedRegions + ## AWS EC2 Compute Optimizer Recommendations + - paramPermsAWSEC2ComputeOptimizerRecommendations + ## AWS EC2 Instances Time Stopped Report + - paramPermsAWSEC2InstancesTimeStoppedReport + ## AWS EC2 Instances not running FlexNet Inventory Agent + - paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent + ## AWS EKS Clusters Without Spot Instances + - paramPermsAWSEKSClustersWithoutSpotInstances + ## AWS Elastic Load Balancers With Unencrypted Listeners + - paramPermsAWSElasticLoadBalancersWithUnencryptedListeners + ## AWS Expiring Savings Plans + - paramPermsAWSExpiringSavingsPlans + ## AWS IAM Account Missing Support Role + - paramPermsAWSIAMAccountMissingSupportRole + ## AWS IAM Attached Admin Policies + - paramPermsAWSIAMAttachedAdminPolicies + ## AWS IAM Expired SSL/TLS Certificates + - paramPermsAWSIAMExpiredSSLTLSCertificates + ## AWS IAM Insufficient Required Password Length + - paramPermsAWSIAMInsufficientRequiredPasswordLength + ## AWS IAM Password Policy Not Restricting Password Reuse + - paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse + ## AWS IAM Role Audit + - paramPermsAWSIAMRoleAudit + ## AWS IAM Root Account Access Keys + - paramPermsAWSIAMRootAccountAccessKeys + ## AWS IAM Root User Account Without Hardware MFA + - paramPermsAWSIAMRootUserAccountWithoutHardwareMFA + ## AWS IAM Root User Account Without MFA + - paramPermsAWSIAMRootUserAccountWithoutMFA + ## AWS IAM Root User Doing Everyday Tasks + - paramPermsAWSIAMRootUserDoingEverydayTasks + ## AWS IAM User Accounts Without MFA + - paramPermsAWSIAMUserAccountsWithoutMFA + ## AWS IAM Users With Directly-Attached Policies + - paramPermsAWSIAMUsersWithDirectlyAttachedPolicies + ## AWS IAM Users With Multiple Active Access Keys + - paramPermsAWSIAMUsersWithMultipleActiveAccessKeys + ## AWS IAM Users With Old Access Keys + - paramPermsAWSIAMUsersWithOldAccessKeys + ## AWS Idle NAT Gateways + - paramPermsAWSIdleNATGateways + ## AWS Internet-Accessible Elastic Load Balancers + - paramPermsAWSInternetAccessibleElasticLoadBalancers + ## AWS Lambda Functions With High Error Rate + - paramPermsAWSLambdaFunctionsWithHighErrorRate + ## AWS Lambda Functions Without Provisioned Concurrency + - paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency + ## AWS Long Running Instances + - paramPermsAWSLongRunningInstances + ## AWS Long Stopped EC2 Instances + - paramPermsAWSLongStoppedEC2Instances + ## AWS Missing Regions + - paramPermsAWSMissingRegions + ## AWS Old Snapshots - paramPermsAWSOldSnapshots + ## AWS Open S3 Buckets + - paramPermsAWSOpenS3Buckets + ## AWS Oversized S3 Buckets + - paramPermsAWSOversizedS3Buckets + ## AWS Publicly Accessible CloudTrail S3 Buckets + - paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets + ## AWS Publicly Accessible RDS Instances + - paramPermsAWSPubliclyAccessibleRDSInstances + ## AWS RDS Instances With Unapproved Backup Settings + - paramPermsAWSRDSInstancesWithUnapprovedBackupSettings + ## AWS Regions Without Access Analyzer Enabled + - paramPermsAWSRegionsWithoutAccessAnalyzerEnabled + ## AWS Regions Without Config Fully Enabled + - paramPermsAWSRegionsWithoutConfigFullyEnabled + ## AWS Regions Without Default EBS Encryption + - paramPermsAWSRegionsWithoutDefaultEBSEncryption + ## AWS Reserved Instances Coverage + - paramPermsAWSReservedInstancesCoverage + ## AWS Reserved Instances Recommendations + - paramPermsAWSReservedInstancesRecommendations + ## AWS Rightsize EBS Volumes + - paramPermsAWSRightsizeEBSVolumes + ## AWS Rightsize EC2 Instances - paramPermsAWSRightsizeEC2Instances - - paramPermsAWSSupersededEC2Instances - - paramPermsAWSReservedInstancesRecommendation - - paramPermsAWSObjectStorageOptimization - - paramPermsAWSExpiringSavingsPlans + ## AWS Rightsize ElastiCache + - paramPermsAWSRightsizeElastiCache + ## AWS Rightsize RDS Instances + - paramPermsAWSRightsizeRDSInstances + ## AWS Rightsize Redshift + - paramPermsAWSRightsizeRedshift + ## AWS S3 Buckets Accepting HTTP Requests + - paramPermsAWSS3BucketsAcceptingHTTPRequests + ## AWS S3 Buckets Without Default Encryption Configuration + - paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration + ## AWS S3 Buckets Without Intelligent Tiering + - paramPermsAWSS3BucketsWithoutIntelligentTiering + ## AWS S3 Buckets Without Lifecycle Configuration + - paramPermsAWSS3BucketsWithoutLifecycleConfiguration + ## AWS S3 Buckets Without MFA Delete Enabled + - paramPermsAWSS3BucketsWithoutMFADeleteEnabled + ## AWS S3 Buckets Without Public Access Blocked + - paramPermsAWSS3BucketsWithoutPublicAccessBlocked + ## AWS S3 Buckets Without Server Access Logging + - paramPermsAWSS3BucketsWithoutServerAccessLogging + ## AWS S3 Incomplete Multi-Part Uploads + - paramPermsAWSS3IncompleteMultiPartUploads + ## AWS Savings Plan Recommendations - paramPermsAWSSavingsPlanRecommendations + ## AWS Savings Plan Utilization - paramPermsAWSSavingsPlanUtilization + ## AWS Schedule Instance + - paramPermsAWSScheduleInstance + ## AWS Scheduled EC2 Events + - paramPermsAWSScheduledEC2Events + ## AWS Superseded EBS Volumes + - paramPermsAWSSupersededEBSVolumes + ## AWS Superseded EC2 Instances + - paramPermsAWSSupersededEC2Instances + ## AWS Superseded EC2 Instances + - paramPermsAWSSupersededEC2Instances + ## AWS Tag Cardinality Report - paramPermsAWSTagCardinalityReport + ## AWS Unencrypted EBS Volumes + - paramPermsAWSUnencryptedEBSVolumes + ## AWS Unencrypted RDS Instances + - paramPermsAWSUnencryptedRDSInstances + ## AWS Untagged Resources - paramPermsAWSUntaggedResources + ## AWS Unused Application Load Balancers + - paramPermsAWSUnusedApplicationLoadBalancers + ## AWS Unused Classic Load Balancers + - paramPermsAWSUnusedClassicLoadBalancers + ## AWS Unused ECS Clusters + - paramPermsAWSUnusedECSClusters + ## AWS Unused IAM Credentials + - paramPermsAWSUnusedIAMCredentials + ## AWS Unused IP Addresses + - paramPermsAWSUnusedIPAddresses + ## AWS Unused Network Load Balancers + - paramPermsAWSUnusedNetworkLoadBalancers + ## AWS VPCs Without FlowLogs Enabled + - paramPermsAWSVPCsWithoutFlowLogsEnabled + ## Common Bill Ingestion from AWS S3 Object Storage + - paramPermsCommonBillIngestionfromAWSS3ObjectStorage + # End for each policy template - paramPermsAttachExistingPolicies # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-parameterlabel.html @@ -53,39 +205,256 @@ Metadata: default: "Flexera Organization ID" paramFlexeraZone: default: "Flexera Zone" - #### For each policy template append: - # paramPerms: - # default: "Permissions for Policy Template: " - paramPermsAWSUnusedVolumes: - default: "Permissions for Policy Template: AWS Unused Volumes" - paramPermsAWSRightsizeEBSVolumes: - default: "Permissions for Policy Template: AWS Rightsize EBS Volumes" - paramPermsAWSRightsizeRDSInstances: - default: "Permissions for Policy Template: AWS Rightsize RDS Instances" - paramPermsAWSUnusedIPAddresses: - default: "Permissions for Policy Template: AWS Unused IP Addresses" - paramPermsAWSUnusedCLBs: - default: "Permissions for Policy Template: AWS Unused Classic Load Balancers" + ## All AWS Policy Templates + paramPermsAllAWSPolicyTemplates: + default: "Permissions for all AWS Policy Templates" + ## AWS Account Credentials + paramPermsAWSAccountCredentials: + default: "Permissions for Policy Template: AWS Account Credentials" + ## AWS Accounts Missing Service Control Policies + paramPermsAWSAccountsMissingServiceControlPolicies: + default: "Permissions for Policy Template: AWS Accounts Missing Service Control Policies" + ## AWS Burstable EC2 Instances + paramPermsAWSBurstableEC2Instances: + default: "Permissions for Policy Template: AWS Burstable EC2 Instances" + ## AWS CloudTrail Not Enabled In All Regions + paramPermsAWSCloudTrailNotEnabledInAllRegions: + default: "Permissions for Policy Template: AWS CloudTrail Not Enabled In All Regions" + ## AWS CloudTrail S3 Buckets Without Access Logging + paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging: + default: "Permissions for Policy Template: AWS CloudTrail S3 Buckets Without Access Logging" + ## AWS CloudTrails Not Integrated With CloudWatch + paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch: + default: "Permissions for Policy Template: AWS CloudTrails Not Integrated With CloudWatch" + ## AWS CloudTrails With Read Logging Enabled + paramPermsAWSCloudTrailsWithReadLoggingEnabled: + default: "Permissions for Policy Template: AWS CloudTrails With Read Logging Enabled" + ## AWS CloudTrails Without Encrypted Logs + paramPermsAWSCloudTrailsWithoutEncryptedLogs: + default: "Permissions for Policy Template: AWS CloudTrails Without Encrypted Logs" + ## AWS CloudTrails Without Log File Validation Enabled + paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled: + default: "Permissions for Policy Template: AWS CloudTrails Without Log File Validation Enabled" + ## AWS CloudTrails Without Object-level Events Logging Enabled + paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: + default: "Permissions for Policy Template: AWS CloudTrails Without Object-level Events Logging Enabled" + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled: + default: "Permissions for Policy Template: AWS Customer Managed Keys (CMKs) Without Rotation Enabled" + ## AWS Disallowed Regions + paramPermsAWSDisallowedRegions: + default: "Permissions for Policy Template: AWS Disallowed Regions" + ## AWS EC2 Compute Optimizer Recommendations + paramPermsAWSEC2ComputeOptimizerRecommendations: + default: "Permissions for Policy Template: AWS EC2 Compute Optimizer Recommendations" + ## AWS EC2 Instances Time Stopped Report + paramPermsAWSEC2InstancesTimeStoppedReport: + default: "Permissions for Policy Template: AWS EC2 Instances Time Stopped Report" + ## AWS EC2 Instances not running FlexNet Inventory Agent + paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent: + default: "Permissions for Policy Template: AWS EC2 Instances not running FlexNet Inventory Agent" + ## AWS EKS Clusters Without Spot Instances + paramPermsAWSEKSClustersWithoutSpotInstances: + default: "Permissions for Policy Template: AWS EKS Clusters Without Spot Instances" + ## AWS Elastic Load Balancers With Unencrypted Listeners + paramPermsAWSElasticLoadBalancersWithUnencryptedListeners: + default: "Permissions for Policy Template: AWS Elastic Load Balancers With Unencrypted Listeners" + ## AWS Expiring Savings Plans + paramPermsAWSExpiringSavingsPlans: + default: "Permissions for Policy Template: AWS Expiring Savings Plans" + ## AWS IAM Account Missing Support Role + paramPermsAWSIAMAccountMissingSupportRole: + default: "Permissions for Policy Template: AWS IAM Account Missing Support Role" + ## AWS IAM Attached Admin Policies + paramPermsAWSIAMAttachedAdminPolicies: + default: "Permissions for Policy Template: AWS IAM Attached Admin Policies" + ## AWS IAM Expired SSL/TLS Certificates + paramPermsAWSIAMExpiredSSLTLSCertificates: + default: "Permissions for Policy Template: AWS IAM Expired SSL/TLS Certificates" + ## AWS IAM Insufficient Required Password Length + paramPermsAWSIAMInsufficientRequiredPasswordLength: + default: "Permissions for Policy Template: AWS IAM Insufficient Required Password Length" + ## AWS IAM Password Policy Not Restricting Password Reuse + paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse: + default: "Permissions for Policy Template: AWS IAM Password Policy Not Restricting Password Reuse" + ## AWS IAM Role Audit + paramPermsAWSIAMRoleAudit: + default: "Permissions for Policy Template: AWS IAM Role Audit" + ## AWS IAM Root Account Access Keys + paramPermsAWSIAMRootAccountAccessKeys: + default: "Permissions for Policy Template: AWS IAM Root Account Access Keys" + ## AWS IAM Root User Account Without Hardware MFA + paramPermsAWSIAMRootUserAccountWithoutHardwareMFA: + default: "Permissions for Policy Template: AWS IAM Root User Account Without Hardware MFA" + ## AWS IAM Root User Account Without MFA + paramPermsAWSIAMRootUserAccountWithoutMFA: + default: "Permissions for Policy Template: AWS IAM Root User Account Without MFA" + ## AWS IAM Root User Doing Everyday Tasks + paramPermsAWSIAMRootUserDoingEverydayTasks: + default: "Permissions for Policy Template: AWS IAM Root User Doing Everyday Tasks" + ## AWS IAM User Accounts Without MFA + paramPermsAWSIAMUserAccountsWithoutMFA: + default: "Permissions for Policy Template: AWS IAM User Accounts Without MFA" + ## AWS IAM Users With Directly-Attached Policies + paramPermsAWSIAMUsersWithDirectlyAttachedPolicies: + default: "Permissions for Policy Template: AWS IAM Users With Directly-Attached Policies" + ## AWS IAM Users With Multiple Active Access Keys + paramPermsAWSIAMUsersWithMultipleActiveAccessKeys: + default: "Permissions for Policy Template: AWS IAM Users With Multiple Active Access Keys" + ## AWS IAM Users With Old Access Keys + paramPermsAWSIAMUsersWithOldAccessKeys: + default: "Permissions for Policy Template: AWS IAM Users With Old Access Keys" + ## AWS Idle NAT Gateways + paramPermsAWSIdleNATGateways: + default: "Permissions for Policy Template: AWS Idle NAT Gateways" + ## AWS Internet-Accessible Elastic Load Balancers + paramPermsAWSInternetAccessibleElasticLoadBalancers: + default: "Permissions for Policy Template: AWS Internet-Accessible Elastic Load Balancers" + ## AWS Lambda Functions With High Error Rate + paramPermsAWSLambdaFunctionsWithHighErrorRate: + default: "Permissions for Policy Template: AWS Lambda Functions With High Error Rate" + ## AWS Lambda Functions Without Provisioned Concurrency + paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency: + default: "Permissions for Policy Template: AWS Lambda Functions Without Provisioned Concurrency" + ## AWS Long Running Instances + paramPermsAWSLongRunningInstances: + default: "Permissions for Policy Template: AWS Long Running Instances" + ## AWS Long Stopped EC2 Instances + paramPermsAWSLongStoppedEC2Instances: + default: "Permissions for Policy Template: AWS Long Stopped EC2 Instances" + ## AWS Missing Regions + paramPermsAWSMissingRegions: + default: "Permissions for Policy Template: AWS Missing Regions" + ## AWS Old Snapshots paramPermsAWSOldSnapshots: default: "Permissions for Policy Template: AWS Old Snapshots" + ## AWS Open S3 Buckets + paramPermsAWSOpenS3Buckets: + default: "Permissions for Policy Template: AWS Open S3 Buckets" + ## AWS Oversized S3 Buckets + paramPermsAWSOversizedS3Buckets: + default: "Permissions for Policy Template: AWS Oversized S3 Buckets" + ## AWS Publicly Accessible CloudTrail S3 Buckets + paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets: + default: "Permissions for Policy Template: AWS Publicly Accessible CloudTrail S3 Buckets" + ## AWS Publicly Accessible RDS Instances + paramPermsAWSPubliclyAccessibleRDSInstances: + default: "Permissions for Policy Template: AWS Publicly Accessible RDS Instances" + ## AWS RDS Instances With Unapproved Backup Settings + paramPermsAWSRDSInstancesWithUnapprovedBackupSettings: + default: "Permissions for Policy Template: AWS RDS Instances With Unapproved Backup Settings" + ## AWS Regions Without Access Analyzer Enabled + paramPermsAWSRegionsWithoutAccessAnalyzerEnabled: + default: "Permissions for Policy Template: AWS Regions Without Access Analyzer Enabled" + ## AWS Regions Without Config Fully Enabled + paramPermsAWSRegionsWithoutConfigFullyEnabled: + default: "Permissions for Policy Template: AWS Regions Without Config Fully Enabled" + ## AWS Regions Without Default EBS Encryption + paramPermsAWSRegionsWithoutDefaultEBSEncryption: + default: "Permissions for Policy Template: AWS Regions Without Default EBS Encryption" + ## AWS Reserved Instances Coverage + paramPermsAWSReservedInstancesCoverage: + default: "Permissions for Policy Template: AWS Reserved Instances Coverage" + ## AWS Reserved Instances Recommendations + paramPermsAWSReservedInstancesRecommendations: + default: "Permissions for Policy Template: AWS Reserved Instances Recommendations" + ## AWS Rightsize EBS Volumes + paramPermsAWSRightsizeEBSVolumes: + default: "Permissions for Policy Template: AWS Rightsize EBS Volumes" + ## AWS Rightsize EC2 Instances paramPermsAWSRightsizeEC2Instances: default: "Permissions for Policy Template: AWS Rightsize EC2 Instances" - paramPermsAWSSupersededEC2Instances: - default: "Permissions for Policy Template: AWS Superseded EC2 Instances" - paramPermsAWSReservedInstancesRecommendation: - default: "Permissions for Policy Template: AWS Reserved Instances Recommendation" - paramPermsAWSObjectStorageOptimization: - default: "Permissions for Policy Template: AWS Object Storage Optimization" - paramPermsAWSExpiringSavingsPlans: - default: "Permissions for Policy Template: AWS Expiring Savings Plans" + ## AWS Rightsize ElastiCache + paramPermsAWSRightsizeElastiCache: + default: "Permissions for Policy Template: AWS Rightsize ElastiCache" + ## AWS Rightsize RDS Instances + paramPermsAWSRightsizeRDSInstances: + default: "Permissions for Policy Template: AWS Rightsize RDS Instances" + ## AWS Rightsize Redshift + paramPermsAWSRightsizeRedshift: + default: "Permissions for Policy Template: AWS Rightsize Redshift" + ## AWS S3 Buckets Accepting HTTP Requests + paramPermsAWSS3BucketsAcceptingHTTPRequests: + default: "Permissions for Policy Template: AWS S3 Buckets Accepting HTTP Requests" + ## AWS S3 Buckets Without Default Encryption Configuration + paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration: + default: "Permissions for Policy Template: AWS S3 Buckets Without Default Encryption Configuration" + ## AWS S3 Buckets Without Intelligent Tiering + paramPermsAWSS3BucketsWithoutIntelligentTiering: + default: "Permissions for Policy Template: AWS S3 Buckets Without Intelligent Tiering" + ## AWS S3 Buckets Without Lifecycle Configuration + paramPermsAWSS3BucketsWithoutLifecycleConfiguration: + default: "Permissions for Policy Template: AWS S3 Buckets Without Lifecycle Configuration" + ## AWS S3 Buckets Without MFA Delete Enabled + paramPermsAWSS3BucketsWithoutMFADeleteEnabled: + default: "Permissions for Policy Template: AWS S3 Buckets Without MFA Delete Enabled" + ## AWS S3 Buckets Without Public Access Blocked + paramPermsAWSS3BucketsWithoutPublicAccessBlocked: + default: "Permissions for Policy Template: AWS S3 Buckets Without Public Access Blocked" + ## AWS S3 Buckets Without Server Access Logging + paramPermsAWSS3BucketsWithoutServerAccessLogging: + default: "Permissions for Policy Template: AWS S3 Buckets Without Server Access Logging" + ## AWS S3 Incomplete Multi-Part Uploads + paramPermsAWSS3IncompleteMultiPartUploads: + default: "Permissions for Policy Template: AWS S3 Incomplete Multi-Part Uploads" + ## AWS Savings Plan Recommendations paramPermsAWSSavingsPlanRecommendations: default: "Permissions for Policy Template: AWS Savings Plan Recommendations" + ## AWS Savings Plan Utilization paramPermsAWSSavingsPlanUtilization: default: "Permissions for Policy Template: AWS Savings Plan Utilization" + ## AWS Schedule Instance + paramPermsAWSScheduleInstance: + default: "Permissions for Policy Template: AWS Schedule Instance" + ## AWS Scheduled EC2 Events + paramPermsAWSScheduledEC2Events: + default: "Permissions for Policy Template: AWS Scheduled EC2 Events" + ## AWS Superseded EBS Volumes + paramPermsAWSSupersededEBSVolumes: + default: "Permissions for Policy Template: AWS Superseded EBS Volumes" + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + default: "Permissions for Policy Template: AWS Superseded EC2 Instances" + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + default: "Permissions for Policy Template: AWS Superseded EC2 Instances" + ## AWS Tag Cardinality Report paramPermsAWSTagCardinalityReport: default: "Permissions for Policy Template: AWS Tag Cardinality Report" + ## AWS Unencrypted EBS Volumes + paramPermsAWSUnencryptedEBSVolumes: + default: "Permissions for Policy Template: AWS Unencrypted EBS Volumes" + ## AWS Unencrypted RDS Instances + paramPermsAWSUnencryptedRDSInstances: + default: "Permissions for Policy Template: AWS Unencrypted RDS Instances" + ## AWS Untagged Resources paramPermsAWSUntaggedResources: default: "Permissions for Policy Template: AWS Untagged Resources" + ## AWS Unused Application Load Balancers + paramPermsAWSUnusedApplicationLoadBalancers: + default: "Permissions for Policy Template: AWS Unused Application Load Balancers" + ## AWS Unused Classic Load Balancers + paramPermsAWSUnusedClassicLoadBalancers: + default: "Permissions for Policy Template: AWS Unused Classic Load Balancers" + ## AWS Unused ECS Clusters + paramPermsAWSUnusedECSClusters: + default: "Permissions for Policy Template: AWS Unused ECS Clusters" + ## AWS Unused IAM Credentials + paramPermsAWSUnusedIAMCredentials: + default: "Permissions for Policy Template: AWS Unused IAM Credentials" + ## AWS Unused IP Addresses + paramPermsAWSUnusedIPAddresses: + default: "Permissions for Policy Template: AWS Unused IP Addresses" + ## AWS Unused Network Load Balancers + paramPermsAWSUnusedNetworkLoadBalancers: + default: "Permissions for Policy Template: AWS Unused Network Load Balancers" + ## AWS VPCs Without FlowLogs Enabled + paramPermsAWSVPCsWithoutFlowLogsEnabled: + default: "Permissions for Policy Template: AWS VPCs Without FlowLogs Enabled" + ## Common Bill Ingestion from AWS S3 Object Storage + paramPermsCommonBillIngestionfromAWSS3ObjectStorage: + default: "Permissions for Policy Template: Common Bill Ingestion from AWS S3 Object Storage" + # End for each policy template paramPermsAttachExistingPolicies: default: "Additional IAM Permission Policies for IAM Role" @@ -123,135 +492,701 @@ Parameters: Default: / # ParameterGroup: Parameters to define Policy Template permissions on the IAM Role that is created - #### For each policy template append: - # paramPerms: - # Description: 'What permissions should policies using "" Policy Template be granted on the IAM Role that will be created?' - # Type: String - # Default: Read Only - # AllowedValues: - # - No Access - # - Read Only - # - Read and Take Action - paramPermsAWSUnusedVolumes: - Description: 'What permissions should policies using "AWS Unused Volumes" Policy Template be granted on the IAM Role that will be created?' + ## All AWS Policy Templates + paramPermsAllAWSPolicyTemplates: + Description: 'What permissions for all AWS Policy Templates should be granted on the AWS Role that will be created? Note that the more granular permissions below only need to be enabled if this option is disabled or you want to grant access to take actions only for specific policy templates.' Type: String Default: Read Only AllowedValues: - - No Access + - None - Read Only - Read and Take Action - paramPermsAWSRightsizeEBSVolumes: - Description: 'What permissions should policies using "AWS Rightsize EBS Volumes" Policy Template be granted on the IAM Role that will be created?' + ## AWS Account Credentials + paramPermsAWSAccountCredentials: + Description: 'What permissions for the "AWS Account Credentials" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None + AllowedValues: + - None + - Read Only + ## AWS Accounts Missing Service Control Policies + paramPermsAWSAccountsMissingServiceControlPolicies: + Description: 'What permissions for the "AWS Accounts Missing Service Control Policies" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Burstable EC2 Instances + paramPermsAWSBurstableEC2Instances: + Description: 'What permissions for the "AWS Burstable EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None AllowedValues: - - No Access + - None - Read Only - Read and Take Action - paramPermsAWSRightsizeRDSInstances: - Description: 'What permissions should policies using "AWS Rightsize RDS Instances" Policy Template be granted on the IAM Role that will be created?' + ## AWS CloudTrail Not Enabled In All Regions + paramPermsAWSCloudTrailNotEnabledInAllRegions: + Description: 'What permissions for the "AWS CloudTrail Not Enabled In All Regions" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrail S3 Buckets Without Access Logging + paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging: + Description: 'What permissions for the "AWS CloudTrail S3 Buckets Without Access Logging" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails Not Integrated With CloudWatch + paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch: + Description: 'What permissions for the "AWS CloudTrails Not Integrated With CloudWatch" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails With Read Logging Enabled + paramPermsAWSCloudTrailsWithReadLoggingEnabled: + Description: 'What permissions for the "AWS CloudTrails With Read Logging Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None AllowedValues: - - No Access + - None - Read Only - Read and Take Action - paramPermsAWSUnusedIPAddresses: - Description: 'What permissions should policies using "AWS Unused IP Addresses" Policy Template be granted on the IAM Role that will be created?' + ## AWS CloudTrails Without Encrypted Logs + paramPermsAWSCloudTrailsWithoutEncryptedLogs: + Description: 'What permissions for the "AWS CloudTrails Without Encrypted Logs" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails Without Log File Validation Enabled + paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled: + Description: 'What permissions for the "AWS CloudTrails Without Log File Validation Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails Without Object-level Events Logging Enabled + paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: + Description: 'What permissions for the "AWS CloudTrails Without Object-level Events Logging Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None AllowedValues: - - No Access + - None + - Read Only + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled: + Description: 'What permissions for the "AWS Customer Managed Keys (CMKs) Without Rotation Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Disallowed Regions + paramPermsAWSDisallowedRegions: + Description: 'What permissions for the "AWS Disallowed Regions" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None - Read Only - Read and Take Action - paramPermsAWSUnusedCLBs: - Description: 'What permissions should policies using "AWS Unused Classic Load Balancers" Policy Template be granted on the IAM Role that will be created?' + ## AWS EC2 Compute Optimizer Recommendations + paramPermsAWSEC2ComputeOptimizerRecommendations: + Description: 'What permissions for the "AWS EC2 Compute Optimizer Recommendations" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS EC2 Instances Time Stopped Report + paramPermsAWSEC2InstancesTimeStoppedReport: + Description: 'What permissions for the "AWS EC2 Instances Time Stopped Report" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS EC2 Instances not running FlexNet Inventory Agent + paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent: + Description: 'What permissions for the "AWS EC2 Instances not running FlexNet Inventory Agent" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS EKS Clusters Without Spot Instances + paramPermsAWSEKSClustersWithoutSpotInstances: + Description: 'What permissions for the "AWS EKS Clusters Without Spot Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Elastic Load Balancers With Unencrypted Listeners + paramPermsAWSElasticLoadBalancersWithUnencryptedListeners: + Description: 'What permissions for the "AWS Elastic Load Balancers With Unencrypted Listeners" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Expiring Savings Plans + paramPermsAWSExpiringSavingsPlans: + Description: 'What permissions for the "AWS Expiring Savings Plans" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Account Missing Support Role + paramPermsAWSIAMAccountMissingSupportRole: + Description: 'What permissions for the "AWS IAM Account Missing Support Role" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Attached Admin Policies + paramPermsAWSIAMAttachedAdminPolicies: + Description: 'What permissions for the "AWS IAM Attached Admin Policies" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Expired SSL/TLS Certificates + paramPermsAWSIAMExpiredSSLTLSCertificates: + Description: 'What permissions for the "AWS IAM Expired SSL/TLS Certificates" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Insufficient Required Password Length + paramPermsAWSIAMInsufficientRequiredPasswordLength: + Description: 'What permissions for the "AWS IAM Insufficient Required Password Length" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Password Policy Not Restricting Password Reuse + paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse: + Description: 'What permissions for the "AWS IAM Password Policy Not Restricting Password Reuse" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Role Audit + paramPermsAWSIAMRoleAudit: + Description: 'What permissions for the "AWS IAM Role Audit" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root Account Access Keys + paramPermsAWSIAMRootAccountAccessKeys: + Description: 'What permissions for the "AWS IAM Root Account Access Keys" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root User Account Without Hardware MFA + paramPermsAWSIAMRootUserAccountWithoutHardwareMFA: + Description: 'What permissions for the "AWS IAM Root User Account Without Hardware MFA" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root User Account Without MFA + paramPermsAWSIAMRootUserAccountWithoutMFA: + Description: 'What permissions for the "AWS IAM Root User Account Without MFA" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root User Doing Everyday Tasks + paramPermsAWSIAMRootUserDoingEverydayTasks: + Description: 'What permissions for the "AWS IAM Root User Doing Everyday Tasks" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM User Accounts Without MFA + paramPermsAWSIAMUserAccountsWithoutMFA: + Description: 'What permissions for the "AWS IAM User Accounts Without MFA" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Users With Directly-Attached Policies + paramPermsAWSIAMUsersWithDirectlyAttachedPolicies: + Description: 'What permissions for the "AWS IAM Users With Directly-Attached Policies" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Users With Multiple Active Access Keys + paramPermsAWSIAMUsersWithMultipleActiveAccessKeys: + Description: 'What permissions for the "AWS IAM Users With Multiple Active Access Keys" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None AllowedValues: - - No Access + - None + - Read Only + ## AWS IAM Users With Old Access Keys + paramPermsAWSIAMUsersWithOldAccessKeys: + Description: 'What permissions for the "AWS IAM Users With Old Access Keys" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Idle NAT Gateways + paramPermsAWSIdleNATGateways: + Description: 'What permissions for the "AWS Idle NAT Gateways" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Internet-Accessible Elastic Load Balancers + paramPermsAWSInternetAccessibleElasticLoadBalancers: + Description: 'What permissions for the "AWS Internet-Accessible Elastic Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Lambda Functions With High Error Rate + paramPermsAWSLambdaFunctionsWithHighErrorRate: + Description: 'What permissions for the "AWS Lambda Functions With High Error Rate" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Lambda Functions Without Provisioned Concurrency + paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency: + Description: 'What permissions for the "AWS Lambda Functions Without Provisioned Concurrency" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Long Running Instances + paramPermsAWSLongRunningInstances: + Description: 'What permissions for the "AWS Long Running Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Long Stopped EC2 Instances + paramPermsAWSLongStoppedEC2Instances: + Description: 'What permissions for the "AWS Long Stopped EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None - Read Only - Read and Take Action + ## AWS Missing Regions + paramPermsAWSMissingRegions: + Description: 'What permissions for the "AWS Missing Regions" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Old Snapshots paramPermsAWSOldSnapshots: - Description: 'What permissions should policies using "AWS Old Snapshots" Policy Template be granted on the IAM Role that will be created?' + Description: 'What permissions for the "AWS Old Snapshots" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Open S3 Buckets + paramPermsAWSOpenS3Buckets: + Description: 'What permissions for the "AWS Open S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Oversized S3 Buckets + paramPermsAWSOversizedS3Buckets: + Description: 'What permissions for the "AWS Oversized S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Publicly Accessible CloudTrail S3 Buckets + paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets: + Description: 'What permissions for the "AWS Publicly Accessible CloudTrail S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Publicly Accessible RDS Instances + paramPermsAWSPubliclyAccessibleRDSInstances: + Description: 'What permissions for the "AWS Publicly Accessible RDS Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS RDS Instances With Unapproved Backup Settings + paramPermsAWSRDSInstancesWithUnapprovedBackupSettings: + Description: 'What permissions for the "AWS RDS Instances With Unapproved Backup Settings" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Regions Without Access Analyzer Enabled + paramPermsAWSRegionsWithoutAccessAnalyzerEnabled: + Description: 'What permissions for the "AWS Regions Without Access Analyzer Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Regions Without Config Fully Enabled + paramPermsAWSRegionsWithoutConfigFullyEnabled: + Description: 'What permissions for the "AWS Regions Without Config Fully Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Regions Without Default EBS Encryption + paramPermsAWSRegionsWithoutDefaultEBSEncryption: + Description: 'What permissions for the "AWS Regions Without Default EBS Encryption" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Reserved Instances Coverage + paramPermsAWSReservedInstancesCoverage: + Description: 'What permissions for the "AWS Reserved Instances Coverage" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Reserved Instances Recommendations + paramPermsAWSReservedInstancesRecommendations: + Description: 'What permissions for the "AWS Reserved Instances Recommendations" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Rightsize EBS Volumes + paramPermsAWSRightsizeEBSVolumes: + Description: 'What permissions for the "AWS Rightsize EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None AllowedValues: - - No Access + - None - Read Only - Read and Take Action + ## AWS Rightsize EC2 Instances paramPermsAWSRightsizeEC2Instances: - Description: 'What permissions should policies using "AWS Rightsize EC2 Instances" Policy Template be granted on the IAM Role that will be created?' + Description: 'What permissions for the "AWS Rightsize EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None AllowedValues: - - No Access + - None - Read Only - Read and Take Action - paramPermsAWSSupersededEC2Instances: - Description: 'What permissions should policies using "AWS Superseded EC2 Instances" Policy Template be granted on the IAM Role that will be created?' + ## AWS Rightsize ElastiCache + paramPermsAWSRightsizeElastiCache: + Description: 'What permissions for the "AWS Rightsize ElastiCache" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None AllowedValues: - - No Access + - None - Read Only - Read and Take Action - paramPermsAWSReservedInstancesRecommendation: - Description: 'What permissions should policies using "AWS Reserved Instances Recommendation" Policy Template be granted on the IAM Role that will be created?' + ## AWS Rightsize RDS Instances + paramPermsAWSRightsizeRDSInstances: + Description: 'What permissions for the "AWS Rightsize RDS Instances" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None AllowedValues: - - No Access + - None - Read Only - # - Read and Take Action - paramPermsAWSObjectStorageOptimization: - Description: 'What permissions should policies using "AWS Object Storage Optimization" Policy Template be granted on the IAM Role that will be created?' + - Read and Take Action + ## AWS Rightsize Redshift + paramPermsAWSRightsizeRedshift: + Description: 'What permissions for the "AWS Rightsize Redshift" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None AllowedValues: - - No Access + - None - Read Only - Read and Take Action - paramPermsAWSExpiringSavingsPlans: - Description: 'What permissions should policies using "AWS Expiring Savings Plans" Policy Template be granted on the IAM Role that will be created?' + ## AWS S3 Buckets Accepting HTTP Requests + paramPermsAWSS3BucketsAcceptingHTTPRequests: + Description: 'What permissions for the "AWS S3 Buckets Accepting HTTP Requests" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Default Encryption Configuration + paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration: + Description: 'What permissions for the "AWS S3 Buckets Without Default Encryption Configuration" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS S3 Buckets Without Intelligent Tiering + paramPermsAWSS3BucketsWithoutIntelligentTiering: + Description: 'What permissions for the "AWS S3 Buckets Without Intelligent Tiering" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Lifecycle Configuration + paramPermsAWSS3BucketsWithoutLifecycleConfiguration: + Description: 'What permissions for the "AWS S3 Buckets Without Lifecycle Configuration" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without MFA Delete Enabled + paramPermsAWSS3BucketsWithoutMFADeleteEnabled: + Description: 'What permissions for the "AWS S3 Buckets Without MFA Delete Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Public Access Blocked + paramPermsAWSS3BucketsWithoutPublicAccessBlocked: + Description: 'What permissions for the "AWS S3 Buckets Without Public Access Blocked" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Server Access Logging + paramPermsAWSS3BucketsWithoutServerAccessLogging: + Description: 'What permissions for the "AWS S3 Buckets Without Server Access Logging" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS S3 Incomplete Multi-Part Uploads + paramPermsAWSS3IncompleteMultiPartUploads: + Description: 'What permissions for the "AWS S3 Incomplete Multi-Part Uploads" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None AllowedValues: - - No Access + - None - Read Only - # - Read and Take Action + - Read and Take Action + ## AWS Savings Plan Recommendations paramPermsAWSSavingsPlanRecommendations: - Description: 'What permissions should policies using "AWS Savings Plan Recommendations" Policy Template be granted on the IAM Role that will be created?' + Description: 'What permissions for the "AWS Savings Plan Recommendations" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None AllowedValues: - - No Access + - None - Read Only - # - Read and Take Action + ## AWS Savings Plan Utilization paramPermsAWSSavingsPlanUtilization: - Description: 'What permissions should policies using "AWS Savings Plan Utilization" Policy Template be granted on the IAM Role that will be created?' + Description: 'What permissions for the "AWS Savings Plan Utilization" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None + AllowedValues: + - None + - Read Only + ## AWS Schedule Instance + paramPermsAWSScheduleInstance: + Description: 'What permissions for the "AWS Schedule Instance" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Scheduled EC2 Events + paramPermsAWSScheduledEC2Events: + Description: 'What permissions for the "AWS Scheduled EC2 Events" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Superseded EBS Volumes + paramPermsAWSSupersededEBSVolumes: + Description: 'What permissions for the "AWS Superseded EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None AllowedValues: - - No Access + - None - Read Only - # - Read and Take Action + - Read and Take Action + ## AWS Tag Cardinality Report paramPermsAWSTagCardinalityReport: - Description: 'What permissions should policies using "AWS Tag Cardinality Report" Policy Template be granted on the IAM Role that will be created?' + Description: 'What permissions for the "AWS Tag Cardinality Report" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None AllowedValues: - - No Access + - None - Read Only - # - Read and Take Action + ## AWS Unencrypted EBS Volumes + paramPermsAWSUnencryptedEBSVolumes: + Description: 'What permissions for the "AWS Unencrypted EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Unencrypted RDS Instances + paramPermsAWSUnencryptedRDSInstances: + Description: 'What permissions for the "AWS Unencrypted RDS Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Untagged Resources paramPermsAWSUntaggedResources: - Description: 'What permissions should policies using "AWS Untagged Resources" Policy Template be granted on the IAM Role that will be created?' + Description: 'What permissions for the "AWS Untagged Resources" Policy Template should be granted on the AWS Role that will be created?' Type: String - Default: Read Only + Default: None AllowedValues: - - No Access + - None - Read Only - Read and Take Action + ## AWS Unused Application Load Balancers + paramPermsAWSUnusedApplicationLoadBalancers: + Description: 'What permissions for the "AWS Unused Application Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused Classic Load Balancers + paramPermsAWSUnusedClassicLoadBalancers: + Description: 'What permissions for the "AWS Unused Classic Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused ECS Clusters + paramPermsAWSUnusedECSClusters: + Description: 'What permissions for the "AWS Unused ECS Clusters" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused IAM Credentials + paramPermsAWSUnusedIAMCredentials: + Description: 'What permissions for the "AWS Unused IAM Credentials" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Unused IP Addresses + paramPermsAWSUnusedIPAddresses: + Description: 'What permissions for the "AWS Unused IP Addresses" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused Network Load Balancers + paramPermsAWSUnusedNetworkLoadBalancers: + Description: 'What permissions for the "AWS Unused Network Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS VPCs Without FlowLogs Enabled + paramPermsAWSVPCsWithoutFlowLogsEnabled: + Description: 'What permissions for the "AWS VPCs Without FlowLogs Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## Common Bill Ingestion from AWS S3 Object Storage + paramPermsCommonBillIngestionfromAWSS3ObjectStorage: + Description: 'What permissions for the "Common Bill Ingestion from AWS S3 Object Storage" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + # End for each policy template paramPermsAttachExistingPolicies: Description: 'Existing IAM Permission Policies to attach to the IAM Role that will be created. Optional, comma separated list of IAM Policy ARNs -- i.e. arn:aws:iam::aws:policy/ReadOnlyAccess' @@ -262,124 +1197,512 @@ Parameters: ConstraintDescription: 'Malformed IAM Policy ARN. Must match pattern ^((arn:aws:iam::(\d{12}|aws)?:policy\/[\w+=,.@-]{1,128})(,)?)*$' Conditions: - #### For each policy template append: - # CreatePolicyRead: !Not - # - !Equals - # - !Ref paramPerms - # - No Access - # CreatePolicyAction: !Equals - # - !Ref paramPerms - # - Read and Take Action - CreatePolicyAWSUnusedVolumesRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedVolumes - - No Access - CreatePolicyAWSUnusedVolumesAction: !Equals - - !Ref paramPermsAWSUnusedVolumes + ## All AWS Policy Templates + CreatePolicyAllAWSPolicyTemplatesRead: !Not + - !Equals + - !Ref paramPermsAllAWSPolicyTemplates + - None + CreatePolicyAllAWSPolicyTemplatesAction: !Equals + - !Ref paramPermsAllAWSPolicyTemplates - Read and Take Action - CreatePolicyAWSRightsizeEBSVolumesRead: !Not + ## AWS Account Credentials + CreatePolicyAWSAccountCredentialsRead: !Not - !Equals - - !Ref paramPermsAWSRightsizeEBSVolumes - - No Access - CreatePolicyAWSRightsizeEBSVolumesAction: !Equals - - !Ref paramPermsAWSRightsizeEBSVolumes + - !Ref paramPermsAWSAccountCredentials + - None + ## AWS Accounts Missing Service Control Policies + CreatePolicyAWSAccountsMissingServiceControlPoliciesRead: !Not + - !Equals + - !Ref paramPermsAWSAccountsMissingServiceControlPolicies + - None + ## AWS Burstable EC2 Instances + CreatePolicyAWSBurstableEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSBurstableEC2Instances + - None + CreatePolicyAWSBurstableEC2InstancesAction: !Equals + - !Ref paramPermsAWSBurstableEC2Instances - Read and Take Action - CreatePolicyAWSRightsizeRDSInstancesRead: !Not + ## AWS CloudTrail Not Enabled In All Regions + CreatePolicyAWSCloudTrailNotEnabledInAllRegionsRead: !Not - !Equals - - !Ref paramPermsAWSRightsizeRDSInstances - - No Access - CreatePolicyAWSRightsizeRDSInstancesAction: !Equals - - !Ref paramPermsAWSRightsizeRDSInstances + - !Ref paramPermsAWSCloudTrailNotEnabledInAllRegions + - None + ## AWS CloudTrail S3 Buckets Without Access Logging + CreatePolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging + - None + ## AWS CloudTrails Not Integrated With CloudWatch + CreatePolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch + - None + ## AWS CloudTrails With Read Logging Enabled + CreatePolicyAWSCloudTrailsWithReadLoggingEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsWithReadLoggingEnabled + - None + CreatePolicyAWSCloudTrailsWithReadLoggingEnabledAction: !Equals + - !Ref paramPermsAWSCloudTrailsWithReadLoggingEnabled - Read and Take Action - CreatePolicyAWSUnusedIPAddressesRead: !Not + ## AWS CloudTrails Without Encrypted Logs + CreatePolicyAWSCloudTrailsWithoutEncryptedLogsRead: !Not - !Equals - - !Ref paramPermsAWSUnusedIPAddresses - - No Access - CreatePolicyAWSUnusedIPAddressesAction: !Equals - - !Ref paramPermsAWSUnusedIPAddresses + - !Ref paramPermsAWSCloudTrailsWithoutEncryptedLogs + - None + ## AWS CloudTrails Without Log File Validation Enabled + CreatePolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled + - None + ## AWS CloudTrails Without Object-level Events Logging Enabled + CreatePolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled + - None + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + CreatePolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled + - None + ## AWS Disallowed Regions + CreatePolicyAWSDisallowedRegionsRead: !Not + - !Equals + - !Ref paramPermsAWSDisallowedRegions + - None + CreatePolicyAWSDisallowedRegionsAction: !Equals + - !Ref paramPermsAWSDisallowedRegions + - Read and Take Action + ## AWS EC2 Compute Optimizer Recommendations + CreatePolicyAWSEC2ComputeOptimizerRecommendationsRead: !Not + - !Equals + - !Ref paramPermsAWSEC2ComputeOptimizerRecommendations + - None + CreatePolicyAWSEC2ComputeOptimizerRecommendationsAction: !Equals + - !Ref paramPermsAWSEC2ComputeOptimizerRecommendations + - Read and Take Action + ## AWS EC2 Instances Time Stopped Report + CreatePolicyAWSEC2InstancesTimeStoppedReportRead: !Not + - !Equals + - !Ref paramPermsAWSEC2InstancesTimeStoppedReport + - None + CreatePolicyAWSEC2InstancesTimeStoppedReportAction: !Equals + - !Ref paramPermsAWSEC2InstancesTimeStoppedReport + - Read and Take Action + ## AWS EC2 Instances not running FlexNet Inventory Agent + CreatePolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead: !Not + - !Equals + - !Ref paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent + - None + ## AWS EKS Clusters Without Spot Instances + CreatePolicyAWSEKSClustersWithoutSpotInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSEKSClustersWithoutSpotInstances + - None + ## AWS Elastic Load Balancers With Unencrypted Listeners + CreatePolicyAWSElasticLoadBalancersWithUnencryptedListenersRead: !Not + - !Equals + - !Ref paramPermsAWSElasticLoadBalancersWithUnencryptedListeners + - None + ## AWS Expiring Savings Plans + CreatePolicyAWSExpiringSavingsPlansRead: !Not + - !Equals + - !Ref paramPermsAWSExpiringSavingsPlans + - None + ## AWS IAM Account Missing Support Role + CreatePolicyAWSIAMAccountMissingSupportRoleRead: !Not + - !Equals + - !Ref paramPermsAWSIAMAccountMissingSupportRole + - None + ## AWS IAM Attached Admin Policies + CreatePolicyAWSIAMAttachedAdminPoliciesRead: !Not + - !Equals + - !Ref paramPermsAWSIAMAttachedAdminPolicies + - None + ## AWS IAM Expired SSL/TLS Certificates + CreatePolicyAWSIAMExpiredSSLTLSCertificatesRead: !Not + - !Equals + - !Ref paramPermsAWSIAMExpiredSSLTLSCertificates + - None + ## AWS IAM Insufficient Required Password Length + CreatePolicyAWSIAMInsufficientRequiredPasswordLengthRead: !Not + - !Equals + - !Ref paramPermsAWSIAMInsufficientRequiredPasswordLength + - None + ## AWS IAM Password Policy Not Restricting Password Reuse + CreatePolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead: !Not + - !Equals + - !Ref paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse + - None + ## AWS IAM Role Audit + CreatePolicyAWSIAMRoleAuditRead: !Not + - !Equals + - !Ref paramPermsAWSIAMRoleAudit + - None + ## AWS IAM Root Account Access Keys + CreatePolicyAWSIAMRootAccountAccessKeysRead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootAccountAccessKeys + - None + ## AWS IAM Root User Account Without Hardware MFA + CreatePolicyAWSIAMRootUserAccountWithoutHardwareMFARead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootUserAccountWithoutHardwareMFA + - None + ## AWS IAM Root User Account Without MFA + CreatePolicyAWSIAMRootUserAccountWithoutMFARead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootUserAccountWithoutMFA + - None + ## AWS IAM Root User Doing Everyday Tasks + CreatePolicyAWSIAMRootUserDoingEverydayTasksRead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootUserDoingEverydayTasks + - None + ## AWS IAM User Accounts Without MFA + CreatePolicyAWSIAMUserAccountsWithoutMFARead: !Not + - !Equals + - !Ref paramPermsAWSIAMUserAccountsWithoutMFA + - None + ## AWS IAM Users With Directly-Attached Policies + CreatePolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead: !Not + - !Equals + - !Ref paramPermsAWSIAMUsersWithDirectlyAttachedPolicies + - None + ## AWS IAM Users With Multiple Active Access Keys + CreatePolicyAWSIAMUsersWithMultipleActiveAccessKeysRead: !Not + - !Equals + - !Ref paramPermsAWSIAMUsersWithMultipleActiveAccessKeys + - None + ## AWS IAM Users With Old Access Keys + CreatePolicyAWSIAMUsersWithOldAccessKeysRead: !Not + - !Equals + - !Ref paramPermsAWSIAMUsersWithOldAccessKeys + - None + ## AWS Idle NAT Gateways + CreatePolicyAWSIdleNATGatewaysRead: !Not + - !Equals + - !Ref paramPermsAWSIdleNATGateways + - None + CreatePolicyAWSIdleNATGatewaysAction: !Equals + - !Ref paramPermsAWSIdleNATGateways + - Read and Take Action + ## AWS Internet-Accessible Elastic Load Balancers + CreatePolicyAWSInternetAccessibleElasticLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSInternetAccessibleElasticLoadBalancers + - None + CreatePolicyAWSInternetAccessibleElasticLoadBalancersAction: !Equals + - !Ref paramPermsAWSInternetAccessibleElasticLoadBalancers + - Read and Take Action + ## AWS Lambda Functions With High Error Rate + CreatePolicyAWSLambdaFunctionsWithHighErrorRateRead: !Not + - !Equals + - !Ref paramPermsAWSLambdaFunctionsWithHighErrorRate + - None + ## AWS Lambda Functions Without Provisioned Concurrency + CreatePolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead: !Not + - !Equals + - !Ref paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency + - None + ## AWS Long Running Instances + CreatePolicyAWSLongRunningInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSLongRunningInstances + - None + CreatePolicyAWSLongRunningInstancesAction: !Equals + - !Ref paramPermsAWSLongRunningInstances - Read and Take Action - CreatePolicyAWSUnusedCLBsRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedCLBs - - No Access - CreatePolicyAWSUnusedCLBsAction: !Equals - - !Ref paramPermsAWSUnusedCLBs + ## AWS Long Stopped EC2 Instances + CreatePolicyAWSLongStoppedEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSLongStoppedEC2Instances + - None + CreatePolicyAWSLongStoppedEC2InstancesAction: !Equals + - !Ref paramPermsAWSLongStoppedEC2Instances - Read and Take Action + ## AWS Missing Regions + CreatePolicyAWSMissingRegionsRead: !Not + - !Equals + - !Ref paramPermsAWSMissingRegions + - None + ## AWS Old Snapshots CreatePolicyAWSOldSnapshotsRead: !Not - !Equals - !Ref paramPermsAWSOldSnapshots - - No Access + - None CreatePolicyAWSOldSnapshotsAction: !Equals - !Ref paramPermsAWSOldSnapshots - Read and Take Action + ## AWS Open S3 Buckets + CreatePolicyAWSOpenS3BucketsRead: !Not + - !Equals + - !Ref paramPermsAWSOpenS3Buckets + - None + ## AWS Oversized S3 Buckets + CreatePolicyAWSOversizedS3BucketsRead: !Not + - !Equals + - !Ref paramPermsAWSOversizedS3Buckets + - None + ## AWS Publicly Accessible CloudTrail S3 Buckets + CreatePolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead: !Not + - !Equals + - !Ref paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets + - None + ## AWS Publicly Accessible RDS Instances + CreatePolicyAWSPubliclyAccessibleRDSInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSPubliclyAccessibleRDSInstances + - None + CreatePolicyAWSPubliclyAccessibleRDSInstancesAction: !Equals + - !Ref paramPermsAWSPubliclyAccessibleRDSInstances + - Read and Take Action + ## AWS RDS Instances With Unapproved Backup Settings + CreatePolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead: !Not + - !Equals + - !Ref paramPermsAWSRDSInstancesWithUnapprovedBackupSettings + - None + ## AWS Regions Without Access Analyzer Enabled + CreatePolicyAWSRegionsWithoutAccessAnalyzerEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSRegionsWithoutAccessAnalyzerEnabled + - None + ## AWS Regions Without Config Fully Enabled + CreatePolicyAWSRegionsWithoutConfigFullyEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSRegionsWithoutConfigFullyEnabled + - None + ## AWS Regions Without Default EBS Encryption + CreatePolicyAWSRegionsWithoutDefaultEBSEncryptionRead: !Not + - !Equals + - !Ref paramPermsAWSRegionsWithoutDefaultEBSEncryption + - None + ## AWS Reserved Instances Coverage + CreatePolicyAWSReservedInstancesCoverageRead: !Not + - !Equals + - !Ref paramPermsAWSReservedInstancesCoverage + - None + ## AWS Reserved Instances Recommendations + CreatePolicyAWSReservedInstancesRecommendationsRead: !Not + - !Equals + - !Ref paramPermsAWSReservedInstancesRecommendations + - None + ## AWS Rightsize EBS Volumes + CreatePolicyAWSRightsizeEBSVolumesRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeEBSVolumes + - None + CreatePolicyAWSRightsizeEBSVolumesAction: !Equals + - !Ref paramPermsAWSRightsizeEBSVolumes + - Read and Take Action + ## AWS Rightsize EC2 Instances CreatePolicyAWSRightsizeEC2InstancesRead: !Not - !Equals - !Ref paramPermsAWSRightsizeEC2Instances - - No Access + - None CreatePolicyAWSRightsizeEC2InstancesAction: !Equals - !Ref paramPermsAWSRightsizeEC2Instances - Read and Take Action - CreatePolicyAWSSupersededEC2InstancesRead: !Not + ## AWS Rightsize ElastiCache + CreatePolicyAWSRightsizeElastiCacheRead: !Not - !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - No Access - CreatePolicyAWSSupersededEC2InstancesAction: !Equals - - !Ref paramPermsAWSSupersededEC2Instances + - !Ref paramPermsAWSRightsizeElastiCache + - None + CreatePolicyAWSRightsizeElastiCacheAction: !Equals + - !Ref paramPermsAWSRightsizeElastiCache + - Read and Take Action + ## AWS Rightsize RDS Instances + CreatePolicyAWSRightsizeRDSInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeRDSInstances + - None + CreatePolicyAWSRightsizeRDSInstancesAction: !Equals + - !Ref paramPermsAWSRightsizeRDSInstances - Read and Take Action - CreatePolicyAWSReservedInstancesRecommendationRead: !Not - - !Equals - - !Ref paramPermsAWSReservedInstancesRecommendation - - No Access - # Policy has no actions currently, commenting out to prevent cfn-lint W8001 Error Condition not used - # CreatePolicyAWSReservedInstancesRecommendationAction: !Equals - # - !Ref paramPermsAWSReservedInstancesRecommendation - # - Read and Take Action - CreatePolicyAWSObjectStorageOptimizationRead: !Not - - !Equals - - !Ref paramPermsAWSObjectStorageOptimization - - No Access - CreatePolicyAWSObjectStorageOptimizationAction: !Equals - - !Ref paramPermsAWSObjectStorageOptimization + ## AWS Rightsize Redshift + CreatePolicyAWSRightsizeRedshiftRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeRedshift + - None + CreatePolicyAWSRightsizeRedshiftAction: !Equals + - !Ref paramPermsAWSRightsizeRedshift - Read and Take Action - CreatePolicyAWSExpiringSavingsPlansRead: !Not + ## AWS S3 Buckets Accepting HTTP Requests + CreatePolicyAWSS3BucketsAcceptingHTTPRequestsRead: !Not - !Equals - - !Ref paramPermsAWSExpiringSavingsPlans - - No Access - # Policy has no actions currently, commenting out to prevent cfn-lint W8001 Error Condition not used - # CreatePolicyAWSExpiringSavingsPlansAction: !Equals - # - !Ref paramPermsAWSExpiringSavingsPlans - # - Read and Take Action + - !Ref paramPermsAWSS3BucketsAcceptingHTTPRequests + - None + ## AWS S3 Buckets Without Default Encryption Configuration + CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration + - None + CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction: !Equals + - !Ref paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration + - Read and Take Action + ## AWS S3 Buckets Without Intelligent Tiering + CreatePolicyAWSS3BucketsWithoutIntelligentTieringRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutIntelligentTiering + - None + ## AWS S3 Buckets Without Lifecycle Configuration + CreatePolicyAWSS3BucketsWithoutLifecycleConfigurationRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutLifecycleConfiguration + - None + ## AWS S3 Buckets Without MFA Delete Enabled + CreatePolicyAWSS3BucketsWithoutMFADeleteEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutMFADeleteEnabled + - None + ## AWS S3 Buckets Without Public Access Blocked + CreatePolicyAWSS3BucketsWithoutPublicAccessBlockedRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutPublicAccessBlocked + - None + ## AWS S3 Buckets Without Server Access Logging + CreatePolicyAWSS3BucketsWithoutServerAccessLoggingRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutServerAccessLogging + - None + CreatePolicyAWSS3BucketsWithoutServerAccessLoggingAction: !Equals + - !Ref paramPermsAWSS3BucketsWithoutServerAccessLogging + - Read and Take Action + ## AWS S3 Incomplete Multi-Part Uploads + CreatePolicyAWSS3IncompleteMultiPartUploadsRead: !Not + - !Equals + - !Ref paramPermsAWSS3IncompleteMultiPartUploads + - None + CreatePolicyAWSS3IncompleteMultiPartUploadsAction: !Equals + - !Ref paramPermsAWSS3IncompleteMultiPartUploads + - Read and Take Action + ## AWS Savings Plan Recommendations CreatePolicyAWSSavingsPlanRecommendationsRead: !Not - !Equals - !Ref paramPermsAWSSavingsPlanRecommendations - - No Access - # Policy has no actions currently, commenting out to prevent cfn-lint W8001 Error Condition not used - # CreatePolicyAWSSavingsPlanRecommendationsAction: !Equals - # - !Ref paramPermsAWSSavingsPlanRecommendations - # - Read and Take Action + - None + ## AWS Savings Plan Utilization CreatePolicyAWSSavingsPlanUtilizationRead: !Not - !Equals - !Ref paramPermsAWSSavingsPlanUtilization - - No Access - # Policy has no actions currently, commenting out to prevent cfn-lint W8001 Error Condition not used - # CreatePolicyAWSSavingsPlanUtilizationAction: !Equals - # - !Ref paramPermsAWSSavingsPlanUtilization - # - Read and Take Action + - None + ## AWS Schedule Instance + CreatePolicyAWSScheduleInstanceRead: !Not + - !Equals + - !Ref paramPermsAWSScheduleInstance + - None + ## AWS Scheduled EC2 Events + CreatePolicyAWSScheduledEC2EventsRead: !Not + - !Equals + - !Ref paramPermsAWSScheduledEC2Events + - None + ## AWS Superseded EBS Volumes + CreatePolicyAWSSupersededEBSVolumesRead: !Not + - !Equals + - !Ref paramPermsAWSSupersededEBSVolumes + - None + CreatePolicyAWSSupersededEBSVolumesAction: !Equals + - !Ref paramPermsAWSSupersededEBSVolumes + - Read and Take Action + ## AWS Superseded EC2 Instances + CreatePolicyAWSSupersededEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - None + CreatePolicyAWSSupersededEC2InstancesAction: !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - Read and Take Action + ## AWS Superseded EC2 Instances + CreatePolicyAWSSupersededEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - None + CreatePolicyAWSSupersededEC2InstancesAction: !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - Read and Take Action + ## AWS Tag Cardinality Report CreatePolicyAWSTagCardinalityReportRead: !Not - !Equals - !Ref paramPermsAWSTagCardinalityReport - - No Access - # Policy has no actions currently, commenting out to prevent cfn-lint W8001 Error Condition not used - # CreatePolicyAWSTagCardinalityReportAction: !Equals - # - !Ref paramPermsAWSTagCardinalityReport - # - Read and Take Action + - None + ## AWS Unencrypted EBS Volumes + CreatePolicyAWSUnencryptedEBSVolumesRead: !Not + - !Equals + - !Ref paramPermsAWSUnencryptedEBSVolumes + - None + ## AWS Unencrypted RDS Instances + CreatePolicyAWSUnencryptedRDSInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSUnencryptedRDSInstances + - None + CreatePolicyAWSUnencryptedRDSInstancesAction: !Equals + - !Ref paramPermsAWSUnencryptedRDSInstances + - Read and Take Action + ## AWS Untagged Resources CreatePolicyAWSUntaggedResourcesRead: !Not - !Equals - !Ref paramPermsAWSUntaggedResources - - No Access + - None CreatePolicyAWSUntaggedResourcesAction: !Equals - !Ref paramPermsAWSUntaggedResources - Read and Take Action + ## AWS Unused Application Load Balancers + CreatePolicyAWSUnusedApplicationLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedApplicationLoadBalancers + - None + CreatePolicyAWSUnusedApplicationLoadBalancersAction: !Equals + - !Ref paramPermsAWSUnusedApplicationLoadBalancers + - Read and Take Action + ## AWS Unused Classic Load Balancers + CreatePolicyAWSUnusedClassicLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedClassicLoadBalancers + - None + CreatePolicyAWSUnusedClassicLoadBalancersAction: !Equals + - !Ref paramPermsAWSUnusedClassicLoadBalancers + - Read and Take Action + ## AWS Unused ECS Clusters + CreatePolicyAWSUnusedECSClustersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedECSClusters + - None + CreatePolicyAWSUnusedECSClustersAction: !Equals + - !Ref paramPermsAWSUnusedECSClusters + - Read and Take Action + ## AWS Unused IAM Credentials + CreatePolicyAWSUnusedIAMCredentialsRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedIAMCredentials + - None + ## AWS Unused IP Addresses + CreatePolicyAWSUnusedIPAddressesRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedIPAddresses + - None + CreatePolicyAWSUnusedIPAddressesAction: !Equals + - !Ref paramPermsAWSUnusedIPAddresses + - Read and Take Action + ## AWS Unused Network Load Balancers + CreatePolicyAWSUnusedNetworkLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedNetworkLoadBalancers + - None + CreatePolicyAWSUnusedNetworkLoadBalancersAction: !Equals + - !Ref paramPermsAWSUnusedNetworkLoadBalancers + - Read and Take Action + ## AWS VPCs Without FlowLogs Enabled + CreatePolicyAWSVPCsWithoutFlowLogsEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSVPCsWithoutFlowLogsEnabled + - None + ## Common Bill Ingestion from AWS S3 Object Storage + CreatePolicyCommonBillIngestionfromAWSS3ObjectStorageRead: !Not + - !Equals + - !Ref paramPermsCommonBillIngestionfromAWSS3ObjectStorage + - None + # End for each policy template ValueProvidedparamPermsAttachExistingPolicies: !Not - !Equals @@ -399,166 +1722,855 @@ Mappings: PermissionMap: # Begin IAM Permissions Map # Expect 2 lists for each Policy Template (read and action) - #### For each policy template append: - # : - # read: - # - "" - # action: - # - "" - AWSUnusedVolumes: + ## All AWS Policy Templates + AllAWSPolicyTemplates: read: - - "ec2:DescribeRegions" - - "ec2:DescribeVolumes" - - "ec2:DescribeSnapshots" - - "cloudwatch:GetMetricStatistics" + - "access-analyzer:ListAnalyzers" + - "ce:GetReservationCoverage" + - "ce:GetReservationPurchaseRecommendation" + - "ce:GetSavingsPlansPurchaseRecommendation" + - "ce:GetSavingsPlansUtilization" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetEventSelectors" + - "cloudtrail:GetTrailStatus" + - "cloudtrail:LookupEvents" - "cloudwatch:GetMetricData" - action: + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:ListMetrics" + - "compute-optimizer:GetEC2InstanceRecommendations" + - "config:DescribeConfigurationRecorderStatus" - "ec2:CreateTags" - - "ec2:CreateSnapshot" - - "ec2:DetachVolume" - - "ec2:DeleteVolume" - AWSRightsizeEBSVolumes: - read: + - "ec2:DeleteTags" + - "ec2:DescribeAddresses" + - "ec2:DescribeFlowLogs" + - "ec2:DescribeImages" + - "ec2:DescribeInstanceStatus" + - "ec2:DescribeInstances" + - "ec2:DescribeNatGateways" - "ec2:DescribeRegions" + - "ec2:DescribeSnapshots" + - "ec2:DescribeTags" - "ec2:DescribeVolumes" + - "ec2:DescribeVpcs" + - "ec2:GetEbsEncryptionByDefault" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + - "ecs:DescribeClusters" + - "ecs:ListClusters" + - "eks:DescribeCluster" + - "eks:DescribeNodegroup" + - "eks:ListClusters" + - "eks:ListNodegroups" + - "elasticache:DescribeCacheClusters" + - "elasticache:ListTagsForResource" + - "elasticloadbalancing:DescribeInstanceHealth" + - "elasticloadbalancing:DescribeListeners" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeTargetGroups" + - "elasticloadbalancing:DescribeTargetHealth" + - "iam:GenerateCredentialReport" + - "iam:GetAccountPasswordPolicy" + - "iam:GetAccountSummary" + - "iam:GetCredentialReport" + - "iam:GetPolicyVersion" + - "iam:ListAccessKeys" + - "iam:ListAttachedUserPolicies" + - "iam:ListEntitiesForPolicy" + - "iam:ListPolicies" + - "iam:ListRoleTags" + - "iam:ListRoles" + - "iam:ListServerCertificates" + - "iam:ListUserPolicies" + - "iam:ListUsers" + - "iam:ListVirtualMFADevices" + - "kms:CreateGrant" + - "kms:Decrypt" + - "kms:GetKeyRotationStatus" + - "kms:ListKeys" + - "lambda:ListFunctions" + - "lambda:ListProvisionedConcurrencyConfigs" + - "lambda:ListTags" + - "lambda:ListVersionsByFunction" + - "organizations:ListAccounts" + - "organizations:ListPolicies" + - "organizations:ListPoliciesForTarget" + - "organizations:ListTagsForResource" - "pricing:GetProducts" - action: - - "ec2:ModifyVolume" - AWSRightsizeRDSInstances: - read: - - "sts:GetCallerIdentity" - - "cloudwatch:GetMetricStatistics" - - "cloudwatch:GetMetricData" - - "ec2:DescribeRegions" + - "rds:DescribeDBClusterSnapshots" + - "rds:DescribeDBClusters" - "rds:DescribeDBInstances" - - "rds:ListTagsForResource" + - "rds:DescribeDBSnapshots" - "rds:DescribeOrderableDBInstanceOptions" + - "rds:ListTagsForResource" + - "redshift:DescribeClusters" + - "s3:GetBucketAcl" + - "s3:GetBucketLifecycleConfiguration" + - "s3:GetBucketLocation" + - "s3:GetBucketLogging" + - "s3:GetBucketPolicy" + - "s3:GetBucketPublicAccessBlock" + - "s3:GetBucketTagging" + - "s3:GetBucketVersioning" + - "s3:GetEncryptionConfiguration" + - "s3:GetIntelligentTieringConfiguration" + - "s3:GetObject" + - "s3:ListAllMyBuckets" + - "s3:ListBucketMultipartUploads" + - "s3:ListMultipartUploadParts" + - "savingsplans:DescribeSavingsPlans" + - "sts:GetCallerIdentity" + - "tag:GetResources" action: - - "rds:ModifyDBInstance" + - "cloudtrail:PutEventSelectors" + - "ec2:DeleteNatGateway" + - "ec2:DeleteSnapshot" + - "ec2:DeregisterImage" + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:ModifyVolume" + - "ec2:ReleaseAddress" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + - "ecs:DeleteCluster" + - "elasticache:ModifyCacheCluster" + - "elasticloadbalancing:DeleteLoadBalancer" + - "organizations:TagResource" + - "rds:DeleteDBClusterSnapshot" - "rds:DeleteDBInstance" - AWSUnusedIPAddresses: + - "rds:DeleteDBSnapshot" + - "rds:ModifyDBInstance" + - "redshift:ModifyCluster" + - "s3:AbortMultipartUpload" + - "s3:DeleteBucket" + - "s3:PutBucketLogging" + - "s3:PutEncryptionConfiguration" + - "tag:TagResources" + ## AWS Account Credentials + AWSAccountCredentials: read: - - "ec2:DescribeRegions" - - "ec2:DescribeAddresses" - - "pricing:GetProducts" - "sts:GetCallerIdentity" - - "cloudtrail:LookupEvents" - action: - - "ec2:ReleaseAddress" - AWSUnusedCLBs: + action: [] + ## AWS Accounts Missing Service Control Policies + AWSAccountsMissingServiceControlPolicies: + read: + - "organizations:ListPolicies" + - "organizations:ListAccounts" + - "organizations:ListPoliciesForTarget" + action: [] + ## AWS Burstable EC2 Instances + AWSBurstableEC2Instances: read: - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricData" + - "cloudwatch:ListMetrics" - "ec2:DescribeRegions" - - "elasticloadbalancing:DescribeLoadBalancers" - - "elasticloadbalancing:DescribeInstanceHealth" - - "elasticloadbalancing:DescribeTags" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" action: - - "elasticloadbalancing:DeleteLoadBalancer" - AWSOldSnapshots: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + ## AWS CloudTrail Not Enabled In All Regions + AWSCloudTrailNotEnabledInAllRegions: read: - - "ec2:DescribeRegions" - - "ec2:DescribeImages" - - "ec2:DescribeSnapshots" - - "rds:DescribeDBInstances" - - "rds:DescribeDBSnapshots" - - "rds:DescribeDBClusters" - - "rds:DescribeDBClusterSnapshots" - "sts:GetCallerIdentity" - - "cloudtrail:LookupEvents" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetTrailStatus" + - "cloudtrail:GetEventSelectors" + action: [] + ## AWS CloudTrail S3 Buckets Without Access Logging + AWSCloudTrailS3BucketsWithoutAccessLogging: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "s3:GetBucketLocation" + - "s3:GetBucketLogging" + action: [] + ## AWS CloudTrails Not Integrated With CloudWatch + AWSCloudTrailsNotIntegratedWithCloudWatch: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetTrailStatus" + action: [] + ## AWS CloudTrails With Read Logging Enabled + AWSCloudTrailsWithReadLoggingEnabled: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetEventSelectors" action: - - "ec2:DeregisterImage" - - "ec2:DeleteSnapshot" - - "rds:DeleteDBClusterSnapshot" - - "rds:DeleteDBSnapshot" - AWSRightsizeEC2Instances: + - "cloudtrail:PutEventSelectors" + ## AWS CloudTrails Without Encrypted Logs + AWSCloudTrailsWithoutEncryptedLogs: read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + action: [] + ## AWS CloudTrails Without Log File Validation Enabled + AWSCloudTrailsWithoutLogFileValidationEnabled: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + action: [] + ## AWS CloudTrails Without Object-level Events Logging Enabled + AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetEventSelectors" + action: [] + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + AWSCustomerManagedKeysCMKsWithoutRotationEnabled: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "kms:ListKeys" + - "kms:GetKeyRotationStatus" + action: [] + ## AWS Disallowed Regions + AWSDisallowedRegions: + read: + - "sts:GetCallerIdentity" - "ec2:DescribeRegions" - "ec2:DescribeInstances" - - "ec2:DescribeTags" - - "cloudwatch:GetMetricStatistics" - - "cloudwatch:GetMetricData" - - "cloudwatch:ListMetrics" + action: + - "ec2:StopInstances" + - "ec2:TerminateInstances" + ## AWS EC2 Compute Optimizer Recommendations + AWSEC2ComputeOptimizerRecommendations: + read: - "sts:GetCallerIdentity" + - "compute-optimizer:GetEC2InstanceRecommendations" + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" action: - - "ec2:DescribeInstanceStatus" - "ec2:ModifyInstanceAttribute" - "ec2:StartInstances" - "ec2:StopInstances" + ## AWS EC2 Instances Time Stopped Report + AWSEC2InstancesTimeStoppedReport: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:StopInstances" - "ec2:TerminateInstances" - AWSSupersededEC2Instances: + ## AWS EC2 Instances not running FlexNet Inventory Agent + AWSEC2InstancesnotrunningFlexNetInventoryAgent: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + action: [] + ## AWS EKS Clusters Without Spot Instances + AWSEKSClustersWithoutSpotInstances: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "eks:ListClusters" + - "eks:ListNodegroups" + - "eks:DescribeCluster" + - "eks:DescribeNodegroup" + action: [] + ## AWS Elastic Load Balancers With Unencrypted Listeners + AWSElasticLoadBalancersWithUnencryptedListeners: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeListeners" + action: [] + ## AWS Expiring Savings Plans + AWSExpiringSavingsPlans: + read: + - "savingsplans:DescribeSavingsPlans" + action: [] + ## AWS IAM Account Missing Support Role + AWSIAMAccountMissingSupportRole: + read: + - "sts:GetCallerIdentity" + - "iam:ListPolicies" + - "iam:ListEntitiesForPolicy" + action: [] + ## AWS IAM Attached Admin Policies + AWSIAMAttachedAdminPolicies: + read: + - "sts:GetCallerIdentity" + - "iam:ListPolicies" + - "iam:GetPolicyVersion" + action: [] + ## AWS IAM Expired SSL/TLS Certificates + AWSIAMExpiredSSLTLSCertificates: + read: + - "sts:GetCallerIdentity" + - "iam:ListServerCertificates" + action: [] + ## AWS IAM Insufficient Required Password Length + AWSIAMInsufficientRequiredPasswordLength: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountPasswordPolicy" + action: [] + ## AWS IAM Password Policy Not Restricting Password Reuse + AWSIAMPasswordPolicyNotRestrictingPasswordReuse: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountPasswordPolicy" + action: [] + ## AWS IAM Role Audit + AWSIAMRoleAudit: + read: + - "sts:GetCallerIdentity" + - "iam:ListRoles" + - "iam:ListRoleTags" + action: [] + ## AWS IAM Root Account Access Keys + AWSIAMRootAccountAccessKeys: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountSummary" + action: [] + ## AWS IAM Root User Account Without Hardware MFA + AWSIAMRootUserAccountWithoutHardwareMFA: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountSummary" + - "iam:ListVirtualMFADevices" + action: [] + ## AWS IAM Root User Account Without MFA + AWSIAMRootUserAccountWithoutMFA: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountSummary" + - "iam:ListVirtualMFADevices" + action: [] + ## AWS IAM Root User Doing Everyday Tasks + AWSIAMRootUserDoingEverydayTasks: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS IAM User Accounts Without MFA + AWSIAMUserAccountsWithoutMFA: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS IAM Users With Directly-Attached Policies + AWSIAMUsersWithDirectlyAttachedPolicies: + read: + - "sts:GetCallerIdentity" + - "iam:ListUsers" + - "iam:ListUserPolicies" + - "iam:ListAttachedUserPolicies" + action: [] + ## AWS IAM Users With Multiple Active Access Keys + AWSIAMUsersWithMultipleActiveAccessKeys: + read: + - "sts:GetCallerIdentity" + - "iam:ListUsers" + - "iam:ListAccessKeys" + action: [] + ## AWS IAM Users With Old Access Keys + AWSIAMUsersWithOldAccessKeys: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS Idle NAT Gateways + AWSIdleNATGateways: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeNatGateways" + - "sts:GetCallerIdentity" + action: + - "ec2:DeleteNatGateway" + ## AWS Internet-Accessible Elastic Load Balancers + AWSInternetAccessibleElasticLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeListeners" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS Lambda Functions With High Error Rate + AWSLambdaFunctionsWithHighErrorRate: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "lambda:ListFunctions" + - "lambda:ListTags" + - "cloudwatch:ListMetrics" + - "cloudwatch:GetMetricData" + action: [] + ## AWS Lambda Functions Without Provisioned Concurrency + AWSLambdaFunctionsWithoutProvisionedConcurrency: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "lambda:ListFunctions" + - "lambda:ListTags" + - "lambda:ListProvisionedConcurrencyConfigs" + - "lambda:ListVersionsByFunction" + action: [] + ## AWS Long Running Instances + AWSLongRunningInstances: read: - "ec2:DescribeRegions" - "ec2:DescribeInstances" - - "ec2:DescribeTags" - "sts:GetCallerIdentity" action: - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - "ec2:StopInstances" - AWSReservedInstancesRecommendation: + - "ec2:TerminateInstances" + ## AWS Long Stopped EC2 Instances + AWSLongStoppedEC2Instances: read: - - "ce:GetReservationPurchaseRecommendation" + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:GetMetricData" + - "cloudwatch:ListMetrics" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:TerminateInstances" + ## AWS Missing Regions + AWSMissingRegions: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "sts:GetCallerIdentity" action: [] - AWSObjectStorageOptimization: + ## AWS Old Snapshots + AWSOldSnapshots: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeImages" + - "ec2:DescribeSnapshots" + - "rds:DescribeDBInstances" + - "rds:DescribeDBSnapshots" + - "rds:DescribeDBClusters" + - "rds:DescribeDBClusterSnapshots" + - "sts:GetCallerIdentity" + - "cloudtrail:LookupEvents" + action: + - "ec2:DeregisterImage" + - "ec2:DeleteSnapshot" + - "rds:DeleteDBClusterSnapshot" + - "rds:DeleteDBSnapshot" + ## AWS Open S3 Buckets + AWSOpenS3Buckets: read: + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketAcl" - "sts:GetCallerIdentity" + action: [] + ## AWS Oversized S3 Buckets + AWSOversizedS3Buckets: + read: - "s3:ListAllMyBuckets" - "s3:GetBucketLocation" - - "s3:ListBucket" - - "s3:GetObject" - - "s3:GetObjectTagging" + - "s3:GetBucketTagging" + - "cloudwatch:ListMetrics" + - "cloudwatch:GetMetricData" + - "sts:GetCallerIdentity" + action: [] + ## AWS Publicly Accessible CloudTrail S3 Buckets + AWSPubliclyAccessibleCloudTrailS3Buckets: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "s3:GetBucketLocation" + - "s3:GetBucketAcl" + - "s3:GetBucketPolicy" + action: [] + ## AWS Publicly Accessible RDS Instances + AWSPubliclyAccessibleRDSInstances: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" action: - - "s3:PutObject" - - "s3:DeleteObject" - AWSExpiringSavingsPlans: + - "rds:ModifyDBInstance" + - "rds:DeleteDBInstance" + ## AWS RDS Instances With Unapproved Backup Settings + AWSRDSInstancesWithUnapprovedBackupSettings: read: - - "savingsplans:DescribeSavingsPlans" + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" action: [] - AWSSavingsPlanRecommendations: + ## AWS Regions Without Access Analyzer Enabled + AWSRegionsWithoutAccessAnalyzerEnabled: read: - - "ce:GetSavingsPlansPurchaseRecommendation" + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "access-analyzer:ListAnalyzers" action: [] - AWSSavingsPlanUtilization: + ## AWS Regions Without Config Fully Enabled + AWSRegionsWithoutConfigFullyEnabled: read: - - "ce:GetSavingsPlansUtilization" - - "savingsplans:DescribeSavingsPlans" + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "config:DescribeConfigurationRecorderStatus" action: [] - AWSTagCardinalityReport: + ## AWS Regions Without Default EBS Encryption + AWSRegionsWithoutDefaultEBSEncryption: read: - - "tag:GetResources" + - "sts:GetCallerIdentity" - "ec2:DescribeRegions" - - "organizations:ListAccounts" - - "organizations:ListTagsForResource" + - "ec2:GetEbsEncryptionByDefault" action: [] - AWSUntaggedResources: + ## AWS Reserved Instances Coverage + AWSReservedInstancesCoverage: + read: + - "ce:GetReservationCoverage" + action: [] + ## AWS Reserved Instances Recommendations + AWSReservedInstancesRecommendations: + read: + - "ce:GetReservationPurchaseRecommendation" + action: [] + ## AWS Rightsize EBS Volumes + AWSRightsizeEBSVolumes: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeVolumes" + - "pricing:GetProducts" + action: + - "ec2:ModifyVolume" + ## AWS Rightsize EC2 Instances + AWSRightsizeEC2Instances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:GetMetricData" + - "cloudwatch:ListMetrics" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + ## AWS Rightsize ElastiCache + AWSRightsizeElastiCache: read: - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricData" - "ec2:DescribeRegions" - - "tag:GetResources" + - "elasticache:DescribeCacheClusters" + - "elasticache:ListTagsForResource" action: - - "tag:TagResources" - # End for each policy template - - -Resources: - # IAM Role Resource - iamRole: - Type: "AWS::IAM::Role" - Properties: - RoleName: !Ref paramRoleName - Description: !Join - - " " - - - "Allows access from Flexera Platform. This IAM Role and the attached permission policies were created and are managed by CloudFormation Stack:" - - !Ref AWS::StackId - Path: !Ref paramRolePath - AssumeRolePolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Principal: - AWS: !FindInMap - - TrustedRoleMap + - "elasticache:ModifyCacheCluster" + ## AWS Rightsize RDS Instances + AWSRightsizeRDSInstances: + read: + - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:GetMetricData" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" + - "rds:DescribeOrderableDBInstanceOptions" + action: + - "rds:ModifyDBInstance" + - "rds:DeleteDBInstance" + ## AWS Rightsize Redshift + AWSRightsizeRedshift: + read: + - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricData" + - "ec2:DescribeRegions" + - "redshift:DescribeClusters" + action: + - "redshift:ModifyCluster" + ## AWS S3 Buckets Accepting HTTP Requests + AWSS3BucketsAcceptingHTTPRequests: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketPolicy" + action: [] + ## AWS S3 Buckets Without Default Encryption Configuration + AWSS3BucketsWithoutDefaultEncryptionConfiguration: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetEncryptionConfiguration" + action: + - "s3:PutEncryptionConfiguration" + - "s3:DeleteBucket" + ## AWS S3 Buckets Without Intelligent Tiering + AWSS3BucketsWithoutIntelligentTiering: + read: + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetIntelligentTieringConfiguration" + - "sts:GetCallerIdentity" + action: [] + ## AWS S3 Buckets Without Lifecycle Configuration + AWSS3BucketsWithoutLifecycleConfiguration: + read: + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketLifecycleConfiguration" + - "sts:GetCallerIdentity" + action: [] + ## AWS S3 Buckets Without MFA Delete Enabled + AWSS3BucketsWithoutMFADeleteEnabled: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketVersioning" + action: [] + ## AWS S3 Buckets Without Public Access Blocked + AWSS3BucketsWithoutPublicAccessBlocked: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketPublicAccessBlock" + action: [] + ## AWS S3 Buckets Without Server Access Logging + AWSS3BucketsWithoutServerAccessLogging: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketLogging" + action: + - "s3:PutBucketLogging" + ## AWS S3 Incomplete Multi-Part Uploads + AWSS3IncompleteMultiPartUploads: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:ListBucketMultipartUploads" + - "s3:ListMultipartUploadParts" + action: + - "s3:AbortMultipartUpload" + ## AWS Savings Plan Recommendations + AWSSavingsPlanRecommendations: + read: + - "ce:GetSavingsPlansPurchaseRecommendation" + action: [] + ## AWS Savings Plan Utilization + AWSSavingsPlanUtilization: + read: + - "ce:GetSavingsPlansUtilization" + - "savingsplans:DescribeSavingsPlans" + action: [] + ## AWS Schedule Instance + AWSScheduleInstance: + read: + - "ec2:DescribeInstances" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:DeleteTags" + - "ec2:DescribeRegions" + - "kms:CreateGrant" + - "kms:Decrypt" + - "ec2:CreateTags" + - "ec2:TerminateInstances" + action: [] + ## AWS Scheduled EC2 Events + AWSScheduledEC2Events: + read: + - "ec2:DescribeInstances" + - "ec2:DescribeInstanceStatus" + - "ec2:DescribeRegions" + - "sts:GetCallerIdentity" + action: [] + ## AWS Superseded EBS Volumes + AWSSupersededEBSVolumes: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:DescribeVolumes" + - "pricing:GetProducts" + action: + - "ec2:ModifyVolume" + ## AWS Superseded EC2 Instances + AWSSupersededEC2Instances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + ## AWS Superseded EC2 Instances + AWSSupersededEC2Instances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + ## AWS Tag Cardinality Report + AWSTagCardinalityReport: + read: + - "tag:GetResources" + - "ec2:DescribeRegions" + - "organizations:ListAccounts" + - "organizations:ListTagsForResource" + action: [] + ## AWS Unencrypted EBS Volumes + AWSUnencryptedEBSVolumes: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:DescribeVolumes" + action: [] + ## AWS Unencrypted RDS Instances + AWSUnencryptedRDSInstances: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" + action: + - "rds:DeleteDBInstance" + ## AWS Untagged Resources + AWSUntaggedResources: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "tag:GetResources" + action: + - "tag:TagResources" + - "organizations:TagResource" + ## AWS Unused Application Load Balancers + AWSUnusedApplicationLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeListeners" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeTargetGroups" + - "elasticloadbalancing:DescribeTargetHealth" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS Unused Classic Load Balancers + AWSUnusedClassicLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeInstanceHealth" + - "elasticloadbalancing:DescribeTags" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS Unused ECS Clusters + AWSUnusedECSClusters: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ecs:ListClusters" + - "ecs:DescribeClusters" + action: + - "ecs:DeleteCluster" + ## AWS Unused IAM Credentials + AWSUnusedIAMCredentials: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS Unused IP Addresses + AWSUnusedIPAddresses: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeAddresses" + - "sts:GetCallerIdentity" + - "cloudtrail:LookupEvents" + action: + - "ec2:ReleaseAddress" + ## AWS Unused Network Load Balancers + AWSUnusedNetworkLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeListeners" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeTargetGroups" + - "elasticloadbalancing:DescribeTargetHealth" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS VPCs Without FlowLogs Enabled + AWSVPCsWithoutFlowLogsEnabled: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:DescribeVpcs" + - "ec2:DescribeFlowLogs" + action: [] + ## Common Bill Ingestion from AWS S3 Object Storage + CommonBillIngestionfromAWSS3ObjectStorage: + read: + - "s3:GetObject" + action: [] + + # End for each policy template + +Resources: + # IAM Role Resource + iamRole: + Type: "AWS::IAM::Role" + Properties: + RoleName: !Ref paramRoleName + Description: !Join + - " " + - - "Allows access from Flexera Platform. This IAM Role and the attached permission policies were created and are managed by CloudFormation Stack:" + - !Ref AWS::StackId + Path: !Ref paramRolePath + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: !FindInMap + - TrustedRoleMap - !Ref paramFlexeraZone - roleArn Action: "sts:AssumeRole" @@ -575,54 +2587,1557 @@ Resources: # Begin IAM Permission Policy Resources # 1 or 2 Permission Policies per Policy Template (read and action) # Policy create/attachment is conditional based on parameter input for each policy - #### For each policy template append: - # iamPolicyRead: - # Type: "AWS::IAM::Policy" - # Condition: CreatePolicyRead - # Properties: - # PolicyName: !Join - # - "_" - # - - !Ref paramRoleName - # - ReadPermissionPolicy - # Roles: - # - !Ref iamRole - # PolicyDocument: - # Version: 2012-10-17 - # Statement: - # - Effect: Allow - # Action: !FindInMap - # - PermissionMap - # - - # - read - # Resource: "*" - # iamPolicyAction: - # Type: "AWS::IAM::Policy" - # Condition: CreatePolicyAction - # Properties: - # PolicyName: !Join - # - "_" - # - - !Ref paramRoleName - # - ActionPermissionPolicy - # Roles: - # - !Ref iamRole - # PolicyDocument: - # Version: 2012-10-17 - # Statement: - # - Effect: Allow - # Action: !FindInMap - # - PermissionMap - # - - # - action - # Resource: "*" - ## AWS Unused Volumes Permission Policies - iamPolicyAWSUnusedVolumesRead: + ## All AWS Policy Templates + iamPolicyAllAWSPolicyTemplatesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAllAWSPolicyTemplatesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AllAWSPolicyTemplatesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AllAWSPolicyTemplates + - read + Resource: "*" + iamPolicyAllAWSPolicyTemplatesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAllAWSPolicyTemplatesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AllAWSPolicyTemplatesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AllAWSPolicyTemplates + - action + Resource: "*" + ## AWS Account Credentials + iamPolicyAWSAccountCredentialsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSAccountCredentialsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSAccountCredentialsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSAccountCredentials + - read + Resource: "*" + ## AWS Accounts Missing Service Control Policies + iamPolicyAWSAccountsMissingServiceControlPoliciesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSAccountsMissingServiceControlPoliciesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSAccountsMissingServiceControlPoliciesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSAccountsMissingServiceControlPolicies + - read + Resource: "*" + ## AWS Burstable EC2 Instances + iamPolicyAWSBurstableEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSBurstableEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSBurstableEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSBurstableEC2Instances + - read + Resource: "*" + iamPolicyAWSBurstableEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSBurstableEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSBurstableEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSBurstableEC2Instances + - action + Resource: "*" + ## AWS CloudTrail Not Enabled In All Regions + iamPolicyAWSCloudTrailNotEnabledInAllRegionsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailNotEnabledInAllRegionsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailNotEnabledInAllRegionsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailNotEnabledInAllRegions + - read + Resource: "*" + ## AWS CloudTrail S3 Buckets Without Access Logging + iamPolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailS3BucketsWithoutAccessLoggingReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailS3BucketsWithoutAccessLogging + - read + Resource: "*" + ## AWS CloudTrails Not Integrated With CloudWatch + iamPolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsNotIntegratedWithCloudWatchReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsNotIntegratedWithCloudWatch + - read + Resource: "*" + ## AWS CloudTrails With Read Logging Enabled + iamPolicyAWSCloudTrailsWithReadLoggingEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithReadLoggingEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithReadLoggingEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithReadLoggingEnabled + - read + Resource: "*" + iamPolicyAWSCloudTrailsWithReadLoggingEnabledAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithReadLoggingEnabledAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithReadLoggingEnabledActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithReadLoggingEnabled + - action + Resource: "*" + ## AWS CloudTrails Without Encrypted Logs + iamPolicyAWSCloudTrailsWithoutEncryptedLogsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithoutEncryptedLogsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithoutEncryptedLogsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithoutEncryptedLogs + - read + Resource: "*" + ## AWS CloudTrails Without Log File Validation Enabled + iamPolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithoutLogFileValidationEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithoutLogFileValidationEnabled + - read + Resource: "*" + ## AWS CloudTrails Without Object-level Events Logging Enabled + iamPolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled + - read + Resource: "*" + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + iamPolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCustomerManagedKeysCMKsWithoutRotationEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCustomerManagedKeysCMKsWithoutRotationEnabled + - read + Resource: "*" + ## AWS Disallowed Regions + iamPolicyAWSDisallowedRegionsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSDisallowedRegionsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSDisallowedRegionsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSDisallowedRegions + - read + Resource: "*" + iamPolicyAWSDisallowedRegionsAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSDisallowedRegionsAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSDisallowedRegionsActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSDisallowedRegions + - action + Resource: "*" + ## AWS EC2 Compute Optimizer Recommendations + iamPolicyAWSEC2ComputeOptimizerRecommendationsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2ComputeOptimizerRecommendationsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2ComputeOptimizerRecommendationsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2ComputeOptimizerRecommendations + - read + Resource: "*" + iamPolicyAWSEC2ComputeOptimizerRecommendationsAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2ComputeOptimizerRecommendationsAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2ComputeOptimizerRecommendationsActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2ComputeOptimizerRecommendations + - action + Resource: "*" + ## AWS EC2 Instances Time Stopped Report + iamPolicyAWSEC2InstancesTimeStoppedReportRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2InstancesTimeStoppedReportRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2InstancesTimeStoppedReportReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2InstancesTimeStoppedReport + - read + Resource: "*" + iamPolicyAWSEC2InstancesTimeStoppedReportAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2InstancesTimeStoppedReportAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2InstancesTimeStoppedReportActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2InstancesTimeStoppedReport + - action + Resource: "*" + ## AWS EC2 Instances not running FlexNet Inventory Agent + iamPolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2InstancesnotrunningFlexNetInventoryAgentReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2InstancesnotrunningFlexNetInventoryAgent + - read + Resource: "*" + ## AWS EKS Clusters Without Spot Instances + iamPolicyAWSEKSClustersWithoutSpotInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEKSClustersWithoutSpotInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEKSClustersWithoutSpotInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEKSClustersWithoutSpotInstances + - read + Resource: "*" + ## AWS Elastic Load Balancers With Unencrypted Listeners + iamPolicyAWSElasticLoadBalancersWithUnencryptedListenersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSElasticLoadBalancersWithUnencryptedListenersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSElasticLoadBalancersWithUnencryptedListenersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSElasticLoadBalancersWithUnencryptedListeners + - read + Resource: "*" + ## AWS Expiring Savings Plans + iamPolicyAWSExpiringSavingsPlansRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSExpiringSavingsPlansRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSExpiringSavingsPlansReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSExpiringSavingsPlans + - read + Resource: "*" + ## AWS IAM Account Missing Support Role + iamPolicyAWSIAMAccountMissingSupportRoleRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMAccountMissingSupportRoleRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMAccountMissingSupportRoleReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMAccountMissingSupportRole + - read + Resource: "*" + ## AWS IAM Attached Admin Policies + iamPolicyAWSIAMAttachedAdminPoliciesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMAttachedAdminPoliciesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMAttachedAdminPoliciesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMAttachedAdminPolicies + - read + Resource: "*" + ## AWS IAM Expired SSL/TLS Certificates + iamPolicyAWSIAMExpiredSSLTLSCertificatesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMExpiredSSLTLSCertificatesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMExpiredSSLTLSCertificatesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMExpiredSSLTLSCertificates + - read + Resource: "*" + ## AWS IAM Insufficient Required Password Length + iamPolicyAWSIAMInsufficientRequiredPasswordLengthRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMInsufficientRequiredPasswordLengthRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMInsufficientRequiredPasswordLengthReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMInsufficientRequiredPasswordLength + - read + Resource: "*" + ## AWS IAM Password Policy Not Restricting Password Reuse + iamPolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMPasswordPolicyNotRestrictingPasswordReuseReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMPasswordPolicyNotRestrictingPasswordReuse + - read + Resource: "*" + ## AWS IAM Role Audit + iamPolicyAWSIAMRoleAuditRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRoleAuditRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRoleAuditReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRoleAudit + - read + Resource: "*" + ## AWS IAM Root Account Access Keys + iamPolicyAWSIAMRootAccountAccessKeysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootAccountAccessKeysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootAccountAccessKeysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootAccountAccessKeys + - read + Resource: "*" + ## AWS IAM Root User Account Without Hardware MFA + iamPolicyAWSIAMRootUserAccountWithoutHardwareMFARead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootUserAccountWithoutHardwareMFARead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootUserAccountWithoutHardwareMFAReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootUserAccountWithoutHardwareMFA + - read + Resource: "*" + ## AWS IAM Root User Account Without MFA + iamPolicyAWSIAMRootUserAccountWithoutMFARead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootUserAccountWithoutMFARead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootUserAccountWithoutMFAReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootUserAccountWithoutMFA + - read + Resource: "*" + ## AWS IAM Root User Doing Everyday Tasks + iamPolicyAWSIAMRootUserDoingEverydayTasksRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootUserDoingEverydayTasksRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootUserDoingEverydayTasksReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootUserDoingEverydayTasks + - read + Resource: "*" + ## AWS IAM User Accounts Without MFA + iamPolicyAWSIAMUserAccountsWithoutMFARead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUserAccountsWithoutMFARead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUserAccountsWithoutMFAReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUserAccountsWithoutMFA + - read + Resource: "*" + ## AWS IAM Users With Directly-Attached Policies + iamPolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUsersWithDirectlyAttachedPoliciesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUsersWithDirectlyAttachedPolicies + - read + Resource: "*" + ## AWS IAM Users With Multiple Active Access Keys + iamPolicyAWSIAMUsersWithMultipleActiveAccessKeysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUsersWithMultipleActiveAccessKeysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUsersWithMultipleActiveAccessKeysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUsersWithMultipleActiveAccessKeys + - read + Resource: "*" + ## AWS IAM Users With Old Access Keys + iamPolicyAWSIAMUsersWithOldAccessKeysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUsersWithOldAccessKeysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUsersWithOldAccessKeysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUsersWithOldAccessKeys + - read + Resource: "*" + ## AWS Idle NAT Gateways + iamPolicyAWSIdleNATGatewaysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIdleNATGatewaysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIdleNATGatewaysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIdleNATGateways + - read + Resource: "*" + iamPolicyAWSIdleNATGatewaysAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIdleNATGatewaysAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIdleNATGatewaysActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIdleNATGateways + - action + Resource: "*" + ## AWS Internet-Accessible Elastic Load Balancers + iamPolicyAWSInternetAccessibleElasticLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSInternetAccessibleElasticLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSInternetAccessibleElasticLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSInternetAccessibleElasticLoadBalancers + - read + Resource: "*" + iamPolicyAWSInternetAccessibleElasticLoadBalancersAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSInternetAccessibleElasticLoadBalancersAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSInternetAccessibleElasticLoadBalancersActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSInternetAccessibleElasticLoadBalancers + - action + Resource: "*" + ## AWS Lambda Functions With High Error Rate + iamPolicyAWSLambdaFunctionsWithHighErrorRateRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLambdaFunctionsWithHighErrorRateRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLambdaFunctionsWithHighErrorRateReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLambdaFunctionsWithHighErrorRate + - read + Resource: "*" + ## AWS Lambda Functions Without Provisioned Concurrency + iamPolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLambdaFunctionsWithoutProvisionedConcurrencyReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLambdaFunctionsWithoutProvisionedConcurrency + - read + Resource: "*" + ## AWS Long Running Instances + iamPolicyAWSLongRunningInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongRunningInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongRunningInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongRunningInstances + - read + Resource: "*" + iamPolicyAWSLongRunningInstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongRunningInstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongRunningInstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongRunningInstances + - action + Resource: "*" + ## AWS Long Stopped EC2 Instances + iamPolicyAWSLongStoppedEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongStoppedEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongStoppedEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongStoppedEC2Instances + - read + Resource: "*" + iamPolicyAWSLongStoppedEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongStoppedEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongStoppedEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongStoppedEC2Instances + - action + Resource: "*" + ## AWS Missing Regions + iamPolicyAWSMissingRegionsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSMissingRegionsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSMissingRegionsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSMissingRegions + - read + Resource: "*" + ## AWS Old Snapshots + iamPolicyAWSOldSnapshotsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOldSnapshotsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOldSnapshotsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOldSnapshots + - read + Resource: "*" + iamPolicyAWSOldSnapshotsAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOldSnapshotsAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOldSnapshotsActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOldSnapshots + - action + Resource: "*" + ## AWS Open S3 Buckets + iamPolicyAWSOpenS3BucketsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOpenS3BucketsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOpenS3BucketsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOpenS3Buckets + - read + Resource: "*" + ## AWS Oversized S3 Buckets + iamPolicyAWSOversizedS3BucketsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOversizedS3BucketsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOversizedS3BucketsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOversizedS3Buckets + - read + Resource: "*" + ## AWS Publicly Accessible CloudTrail S3 Buckets + iamPolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSPubliclyAccessibleCloudTrailS3BucketsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSPubliclyAccessibleCloudTrailS3Buckets + - read + Resource: "*" + ## AWS Publicly Accessible RDS Instances + iamPolicyAWSPubliclyAccessibleRDSInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSPubliclyAccessibleRDSInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSPubliclyAccessibleRDSInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSPubliclyAccessibleRDSInstances + - read + Resource: "*" + iamPolicyAWSPubliclyAccessibleRDSInstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSPubliclyAccessibleRDSInstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSPubliclyAccessibleRDSInstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSPubliclyAccessibleRDSInstances + - action + Resource: "*" + ## AWS RDS Instances With Unapproved Backup Settings + iamPolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRDSInstancesWithUnapprovedBackupSettingsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRDSInstancesWithUnapprovedBackupSettings + - read + Resource: "*" + ## AWS Regions Without Access Analyzer Enabled + iamPolicyAWSRegionsWithoutAccessAnalyzerEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRegionsWithoutAccessAnalyzerEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRegionsWithoutAccessAnalyzerEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRegionsWithoutAccessAnalyzerEnabled + - read + Resource: "*" + ## AWS Regions Without Config Fully Enabled + iamPolicyAWSRegionsWithoutConfigFullyEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRegionsWithoutConfigFullyEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRegionsWithoutConfigFullyEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRegionsWithoutConfigFullyEnabled + - read + Resource: "*" + ## AWS Regions Without Default EBS Encryption + iamPolicyAWSRegionsWithoutDefaultEBSEncryptionRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRegionsWithoutDefaultEBSEncryptionRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRegionsWithoutDefaultEBSEncryptionReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRegionsWithoutDefaultEBSEncryption + - read + Resource: "*" + ## AWS Reserved Instances Coverage + iamPolicyAWSReservedInstancesCoverageRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSReservedInstancesCoverageRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSReservedInstancesCoverageReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSReservedInstancesCoverage + - read + Resource: "*" + ## AWS Reserved Instances Recommendations + iamPolicyAWSReservedInstancesRecommendationsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSReservedInstancesRecommendationsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSReservedInstancesRecommendationsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSReservedInstancesRecommendations + - read + Resource: "*" + ## AWS Rightsize EBS Volumes + iamPolicyAWSRightsizeEBSVolumesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEBSVolumesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEBSVolumesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEBSVolumes + - read + Resource: "*" + iamPolicyAWSRightsizeEBSVolumesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEBSVolumesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEBSVolumesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEBSVolumes + - action + Resource: "*" + ## AWS Rightsize EC2 Instances + iamPolicyAWSRightsizeEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEC2Instances + - read + Resource: "*" + iamPolicyAWSRightsizeEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEC2Instances + - action + Resource: "*" + ## AWS Rightsize ElastiCache + iamPolicyAWSRightsizeElastiCacheRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeElastiCacheRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeElastiCacheReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeElastiCache + - read + Resource: "*" + iamPolicyAWSRightsizeElastiCacheAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeElastiCacheAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeElastiCacheActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeElastiCache + - action + Resource: "*" + ## AWS Rightsize RDS Instances + iamPolicyAWSRightsizeRDSInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRDSInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRDSInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRDSInstances + - read + Resource: "*" + iamPolicyAWSRightsizeRDSInstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRDSInstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRDSInstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRDSInstances + - action + Resource: "*" + ## AWS Rightsize Redshift + iamPolicyAWSRightsizeRedshiftRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRedshiftRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRedshiftReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRedshift + - read + Resource: "*" + iamPolicyAWSRightsizeRedshiftAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRedshiftAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRedshiftActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRedshift + - action + Resource: "*" + ## AWS S3 Buckets Accepting HTTP Requests + iamPolicyAWSS3BucketsAcceptingHTTPRequestsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsAcceptingHTTPRequestsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsAcceptingHTTPRequestsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsAcceptingHTTPRequests + - read + Resource: "*" + ## AWS S3 Buckets Without Default Encryption Configuration + iamPolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutDefaultEncryptionConfigurationReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutDefaultEncryptionConfiguration + - read + Resource: "*" + iamPolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutDefaultEncryptionConfigurationActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutDefaultEncryptionConfiguration + - action + Resource: "*" + ## AWS S3 Buckets Without Intelligent Tiering + iamPolicyAWSS3BucketsWithoutIntelligentTieringRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutIntelligentTieringRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutIntelligentTieringReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutIntelligentTiering + - read + Resource: "*" + ## AWS S3 Buckets Without Lifecycle Configuration + iamPolicyAWSS3BucketsWithoutLifecycleConfigurationRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutLifecycleConfigurationRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutLifecycleConfigurationReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutLifecycleConfiguration + - read + Resource: "*" + ## AWS S3 Buckets Without MFA Delete Enabled + iamPolicyAWSS3BucketsWithoutMFADeleteEnabledRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedVolumesRead + Condition: CreatePolicyAWSS3BucketsWithoutMFADeleteEnabledRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUnusedVolumesReadPermissionPolicy + - AWSS3BucketsWithoutMFADeleteEnabledReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -631,17 +4146,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUnusedVolumes + - AWSS3BucketsWithoutMFADeleteEnabled - read Resource: "*" - iamPolicyAWSUnusedVolumesAction: + ## AWS S3 Buckets Without Public Access Blocked + iamPolicyAWSS3BucketsWithoutPublicAccessBlockedRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedVolumesAction + Condition: CreatePolicyAWSS3BucketsWithoutPublicAccessBlockedRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUnusedVolumesActionPermissionPolicy + - AWSS3BucketsWithoutPublicAccessBlockedReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -650,18 +4166,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUnusedVolumes - - action + - AWSS3BucketsWithoutPublicAccessBlocked + - read Resource: "*" - ## AWS Rightsize EBS Volumes Permission Policies - iamPolicyAWSRightsizeEBSVolumesRead: + ## AWS S3 Buckets Without Server Access Logging + iamPolicyAWSS3BucketsWithoutServerAccessLoggingRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEBSVolumesRead + Condition: CreatePolicyAWSS3BucketsWithoutServerAccessLoggingRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSRightsizeEBSVolumesReadPermissionPolicy + - AWSS3BucketsWithoutServerAccessLoggingReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -670,17 +4186,17 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSRightsizeEBSVolumes + - AWSS3BucketsWithoutServerAccessLogging - read Resource: "*" - iamPolicyAWSRightsizeEBSVolumesAction: + iamPolicyAWSS3BucketsWithoutServerAccessLoggingAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEBSVolumesAction + Condition: CreatePolicyAWSS3BucketsWithoutServerAccessLoggingAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSRightsizeEBSVolumesActionPermissionPolicy + - AWSS3BucketsWithoutServerAccessLoggingActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -689,18 +4205,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSRightsizeEBSVolumes + - AWSS3BucketsWithoutServerAccessLogging - action Resource: "*" - ## AWS Rightsize RDS Instances Permission Policies - iamPolicyAWSRightsizeRDSInstancesRead: + ## AWS S3 Incomplete Multi-Part Uploads + iamPolicyAWSS3IncompleteMultiPartUploadsRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeRDSInstancesRead + Condition: CreatePolicyAWSS3IncompleteMultiPartUploadsRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSRightsizeRDSInstancesReadPermissionPolicy + - AWSS3IncompleteMultiPartUploadsReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -709,17 +4225,17 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSRightsizeRDSInstances + - AWSS3IncompleteMultiPartUploads - read Resource: "*" - iamPolicyAWSRightsizeRDSInstancesAction: + iamPolicyAWSS3IncompleteMultiPartUploadsAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeRDSInstancesAction + Condition: CreatePolicyAWSS3IncompleteMultiPartUploadsAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSRightsizeRDSInstancesActionPermissionPolicy + - AWSS3IncompleteMultiPartUploadsActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -728,18 +4244,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSRightsizeRDSInstances + - AWSS3IncompleteMultiPartUploads - action Resource: "*" - ## AWS Unused IP Addresses Permission Policies - iamPolicyAWSUnusedIPAddressesRead: + ## AWS Savings Plan Recommendations + iamPolicyAWSSavingsPlanRecommendationsRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedIPAddressesRead + Condition: CreatePolicyAWSSavingsPlanRecommendationsRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUnusedIPAddressesReadPermissionPolicy + - AWSSavingsPlanRecommendationsReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -748,17 +4264,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUnusedIPAddresses + - AWSSavingsPlanRecommendations - read Resource: "*" - iamPolicyAWSUnusedIPAddressesAction: + ## AWS Savings Plan Utilization + iamPolicyAWSSavingsPlanUtilizationRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedIPAddressesAction + Condition: CreatePolicyAWSSavingsPlanUtilizationRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUnusedIPAddressesActionPermissionPolicy + - AWSSavingsPlanUtilizationReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -767,18 +4284,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUnusedIPAddresses - - action + - AWSSavingsPlanUtilization + - read Resource: "*" - ## AWS Unused Classic Load Balancers Policies - iamPolicyAWSUnusedCLBsRead: + ## AWS Schedule Instance + iamPolicyAWSScheduleInstanceRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedCLBsRead + Condition: CreatePolicyAWSScheduleInstanceRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUnusedCLBsReadPermissionPolicy + - AWSScheduleInstanceReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -787,17 +4304,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUnusedCLBs + - AWSScheduleInstance - read Resource: "*" - iamPolicyAWSUnusedCLBsAction: + ## AWS Scheduled EC2 Events + iamPolicyAWSScheduledEC2EventsRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedCLBsAction + Condition: CreatePolicyAWSScheduledEC2EventsRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUnusedCLBsActionPermissionPolicy + - AWSScheduledEC2EventsReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -806,18 +4324,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUnusedCLBs - - action + - AWSScheduledEC2Events + - read Resource: "*" - ## AWS Old Snapshots Permission Policies - iamPolicyAWSOldSnapshots: + ## AWS Superseded EBS Volumes + iamPolicyAWSSupersededEBSVolumesRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSOldSnapshotsRead + Condition: CreatePolicyAWSSupersededEBSVolumesRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSOldSnapshotsReadPermissionPolicy + - AWSSupersededEBSVolumesReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -826,17 +4344,17 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSOldSnapshots + - AWSSupersededEBSVolumes - read Resource: "*" - iamPolicyAWSOldSnapshotsAction: + iamPolicyAWSSupersededEBSVolumesAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSOldSnapshotsAction + Condition: CreatePolicyAWSSupersededEBSVolumesAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSOldSnapshotsActionPermissionPolicy + - AWSSupersededEBSVolumesActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -845,18 +4363,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSOldSnapshots + - AWSSupersededEBSVolumes - action Resource: "*" - ## AWS Rightsize EC2 Instances Permission Policies - iamPolicyAWSRightsizeEC2Instances: + ## AWS Superseded EC2 Instances + iamPolicyAWSSupersededEC2InstancesRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEC2InstancesRead + Condition: CreatePolicyAWSSupersededEC2InstancesRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSRightsizeEC2InstancesReadPermissionPolicy + - AWSSupersededEC2InstancesReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -865,17 +4383,17 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSRightsizeEC2Instances + - AWSSupersededEC2Instances - read Resource: "*" - iamPolicyAWSRightsizeEC2InstancesAction: + iamPolicyAWSSupersededEC2InstancesAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEC2InstancesAction + Condition: CreatePolicyAWSSupersededEC2InstancesAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSRightsizeEC2InstancesActionPermissionPolicy + - AWSSupersededEC2InstancesActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -884,11 +4402,11 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSRightsizeEC2Instances + - AWSSupersededEC2Instances - action Resource: "*" - ## AWS Superseded EC2 Instances Permission Policies - iamPolicyAWSSupersededEC2Instances: + ## AWS Superseded EC2 Instances + iamPolicyAWSSupersededEC2InstancesRead: Type: "AWS::IAM::Policy" Condition: CreatePolicyAWSSupersededEC2InstancesRead Properties: @@ -926,15 +4444,35 @@ Resources: - AWSSupersededEC2Instances - action Resource: "*" - ## AWS Reserved Instances Recommendation - iamPolicyAWSReservedInstancesRecommendation: + ## AWS Tag Cardinality Report + iamPolicyAWSTagCardinalityReportRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSTagCardinalityReportRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSTagCardinalityReportReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSTagCardinalityReport + - read + Resource: "*" + ## AWS Unencrypted EBS Volumes + iamPolicyAWSUnencryptedEBSVolumesRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSReservedInstancesRecommendationRead + Condition: CreatePolicyAWSUnencryptedEBSVolumesRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSReservedInstancesRecommendationReadPermissionPolicy + - AWSUnencryptedEBSVolumesReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -943,17 +4481,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSReservedInstancesRecommendation + - AWSUnencryptedEBSVolumes - read Resource: "*" - iamPolicyAWSObjectStorageOptimizationRead: + ## AWS Unencrypted RDS Instances + iamPolicyAWSUnencryptedRDSInstancesRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSObjectStorageOptimizationRead + Condition: CreatePolicyAWSUnencryptedRDSInstancesRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSObjectStorageOptimizationReadPermissionPolicy + - AWSUnencryptedRDSInstancesReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -962,17 +4501,17 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSObjectStorageOptimization + - AWSUnencryptedRDSInstances - read Resource: "*" - iamPolicyAWSObjectStorageOptimizationAction: + iamPolicyAWSUnencryptedRDSInstancesAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSObjectStorageOptimizationAction + Condition: CreatePolicyAWSUnencryptedRDSInstancesAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSObjectStorageOptimizationActionPermissionPolicy + - AWSUnencryptedRDSInstancesActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -981,17 +4520,18 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSObjectStorageOptimization + - AWSUnencryptedRDSInstances - action Resource: "*" - iamPolicyAWSExpiringSavingsPlans: + ## AWS Untagged Resources + iamPolicyAWSUntaggedResourcesRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSExpiringSavingsPlansRead + Condition: CreatePolicyAWSUntaggedResourcesRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSExpiringSavingsPlansReadPermissionPolicy + - AWSUntaggedResourcesReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -1000,17 +4540,17 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSExpiringSavingsPlans + - AWSUntaggedResources - read Resource: "*" - iamPolicyAWSSavingsPlanRecommendations: + iamPolicyAWSUntaggedResourcesAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSavingsPlanRecommendationsRead + Condition: CreatePolicyAWSUntaggedResourcesAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSSavingsPlanRecommendationsReadPermissionPolicy + - AWSUntaggedResourcesActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -1019,17 +4559,37 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSSavingsPlanRecommendations + - AWSUntaggedResources + - action + Resource: "*" + ## AWS Unused Application Load Balancers + iamPolicyAWSUnusedApplicationLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedApplicationLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedApplicationLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedApplicationLoadBalancers - read Resource: "*" - iamPolicyAWSSavingsPlanUtilization: + iamPolicyAWSUnusedApplicationLoadBalancersAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSavingsPlanUtilizationRead + Condition: CreatePolicyAWSUnusedApplicationLoadBalancersAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSSavingsPlanUtilizationReadPermissionPolicy + - AWSUnusedApplicationLoadBalancersActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -1038,17 +4598,37 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSSavingsPlanUtilization + - AWSUnusedApplicationLoadBalancers + - action + Resource: "*" + ## AWS Unused Classic Load Balancers + iamPolicyAWSUnusedClassicLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedClassicLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedClassicLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedClassicLoadBalancers - read Resource: "*" - iamPolicyAWSTagCardinalityReport: + iamPolicyAWSUnusedClassicLoadBalancersAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSTagCardinalityReportRead + Condition: CreatePolicyAWSUnusedClassicLoadBalancersAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSTagCardinalityReportReadPermissionPolicy + - AWSUnusedClassicLoadBalancersActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -1057,17 +4637,37 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSTagCardinalityReport + - AWSUnusedClassicLoadBalancers + - action + Resource: "*" + ## AWS Unused ECS Clusters + iamPolicyAWSUnusedECSClustersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedECSClustersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedECSClustersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedECSClusters - read Resource: "*" - iamPolicyAWSUntaggedResourcesRead: + iamPolicyAWSUnusedECSClustersAction: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUntaggedResourcesRead + Condition: CreatePolicyAWSUnusedECSClustersAction Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUntaggedResourcesReadPermissionPolicy + - AWSUnusedECSClustersActionPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -1076,17 +4676,38 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUntaggedResources + - AWSUnusedECSClusters + - action + Resource: "*" + ## AWS Unused IAM Credentials + iamPolicyAWSUnusedIAMCredentialsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedIAMCredentialsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedIAMCredentialsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedIAMCredentials - read Resource: "*" - iamPolicyAWSUntaggedResourcesAction: + ## AWS Unused IP Addresses + iamPolicyAWSUnusedIPAddressesRead: Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUntaggedResourcesAction + Condition: CreatePolicyAWSUnusedIPAddressesRead Properties: PolicyName: !Join - "_" - - !Ref paramRoleName - - AWSUntaggedResourcesActionPermissionPolicy + - AWSUnusedIPAddressesReadPermissionPolicy Roles: - !Ref iamRole PolicyDocument: @@ -1095,9 +4716,108 @@ Resources: - Effect: Allow Action: !FindInMap - PermissionMap - - AWSUntaggedResources + - AWSUnusedIPAddresses + - read + Resource: "*" + iamPolicyAWSUnusedIPAddressesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedIPAddressesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedIPAddressesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedIPAddresses + - action + Resource: "*" + ## AWS Unused Network Load Balancers + iamPolicyAWSUnusedNetworkLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedNetworkLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedNetworkLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedNetworkLoadBalancers + - read + Resource: "*" + iamPolicyAWSUnusedNetworkLoadBalancersAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedNetworkLoadBalancersAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedNetworkLoadBalancersActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedNetworkLoadBalancers - action Resource: "*" + ## AWS VPCs Without FlowLogs Enabled + iamPolicyAWSVPCsWithoutFlowLogsEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSVPCsWithoutFlowLogsEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSVPCsWithoutFlowLogsEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSVPCsWithoutFlowLogsEnabled + - read + Resource: "*" + ## Common Bill Ingestion from AWS S3 Object Storage + iamPolicyCommonBillIngestionfromAWSS3ObjectStorageRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyCommonBillIngestionfromAWSS3ObjectStorageRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - CommonBillIngestionfromAWSS3ObjectStorageReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - CommonBillIngestionfromAWSS3ObjectStorage + - read + Resource: "*" + # End for each policy template # End IAM Permission Policy Resources diff --git a/tools/cloudformation-template/aws_cft_updater.rb b/tools/cloudformation-template/aws_cft_updater.rb index e69de29bb2..6779ff6a0f 100644 --- a/tools/cloudformation-template/aws_cft_updater.rb +++ b/tools/cloudformation-template/aws_cft_updater.rb @@ -0,0 +1,39 @@ +require "json" +require "time" +require "pathname" +require "digest" +require "fileutils" + +# Method to test if two files are identical +def files_match?(file1, file2) + Digest::SHA256.file(file1).hexdigest == Digest::SHA256.file(file2).hexdigest +end + +# Define the directory containing the files +release_dir = "./releases" +rolling_path = "./rolling/FlexeraAutomationPolicies.template" +local_file_path = "./FlexeraAutomationPolicies.template" + +# Unless the files are identical, create a new version. +unless files_match?(rolling_path, local_file_path) + # Get a list of all template files in the directory + files = Dir.entries(release_dir).select { |file| file =~ /FlexeraAutomationPolicies_v(\d+\.\d+\.\d+)\.template$/ } + + # Extract version numbers and map them to their corresponding files + file_versions = files.map do |file| + match = file.match(/v(\d+\.\d+\.\d+)/) + [file, match[1]] if match + end.compact + + # Find the most recent version + most_recent = file_versions.max_by { |_, version| Gem::Version.new(version) } + most_recent_file, most_recent_version = most_recent + most_recent_path = File.join(release_dir, most_recent_file) + + new_patch_version = (Integer(most_recent_version.split(".")[2]) + 1).to_s + new_version = most_recent_version.split(".")[0] + "." + most_recent_version.split(".")[1] + "." + new_patch_version + new_file_path = release_dir + "/FlexeraAutomationPolicies_v" + new_version + ".template" + + FileUtils.cp(rolling_path, new_file_path, verbose: true) + FileUtils.cp(rolling_path, local_file_path, verbose: true) +end diff --git a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template new file mode 100644 index 0000000000..2f4b8b5b50 --- /dev/null +++ b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template @@ -0,0 +1,4830 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" +# Generated by Flexera automation on 2024-12-12T16:59:05Z +# For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md + +Metadata: + # AWS::CloudFormation::Interface is a metadata key that defines how parameters are grouped and sorted in the AWS CloudFormation console. + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html + AWS::CloudFormation::Interface: + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-parametergroup.html + ParameterGroups: + # ParameterGroup with paramFlexeraOrgId should be first. + # paramFlexeraOrgId only param that is actually required (if Org is on app.flexera.com) + - Label: + default: "Parameters related to your Organization on the Flexera Platform" + Parameters: + - paramFlexeraOrgId + - paramFlexeraZone + - Label: + default: "Parameters related to the IAM Role that is created" + Parameters: + - paramRoleName + - paramRolePath + - Label: + default: "Parameters related to Policy Template permissions on the IAM Role that is created" + Parameters: + ## All AWS Policy Templates + - paramPermsAllAWSPolicyTemplates + ## AWS Account Credentials + - paramPermsAWSAccountCredentials + ## AWS Accounts Missing Service Control Policies + - paramPermsAWSAccountsMissingServiceControlPolicies + ## AWS Burstable EC2 Instances + - paramPermsAWSBurstableEC2Instances + ## AWS CloudTrail Not Enabled In All Regions + - paramPermsAWSCloudTrailNotEnabledInAllRegions + ## AWS CloudTrail S3 Buckets Without Access Logging + - paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging + ## AWS CloudTrails Not Integrated With CloudWatch + - paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch + ## AWS CloudTrails With Read Logging Enabled + - paramPermsAWSCloudTrailsWithReadLoggingEnabled + ## AWS CloudTrails Without Encrypted Logs + - paramPermsAWSCloudTrailsWithoutEncryptedLogs + ## AWS CloudTrails Without Log File Validation Enabled + - paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled + ## AWS CloudTrails Without Object-level Events Logging Enabled + - paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + - paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled + ## AWS Disallowed Regions + - paramPermsAWSDisallowedRegions + ## AWS EC2 Compute Optimizer Recommendations + - paramPermsAWSEC2ComputeOptimizerRecommendations + ## AWS EC2 Instances Time Stopped Report + - paramPermsAWSEC2InstancesTimeStoppedReport + ## AWS EC2 Instances not running FlexNet Inventory Agent + - paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent + ## AWS EKS Clusters Without Spot Instances + - paramPermsAWSEKSClustersWithoutSpotInstances + ## AWS Elastic Load Balancers With Unencrypted Listeners + - paramPermsAWSElasticLoadBalancersWithUnencryptedListeners + ## AWS Expiring Savings Plans + - paramPermsAWSExpiringSavingsPlans + ## AWS IAM Account Missing Support Role + - paramPermsAWSIAMAccountMissingSupportRole + ## AWS IAM Attached Admin Policies + - paramPermsAWSIAMAttachedAdminPolicies + ## AWS IAM Expired SSL/TLS Certificates + - paramPermsAWSIAMExpiredSSLTLSCertificates + ## AWS IAM Insufficient Required Password Length + - paramPermsAWSIAMInsufficientRequiredPasswordLength + ## AWS IAM Password Policy Not Restricting Password Reuse + - paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse + ## AWS IAM Role Audit + - paramPermsAWSIAMRoleAudit + ## AWS IAM Root Account Access Keys + - paramPermsAWSIAMRootAccountAccessKeys + ## AWS IAM Root User Account Without Hardware MFA + - paramPermsAWSIAMRootUserAccountWithoutHardwareMFA + ## AWS IAM Root User Account Without MFA + - paramPermsAWSIAMRootUserAccountWithoutMFA + ## AWS IAM Root User Doing Everyday Tasks + - paramPermsAWSIAMRootUserDoingEverydayTasks + ## AWS IAM User Accounts Without MFA + - paramPermsAWSIAMUserAccountsWithoutMFA + ## AWS IAM Users With Directly-Attached Policies + - paramPermsAWSIAMUsersWithDirectlyAttachedPolicies + ## AWS IAM Users With Multiple Active Access Keys + - paramPermsAWSIAMUsersWithMultipleActiveAccessKeys + ## AWS IAM Users With Old Access Keys + - paramPermsAWSIAMUsersWithOldAccessKeys + ## AWS Idle NAT Gateways + - paramPermsAWSIdleNATGateways + ## AWS Internet-Accessible Elastic Load Balancers + - paramPermsAWSInternetAccessibleElasticLoadBalancers + ## AWS Lambda Functions With High Error Rate + - paramPermsAWSLambdaFunctionsWithHighErrorRate + ## AWS Lambda Functions Without Provisioned Concurrency + - paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency + ## AWS Long Running Instances + - paramPermsAWSLongRunningInstances + ## AWS Long Stopped EC2 Instances + - paramPermsAWSLongStoppedEC2Instances + ## AWS Missing Regions + - paramPermsAWSMissingRegions + ## AWS Old Snapshots + - paramPermsAWSOldSnapshots + ## AWS Open S3 Buckets + - paramPermsAWSOpenS3Buckets + ## AWS Oversized S3 Buckets + - paramPermsAWSOversizedS3Buckets + ## AWS Publicly Accessible CloudTrail S3 Buckets + - paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets + ## AWS Publicly Accessible RDS Instances + - paramPermsAWSPubliclyAccessibleRDSInstances + ## AWS RDS Instances With Unapproved Backup Settings + - paramPermsAWSRDSInstancesWithUnapprovedBackupSettings + ## AWS Regions Without Access Analyzer Enabled + - paramPermsAWSRegionsWithoutAccessAnalyzerEnabled + ## AWS Regions Without Config Fully Enabled + - paramPermsAWSRegionsWithoutConfigFullyEnabled + ## AWS Regions Without Default EBS Encryption + - paramPermsAWSRegionsWithoutDefaultEBSEncryption + ## AWS Reserved Instances Coverage + - paramPermsAWSReservedInstancesCoverage + ## AWS Reserved Instances Recommendations + - paramPermsAWSReservedInstancesRecommendations + ## AWS Rightsize EBS Volumes + - paramPermsAWSRightsizeEBSVolumes + ## AWS Rightsize EC2 Instances + - paramPermsAWSRightsizeEC2Instances + ## AWS Rightsize ElastiCache + - paramPermsAWSRightsizeElastiCache + ## AWS Rightsize RDS Instances + - paramPermsAWSRightsizeRDSInstances + ## AWS Rightsize Redshift + - paramPermsAWSRightsizeRedshift + ## AWS S3 Buckets Accepting HTTP Requests + - paramPermsAWSS3BucketsAcceptingHTTPRequests + ## AWS S3 Buckets Without Default Encryption Configuration + - paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration + ## AWS S3 Buckets Without Intelligent Tiering + - paramPermsAWSS3BucketsWithoutIntelligentTiering + ## AWS S3 Buckets Without Lifecycle Configuration + - paramPermsAWSS3BucketsWithoutLifecycleConfiguration + ## AWS S3 Buckets Without MFA Delete Enabled + - paramPermsAWSS3BucketsWithoutMFADeleteEnabled + ## AWS S3 Buckets Without Public Access Blocked + - paramPermsAWSS3BucketsWithoutPublicAccessBlocked + ## AWS S3 Buckets Without Server Access Logging + - paramPermsAWSS3BucketsWithoutServerAccessLogging + ## AWS S3 Incomplete Multi-Part Uploads + - paramPermsAWSS3IncompleteMultiPartUploads + ## AWS Savings Plan Recommendations + - paramPermsAWSSavingsPlanRecommendations + ## AWS Savings Plan Utilization + - paramPermsAWSSavingsPlanUtilization + ## AWS Schedule Instance + - paramPermsAWSScheduleInstance + ## AWS Scheduled EC2 Events + - paramPermsAWSScheduledEC2Events + ## AWS Superseded EBS Volumes + - paramPermsAWSSupersededEBSVolumes + ## AWS Superseded EC2 Instances + - paramPermsAWSSupersededEC2Instances + ## AWS Superseded EC2 Instances + - paramPermsAWSSupersededEC2Instances + ## AWS Tag Cardinality Report + - paramPermsAWSTagCardinalityReport + ## AWS Unencrypted EBS Volumes + - paramPermsAWSUnencryptedEBSVolumes + ## AWS Unencrypted RDS Instances + - paramPermsAWSUnencryptedRDSInstances + ## AWS Untagged Resources + - paramPermsAWSUntaggedResources + ## AWS Unused Application Load Balancers + - paramPermsAWSUnusedApplicationLoadBalancers + ## AWS Unused Classic Load Balancers + - paramPermsAWSUnusedClassicLoadBalancers + ## AWS Unused ECS Clusters + - paramPermsAWSUnusedECSClusters + ## AWS Unused IAM Credentials + - paramPermsAWSUnusedIAMCredentials + ## AWS Unused IP Addresses + - paramPermsAWSUnusedIPAddresses + ## AWS Unused Network Load Balancers + - paramPermsAWSUnusedNetworkLoadBalancers + ## AWS VPCs Without FlowLogs Enabled + - paramPermsAWSVPCsWithoutFlowLogsEnabled + ## Common Bill Ingestion from AWS S3 Object Storage + - paramPermsCommonBillIngestionfromAWSS3ObjectStorage + + # End for each policy template + - paramPermsAttachExistingPolicies + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-parameterlabel.html + ParameterLabels: + paramRoleName: + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-label.html + # The default label that the CloudFormation console uses to name a parameter group or parameter. + default: "IAM Role Name" + paramRolePath: + default: "IAM Role Path" + paramFlexeraOrgId: + default: "Flexera Organization ID" + paramFlexeraZone: + default: "Flexera Zone" + ## All AWS Policy Templates + paramPermsAllAWSPolicyTemplates: + default: "Permissions for all AWS Policy Templates" + ## AWS Account Credentials + paramPermsAWSAccountCredentials: + default: "Permissions for Policy Template: AWS Account Credentials" + ## AWS Accounts Missing Service Control Policies + paramPermsAWSAccountsMissingServiceControlPolicies: + default: "Permissions for Policy Template: AWS Accounts Missing Service Control Policies" + ## AWS Burstable EC2 Instances + paramPermsAWSBurstableEC2Instances: + default: "Permissions for Policy Template: AWS Burstable EC2 Instances" + ## AWS CloudTrail Not Enabled In All Regions + paramPermsAWSCloudTrailNotEnabledInAllRegions: + default: "Permissions for Policy Template: AWS CloudTrail Not Enabled In All Regions" + ## AWS CloudTrail S3 Buckets Without Access Logging + paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging: + default: "Permissions for Policy Template: AWS CloudTrail S3 Buckets Without Access Logging" + ## AWS CloudTrails Not Integrated With CloudWatch + paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch: + default: "Permissions for Policy Template: AWS CloudTrails Not Integrated With CloudWatch" + ## AWS CloudTrails With Read Logging Enabled + paramPermsAWSCloudTrailsWithReadLoggingEnabled: + default: "Permissions for Policy Template: AWS CloudTrails With Read Logging Enabled" + ## AWS CloudTrails Without Encrypted Logs + paramPermsAWSCloudTrailsWithoutEncryptedLogs: + default: "Permissions for Policy Template: AWS CloudTrails Without Encrypted Logs" + ## AWS CloudTrails Without Log File Validation Enabled + paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled: + default: "Permissions for Policy Template: AWS CloudTrails Without Log File Validation Enabled" + ## AWS CloudTrails Without Object-level Events Logging Enabled + paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: + default: "Permissions for Policy Template: AWS CloudTrails Without Object-level Events Logging Enabled" + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled: + default: "Permissions for Policy Template: AWS Customer Managed Keys (CMKs) Without Rotation Enabled" + ## AWS Disallowed Regions + paramPermsAWSDisallowedRegions: + default: "Permissions for Policy Template: AWS Disallowed Regions" + ## AWS EC2 Compute Optimizer Recommendations + paramPermsAWSEC2ComputeOptimizerRecommendations: + default: "Permissions for Policy Template: AWS EC2 Compute Optimizer Recommendations" + ## AWS EC2 Instances Time Stopped Report + paramPermsAWSEC2InstancesTimeStoppedReport: + default: "Permissions for Policy Template: AWS EC2 Instances Time Stopped Report" + ## AWS EC2 Instances not running FlexNet Inventory Agent + paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent: + default: "Permissions for Policy Template: AWS EC2 Instances not running FlexNet Inventory Agent" + ## AWS EKS Clusters Without Spot Instances + paramPermsAWSEKSClustersWithoutSpotInstances: + default: "Permissions for Policy Template: AWS EKS Clusters Without Spot Instances" + ## AWS Elastic Load Balancers With Unencrypted Listeners + paramPermsAWSElasticLoadBalancersWithUnencryptedListeners: + default: "Permissions for Policy Template: AWS Elastic Load Balancers With Unencrypted Listeners" + ## AWS Expiring Savings Plans + paramPermsAWSExpiringSavingsPlans: + default: "Permissions for Policy Template: AWS Expiring Savings Plans" + ## AWS IAM Account Missing Support Role + paramPermsAWSIAMAccountMissingSupportRole: + default: "Permissions for Policy Template: AWS IAM Account Missing Support Role" + ## AWS IAM Attached Admin Policies + paramPermsAWSIAMAttachedAdminPolicies: + default: "Permissions for Policy Template: AWS IAM Attached Admin Policies" + ## AWS IAM Expired SSL/TLS Certificates + paramPermsAWSIAMExpiredSSLTLSCertificates: + default: "Permissions for Policy Template: AWS IAM Expired SSL/TLS Certificates" + ## AWS IAM Insufficient Required Password Length + paramPermsAWSIAMInsufficientRequiredPasswordLength: + default: "Permissions for Policy Template: AWS IAM Insufficient Required Password Length" + ## AWS IAM Password Policy Not Restricting Password Reuse + paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse: + default: "Permissions for Policy Template: AWS IAM Password Policy Not Restricting Password Reuse" + ## AWS IAM Role Audit + paramPermsAWSIAMRoleAudit: + default: "Permissions for Policy Template: AWS IAM Role Audit" + ## AWS IAM Root Account Access Keys + paramPermsAWSIAMRootAccountAccessKeys: + default: "Permissions for Policy Template: AWS IAM Root Account Access Keys" + ## AWS IAM Root User Account Without Hardware MFA + paramPermsAWSIAMRootUserAccountWithoutHardwareMFA: + default: "Permissions for Policy Template: AWS IAM Root User Account Without Hardware MFA" + ## AWS IAM Root User Account Without MFA + paramPermsAWSIAMRootUserAccountWithoutMFA: + default: "Permissions for Policy Template: AWS IAM Root User Account Without MFA" + ## AWS IAM Root User Doing Everyday Tasks + paramPermsAWSIAMRootUserDoingEverydayTasks: + default: "Permissions for Policy Template: AWS IAM Root User Doing Everyday Tasks" + ## AWS IAM User Accounts Without MFA + paramPermsAWSIAMUserAccountsWithoutMFA: + default: "Permissions for Policy Template: AWS IAM User Accounts Without MFA" + ## AWS IAM Users With Directly-Attached Policies + paramPermsAWSIAMUsersWithDirectlyAttachedPolicies: + default: "Permissions for Policy Template: AWS IAM Users With Directly-Attached Policies" + ## AWS IAM Users With Multiple Active Access Keys + paramPermsAWSIAMUsersWithMultipleActiveAccessKeys: + default: "Permissions for Policy Template: AWS IAM Users With Multiple Active Access Keys" + ## AWS IAM Users With Old Access Keys + paramPermsAWSIAMUsersWithOldAccessKeys: + default: "Permissions for Policy Template: AWS IAM Users With Old Access Keys" + ## AWS Idle NAT Gateways + paramPermsAWSIdleNATGateways: + default: "Permissions for Policy Template: AWS Idle NAT Gateways" + ## AWS Internet-Accessible Elastic Load Balancers + paramPermsAWSInternetAccessibleElasticLoadBalancers: + default: "Permissions for Policy Template: AWS Internet-Accessible Elastic Load Balancers" + ## AWS Lambda Functions With High Error Rate + paramPermsAWSLambdaFunctionsWithHighErrorRate: + default: "Permissions for Policy Template: AWS Lambda Functions With High Error Rate" + ## AWS Lambda Functions Without Provisioned Concurrency + paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency: + default: "Permissions for Policy Template: AWS Lambda Functions Without Provisioned Concurrency" + ## AWS Long Running Instances + paramPermsAWSLongRunningInstances: + default: "Permissions for Policy Template: AWS Long Running Instances" + ## AWS Long Stopped EC2 Instances + paramPermsAWSLongStoppedEC2Instances: + default: "Permissions for Policy Template: AWS Long Stopped EC2 Instances" + ## AWS Missing Regions + paramPermsAWSMissingRegions: + default: "Permissions for Policy Template: AWS Missing Regions" + ## AWS Old Snapshots + paramPermsAWSOldSnapshots: + default: "Permissions for Policy Template: AWS Old Snapshots" + ## AWS Open S3 Buckets + paramPermsAWSOpenS3Buckets: + default: "Permissions for Policy Template: AWS Open S3 Buckets" + ## AWS Oversized S3 Buckets + paramPermsAWSOversizedS3Buckets: + default: "Permissions for Policy Template: AWS Oversized S3 Buckets" + ## AWS Publicly Accessible CloudTrail S3 Buckets + paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets: + default: "Permissions for Policy Template: AWS Publicly Accessible CloudTrail S3 Buckets" + ## AWS Publicly Accessible RDS Instances + paramPermsAWSPubliclyAccessibleRDSInstances: + default: "Permissions for Policy Template: AWS Publicly Accessible RDS Instances" + ## AWS RDS Instances With Unapproved Backup Settings + paramPermsAWSRDSInstancesWithUnapprovedBackupSettings: + default: "Permissions for Policy Template: AWS RDS Instances With Unapproved Backup Settings" + ## AWS Regions Without Access Analyzer Enabled + paramPermsAWSRegionsWithoutAccessAnalyzerEnabled: + default: "Permissions for Policy Template: AWS Regions Without Access Analyzer Enabled" + ## AWS Regions Without Config Fully Enabled + paramPermsAWSRegionsWithoutConfigFullyEnabled: + default: "Permissions for Policy Template: AWS Regions Without Config Fully Enabled" + ## AWS Regions Without Default EBS Encryption + paramPermsAWSRegionsWithoutDefaultEBSEncryption: + default: "Permissions for Policy Template: AWS Regions Without Default EBS Encryption" + ## AWS Reserved Instances Coverage + paramPermsAWSReservedInstancesCoverage: + default: "Permissions for Policy Template: AWS Reserved Instances Coverage" + ## AWS Reserved Instances Recommendations + paramPermsAWSReservedInstancesRecommendations: + default: "Permissions for Policy Template: AWS Reserved Instances Recommendations" + ## AWS Rightsize EBS Volumes + paramPermsAWSRightsizeEBSVolumes: + default: "Permissions for Policy Template: AWS Rightsize EBS Volumes" + ## AWS Rightsize EC2 Instances + paramPermsAWSRightsizeEC2Instances: + default: "Permissions for Policy Template: AWS Rightsize EC2 Instances" + ## AWS Rightsize ElastiCache + paramPermsAWSRightsizeElastiCache: + default: "Permissions for Policy Template: AWS Rightsize ElastiCache" + ## AWS Rightsize RDS Instances + paramPermsAWSRightsizeRDSInstances: + default: "Permissions for Policy Template: AWS Rightsize RDS Instances" + ## AWS Rightsize Redshift + paramPermsAWSRightsizeRedshift: + default: "Permissions for Policy Template: AWS Rightsize Redshift" + ## AWS S3 Buckets Accepting HTTP Requests + paramPermsAWSS3BucketsAcceptingHTTPRequests: + default: "Permissions for Policy Template: AWS S3 Buckets Accepting HTTP Requests" + ## AWS S3 Buckets Without Default Encryption Configuration + paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration: + default: "Permissions for Policy Template: AWS S3 Buckets Without Default Encryption Configuration" + ## AWS S3 Buckets Without Intelligent Tiering + paramPermsAWSS3BucketsWithoutIntelligentTiering: + default: "Permissions for Policy Template: AWS S3 Buckets Without Intelligent Tiering" + ## AWS S3 Buckets Without Lifecycle Configuration + paramPermsAWSS3BucketsWithoutLifecycleConfiguration: + default: "Permissions for Policy Template: AWS S3 Buckets Without Lifecycle Configuration" + ## AWS S3 Buckets Without MFA Delete Enabled + paramPermsAWSS3BucketsWithoutMFADeleteEnabled: + default: "Permissions for Policy Template: AWS S3 Buckets Without MFA Delete Enabled" + ## AWS S3 Buckets Without Public Access Blocked + paramPermsAWSS3BucketsWithoutPublicAccessBlocked: + default: "Permissions for Policy Template: AWS S3 Buckets Without Public Access Blocked" + ## AWS S3 Buckets Without Server Access Logging + paramPermsAWSS3BucketsWithoutServerAccessLogging: + default: "Permissions for Policy Template: AWS S3 Buckets Without Server Access Logging" + ## AWS S3 Incomplete Multi-Part Uploads + paramPermsAWSS3IncompleteMultiPartUploads: + default: "Permissions for Policy Template: AWS S3 Incomplete Multi-Part Uploads" + ## AWS Savings Plan Recommendations + paramPermsAWSSavingsPlanRecommendations: + default: "Permissions for Policy Template: AWS Savings Plan Recommendations" + ## AWS Savings Plan Utilization + paramPermsAWSSavingsPlanUtilization: + default: "Permissions for Policy Template: AWS Savings Plan Utilization" + ## AWS Schedule Instance + paramPermsAWSScheduleInstance: + default: "Permissions for Policy Template: AWS Schedule Instance" + ## AWS Scheduled EC2 Events + paramPermsAWSScheduledEC2Events: + default: "Permissions for Policy Template: AWS Scheduled EC2 Events" + ## AWS Superseded EBS Volumes + paramPermsAWSSupersededEBSVolumes: + default: "Permissions for Policy Template: AWS Superseded EBS Volumes" + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + default: "Permissions for Policy Template: AWS Superseded EC2 Instances" + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + default: "Permissions for Policy Template: AWS Superseded EC2 Instances" + ## AWS Tag Cardinality Report + paramPermsAWSTagCardinalityReport: + default: "Permissions for Policy Template: AWS Tag Cardinality Report" + ## AWS Unencrypted EBS Volumes + paramPermsAWSUnencryptedEBSVolumes: + default: "Permissions for Policy Template: AWS Unencrypted EBS Volumes" + ## AWS Unencrypted RDS Instances + paramPermsAWSUnencryptedRDSInstances: + default: "Permissions for Policy Template: AWS Unencrypted RDS Instances" + ## AWS Untagged Resources + paramPermsAWSUntaggedResources: + default: "Permissions for Policy Template: AWS Untagged Resources" + ## AWS Unused Application Load Balancers + paramPermsAWSUnusedApplicationLoadBalancers: + default: "Permissions for Policy Template: AWS Unused Application Load Balancers" + ## AWS Unused Classic Load Balancers + paramPermsAWSUnusedClassicLoadBalancers: + default: "Permissions for Policy Template: AWS Unused Classic Load Balancers" + ## AWS Unused ECS Clusters + paramPermsAWSUnusedECSClusters: + default: "Permissions for Policy Template: AWS Unused ECS Clusters" + ## AWS Unused IAM Credentials + paramPermsAWSUnusedIAMCredentials: + default: "Permissions for Policy Template: AWS Unused IAM Credentials" + ## AWS Unused IP Addresses + paramPermsAWSUnusedIPAddresses: + default: "Permissions for Policy Template: AWS Unused IP Addresses" + ## AWS Unused Network Load Balancers + paramPermsAWSUnusedNetworkLoadBalancers: + default: "Permissions for Policy Template: AWS Unused Network Load Balancers" + ## AWS VPCs Without FlowLogs Enabled + paramPermsAWSVPCsWithoutFlowLogsEnabled: + default: "Permissions for Policy Template: AWS VPCs Without FlowLogs Enabled" + ## Common Bill Ingestion from AWS S3 Object Storage + paramPermsCommonBillIngestionfromAWSS3ObjectStorage: + default: "Permissions for Policy Template: Common Bill Ingestion from AWS S3 Object Storage" + + # End for each policy template + paramPermsAttachExistingPolicies: + default: "Additional IAM Permission Policies for IAM Role" + +Parameters: + # ParameterGroup: Parameters related to your Organization on the Flexera Platform + paramFlexeraOrgId: + Description: >- + The Organization ID in Flexera which trust will be granted to use the IAM Role that will be created + Type: String + AllowedPattern: "[0-9]+" + MinLength: 1 + ConstraintDescription: Organization ID must be provided and match regex [0-9]+ + paramFlexeraZone: + Description: >- + The Flexera Zone which trust will be granted to. The Organization ID should be located in this Flexera Zone. + Type: String + Default: app.flexera.com + AllowedValues: + - app.flexera.com + - app.flexera.eu + - app.flexera.au + - app.flexeratest.com + + # ParameterGroup: Parameters for the IAM Role that is created + paramRoleName: + Description: Name of the the IAM Role that will be created. If you plan to create more than one IAM Role (i.e. one for each Policy Template, or to trust multiple Orgs) you will need to modify this to prevent naming conflict. + Type: String + Default: FlexeraAutomationAccessRole + # IAM Role Name Max Length is 64chars + MaxLength: 64 + paramRolePath: + Description: Path for the IAM Role that will be created. Generally does not need to be modified. + Type: String + Default: / + + # ParameterGroup: Parameters to define Policy Template permissions on the IAM Role that is created + ## All AWS Policy Templates + paramPermsAllAWSPolicyTemplates: + Description: 'What permissions for all AWS Policy Templates should be granted on the AWS Role that will be created? Note that the more granular permissions below only need to be enabled if this option is disabled or you want to grant access to take actions only for specific policy templates.' + Type: String + Default: Read Only + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Account Credentials + paramPermsAWSAccountCredentials: + Description: 'What permissions for the "AWS Account Credentials" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Accounts Missing Service Control Policies + paramPermsAWSAccountsMissingServiceControlPolicies: + Description: 'What permissions for the "AWS Accounts Missing Service Control Policies" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Burstable EC2 Instances + paramPermsAWSBurstableEC2Instances: + Description: 'What permissions for the "AWS Burstable EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS CloudTrail Not Enabled In All Regions + paramPermsAWSCloudTrailNotEnabledInAllRegions: + Description: 'What permissions for the "AWS CloudTrail Not Enabled In All Regions" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrail S3 Buckets Without Access Logging + paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging: + Description: 'What permissions for the "AWS CloudTrail S3 Buckets Without Access Logging" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails Not Integrated With CloudWatch + paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch: + Description: 'What permissions for the "AWS CloudTrails Not Integrated With CloudWatch" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails With Read Logging Enabled + paramPermsAWSCloudTrailsWithReadLoggingEnabled: + Description: 'What permissions for the "AWS CloudTrails With Read Logging Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS CloudTrails Without Encrypted Logs + paramPermsAWSCloudTrailsWithoutEncryptedLogs: + Description: 'What permissions for the "AWS CloudTrails Without Encrypted Logs" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails Without Log File Validation Enabled + paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled: + Description: 'What permissions for the "AWS CloudTrails Without Log File Validation Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS CloudTrails Without Object-level Events Logging Enabled + paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: + Description: 'What permissions for the "AWS CloudTrails Without Object-level Events Logging Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled: + Description: 'What permissions for the "AWS Customer Managed Keys (CMKs) Without Rotation Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Disallowed Regions + paramPermsAWSDisallowedRegions: + Description: 'What permissions for the "AWS Disallowed Regions" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS EC2 Compute Optimizer Recommendations + paramPermsAWSEC2ComputeOptimizerRecommendations: + Description: 'What permissions for the "AWS EC2 Compute Optimizer Recommendations" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS EC2 Instances Time Stopped Report + paramPermsAWSEC2InstancesTimeStoppedReport: + Description: 'What permissions for the "AWS EC2 Instances Time Stopped Report" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS EC2 Instances not running FlexNet Inventory Agent + paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent: + Description: 'What permissions for the "AWS EC2 Instances not running FlexNet Inventory Agent" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS EKS Clusters Without Spot Instances + paramPermsAWSEKSClustersWithoutSpotInstances: + Description: 'What permissions for the "AWS EKS Clusters Without Spot Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Elastic Load Balancers With Unencrypted Listeners + paramPermsAWSElasticLoadBalancersWithUnencryptedListeners: + Description: 'What permissions for the "AWS Elastic Load Balancers With Unencrypted Listeners" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Expiring Savings Plans + paramPermsAWSExpiringSavingsPlans: + Description: 'What permissions for the "AWS Expiring Savings Plans" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Account Missing Support Role + paramPermsAWSIAMAccountMissingSupportRole: + Description: 'What permissions for the "AWS IAM Account Missing Support Role" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Attached Admin Policies + paramPermsAWSIAMAttachedAdminPolicies: + Description: 'What permissions for the "AWS IAM Attached Admin Policies" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Expired SSL/TLS Certificates + paramPermsAWSIAMExpiredSSLTLSCertificates: + Description: 'What permissions for the "AWS IAM Expired SSL/TLS Certificates" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Insufficient Required Password Length + paramPermsAWSIAMInsufficientRequiredPasswordLength: + Description: 'What permissions for the "AWS IAM Insufficient Required Password Length" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Password Policy Not Restricting Password Reuse + paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse: + Description: 'What permissions for the "AWS IAM Password Policy Not Restricting Password Reuse" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Role Audit + paramPermsAWSIAMRoleAudit: + Description: 'What permissions for the "AWS IAM Role Audit" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root Account Access Keys + paramPermsAWSIAMRootAccountAccessKeys: + Description: 'What permissions for the "AWS IAM Root Account Access Keys" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root User Account Without Hardware MFA + paramPermsAWSIAMRootUserAccountWithoutHardwareMFA: + Description: 'What permissions for the "AWS IAM Root User Account Without Hardware MFA" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root User Account Without MFA + paramPermsAWSIAMRootUserAccountWithoutMFA: + Description: 'What permissions for the "AWS IAM Root User Account Without MFA" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Root User Doing Everyday Tasks + paramPermsAWSIAMRootUserDoingEverydayTasks: + Description: 'What permissions for the "AWS IAM Root User Doing Everyday Tasks" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM User Accounts Without MFA + paramPermsAWSIAMUserAccountsWithoutMFA: + Description: 'What permissions for the "AWS IAM User Accounts Without MFA" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Users With Directly-Attached Policies + paramPermsAWSIAMUsersWithDirectlyAttachedPolicies: + Description: 'What permissions for the "AWS IAM Users With Directly-Attached Policies" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Users With Multiple Active Access Keys + paramPermsAWSIAMUsersWithMultipleActiveAccessKeys: + Description: 'What permissions for the "AWS IAM Users With Multiple Active Access Keys" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS IAM Users With Old Access Keys + paramPermsAWSIAMUsersWithOldAccessKeys: + Description: 'What permissions for the "AWS IAM Users With Old Access Keys" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Idle NAT Gateways + paramPermsAWSIdleNATGateways: + Description: 'What permissions for the "AWS Idle NAT Gateways" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Internet-Accessible Elastic Load Balancers + paramPermsAWSInternetAccessibleElasticLoadBalancers: + Description: 'What permissions for the "AWS Internet-Accessible Elastic Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Lambda Functions With High Error Rate + paramPermsAWSLambdaFunctionsWithHighErrorRate: + Description: 'What permissions for the "AWS Lambda Functions With High Error Rate" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Lambda Functions Without Provisioned Concurrency + paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency: + Description: 'What permissions for the "AWS Lambda Functions Without Provisioned Concurrency" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Long Running Instances + paramPermsAWSLongRunningInstances: + Description: 'What permissions for the "AWS Long Running Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Long Stopped EC2 Instances + paramPermsAWSLongStoppedEC2Instances: + Description: 'What permissions for the "AWS Long Stopped EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Missing Regions + paramPermsAWSMissingRegions: + Description: 'What permissions for the "AWS Missing Regions" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Old Snapshots + paramPermsAWSOldSnapshots: + Description: 'What permissions for the "AWS Old Snapshots" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Open S3 Buckets + paramPermsAWSOpenS3Buckets: + Description: 'What permissions for the "AWS Open S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Oversized S3 Buckets + paramPermsAWSOversizedS3Buckets: + Description: 'What permissions for the "AWS Oversized S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Publicly Accessible CloudTrail S3 Buckets + paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets: + Description: 'What permissions for the "AWS Publicly Accessible CloudTrail S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Publicly Accessible RDS Instances + paramPermsAWSPubliclyAccessibleRDSInstances: + Description: 'What permissions for the "AWS Publicly Accessible RDS Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS RDS Instances With Unapproved Backup Settings + paramPermsAWSRDSInstancesWithUnapprovedBackupSettings: + Description: 'What permissions for the "AWS RDS Instances With Unapproved Backup Settings" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Regions Without Access Analyzer Enabled + paramPermsAWSRegionsWithoutAccessAnalyzerEnabled: + Description: 'What permissions for the "AWS Regions Without Access Analyzer Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Regions Without Config Fully Enabled + paramPermsAWSRegionsWithoutConfigFullyEnabled: + Description: 'What permissions for the "AWS Regions Without Config Fully Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Regions Without Default EBS Encryption + paramPermsAWSRegionsWithoutDefaultEBSEncryption: + Description: 'What permissions for the "AWS Regions Without Default EBS Encryption" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Reserved Instances Coverage + paramPermsAWSReservedInstancesCoverage: + Description: 'What permissions for the "AWS Reserved Instances Coverage" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Reserved Instances Recommendations + paramPermsAWSReservedInstancesRecommendations: + Description: 'What permissions for the "AWS Reserved Instances Recommendations" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Rightsize EBS Volumes + paramPermsAWSRightsizeEBSVolumes: + Description: 'What permissions for the "AWS Rightsize EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Rightsize EC2 Instances + paramPermsAWSRightsizeEC2Instances: + Description: 'What permissions for the "AWS Rightsize EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Rightsize ElastiCache + paramPermsAWSRightsizeElastiCache: + Description: 'What permissions for the "AWS Rightsize ElastiCache" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Rightsize RDS Instances + paramPermsAWSRightsizeRDSInstances: + Description: 'What permissions for the "AWS Rightsize RDS Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Rightsize Redshift + paramPermsAWSRightsizeRedshift: + Description: 'What permissions for the "AWS Rightsize Redshift" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS S3 Buckets Accepting HTTP Requests + paramPermsAWSS3BucketsAcceptingHTTPRequests: + Description: 'What permissions for the "AWS S3 Buckets Accepting HTTP Requests" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Default Encryption Configuration + paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration: + Description: 'What permissions for the "AWS S3 Buckets Without Default Encryption Configuration" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS S3 Buckets Without Intelligent Tiering + paramPermsAWSS3BucketsWithoutIntelligentTiering: + Description: 'What permissions for the "AWS S3 Buckets Without Intelligent Tiering" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Lifecycle Configuration + paramPermsAWSS3BucketsWithoutLifecycleConfiguration: + Description: 'What permissions for the "AWS S3 Buckets Without Lifecycle Configuration" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without MFA Delete Enabled + paramPermsAWSS3BucketsWithoutMFADeleteEnabled: + Description: 'What permissions for the "AWS S3 Buckets Without MFA Delete Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Public Access Blocked + paramPermsAWSS3BucketsWithoutPublicAccessBlocked: + Description: 'What permissions for the "AWS S3 Buckets Without Public Access Blocked" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS S3 Buckets Without Server Access Logging + paramPermsAWSS3BucketsWithoutServerAccessLogging: + Description: 'What permissions for the "AWS S3 Buckets Without Server Access Logging" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS S3 Incomplete Multi-Part Uploads + paramPermsAWSS3IncompleteMultiPartUploads: + Description: 'What permissions for the "AWS S3 Incomplete Multi-Part Uploads" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Savings Plan Recommendations + paramPermsAWSSavingsPlanRecommendations: + Description: 'What permissions for the "AWS Savings Plan Recommendations" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Savings Plan Utilization + paramPermsAWSSavingsPlanUtilization: + Description: 'What permissions for the "AWS Savings Plan Utilization" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Schedule Instance + paramPermsAWSScheduleInstance: + Description: 'What permissions for the "AWS Schedule Instance" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Scheduled EC2 Events + paramPermsAWSScheduledEC2Events: + Description: 'What permissions for the "AWS Scheduled EC2 Events" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Superseded EBS Volumes + paramPermsAWSSupersededEBSVolumes: + Description: 'What permissions for the "AWS Superseded EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Superseded EC2 Instances + paramPermsAWSSupersededEC2Instances: + Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Tag Cardinality Report + paramPermsAWSTagCardinalityReport: + Description: 'What permissions for the "AWS Tag Cardinality Report" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Unencrypted EBS Volumes + paramPermsAWSUnencryptedEBSVolumes: + Description: 'What permissions for the "AWS Unencrypted EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Unencrypted RDS Instances + paramPermsAWSUnencryptedRDSInstances: + Description: 'What permissions for the "AWS Unencrypted RDS Instances" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Untagged Resources + paramPermsAWSUntaggedResources: + Description: 'What permissions for the "AWS Untagged Resources" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused Application Load Balancers + paramPermsAWSUnusedApplicationLoadBalancers: + Description: 'What permissions for the "AWS Unused Application Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused Classic Load Balancers + paramPermsAWSUnusedClassicLoadBalancers: + Description: 'What permissions for the "AWS Unused Classic Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused ECS Clusters + paramPermsAWSUnusedECSClusters: + Description: 'What permissions for the "AWS Unused ECS Clusters" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused IAM Credentials + paramPermsAWSUnusedIAMCredentials: + Description: 'What permissions for the "AWS Unused IAM Credentials" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## AWS Unused IP Addresses + paramPermsAWSUnusedIPAddresses: + Description: 'What permissions for the "AWS Unused IP Addresses" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS Unused Network Load Balancers + paramPermsAWSUnusedNetworkLoadBalancers: + Description: 'What permissions for the "AWS Unused Network Load Balancers" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + - Read and Take Action + ## AWS VPCs Without FlowLogs Enabled + paramPermsAWSVPCsWithoutFlowLogsEnabled: + Description: 'What permissions for the "AWS VPCs Without FlowLogs Enabled" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + ## Common Bill Ingestion from AWS S3 Object Storage + paramPermsCommonBillIngestionfromAWSS3ObjectStorage: + Description: 'What permissions for the "Common Bill Ingestion from AWS S3 Object Storage" Policy Template should be granted on the AWS Role that will be created?' + Type: String + Default: None + AllowedValues: + - None + - Read Only + + # End for each policy template + paramPermsAttachExistingPolicies: + Description: 'Existing IAM Permission Policies to attach to the IAM Role that will be created. Optional, comma separated list of IAM Policy ARNs -- i.e. arn:aws:iam::aws:policy/ReadOnlyAccess' + Type: String + # AWS Managed Policy ARN: arn:aws:iam::aws:policy/ReadOnlyAccess + # Customer Managed Policy ARN: arn:aws:iam::123456789012:policy/CustomPolicy + AllowedPattern: '^((arn:aws:iam::(\d{12}|aws)?:policy\/[\w+=,.@-]{1,128})(,)?)*$' + ConstraintDescription: 'Malformed IAM Policy ARN. Must match pattern ^((arn:aws:iam::(\d{12}|aws)?:policy\/[\w+=,.@-]{1,128})(,)?)*$' + +Conditions: + ## All AWS Policy Templates + CreatePolicyAllAWSPolicyTemplatesRead: !Not + - !Equals + - !Ref paramPermsAllAWSPolicyTemplates + - None + CreatePolicyAllAWSPolicyTemplatesAction: !Equals + - !Ref paramPermsAllAWSPolicyTemplates + - Read and Take Action + ## AWS Account Credentials + CreatePolicyAWSAccountCredentialsRead: !Not + - !Equals + - !Ref paramPermsAWSAccountCredentials + - None + ## AWS Accounts Missing Service Control Policies + CreatePolicyAWSAccountsMissingServiceControlPoliciesRead: !Not + - !Equals + - !Ref paramPermsAWSAccountsMissingServiceControlPolicies + - None + ## AWS Burstable EC2 Instances + CreatePolicyAWSBurstableEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSBurstableEC2Instances + - None + CreatePolicyAWSBurstableEC2InstancesAction: !Equals + - !Ref paramPermsAWSBurstableEC2Instances + - Read and Take Action + ## AWS CloudTrail Not Enabled In All Regions + CreatePolicyAWSCloudTrailNotEnabledInAllRegionsRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailNotEnabledInAllRegions + - None + ## AWS CloudTrail S3 Buckets Without Access Logging + CreatePolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging + - None + ## AWS CloudTrails Not Integrated With CloudWatch + CreatePolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch + - None + ## AWS CloudTrails With Read Logging Enabled + CreatePolicyAWSCloudTrailsWithReadLoggingEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsWithReadLoggingEnabled + - None + CreatePolicyAWSCloudTrailsWithReadLoggingEnabledAction: !Equals + - !Ref paramPermsAWSCloudTrailsWithReadLoggingEnabled + - Read and Take Action + ## AWS CloudTrails Without Encrypted Logs + CreatePolicyAWSCloudTrailsWithoutEncryptedLogsRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsWithoutEncryptedLogs + - None + ## AWS CloudTrails Without Log File Validation Enabled + CreatePolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled + - None + ## AWS CloudTrails Without Object-level Events Logging Enabled + CreatePolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled + - None + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + CreatePolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled + - None + ## AWS Disallowed Regions + CreatePolicyAWSDisallowedRegionsRead: !Not + - !Equals + - !Ref paramPermsAWSDisallowedRegions + - None + CreatePolicyAWSDisallowedRegionsAction: !Equals + - !Ref paramPermsAWSDisallowedRegions + - Read and Take Action + ## AWS EC2 Compute Optimizer Recommendations + CreatePolicyAWSEC2ComputeOptimizerRecommendationsRead: !Not + - !Equals + - !Ref paramPermsAWSEC2ComputeOptimizerRecommendations + - None + CreatePolicyAWSEC2ComputeOptimizerRecommendationsAction: !Equals + - !Ref paramPermsAWSEC2ComputeOptimizerRecommendations + - Read and Take Action + ## AWS EC2 Instances Time Stopped Report + CreatePolicyAWSEC2InstancesTimeStoppedReportRead: !Not + - !Equals + - !Ref paramPermsAWSEC2InstancesTimeStoppedReport + - None + CreatePolicyAWSEC2InstancesTimeStoppedReportAction: !Equals + - !Ref paramPermsAWSEC2InstancesTimeStoppedReport + - Read and Take Action + ## AWS EC2 Instances not running FlexNet Inventory Agent + CreatePolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead: !Not + - !Equals + - !Ref paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent + - None + ## AWS EKS Clusters Without Spot Instances + CreatePolicyAWSEKSClustersWithoutSpotInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSEKSClustersWithoutSpotInstances + - None + ## AWS Elastic Load Balancers With Unencrypted Listeners + CreatePolicyAWSElasticLoadBalancersWithUnencryptedListenersRead: !Not + - !Equals + - !Ref paramPermsAWSElasticLoadBalancersWithUnencryptedListeners + - None + ## AWS Expiring Savings Plans + CreatePolicyAWSExpiringSavingsPlansRead: !Not + - !Equals + - !Ref paramPermsAWSExpiringSavingsPlans + - None + ## AWS IAM Account Missing Support Role + CreatePolicyAWSIAMAccountMissingSupportRoleRead: !Not + - !Equals + - !Ref paramPermsAWSIAMAccountMissingSupportRole + - None + ## AWS IAM Attached Admin Policies + CreatePolicyAWSIAMAttachedAdminPoliciesRead: !Not + - !Equals + - !Ref paramPermsAWSIAMAttachedAdminPolicies + - None + ## AWS IAM Expired SSL/TLS Certificates + CreatePolicyAWSIAMExpiredSSLTLSCertificatesRead: !Not + - !Equals + - !Ref paramPermsAWSIAMExpiredSSLTLSCertificates + - None + ## AWS IAM Insufficient Required Password Length + CreatePolicyAWSIAMInsufficientRequiredPasswordLengthRead: !Not + - !Equals + - !Ref paramPermsAWSIAMInsufficientRequiredPasswordLength + - None + ## AWS IAM Password Policy Not Restricting Password Reuse + CreatePolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead: !Not + - !Equals + - !Ref paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse + - None + ## AWS IAM Role Audit + CreatePolicyAWSIAMRoleAuditRead: !Not + - !Equals + - !Ref paramPermsAWSIAMRoleAudit + - None + ## AWS IAM Root Account Access Keys + CreatePolicyAWSIAMRootAccountAccessKeysRead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootAccountAccessKeys + - None + ## AWS IAM Root User Account Without Hardware MFA + CreatePolicyAWSIAMRootUserAccountWithoutHardwareMFARead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootUserAccountWithoutHardwareMFA + - None + ## AWS IAM Root User Account Without MFA + CreatePolicyAWSIAMRootUserAccountWithoutMFARead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootUserAccountWithoutMFA + - None + ## AWS IAM Root User Doing Everyday Tasks + CreatePolicyAWSIAMRootUserDoingEverydayTasksRead: !Not + - !Equals + - !Ref paramPermsAWSIAMRootUserDoingEverydayTasks + - None + ## AWS IAM User Accounts Without MFA + CreatePolicyAWSIAMUserAccountsWithoutMFARead: !Not + - !Equals + - !Ref paramPermsAWSIAMUserAccountsWithoutMFA + - None + ## AWS IAM Users With Directly-Attached Policies + CreatePolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead: !Not + - !Equals + - !Ref paramPermsAWSIAMUsersWithDirectlyAttachedPolicies + - None + ## AWS IAM Users With Multiple Active Access Keys + CreatePolicyAWSIAMUsersWithMultipleActiveAccessKeysRead: !Not + - !Equals + - !Ref paramPermsAWSIAMUsersWithMultipleActiveAccessKeys + - None + ## AWS IAM Users With Old Access Keys + CreatePolicyAWSIAMUsersWithOldAccessKeysRead: !Not + - !Equals + - !Ref paramPermsAWSIAMUsersWithOldAccessKeys + - None + ## AWS Idle NAT Gateways + CreatePolicyAWSIdleNATGatewaysRead: !Not + - !Equals + - !Ref paramPermsAWSIdleNATGateways + - None + CreatePolicyAWSIdleNATGatewaysAction: !Equals + - !Ref paramPermsAWSIdleNATGateways + - Read and Take Action + ## AWS Internet-Accessible Elastic Load Balancers + CreatePolicyAWSInternetAccessibleElasticLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSInternetAccessibleElasticLoadBalancers + - None + CreatePolicyAWSInternetAccessibleElasticLoadBalancersAction: !Equals + - !Ref paramPermsAWSInternetAccessibleElasticLoadBalancers + - Read and Take Action + ## AWS Lambda Functions With High Error Rate + CreatePolicyAWSLambdaFunctionsWithHighErrorRateRead: !Not + - !Equals + - !Ref paramPermsAWSLambdaFunctionsWithHighErrorRate + - None + ## AWS Lambda Functions Without Provisioned Concurrency + CreatePolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead: !Not + - !Equals + - !Ref paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency + - None + ## AWS Long Running Instances + CreatePolicyAWSLongRunningInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSLongRunningInstances + - None + CreatePolicyAWSLongRunningInstancesAction: !Equals + - !Ref paramPermsAWSLongRunningInstances + - Read and Take Action + ## AWS Long Stopped EC2 Instances + CreatePolicyAWSLongStoppedEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSLongStoppedEC2Instances + - None + CreatePolicyAWSLongStoppedEC2InstancesAction: !Equals + - !Ref paramPermsAWSLongStoppedEC2Instances + - Read and Take Action + ## AWS Missing Regions + CreatePolicyAWSMissingRegionsRead: !Not + - !Equals + - !Ref paramPermsAWSMissingRegions + - None + ## AWS Old Snapshots + CreatePolicyAWSOldSnapshotsRead: !Not + - !Equals + - !Ref paramPermsAWSOldSnapshots + - None + CreatePolicyAWSOldSnapshotsAction: !Equals + - !Ref paramPermsAWSOldSnapshots + - Read and Take Action + ## AWS Open S3 Buckets + CreatePolicyAWSOpenS3BucketsRead: !Not + - !Equals + - !Ref paramPermsAWSOpenS3Buckets + - None + ## AWS Oversized S3 Buckets + CreatePolicyAWSOversizedS3BucketsRead: !Not + - !Equals + - !Ref paramPermsAWSOversizedS3Buckets + - None + ## AWS Publicly Accessible CloudTrail S3 Buckets + CreatePolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead: !Not + - !Equals + - !Ref paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets + - None + ## AWS Publicly Accessible RDS Instances + CreatePolicyAWSPubliclyAccessibleRDSInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSPubliclyAccessibleRDSInstances + - None + CreatePolicyAWSPubliclyAccessibleRDSInstancesAction: !Equals + - !Ref paramPermsAWSPubliclyAccessibleRDSInstances + - Read and Take Action + ## AWS RDS Instances With Unapproved Backup Settings + CreatePolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead: !Not + - !Equals + - !Ref paramPermsAWSRDSInstancesWithUnapprovedBackupSettings + - None + ## AWS Regions Without Access Analyzer Enabled + CreatePolicyAWSRegionsWithoutAccessAnalyzerEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSRegionsWithoutAccessAnalyzerEnabled + - None + ## AWS Regions Without Config Fully Enabled + CreatePolicyAWSRegionsWithoutConfigFullyEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSRegionsWithoutConfigFullyEnabled + - None + ## AWS Regions Without Default EBS Encryption + CreatePolicyAWSRegionsWithoutDefaultEBSEncryptionRead: !Not + - !Equals + - !Ref paramPermsAWSRegionsWithoutDefaultEBSEncryption + - None + ## AWS Reserved Instances Coverage + CreatePolicyAWSReservedInstancesCoverageRead: !Not + - !Equals + - !Ref paramPermsAWSReservedInstancesCoverage + - None + ## AWS Reserved Instances Recommendations + CreatePolicyAWSReservedInstancesRecommendationsRead: !Not + - !Equals + - !Ref paramPermsAWSReservedInstancesRecommendations + - None + ## AWS Rightsize EBS Volumes + CreatePolicyAWSRightsizeEBSVolumesRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeEBSVolumes + - None + CreatePolicyAWSRightsizeEBSVolumesAction: !Equals + - !Ref paramPermsAWSRightsizeEBSVolumes + - Read and Take Action + ## AWS Rightsize EC2 Instances + CreatePolicyAWSRightsizeEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeEC2Instances + - None + CreatePolicyAWSRightsizeEC2InstancesAction: !Equals + - !Ref paramPermsAWSRightsizeEC2Instances + - Read and Take Action + ## AWS Rightsize ElastiCache + CreatePolicyAWSRightsizeElastiCacheRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeElastiCache + - None + CreatePolicyAWSRightsizeElastiCacheAction: !Equals + - !Ref paramPermsAWSRightsizeElastiCache + - Read and Take Action + ## AWS Rightsize RDS Instances + CreatePolicyAWSRightsizeRDSInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeRDSInstances + - None + CreatePolicyAWSRightsizeRDSInstancesAction: !Equals + - !Ref paramPermsAWSRightsizeRDSInstances + - Read and Take Action + ## AWS Rightsize Redshift + CreatePolicyAWSRightsizeRedshiftRead: !Not + - !Equals + - !Ref paramPermsAWSRightsizeRedshift + - None + CreatePolicyAWSRightsizeRedshiftAction: !Equals + - !Ref paramPermsAWSRightsizeRedshift + - Read and Take Action + ## AWS S3 Buckets Accepting HTTP Requests + CreatePolicyAWSS3BucketsAcceptingHTTPRequestsRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsAcceptingHTTPRequests + - None + ## AWS S3 Buckets Without Default Encryption Configuration + CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration + - None + CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction: !Equals + - !Ref paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration + - Read and Take Action + ## AWS S3 Buckets Without Intelligent Tiering + CreatePolicyAWSS3BucketsWithoutIntelligentTieringRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutIntelligentTiering + - None + ## AWS S3 Buckets Without Lifecycle Configuration + CreatePolicyAWSS3BucketsWithoutLifecycleConfigurationRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutLifecycleConfiguration + - None + ## AWS S3 Buckets Without MFA Delete Enabled + CreatePolicyAWSS3BucketsWithoutMFADeleteEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutMFADeleteEnabled + - None + ## AWS S3 Buckets Without Public Access Blocked + CreatePolicyAWSS3BucketsWithoutPublicAccessBlockedRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutPublicAccessBlocked + - None + ## AWS S3 Buckets Without Server Access Logging + CreatePolicyAWSS3BucketsWithoutServerAccessLoggingRead: !Not + - !Equals + - !Ref paramPermsAWSS3BucketsWithoutServerAccessLogging + - None + CreatePolicyAWSS3BucketsWithoutServerAccessLoggingAction: !Equals + - !Ref paramPermsAWSS3BucketsWithoutServerAccessLogging + - Read and Take Action + ## AWS S3 Incomplete Multi-Part Uploads + CreatePolicyAWSS3IncompleteMultiPartUploadsRead: !Not + - !Equals + - !Ref paramPermsAWSS3IncompleteMultiPartUploads + - None + CreatePolicyAWSS3IncompleteMultiPartUploadsAction: !Equals + - !Ref paramPermsAWSS3IncompleteMultiPartUploads + - Read and Take Action + ## AWS Savings Plan Recommendations + CreatePolicyAWSSavingsPlanRecommendationsRead: !Not + - !Equals + - !Ref paramPermsAWSSavingsPlanRecommendations + - None + ## AWS Savings Plan Utilization + CreatePolicyAWSSavingsPlanUtilizationRead: !Not + - !Equals + - !Ref paramPermsAWSSavingsPlanUtilization + - None + ## AWS Schedule Instance + CreatePolicyAWSScheduleInstanceRead: !Not + - !Equals + - !Ref paramPermsAWSScheduleInstance + - None + ## AWS Scheduled EC2 Events + CreatePolicyAWSScheduledEC2EventsRead: !Not + - !Equals + - !Ref paramPermsAWSScheduledEC2Events + - None + ## AWS Superseded EBS Volumes + CreatePolicyAWSSupersededEBSVolumesRead: !Not + - !Equals + - !Ref paramPermsAWSSupersededEBSVolumes + - None + CreatePolicyAWSSupersededEBSVolumesAction: !Equals + - !Ref paramPermsAWSSupersededEBSVolumes + - Read and Take Action + ## AWS Superseded EC2 Instances + CreatePolicyAWSSupersededEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - None + CreatePolicyAWSSupersededEC2InstancesAction: !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - Read and Take Action + ## AWS Superseded EC2 Instances + CreatePolicyAWSSupersededEC2InstancesRead: !Not + - !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - None + CreatePolicyAWSSupersededEC2InstancesAction: !Equals + - !Ref paramPermsAWSSupersededEC2Instances + - Read and Take Action + ## AWS Tag Cardinality Report + CreatePolicyAWSTagCardinalityReportRead: !Not + - !Equals + - !Ref paramPermsAWSTagCardinalityReport + - None + ## AWS Unencrypted EBS Volumes + CreatePolicyAWSUnencryptedEBSVolumesRead: !Not + - !Equals + - !Ref paramPermsAWSUnencryptedEBSVolumes + - None + ## AWS Unencrypted RDS Instances + CreatePolicyAWSUnencryptedRDSInstancesRead: !Not + - !Equals + - !Ref paramPermsAWSUnencryptedRDSInstances + - None + CreatePolicyAWSUnencryptedRDSInstancesAction: !Equals + - !Ref paramPermsAWSUnencryptedRDSInstances + - Read and Take Action + ## AWS Untagged Resources + CreatePolicyAWSUntaggedResourcesRead: !Not + - !Equals + - !Ref paramPermsAWSUntaggedResources + - None + CreatePolicyAWSUntaggedResourcesAction: !Equals + - !Ref paramPermsAWSUntaggedResources + - Read and Take Action + ## AWS Unused Application Load Balancers + CreatePolicyAWSUnusedApplicationLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedApplicationLoadBalancers + - None + CreatePolicyAWSUnusedApplicationLoadBalancersAction: !Equals + - !Ref paramPermsAWSUnusedApplicationLoadBalancers + - Read and Take Action + ## AWS Unused Classic Load Balancers + CreatePolicyAWSUnusedClassicLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedClassicLoadBalancers + - None + CreatePolicyAWSUnusedClassicLoadBalancersAction: !Equals + - !Ref paramPermsAWSUnusedClassicLoadBalancers + - Read and Take Action + ## AWS Unused ECS Clusters + CreatePolicyAWSUnusedECSClustersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedECSClusters + - None + CreatePolicyAWSUnusedECSClustersAction: !Equals + - !Ref paramPermsAWSUnusedECSClusters + - Read and Take Action + ## AWS Unused IAM Credentials + CreatePolicyAWSUnusedIAMCredentialsRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedIAMCredentials + - None + ## AWS Unused IP Addresses + CreatePolicyAWSUnusedIPAddressesRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedIPAddresses + - None + CreatePolicyAWSUnusedIPAddressesAction: !Equals + - !Ref paramPermsAWSUnusedIPAddresses + - Read and Take Action + ## AWS Unused Network Load Balancers + CreatePolicyAWSUnusedNetworkLoadBalancersRead: !Not + - !Equals + - !Ref paramPermsAWSUnusedNetworkLoadBalancers + - None + CreatePolicyAWSUnusedNetworkLoadBalancersAction: !Equals + - !Ref paramPermsAWSUnusedNetworkLoadBalancers + - Read and Take Action + ## AWS VPCs Without FlowLogs Enabled + CreatePolicyAWSVPCsWithoutFlowLogsEnabledRead: !Not + - !Equals + - !Ref paramPermsAWSVPCsWithoutFlowLogsEnabled + - None + ## Common Bill Ingestion from AWS S3 Object Storage + CreatePolicyCommonBillIngestionfromAWSS3ObjectStorageRead: !Not + - !Equals + - !Ref paramPermsCommonBillIngestionfromAWSS3ObjectStorage + - None + + # End for each policy template + ValueProvidedparamPermsAttachExistingPolicies: !Not + - !Equals + - !Ref paramPermsAttachExistingPolicies + - "" + +Mappings: + TrustedRoleMap: + app.flexera.com: + roleArn: "arn:aws:iam::451234325714:role/production_customer_access" + app.flexera.eu: + roleArn: "arn:aws:iam::451234325714:role/production_eu_customer_access" + app.flexera.au: + roleArn: "arn:aws:iam::451234325714:role/production_apac_customer_access" + app.flexeratest.com: + roleArn: "arn:aws:iam::274571843445:role/staging_customer_access" + PermissionMap: + # Begin IAM Permissions Map + # Expect 2 lists for each Policy Template (read and action) + ## All AWS Policy Templates + AllAWSPolicyTemplates: + read: + - "access-analyzer:ListAnalyzers" + - "ce:GetReservationCoverage" + - "ce:GetReservationPurchaseRecommendation" + - "ce:GetSavingsPlansPurchaseRecommendation" + - "ce:GetSavingsPlansUtilization" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetEventSelectors" + - "cloudtrail:GetTrailStatus" + - "cloudtrail:LookupEvents" + - "cloudwatch:GetMetricData" + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:ListMetrics" + - "compute-optimizer:GetEC2InstanceRecommendations" + - "config:DescribeConfigurationRecorderStatus" + - "ec2:CreateTags" + - "ec2:DeleteTags" + - "ec2:DescribeAddresses" + - "ec2:DescribeFlowLogs" + - "ec2:DescribeImages" + - "ec2:DescribeInstanceStatus" + - "ec2:DescribeInstances" + - "ec2:DescribeNatGateways" + - "ec2:DescribeRegions" + - "ec2:DescribeSnapshots" + - "ec2:DescribeTags" + - "ec2:DescribeVolumes" + - "ec2:DescribeVpcs" + - "ec2:GetEbsEncryptionByDefault" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + - "ecs:DescribeClusters" + - "ecs:ListClusters" + - "eks:DescribeCluster" + - "eks:DescribeNodegroup" + - "eks:ListClusters" + - "eks:ListNodegroups" + - "elasticache:DescribeCacheClusters" + - "elasticache:ListTagsForResource" + - "elasticloadbalancing:DescribeInstanceHealth" + - "elasticloadbalancing:DescribeListeners" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeTargetGroups" + - "elasticloadbalancing:DescribeTargetHealth" + - "iam:GenerateCredentialReport" + - "iam:GetAccountPasswordPolicy" + - "iam:GetAccountSummary" + - "iam:GetCredentialReport" + - "iam:GetPolicyVersion" + - "iam:ListAccessKeys" + - "iam:ListAttachedUserPolicies" + - "iam:ListEntitiesForPolicy" + - "iam:ListPolicies" + - "iam:ListRoleTags" + - "iam:ListRoles" + - "iam:ListServerCertificates" + - "iam:ListUserPolicies" + - "iam:ListUsers" + - "iam:ListVirtualMFADevices" + - "kms:CreateGrant" + - "kms:Decrypt" + - "kms:GetKeyRotationStatus" + - "kms:ListKeys" + - "lambda:ListFunctions" + - "lambda:ListProvisionedConcurrencyConfigs" + - "lambda:ListTags" + - "lambda:ListVersionsByFunction" + - "organizations:ListAccounts" + - "organizations:ListPolicies" + - "organizations:ListPoliciesForTarget" + - "organizations:ListTagsForResource" + - "pricing:GetProducts" + - "rds:DescribeDBClusterSnapshots" + - "rds:DescribeDBClusters" + - "rds:DescribeDBInstances" + - "rds:DescribeDBSnapshots" + - "rds:DescribeOrderableDBInstanceOptions" + - "rds:ListTagsForResource" + - "redshift:DescribeClusters" + - "s3:GetBucketAcl" + - "s3:GetBucketLifecycleConfiguration" + - "s3:GetBucketLocation" + - "s3:GetBucketLogging" + - "s3:GetBucketPolicy" + - "s3:GetBucketPublicAccessBlock" + - "s3:GetBucketTagging" + - "s3:GetBucketVersioning" + - "s3:GetEncryptionConfiguration" + - "s3:GetIntelligentTieringConfiguration" + - "s3:GetObject" + - "s3:ListAllMyBuckets" + - "s3:ListBucketMultipartUploads" + - "s3:ListMultipartUploadParts" + - "savingsplans:DescribeSavingsPlans" + - "sts:GetCallerIdentity" + - "tag:GetResources" + action: + - "cloudtrail:PutEventSelectors" + - "ec2:DeleteNatGateway" + - "ec2:DeleteSnapshot" + - "ec2:DeregisterImage" + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:ModifyVolume" + - "ec2:ReleaseAddress" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + - "ecs:DeleteCluster" + - "elasticache:ModifyCacheCluster" + - "elasticloadbalancing:DeleteLoadBalancer" + - "organizations:TagResource" + - "rds:DeleteDBClusterSnapshot" + - "rds:DeleteDBInstance" + - "rds:DeleteDBSnapshot" + - "rds:ModifyDBInstance" + - "redshift:ModifyCluster" + - "s3:AbortMultipartUpload" + - "s3:DeleteBucket" + - "s3:PutBucketLogging" + - "s3:PutEncryptionConfiguration" + - "tag:TagResources" + ## AWS Account Credentials + AWSAccountCredentials: + read: + - "sts:GetCallerIdentity" + action: [] + ## AWS Accounts Missing Service Control Policies + AWSAccountsMissingServiceControlPolicies: + read: + - "organizations:ListPolicies" + - "organizations:ListAccounts" + - "organizations:ListPoliciesForTarget" + action: [] + ## AWS Burstable EC2 Instances + AWSBurstableEC2Instances: + read: + - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricData" + - "cloudwatch:ListMetrics" + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + ## AWS CloudTrail Not Enabled In All Regions + AWSCloudTrailNotEnabledInAllRegions: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetTrailStatus" + - "cloudtrail:GetEventSelectors" + action: [] + ## AWS CloudTrail S3 Buckets Without Access Logging + AWSCloudTrailS3BucketsWithoutAccessLogging: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "s3:GetBucketLocation" + - "s3:GetBucketLogging" + action: [] + ## AWS CloudTrails Not Integrated With CloudWatch + AWSCloudTrailsNotIntegratedWithCloudWatch: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetTrailStatus" + action: [] + ## AWS CloudTrails With Read Logging Enabled + AWSCloudTrailsWithReadLoggingEnabled: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetEventSelectors" + action: + - "cloudtrail:PutEventSelectors" + ## AWS CloudTrails Without Encrypted Logs + AWSCloudTrailsWithoutEncryptedLogs: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + action: [] + ## AWS CloudTrails Without Log File Validation Enabled + AWSCloudTrailsWithoutLogFileValidationEnabled: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + action: [] + ## AWS CloudTrails Without Object-level Events Logging Enabled + AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "cloudtrail:GetEventSelectors" + action: [] + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + AWSCustomerManagedKeysCMKsWithoutRotationEnabled: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "kms:ListKeys" + - "kms:GetKeyRotationStatus" + action: [] + ## AWS Disallowed Regions + AWSDisallowedRegions: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + action: + - "ec2:StopInstances" + - "ec2:TerminateInstances" + ## AWS EC2 Compute Optimizer Recommendations + AWSEC2ComputeOptimizerRecommendations: + read: + - "sts:GetCallerIdentity" + - "compute-optimizer:GetEC2InstanceRecommendations" + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + action: + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + ## AWS EC2 Instances Time Stopped Report + AWSEC2InstancesTimeStoppedReport: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + ## AWS EC2 Instances not running FlexNet Inventory Agent + AWSEC2InstancesnotrunningFlexNetInventoryAgent: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + action: [] + ## AWS EKS Clusters Without Spot Instances + AWSEKSClustersWithoutSpotInstances: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "eks:ListClusters" + - "eks:ListNodegroups" + - "eks:DescribeCluster" + - "eks:DescribeNodegroup" + action: [] + ## AWS Elastic Load Balancers With Unencrypted Listeners + AWSElasticLoadBalancersWithUnencryptedListeners: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeListeners" + action: [] + ## AWS Expiring Savings Plans + AWSExpiringSavingsPlans: + read: + - "savingsplans:DescribeSavingsPlans" + action: [] + ## AWS IAM Account Missing Support Role + AWSIAMAccountMissingSupportRole: + read: + - "sts:GetCallerIdentity" + - "iam:ListPolicies" + - "iam:ListEntitiesForPolicy" + action: [] + ## AWS IAM Attached Admin Policies + AWSIAMAttachedAdminPolicies: + read: + - "sts:GetCallerIdentity" + - "iam:ListPolicies" + - "iam:GetPolicyVersion" + action: [] + ## AWS IAM Expired SSL/TLS Certificates + AWSIAMExpiredSSLTLSCertificates: + read: + - "sts:GetCallerIdentity" + - "iam:ListServerCertificates" + action: [] + ## AWS IAM Insufficient Required Password Length + AWSIAMInsufficientRequiredPasswordLength: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountPasswordPolicy" + action: [] + ## AWS IAM Password Policy Not Restricting Password Reuse + AWSIAMPasswordPolicyNotRestrictingPasswordReuse: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountPasswordPolicy" + action: [] + ## AWS IAM Role Audit + AWSIAMRoleAudit: + read: + - "sts:GetCallerIdentity" + - "iam:ListRoles" + - "iam:ListRoleTags" + action: [] + ## AWS IAM Root Account Access Keys + AWSIAMRootAccountAccessKeys: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountSummary" + action: [] + ## AWS IAM Root User Account Without Hardware MFA + AWSIAMRootUserAccountWithoutHardwareMFA: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountSummary" + - "iam:ListVirtualMFADevices" + action: [] + ## AWS IAM Root User Account Without MFA + AWSIAMRootUserAccountWithoutMFA: + read: + - "sts:GetCallerIdentity" + - "iam:GetAccountSummary" + - "iam:ListVirtualMFADevices" + action: [] + ## AWS IAM Root User Doing Everyday Tasks + AWSIAMRootUserDoingEverydayTasks: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS IAM User Accounts Without MFA + AWSIAMUserAccountsWithoutMFA: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS IAM Users With Directly-Attached Policies + AWSIAMUsersWithDirectlyAttachedPolicies: + read: + - "sts:GetCallerIdentity" + - "iam:ListUsers" + - "iam:ListUserPolicies" + - "iam:ListAttachedUserPolicies" + action: [] + ## AWS IAM Users With Multiple Active Access Keys + AWSIAMUsersWithMultipleActiveAccessKeys: + read: + - "sts:GetCallerIdentity" + - "iam:ListUsers" + - "iam:ListAccessKeys" + action: [] + ## AWS IAM Users With Old Access Keys + AWSIAMUsersWithOldAccessKeys: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS Idle NAT Gateways + AWSIdleNATGateways: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeNatGateways" + - "sts:GetCallerIdentity" + action: + - "ec2:DeleteNatGateway" + ## AWS Internet-Accessible Elastic Load Balancers + AWSInternetAccessibleElasticLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeListeners" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS Lambda Functions With High Error Rate + AWSLambdaFunctionsWithHighErrorRate: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "lambda:ListFunctions" + - "lambda:ListTags" + - "cloudwatch:ListMetrics" + - "cloudwatch:GetMetricData" + action: [] + ## AWS Lambda Functions Without Provisioned Concurrency + AWSLambdaFunctionsWithoutProvisionedConcurrency: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "lambda:ListFunctions" + - "lambda:ListTags" + - "lambda:ListProvisionedConcurrencyConfigs" + - "lambda:ListVersionsByFunction" + action: [] + ## AWS Long Running Instances + AWSLongRunningInstances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + ## AWS Long Stopped EC2 Instances + AWSLongStoppedEC2Instances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:GetMetricData" + - "cloudwatch:ListMetrics" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:TerminateInstances" + ## AWS Missing Regions + AWSMissingRegions: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "sts:GetCallerIdentity" + action: [] + ## AWS Old Snapshots + AWSOldSnapshots: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeImages" + - "ec2:DescribeSnapshots" + - "rds:DescribeDBInstances" + - "rds:DescribeDBSnapshots" + - "rds:DescribeDBClusters" + - "rds:DescribeDBClusterSnapshots" + - "sts:GetCallerIdentity" + - "cloudtrail:LookupEvents" + action: + - "ec2:DeregisterImage" + - "ec2:DeleteSnapshot" + - "rds:DeleteDBClusterSnapshot" + - "rds:DeleteDBSnapshot" + ## AWS Open S3 Buckets + AWSOpenS3Buckets: + read: + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketAcl" + - "sts:GetCallerIdentity" + action: [] + ## AWS Oversized S3 Buckets + AWSOversizedS3Buckets: + read: + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "cloudwatch:ListMetrics" + - "cloudwatch:GetMetricData" + - "sts:GetCallerIdentity" + action: [] + ## AWS Publicly Accessible CloudTrail S3 Buckets + AWSPubliclyAccessibleCloudTrailS3Buckets: + read: + - "sts:GetCallerIdentity" + - "cloudtrail:DescribeTrails" + - "s3:GetBucketLocation" + - "s3:GetBucketAcl" + - "s3:GetBucketPolicy" + action: [] + ## AWS Publicly Accessible RDS Instances + AWSPubliclyAccessibleRDSInstances: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" + action: + - "rds:ModifyDBInstance" + - "rds:DeleteDBInstance" + ## AWS RDS Instances With Unapproved Backup Settings + AWSRDSInstancesWithUnapprovedBackupSettings: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" + action: [] + ## AWS Regions Without Access Analyzer Enabled + AWSRegionsWithoutAccessAnalyzerEnabled: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "access-analyzer:ListAnalyzers" + action: [] + ## AWS Regions Without Config Fully Enabled + AWSRegionsWithoutConfigFullyEnabled: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "config:DescribeConfigurationRecorderStatus" + action: [] + ## AWS Regions Without Default EBS Encryption + AWSRegionsWithoutDefaultEBSEncryption: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:GetEbsEncryptionByDefault" + action: [] + ## AWS Reserved Instances Coverage + AWSReservedInstancesCoverage: + read: + - "ce:GetReservationCoverage" + action: [] + ## AWS Reserved Instances Recommendations + AWSReservedInstancesRecommendations: + read: + - "ce:GetReservationPurchaseRecommendation" + action: [] + ## AWS Rightsize EBS Volumes + AWSRightsizeEBSVolumes: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeVolumes" + - "pricing:GetProducts" + action: + - "ec2:ModifyVolume" + ## AWS Rightsize EC2 Instances + AWSRightsizeEC2Instances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:GetMetricData" + - "cloudwatch:ListMetrics" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:TerminateInstances" + ## AWS Rightsize ElastiCache + AWSRightsizeElastiCache: + read: + - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricData" + - "ec2:DescribeRegions" + - "elasticache:DescribeCacheClusters" + - "elasticache:ListTagsForResource" + action: + - "elasticache:ModifyCacheCluster" + ## AWS Rightsize RDS Instances + AWSRightsizeRDSInstances: + read: + - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricStatistics" + - "cloudwatch:GetMetricData" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" + - "rds:DescribeOrderableDBInstanceOptions" + action: + - "rds:ModifyDBInstance" + - "rds:DeleteDBInstance" + ## AWS Rightsize Redshift + AWSRightsizeRedshift: + read: + - "sts:GetCallerIdentity" + - "cloudwatch:GetMetricData" + - "ec2:DescribeRegions" + - "redshift:DescribeClusters" + action: + - "redshift:ModifyCluster" + ## AWS S3 Buckets Accepting HTTP Requests + AWSS3BucketsAcceptingHTTPRequests: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketPolicy" + action: [] + ## AWS S3 Buckets Without Default Encryption Configuration + AWSS3BucketsWithoutDefaultEncryptionConfiguration: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetEncryptionConfiguration" + action: + - "s3:PutEncryptionConfiguration" + - "s3:DeleteBucket" + ## AWS S3 Buckets Without Intelligent Tiering + AWSS3BucketsWithoutIntelligentTiering: + read: + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetIntelligentTieringConfiguration" + - "sts:GetCallerIdentity" + action: [] + ## AWS S3 Buckets Without Lifecycle Configuration + AWSS3BucketsWithoutLifecycleConfiguration: + read: + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketLifecycleConfiguration" + - "sts:GetCallerIdentity" + action: [] + ## AWS S3 Buckets Without MFA Delete Enabled + AWSS3BucketsWithoutMFADeleteEnabled: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketVersioning" + action: [] + ## AWS S3 Buckets Without Public Access Blocked + AWSS3BucketsWithoutPublicAccessBlocked: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketPublicAccessBlock" + action: [] + ## AWS S3 Buckets Without Server Access Logging + AWSS3BucketsWithoutServerAccessLogging: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:GetBucketLogging" + action: + - "s3:PutBucketLogging" + ## AWS S3 Incomplete Multi-Part Uploads + AWSS3IncompleteMultiPartUploads: + read: + - "sts:GetCallerIdentity" + - "s3:ListAllMyBuckets" + - "s3:GetBucketLocation" + - "s3:GetBucketTagging" + - "s3:ListBucketMultipartUploads" + - "s3:ListMultipartUploadParts" + action: + - "s3:AbortMultipartUpload" + ## AWS Savings Plan Recommendations + AWSSavingsPlanRecommendations: + read: + - "ce:GetSavingsPlansPurchaseRecommendation" + action: [] + ## AWS Savings Plan Utilization + AWSSavingsPlanUtilization: + read: + - "ce:GetSavingsPlansUtilization" + - "savingsplans:DescribeSavingsPlans" + action: [] + ## AWS Schedule Instance + AWSScheduleInstance: + read: + - "ec2:DescribeInstances" + - "ec2:StartInstances" + - "ec2:StopInstances" + - "ec2:DeleteTags" + - "ec2:DescribeRegions" + - "kms:CreateGrant" + - "kms:Decrypt" + - "ec2:CreateTags" + - "ec2:TerminateInstances" + action: [] + ## AWS Scheduled EC2 Events + AWSScheduledEC2Events: + read: + - "ec2:DescribeInstances" + - "ec2:DescribeInstanceStatus" + - "ec2:DescribeRegions" + - "sts:GetCallerIdentity" + action: [] + ## AWS Superseded EBS Volumes + AWSSupersededEBSVolumes: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:DescribeVolumes" + - "pricing:GetProducts" + action: + - "ec2:ModifyVolume" + ## AWS Superseded EC2 Instances + AWSSupersededEC2Instances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + ## AWS Superseded EC2 Instances + AWSSupersededEC2Instances: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeInstances" + - "ec2:DescribeTags" + - "sts:GetCallerIdentity" + action: + - "ec2:DescribeInstanceStatus" + - "ec2:ModifyInstanceAttribute" + - "ec2:StartInstances" + - "ec2:StopInstances" + ## AWS Tag Cardinality Report + AWSTagCardinalityReport: + read: + - "tag:GetResources" + - "ec2:DescribeRegions" + - "organizations:ListAccounts" + - "organizations:ListTagsForResource" + action: [] + ## AWS Unencrypted EBS Volumes + AWSUnencryptedEBSVolumes: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:DescribeVolumes" + action: [] + ## AWS Unencrypted RDS Instances + AWSUnencryptedRDSInstances: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "rds:DescribeDBInstances" + - "rds:ListTagsForResource" + action: + - "rds:DeleteDBInstance" + ## AWS Untagged Resources + AWSUntaggedResources: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "tag:GetResources" + action: + - "tag:TagResources" + - "organizations:TagResource" + ## AWS Unused Application Load Balancers + AWSUnusedApplicationLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeListeners" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeTargetGroups" + - "elasticloadbalancing:DescribeTargetHealth" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS Unused Classic Load Balancers + AWSUnusedClassicLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeInstanceHealth" + - "elasticloadbalancing:DescribeTags" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS Unused ECS Clusters + AWSUnusedECSClusters: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ecs:ListClusters" + - "ecs:DescribeClusters" + action: + - "ecs:DeleteCluster" + ## AWS Unused IAM Credentials + AWSUnusedIAMCredentials: + read: + - "sts:GetCallerIdentity" + - "iam:GenerateCredentialReport" + - "iam:GetCredentialReport" + action: [] + ## AWS Unused IP Addresses + AWSUnusedIPAddresses: + read: + - "ec2:DescribeRegions" + - "ec2:DescribeAddresses" + - "sts:GetCallerIdentity" + - "cloudtrail:LookupEvents" + action: + - "ec2:ReleaseAddress" + ## AWS Unused Network Load Balancers + AWSUnusedNetworkLoadBalancers: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "elasticloadbalancing:DescribeLoadBalancers" + - "elasticloadbalancing:DescribeListeners" + - "elasticloadbalancing:DescribeTags" + - "elasticloadbalancing:DescribeTargetGroups" + - "elasticloadbalancing:DescribeTargetHealth" + action: + - "elasticloadbalancing:DeleteLoadBalancer" + ## AWS VPCs Without FlowLogs Enabled + AWSVPCsWithoutFlowLogsEnabled: + read: + - "sts:GetCallerIdentity" + - "ec2:DescribeRegions" + - "ec2:DescribeVpcs" + - "ec2:DescribeFlowLogs" + action: [] + ## Common Bill Ingestion from AWS S3 Object Storage + CommonBillIngestionfromAWSS3ObjectStorage: + read: + - "s3:GetObject" + action: [] + + # End for each policy template + +Resources: + # IAM Role Resource + iamRole: + Type: "AWS::IAM::Role" + Properties: + RoleName: !Ref paramRoleName + Description: !Join + - " " + - - "Allows access from Flexera Platform. This IAM Role and the attached permission policies were created and are managed by CloudFormation Stack:" + - !Ref AWS::StackId + Path: !Ref paramRolePath + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: !FindInMap + - TrustedRoleMap + - !Ref paramFlexeraZone + - roleArn + Action: "sts:AssumeRole" + Condition: + StringEquals: + "sts:ExternalId": !Ref paramFlexeraOrgId + # ManagedPolicyArns value is conditional based on input paramPermsAttachExistingPolicies + ManagedPolicyArns: !If + - ValueProvidedparamPermsAttachExistingPolicies + # If value is provided for paramPermsAttachExistingPolicies, split that comma-separated list into a list object + - !Split [ ",", !Ref paramPermsAttachExistingPolicies ] + # Provide a null value if nothing provided for paramPermsAttachExistingPolicies + - !Ref AWS::NoValue + # Begin IAM Permission Policy Resources + # 1 or 2 Permission Policies per Policy Template (read and action) + # Policy create/attachment is conditional based on parameter input for each policy + ## All AWS Policy Templates + iamPolicyAllAWSPolicyTemplatesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAllAWSPolicyTemplatesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AllAWSPolicyTemplatesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AllAWSPolicyTemplates + - read + Resource: "*" + iamPolicyAllAWSPolicyTemplatesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAllAWSPolicyTemplatesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AllAWSPolicyTemplatesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AllAWSPolicyTemplates + - action + Resource: "*" + ## AWS Account Credentials + iamPolicyAWSAccountCredentialsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSAccountCredentialsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSAccountCredentialsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSAccountCredentials + - read + Resource: "*" + ## AWS Accounts Missing Service Control Policies + iamPolicyAWSAccountsMissingServiceControlPoliciesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSAccountsMissingServiceControlPoliciesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSAccountsMissingServiceControlPoliciesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSAccountsMissingServiceControlPolicies + - read + Resource: "*" + ## AWS Burstable EC2 Instances + iamPolicyAWSBurstableEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSBurstableEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSBurstableEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSBurstableEC2Instances + - read + Resource: "*" + iamPolicyAWSBurstableEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSBurstableEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSBurstableEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSBurstableEC2Instances + - action + Resource: "*" + ## AWS CloudTrail Not Enabled In All Regions + iamPolicyAWSCloudTrailNotEnabledInAllRegionsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailNotEnabledInAllRegionsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailNotEnabledInAllRegionsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailNotEnabledInAllRegions + - read + Resource: "*" + ## AWS CloudTrail S3 Buckets Without Access Logging + iamPolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailS3BucketsWithoutAccessLoggingReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailS3BucketsWithoutAccessLogging + - read + Resource: "*" + ## AWS CloudTrails Not Integrated With CloudWatch + iamPolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsNotIntegratedWithCloudWatchReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsNotIntegratedWithCloudWatch + - read + Resource: "*" + ## AWS CloudTrails With Read Logging Enabled + iamPolicyAWSCloudTrailsWithReadLoggingEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithReadLoggingEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithReadLoggingEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithReadLoggingEnabled + - read + Resource: "*" + iamPolicyAWSCloudTrailsWithReadLoggingEnabledAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithReadLoggingEnabledAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithReadLoggingEnabledActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithReadLoggingEnabled + - action + Resource: "*" + ## AWS CloudTrails Without Encrypted Logs + iamPolicyAWSCloudTrailsWithoutEncryptedLogsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithoutEncryptedLogsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithoutEncryptedLogsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithoutEncryptedLogs + - read + Resource: "*" + ## AWS CloudTrails Without Log File Validation Enabled + iamPolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithoutLogFileValidationEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithoutLogFileValidationEnabled + - read + Resource: "*" + ## AWS CloudTrails Without Object-level Events Logging Enabled + iamPolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled + - read + Resource: "*" + ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled + iamPolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSCustomerManagedKeysCMKsWithoutRotationEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSCustomerManagedKeysCMKsWithoutRotationEnabled + - read + Resource: "*" + ## AWS Disallowed Regions + iamPolicyAWSDisallowedRegionsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSDisallowedRegionsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSDisallowedRegionsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSDisallowedRegions + - read + Resource: "*" + iamPolicyAWSDisallowedRegionsAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSDisallowedRegionsAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSDisallowedRegionsActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSDisallowedRegions + - action + Resource: "*" + ## AWS EC2 Compute Optimizer Recommendations + iamPolicyAWSEC2ComputeOptimizerRecommendationsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2ComputeOptimizerRecommendationsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2ComputeOptimizerRecommendationsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2ComputeOptimizerRecommendations + - read + Resource: "*" + iamPolicyAWSEC2ComputeOptimizerRecommendationsAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2ComputeOptimizerRecommendationsAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2ComputeOptimizerRecommendationsActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2ComputeOptimizerRecommendations + - action + Resource: "*" + ## AWS EC2 Instances Time Stopped Report + iamPolicyAWSEC2InstancesTimeStoppedReportRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2InstancesTimeStoppedReportRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2InstancesTimeStoppedReportReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2InstancesTimeStoppedReport + - read + Resource: "*" + iamPolicyAWSEC2InstancesTimeStoppedReportAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2InstancesTimeStoppedReportAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2InstancesTimeStoppedReportActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2InstancesTimeStoppedReport + - action + Resource: "*" + ## AWS EC2 Instances not running FlexNet Inventory Agent + iamPolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEC2InstancesnotrunningFlexNetInventoryAgentReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEC2InstancesnotrunningFlexNetInventoryAgent + - read + Resource: "*" + ## AWS EKS Clusters Without Spot Instances + iamPolicyAWSEKSClustersWithoutSpotInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSEKSClustersWithoutSpotInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSEKSClustersWithoutSpotInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSEKSClustersWithoutSpotInstances + - read + Resource: "*" + ## AWS Elastic Load Balancers With Unencrypted Listeners + iamPolicyAWSElasticLoadBalancersWithUnencryptedListenersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSElasticLoadBalancersWithUnencryptedListenersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSElasticLoadBalancersWithUnencryptedListenersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSElasticLoadBalancersWithUnencryptedListeners + - read + Resource: "*" + ## AWS Expiring Savings Plans + iamPolicyAWSExpiringSavingsPlansRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSExpiringSavingsPlansRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSExpiringSavingsPlansReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSExpiringSavingsPlans + - read + Resource: "*" + ## AWS IAM Account Missing Support Role + iamPolicyAWSIAMAccountMissingSupportRoleRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMAccountMissingSupportRoleRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMAccountMissingSupportRoleReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMAccountMissingSupportRole + - read + Resource: "*" + ## AWS IAM Attached Admin Policies + iamPolicyAWSIAMAttachedAdminPoliciesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMAttachedAdminPoliciesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMAttachedAdminPoliciesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMAttachedAdminPolicies + - read + Resource: "*" + ## AWS IAM Expired SSL/TLS Certificates + iamPolicyAWSIAMExpiredSSLTLSCertificatesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMExpiredSSLTLSCertificatesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMExpiredSSLTLSCertificatesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMExpiredSSLTLSCertificates + - read + Resource: "*" + ## AWS IAM Insufficient Required Password Length + iamPolicyAWSIAMInsufficientRequiredPasswordLengthRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMInsufficientRequiredPasswordLengthRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMInsufficientRequiredPasswordLengthReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMInsufficientRequiredPasswordLength + - read + Resource: "*" + ## AWS IAM Password Policy Not Restricting Password Reuse + iamPolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMPasswordPolicyNotRestrictingPasswordReuseReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMPasswordPolicyNotRestrictingPasswordReuse + - read + Resource: "*" + ## AWS IAM Role Audit + iamPolicyAWSIAMRoleAuditRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRoleAuditRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRoleAuditReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRoleAudit + - read + Resource: "*" + ## AWS IAM Root Account Access Keys + iamPolicyAWSIAMRootAccountAccessKeysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootAccountAccessKeysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootAccountAccessKeysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootAccountAccessKeys + - read + Resource: "*" + ## AWS IAM Root User Account Without Hardware MFA + iamPolicyAWSIAMRootUserAccountWithoutHardwareMFARead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootUserAccountWithoutHardwareMFARead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootUserAccountWithoutHardwareMFAReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootUserAccountWithoutHardwareMFA + - read + Resource: "*" + ## AWS IAM Root User Account Without MFA + iamPolicyAWSIAMRootUserAccountWithoutMFARead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootUserAccountWithoutMFARead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootUserAccountWithoutMFAReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootUserAccountWithoutMFA + - read + Resource: "*" + ## AWS IAM Root User Doing Everyday Tasks + iamPolicyAWSIAMRootUserDoingEverydayTasksRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMRootUserDoingEverydayTasksRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMRootUserDoingEverydayTasksReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMRootUserDoingEverydayTasks + - read + Resource: "*" + ## AWS IAM User Accounts Without MFA + iamPolicyAWSIAMUserAccountsWithoutMFARead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUserAccountsWithoutMFARead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUserAccountsWithoutMFAReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUserAccountsWithoutMFA + - read + Resource: "*" + ## AWS IAM Users With Directly-Attached Policies + iamPolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUsersWithDirectlyAttachedPoliciesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUsersWithDirectlyAttachedPolicies + - read + Resource: "*" + ## AWS IAM Users With Multiple Active Access Keys + iamPolicyAWSIAMUsersWithMultipleActiveAccessKeysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUsersWithMultipleActiveAccessKeysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUsersWithMultipleActiveAccessKeysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUsersWithMultipleActiveAccessKeys + - read + Resource: "*" + ## AWS IAM Users With Old Access Keys + iamPolicyAWSIAMUsersWithOldAccessKeysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIAMUsersWithOldAccessKeysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIAMUsersWithOldAccessKeysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIAMUsersWithOldAccessKeys + - read + Resource: "*" + ## AWS Idle NAT Gateways + iamPolicyAWSIdleNATGatewaysRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIdleNATGatewaysRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIdleNATGatewaysReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIdleNATGateways + - read + Resource: "*" + iamPolicyAWSIdleNATGatewaysAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSIdleNATGatewaysAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSIdleNATGatewaysActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSIdleNATGateways + - action + Resource: "*" + ## AWS Internet-Accessible Elastic Load Balancers + iamPolicyAWSInternetAccessibleElasticLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSInternetAccessibleElasticLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSInternetAccessibleElasticLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSInternetAccessibleElasticLoadBalancers + - read + Resource: "*" + iamPolicyAWSInternetAccessibleElasticLoadBalancersAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSInternetAccessibleElasticLoadBalancersAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSInternetAccessibleElasticLoadBalancersActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSInternetAccessibleElasticLoadBalancers + - action + Resource: "*" + ## AWS Lambda Functions With High Error Rate + iamPolicyAWSLambdaFunctionsWithHighErrorRateRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLambdaFunctionsWithHighErrorRateRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLambdaFunctionsWithHighErrorRateReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLambdaFunctionsWithHighErrorRate + - read + Resource: "*" + ## AWS Lambda Functions Without Provisioned Concurrency + iamPolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLambdaFunctionsWithoutProvisionedConcurrencyReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLambdaFunctionsWithoutProvisionedConcurrency + - read + Resource: "*" + ## AWS Long Running Instances + iamPolicyAWSLongRunningInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongRunningInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongRunningInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongRunningInstances + - read + Resource: "*" + iamPolicyAWSLongRunningInstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongRunningInstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongRunningInstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongRunningInstances + - action + Resource: "*" + ## AWS Long Stopped EC2 Instances + iamPolicyAWSLongStoppedEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongStoppedEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongStoppedEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongStoppedEC2Instances + - read + Resource: "*" + iamPolicyAWSLongStoppedEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSLongStoppedEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSLongStoppedEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSLongStoppedEC2Instances + - action + Resource: "*" + ## AWS Missing Regions + iamPolicyAWSMissingRegionsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSMissingRegionsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSMissingRegionsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSMissingRegions + - read + Resource: "*" + ## AWS Old Snapshots + iamPolicyAWSOldSnapshotsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOldSnapshotsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOldSnapshotsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOldSnapshots + - read + Resource: "*" + iamPolicyAWSOldSnapshotsAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOldSnapshotsAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOldSnapshotsActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOldSnapshots + - action + Resource: "*" + ## AWS Open S3 Buckets + iamPolicyAWSOpenS3BucketsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOpenS3BucketsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOpenS3BucketsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOpenS3Buckets + - read + Resource: "*" + ## AWS Oversized S3 Buckets + iamPolicyAWSOversizedS3BucketsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSOversizedS3BucketsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSOversizedS3BucketsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSOversizedS3Buckets + - read + Resource: "*" + ## AWS Publicly Accessible CloudTrail S3 Buckets + iamPolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSPubliclyAccessibleCloudTrailS3BucketsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSPubliclyAccessibleCloudTrailS3Buckets + - read + Resource: "*" + ## AWS Publicly Accessible RDS Instances + iamPolicyAWSPubliclyAccessibleRDSInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSPubliclyAccessibleRDSInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSPubliclyAccessibleRDSInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSPubliclyAccessibleRDSInstances + - read + Resource: "*" + iamPolicyAWSPubliclyAccessibleRDSInstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSPubliclyAccessibleRDSInstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSPubliclyAccessibleRDSInstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSPubliclyAccessibleRDSInstances + - action + Resource: "*" + ## AWS RDS Instances With Unapproved Backup Settings + iamPolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRDSInstancesWithUnapprovedBackupSettingsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRDSInstancesWithUnapprovedBackupSettings + - read + Resource: "*" + ## AWS Regions Without Access Analyzer Enabled + iamPolicyAWSRegionsWithoutAccessAnalyzerEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRegionsWithoutAccessAnalyzerEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRegionsWithoutAccessAnalyzerEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRegionsWithoutAccessAnalyzerEnabled + - read + Resource: "*" + ## AWS Regions Without Config Fully Enabled + iamPolicyAWSRegionsWithoutConfigFullyEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRegionsWithoutConfigFullyEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRegionsWithoutConfigFullyEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRegionsWithoutConfigFullyEnabled + - read + Resource: "*" + ## AWS Regions Without Default EBS Encryption + iamPolicyAWSRegionsWithoutDefaultEBSEncryptionRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRegionsWithoutDefaultEBSEncryptionRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRegionsWithoutDefaultEBSEncryptionReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRegionsWithoutDefaultEBSEncryption + - read + Resource: "*" + ## AWS Reserved Instances Coverage + iamPolicyAWSReservedInstancesCoverageRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSReservedInstancesCoverageRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSReservedInstancesCoverageReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSReservedInstancesCoverage + - read + Resource: "*" + ## AWS Reserved Instances Recommendations + iamPolicyAWSReservedInstancesRecommendationsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSReservedInstancesRecommendationsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSReservedInstancesRecommendationsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSReservedInstancesRecommendations + - read + Resource: "*" + ## AWS Rightsize EBS Volumes + iamPolicyAWSRightsizeEBSVolumesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEBSVolumesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEBSVolumesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEBSVolumes + - read + Resource: "*" + iamPolicyAWSRightsizeEBSVolumesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEBSVolumesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEBSVolumesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEBSVolumes + - action + Resource: "*" + ## AWS Rightsize EC2 Instances + iamPolicyAWSRightsizeEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEC2Instances + - read + Resource: "*" + iamPolicyAWSRightsizeEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeEC2Instances + - action + Resource: "*" + ## AWS Rightsize ElastiCache + iamPolicyAWSRightsizeElastiCacheRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeElastiCacheRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeElastiCacheReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeElastiCache + - read + Resource: "*" + iamPolicyAWSRightsizeElastiCacheAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeElastiCacheAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeElastiCacheActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeElastiCache + - action + Resource: "*" + ## AWS Rightsize RDS Instances + iamPolicyAWSRightsizeRDSInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRDSInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRDSInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRDSInstances + - read + Resource: "*" + iamPolicyAWSRightsizeRDSInstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRDSInstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRDSInstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRDSInstances + - action + Resource: "*" + ## AWS Rightsize Redshift + iamPolicyAWSRightsizeRedshiftRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRedshiftRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRedshiftReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRedshift + - read + Resource: "*" + iamPolicyAWSRightsizeRedshiftAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSRightsizeRedshiftAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSRightsizeRedshiftActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSRightsizeRedshift + - action + Resource: "*" + ## AWS S3 Buckets Accepting HTTP Requests + iamPolicyAWSS3BucketsAcceptingHTTPRequestsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsAcceptingHTTPRequestsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsAcceptingHTTPRequestsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsAcceptingHTTPRequests + - read + Resource: "*" + ## AWS S3 Buckets Without Default Encryption Configuration + iamPolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutDefaultEncryptionConfigurationReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutDefaultEncryptionConfiguration + - read + Resource: "*" + iamPolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutDefaultEncryptionConfigurationActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutDefaultEncryptionConfiguration + - action + Resource: "*" + ## AWS S3 Buckets Without Intelligent Tiering + iamPolicyAWSS3BucketsWithoutIntelligentTieringRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutIntelligentTieringRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutIntelligentTieringReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutIntelligentTiering + - read + Resource: "*" + ## AWS S3 Buckets Without Lifecycle Configuration + iamPolicyAWSS3BucketsWithoutLifecycleConfigurationRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutLifecycleConfigurationRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutLifecycleConfigurationReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutLifecycleConfiguration + - read + Resource: "*" + ## AWS S3 Buckets Without MFA Delete Enabled + iamPolicyAWSS3BucketsWithoutMFADeleteEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutMFADeleteEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutMFADeleteEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutMFADeleteEnabled + - read + Resource: "*" + ## AWS S3 Buckets Without Public Access Blocked + iamPolicyAWSS3BucketsWithoutPublicAccessBlockedRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutPublicAccessBlockedRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutPublicAccessBlockedReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutPublicAccessBlocked + - read + Resource: "*" + ## AWS S3 Buckets Without Server Access Logging + iamPolicyAWSS3BucketsWithoutServerAccessLoggingRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutServerAccessLoggingRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutServerAccessLoggingReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutServerAccessLogging + - read + Resource: "*" + iamPolicyAWSS3BucketsWithoutServerAccessLoggingAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3BucketsWithoutServerAccessLoggingAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3BucketsWithoutServerAccessLoggingActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3BucketsWithoutServerAccessLogging + - action + Resource: "*" + ## AWS S3 Incomplete Multi-Part Uploads + iamPolicyAWSS3IncompleteMultiPartUploadsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3IncompleteMultiPartUploadsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3IncompleteMultiPartUploadsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3IncompleteMultiPartUploads + - read + Resource: "*" + iamPolicyAWSS3IncompleteMultiPartUploadsAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSS3IncompleteMultiPartUploadsAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSS3IncompleteMultiPartUploadsActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSS3IncompleteMultiPartUploads + - action + Resource: "*" + ## AWS Savings Plan Recommendations + iamPolicyAWSSavingsPlanRecommendationsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSavingsPlanRecommendationsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSavingsPlanRecommendationsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSavingsPlanRecommendations + - read + Resource: "*" + ## AWS Savings Plan Utilization + iamPolicyAWSSavingsPlanUtilizationRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSavingsPlanUtilizationRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSavingsPlanUtilizationReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSavingsPlanUtilization + - read + Resource: "*" + ## AWS Schedule Instance + iamPolicyAWSScheduleInstanceRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSScheduleInstanceRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSScheduleInstanceReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSScheduleInstance + - read + Resource: "*" + ## AWS Scheduled EC2 Events + iamPolicyAWSScheduledEC2EventsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSScheduledEC2EventsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSScheduledEC2EventsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSScheduledEC2Events + - read + Resource: "*" + ## AWS Superseded EBS Volumes + iamPolicyAWSSupersededEBSVolumesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSupersededEBSVolumesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSupersededEBSVolumesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSupersededEBSVolumes + - read + Resource: "*" + iamPolicyAWSSupersededEBSVolumesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSupersededEBSVolumesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSupersededEBSVolumesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSupersededEBSVolumes + - action + Resource: "*" + ## AWS Superseded EC2 Instances + iamPolicyAWSSupersededEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSupersededEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSupersededEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSupersededEC2Instances + - read + Resource: "*" + iamPolicyAWSSupersededEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSupersededEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSupersededEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSupersededEC2Instances + - action + Resource: "*" + ## AWS Superseded EC2 Instances + iamPolicyAWSSupersededEC2InstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSupersededEC2InstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSupersededEC2InstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSupersededEC2Instances + - read + Resource: "*" + iamPolicyAWSSupersededEC2InstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSSupersededEC2InstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSSupersededEC2InstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSSupersededEC2Instances + - action + Resource: "*" + ## AWS Tag Cardinality Report + iamPolicyAWSTagCardinalityReportRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSTagCardinalityReportRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSTagCardinalityReportReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSTagCardinalityReport + - read + Resource: "*" + ## AWS Unencrypted EBS Volumes + iamPolicyAWSUnencryptedEBSVolumesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnencryptedEBSVolumesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnencryptedEBSVolumesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnencryptedEBSVolumes + - read + Resource: "*" + ## AWS Unencrypted RDS Instances + iamPolicyAWSUnencryptedRDSInstancesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnencryptedRDSInstancesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnencryptedRDSInstancesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnencryptedRDSInstances + - read + Resource: "*" + iamPolicyAWSUnencryptedRDSInstancesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnencryptedRDSInstancesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnencryptedRDSInstancesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnencryptedRDSInstances + - action + Resource: "*" + ## AWS Untagged Resources + iamPolicyAWSUntaggedResourcesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUntaggedResourcesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUntaggedResourcesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUntaggedResources + - read + Resource: "*" + iamPolicyAWSUntaggedResourcesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUntaggedResourcesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUntaggedResourcesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUntaggedResources + - action + Resource: "*" + ## AWS Unused Application Load Balancers + iamPolicyAWSUnusedApplicationLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedApplicationLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedApplicationLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedApplicationLoadBalancers + - read + Resource: "*" + iamPolicyAWSUnusedApplicationLoadBalancersAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedApplicationLoadBalancersAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedApplicationLoadBalancersActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedApplicationLoadBalancers + - action + Resource: "*" + ## AWS Unused Classic Load Balancers + iamPolicyAWSUnusedClassicLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedClassicLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedClassicLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedClassicLoadBalancers + - read + Resource: "*" + iamPolicyAWSUnusedClassicLoadBalancersAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedClassicLoadBalancersAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedClassicLoadBalancersActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedClassicLoadBalancers + - action + Resource: "*" + ## AWS Unused ECS Clusters + iamPolicyAWSUnusedECSClustersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedECSClustersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedECSClustersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedECSClusters + - read + Resource: "*" + iamPolicyAWSUnusedECSClustersAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedECSClustersAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedECSClustersActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedECSClusters + - action + Resource: "*" + ## AWS Unused IAM Credentials + iamPolicyAWSUnusedIAMCredentialsRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedIAMCredentialsRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedIAMCredentialsReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedIAMCredentials + - read + Resource: "*" + ## AWS Unused IP Addresses + iamPolicyAWSUnusedIPAddressesRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedIPAddressesRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedIPAddressesReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedIPAddresses + - read + Resource: "*" + iamPolicyAWSUnusedIPAddressesAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedIPAddressesAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedIPAddressesActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedIPAddresses + - action + Resource: "*" + ## AWS Unused Network Load Balancers + iamPolicyAWSUnusedNetworkLoadBalancersRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedNetworkLoadBalancersRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedNetworkLoadBalancersReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedNetworkLoadBalancers + - read + Resource: "*" + iamPolicyAWSUnusedNetworkLoadBalancersAction: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSUnusedNetworkLoadBalancersAction + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSUnusedNetworkLoadBalancersActionPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSUnusedNetworkLoadBalancers + - action + Resource: "*" + ## AWS VPCs Without FlowLogs Enabled + iamPolicyAWSVPCsWithoutFlowLogsEnabledRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyAWSVPCsWithoutFlowLogsEnabledRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - AWSVPCsWithoutFlowLogsEnabledReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - AWSVPCsWithoutFlowLogsEnabled + - read + Resource: "*" + ## Common Bill Ingestion from AWS S3 Object Storage + iamPolicyCommonBillIngestionfromAWSS3ObjectStorageRead: + Type: "AWS::IAM::Policy" + Condition: CreatePolicyCommonBillIngestionfromAWSS3ObjectStorageRead + Properties: + PolicyName: !Join + - "_" + - - !Ref paramRoleName + - CommonBillIngestionfromAWSS3ObjectStorageReadPermissionPolicy + Roles: + - !Ref iamRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: !FindInMap + - PermissionMap + - CommonBillIngestionfromAWSS3ObjectStorage + - read + Resource: "*" + + # End for each policy template + + # End IAM Permission Policy Resources + +Outputs: + iamRoleArn: + Description: The ARN of the IAM Role that was created + Value: !GetAtt + - iamRole + - Arn From f90495d9f2a37778267fb1f305794e6c3efaeb5c Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 08:14:43 -0600 Subject: [PATCH 13/23] update --- .../master_policy_permissions_list.json | 66 ---------------- .../master_policy_permissions_list.yaml | 43 ----------- .../FlexeraAutomationPolicies.template | 75 +------------------ .../FlexeraAutomationPolicies_v0.9.0.template | 75 +------------------ .../FlexeraAutomationPolicies.template | 75 +------------------ ...FlexeraAutomationPoliciesReadOnly.template | 48 +----------- .../validated_policy_templates.yaml | 1 - 7 files changed, 4 insertions(+), 379 deletions(-) diff --git a/data/policy_permissions_list/master_policy_permissions_list.json b/data/policy_permissions_list/master_policy_permissions_list.json index 7cc40460c6..723053add3 100644 --- a/data/policy_permissions_list/master_policy_permissions_list.json +++ b/data/policy_permissions_list/master_policy_permissions_list.json @@ -2953,72 +2953,6 @@ } ] }, - { - "id": "./cost/aws/superseded_instances/aws_superseded_instances.pt", - "name": "AWS Superseded EC2 Instances", - "version": "2.3.3", - "providers": [ - { - "name": "aws", - "permissions": [ - { - "name": "ec2:DescribeRegions", - "read_only": true, - "required": true - }, - { - "name": "ec2:DescribeInstances", - "read_only": true, - "required": true - }, - { - "name": "ec2:DescribeInstanceStatus", - "read_only": false, - "required": false, - "description": "Only required for taking action; the policy will still function in a read-only capacity without these permissions." - }, - { - "name": "ec2:DescribeTags", - "read_only": true, - "required": true - }, - { - "name": "ec2:ModifyInstanceAttribute", - "read_only": false, - "required": false, - "description": "Only required for taking action; the policy will still function in a read-only capacity without these permissions." - }, - { - "name": "ec2:StartInstances", - "read_only": false, - "required": false, - "description": "Only required for taking action; the policy will still function in a read-only capacity without these permissions." - }, - { - "name": "ec2:StopInstances", - "read_only": false, - "required": false, - "description": "Only required for taking action; the policy will still function in a read-only capacity without these permissions." - }, - { - "name": "sts:GetCallerIdentity", - "read_only": true, - "required": true - } - ] - }, - { - "name": "flexera", - "permissions": [ - { - "name": "billing_center_viewer", - "read_only": true, - "required": true - } - ] - } - ] - }, { "id": "./cost/aws/unused_albs/aws_unused_albs.pt", "name": "AWS Unused Application Load Balancers", diff --git a/data/policy_permissions_list/master_policy_permissions_list.yaml b/data/policy_permissions_list/master_policy_permissions_list.yaml index a2da1fd1c0..1c9bfd628d 100644 --- a/data/policy_permissions_list/master_policy_permissions_list.yaml +++ b/data/policy_permissions_list/master_policy_permissions_list.yaml @@ -1700,49 +1700,6 @@ - name: billing_center_viewer read_only: true required: true -- id: "./cost/aws/superseded_instances/aws_superseded_instances.pt" - name: AWS Superseded EC2 Instances - version: 2.3.3 - :providers: - - :name: aws - :permissions: - - name: ec2:DescribeRegions - read_only: true - required: true - - name: ec2:DescribeInstances - read_only: true - required: true - - name: ec2:DescribeInstanceStatus - read_only: false - required: false - description: Only required for taking action; the policy will still function - in a read-only capacity without these permissions. - - name: ec2:DescribeTags - read_only: true - required: true - - name: ec2:ModifyInstanceAttribute - read_only: false - required: false - description: Only required for taking action; the policy will still function - in a read-only capacity without these permissions. - - name: ec2:StartInstances - read_only: false - required: false - description: Only required for taking action; the policy will still function - in a read-only capacity without these permissions. - - name: ec2:StopInstances - read_only: false - required: false - description: Only required for taking action; the policy will still function - in a read-only capacity without these permissions. - - name: sts:GetCallerIdentity - read_only: true - required: true - - :name: flexera - :permissions: - - name: billing_center_viewer - read_only: true - required: true - id: "./cost/aws/unused_albs/aws_unused_albs.pt" name: AWS Unused Application Load Balancers version: 0.2.3 diff --git a/tools/cloudformation-template/FlexeraAutomationPolicies.template b/tools/cloudformation-template/FlexeraAutomationPolicies.template index 2f4b8b5b50..86ad7edc1a 100644 --- a/tools/cloudformation-template/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/FlexeraAutomationPolicies.template @@ -1,6 +1,6 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-12T16:59:05Z +# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: @@ -164,8 +164,6 @@ Metadata: - paramPermsAWSSupersededEBSVolumes ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances - ## AWS Superseded EC2 Instances - - paramPermsAWSSupersededEC2Instances ## AWS Tag Cardinality Report - paramPermsAWSTagCardinalityReport ## AWS Unencrypted EBS Volumes @@ -413,9 +411,6 @@ Metadata: paramPermsAWSSupersededEBSVolumes: default: "Permissions for Policy Template: AWS Superseded EBS Volumes" ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - default: "Permissions for Policy Template: AWS Superseded EC2 Instances" - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: default: "Permissions for Policy Template: AWS Superseded EC2 Instances" ## AWS Tag Cardinality Report @@ -1066,15 +1061,6 @@ Parameters: - Read Only - Read and Take Action ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' Type: String @@ -1606,14 +1592,6 @@ Conditions: - !Ref paramPermsAWSSupersededEBSVolumes - Read and Take Action ## AWS Superseded EC2 Instances - CreatePolicyAWSSupersededEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - None - CreatePolicyAWSSupersededEC2InstancesAction: !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - Read and Take Action - ## AWS Superseded EC2 Instances CreatePolicyAWSSupersededEC2InstancesRead: !Not - !Equals - !Ref paramPermsAWSSupersededEC2Instances @@ -2422,18 +2400,6 @@ Mappings: action: - "ec2:ModifyVolume" ## AWS Superseded EC2 Instances - AWSSupersededEC2Instances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "ec2:DescribeTags" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - - "ec2:StopInstances" - ## AWS Superseded EC2 Instances AWSSupersededEC2Instances: read: - "ec2:DescribeRegions" @@ -4367,45 +4333,6 @@ Resources: - action Resource: "*" ## AWS Superseded EC2 Instances - iamPolicyAWSSupersededEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - read - Resource: "*" - iamPolicyAWSSupersededEC2InstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - action - Resource: "*" - ## AWS Superseded EC2 Instances iamPolicyAWSSupersededEC2InstancesRead: Type: "AWS::IAM::Policy" Condition: CreatePolicyAWSSupersededEC2InstancesRead diff --git a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template index 2f4b8b5b50..86ad7edc1a 100644 --- a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template +++ b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template @@ -1,6 +1,6 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-12T16:59:05Z +# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: @@ -164,8 +164,6 @@ Metadata: - paramPermsAWSSupersededEBSVolumes ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances - ## AWS Superseded EC2 Instances - - paramPermsAWSSupersededEC2Instances ## AWS Tag Cardinality Report - paramPermsAWSTagCardinalityReport ## AWS Unencrypted EBS Volumes @@ -413,9 +411,6 @@ Metadata: paramPermsAWSSupersededEBSVolumes: default: "Permissions for Policy Template: AWS Superseded EBS Volumes" ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - default: "Permissions for Policy Template: AWS Superseded EC2 Instances" - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: default: "Permissions for Policy Template: AWS Superseded EC2 Instances" ## AWS Tag Cardinality Report @@ -1066,15 +1061,6 @@ Parameters: - Read Only - Read and Take Action ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' Type: String @@ -1606,14 +1592,6 @@ Conditions: - !Ref paramPermsAWSSupersededEBSVolumes - Read and Take Action ## AWS Superseded EC2 Instances - CreatePolicyAWSSupersededEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - None - CreatePolicyAWSSupersededEC2InstancesAction: !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - Read and Take Action - ## AWS Superseded EC2 Instances CreatePolicyAWSSupersededEC2InstancesRead: !Not - !Equals - !Ref paramPermsAWSSupersededEC2Instances @@ -2422,18 +2400,6 @@ Mappings: action: - "ec2:ModifyVolume" ## AWS Superseded EC2 Instances - AWSSupersededEC2Instances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "ec2:DescribeTags" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - - "ec2:StopInstances" - ## AWS Superseded EC2 Instances AWSSupersededEC2Instances: read: - "ec2:DescribeRegions" @@ -4367,45 +4333,6 @@ Resources: - action Resource: "*" ## AWS Superseded EC2 Instances - iamPolicyAWSSupersededEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - read - Resource: "*" - iamPolicyAWSSupersededEC2InstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - action - Resource: "*" - ## AWS Superseded EC2 Instances iamPolicyAWSSupersededEC2InstancesRead: Type: "AWS::IAM::Policy" Condition: CreatePolicyAWSSupersededEC2InstancesRead diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template b/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template index 2f4b8b5b50..86ad7edc1a 100644 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template @@ -1,6 +1,6 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-12T16:59:05Z +# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: @@ -164,8 +164,6 @@ Metadata: - paramPermsAWSSupersededEBSVolumes ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances - ## AWS Superseded EC2 Instances - - paramPermsAWSSupersededEC2Instances ## AWS Tag Cardinality Report - paramPermsAWSTagCardinalityReport ## AWS Unencrypted EBS Volumes @@ -413,9 +411,6 @@ Metadata: paramPermsAWSSupersededEBSVolumes: default: "Permissions for Policy Template: AWS Superseded EBS Volumes" ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - default: "Permissions for Policy Template: AWS Superseded EC2 Instances" - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: default: "Permissions for Policy Template: AWS Superseded EC2 Instances" ## AWS Tag Cardinality Report @@ -1066,15 +1061,6 @@ Parameters: - Read Only - Read and Take Action ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' Type: String @@ -1606,14 +1592,6 @@ Conditions: - !Ref paramPermsAWSSupersededEBSVolumes - Read and Take Action ## AWS Superseded EC2 Instances - CreatePolicyAWSSupersededEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - None - CreatePolicyAWSSupersededEC2InstancesAction: !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - Read and Take Action - ## AWS Superseded EC2 Instances CreatePolicyAWSSupersededEC2InstancesRead: !Not - !Equals - !Ref paramPermsAWSSupersededEC2Instances @@ -2422,18 +2400,6 @@ Mappings: action: - "ec2:ModifyVolume" ## AWS Superseded EC2 Instances - AWSSupersededEC2Instances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "ec2:DescribeTags" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - - "ec2:StopInstances" - ## AWS Superseded EC2 Instances AWSSupersededEC2Instances: read: - "ec2:DescribeRegions" @@ -4367,45 +4333,6 @@ Resources: - action Resource: "*" ## AWS Superseded EC2 Instances - iamPolicyAWSSupersededEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - read - Resource: "*" - iamPolicyAWSSupersededEC2InstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - action - Resource: "*" - ## AWS Superseded EC2 Instances iamPolicyAWSSupersededEC2InstancesRead: Type: "AWS::IAM::Policy" Condition: CreatePolicyAWSSupersededEC2InstancesRead diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template b/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template index 3fe32b5d7a..6fcef15a5f 100644 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template +++ b/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template @@ -1,6 +1,6 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-12T16:59:05Z +# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: @@ -164,8 +164,6 @@ Metadata: - paramPermsAWSSupersededEBSVolumes ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances - ## AWS Superseded EC2 Instances - - paramPermsAWSSupersededEC2Instances ## AWS Tag Cardinality Report - paramPermsAWSTagCardinalityReport ## AWS Unencrypted EBS Volumes @@ -413,9 +411,6 @@ Metadata: paramPermsAWSSupersededEBSVolumes: default: "Permissions for Policy Template: AWS Superseded EBS Volumes" ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - default: "Permissions for Policy Template: AWS Superseded EC2 Instances" - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: default: "Permissions for Policy Template: AWS Superseded EC2 Instances" ## AWS Tag Cardinality Report @@ -1045,14 +1040,6 @@ Parameters: - None - Read Only ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Superseded EC2 Instances paramPermsAWSSupersededEC2Instances: Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' Type: String @@ -1513,11 +1500,6 @@ Conditions: - !Ref paramPermsAWSSupersededEBSVolumes - None ## AWS Superseded EC2 Instances - CreatePolicyAWSSupersededEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - None - ## AWS Superseded EC2 Instances CreatePolicyAWSSupersededEC2InstancesRead: !Not - !Equals - !Ref paramPermsAWSSupersededEC2Instances @@ -2236,14 +2218,6 @@ Mappings: - "pricing:GetProducts" action: [] ## AWS Superseded EC2 Instances - AWSSupersededEC2Instances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "ec2:DescribeTags" - - "sts:GetCallerIdentity" - action: [] - ## AWS Superseded EC2 Instances AWSSupersededEC2Instances: read: - "ec2:DescribeRegions" @@ -3766,26 +3740,6 @@ Resources: - read Resource: "*" ## AWS Superseded EC2 Instances - iamPolicyAWSSupersededEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - read - Resource: "*" - ## AWS Superseded EC2 Instances iamPolicyAWSSupersededEC2InstancesRead: Type: "AWS::IAM::Policy" Condition: CreatePolicyAWSSupersededEC2InstancesRead diff --git a/tools/policy_master_permission_generation/validated_policy_templates.yaml b/tools/policy_master_permission_generation/validated_policy_templates.yaml index b47d47512f..6fc85f711b 100644 --- a/tools/policy_master_permission_generation/validated_policy_templates.yaml +++ b/tools/policy_master_permission_generation/validated_policy_templates.yaml @@ -29,7 +29,6 @@ validated_policy_templates: - "./cost/aws/object_storage_optimization/aws_object_storage_optimization.pt" - "./cost/aws/old_snapshots/aws_delete_old_snapshots.pt" - "./cost/aws/rds_instance_license_info/rds_instance_license_info.pt" -- "./cost/aws/superseded_instances/aws_superseded_instances.pt" - "./cost/aws/rightsize_ec2_instances/aws_rightsize_ec2_instances.pt" - "./cost/aws/rightsize_elasticache/aws_rightsize_elasticache.pt" - "./cost/aws/rightsize_rds_instances/aws_rightsize_rds_instances.pt" From 09de9836247fe3f07b516663b15a6340d1b6f3fb Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 08:25:01 -0600 Subject: [PATCH 14/23] update --- .github/workflows/cfn-lint.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cfn-lint.yaml b/.github/workflows/cfn-lint.yaml index 9ec0cf2e2a..a95d469458 100644 --- a/.github/workflows/cfn-lint.yaml +++ b/.github/workflows/cfn-lint.yaml @@ -16,8 +16,13 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Setup Cloud Formation Linter with Latest Version - uses: scottbrenner/cfn-lint-action@v2 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install cfn-lint + run: pip install cfn-lint - name: Print the Cloud Formation Linter Version & run Linter. run: | From e24f29e9abca5ea9d2eafeeecf06ca854542574b Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 08:29:27 -0600 Subject: [PATCH 15/23] update --- .github/workflows/cfn-lint.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cfn-lint.yaml b/.github/workflows/cfn-lint.yaml index a95d469458..9e424417a6 100644 --- a/.github/workflows/cfn-lint.yaml +++ b/.github/workflows/cfn-lint.yaml @@ -8,6 +8,9 @@ on: branches: - master + # Workflow dispatch trigger allows manually running workflow + workflow_dispatch: {} + jobs: cloudformation-linter: runs-on: ubuntu-latest From 8bd50ba5bc2b10a24110e9781b2b2392b9f4567b Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 09:05:57 -0600 Subject: [PATCH 16/23] update --- tools/cloudformation-template/aws_cft_updater.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/cloudformation-template/aws_cft_updater.rb b/tools/cloudformation-template/aws_cft_updater.rb index 6779ff6a0f..aa82de117a 100644 --- a/tools/cloudformation-template/aws_cft_updater.rb +++ b/tools/cloudformation-template/aws_cft_updater.rb @@ -6,7 +6,15 @@ # Method to test if two files are identical def files_match?(file1, file2) - Digest::SHA256.file(file1).hexdigest == Digest::SHA256.file(file2).hexdigest + lines1 = File.readlines(file1) + lines2 = File.readlines(file2) + + # Remove line 3 since this contains the date the file was generated + lines1.delete_at(2) if lines1.size > 2 + lines2.delete_at(2) if lines2.size > 2 + + # Compare the remaining content + Digest::SHA256.hexdigest(lines1.join) == Digest::SHA256.hexdigest(lines2.join) end # Define the directory containing the files From bba115d8c7efc7861eafe72c98bdb9fd28e1ef98 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 09:09:46 -0600 Subject: [PATCH 17/23] update --- .../FlexeraAutomationPolicies.template | 1 - tools/cloudformation-template/aws_cft_generator.rb | 3 +-- .../aws_cft_generator.template.txt | 1 - tools/cloudformation-template/aws_cft_updater.rb | 10 +--------- .../releases/FlexeraAutomationPolicies_v0.9.0.template | 1 - .../rolling/FlexeraAutomationPolicies.template | 1 - .../rolling/FlexeraAutomationPoliciesReadOnly.template | 1 - 7 files changed, 2 insertions(+), 16 deletions(-) diff --git a/tools/cloudformation-template/FlexeraAutomationPolicies.template b/tools/cloudformation-template/FlexeraAutomationPolicies.template index 86ad7edc1a..613b5ccf0f 100644 --- a/tools/cloudformation-template/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/FlexeraAutomationPolicies.template @@ -1,6 +1,5 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: diff --git a/tools/cloudformation-template/aws_cft_generator.rb b/tools/cloudformation-template/aws_cft_generator.rb index 5a477b893b..a4f895cc70 100644 --- a/tools/cloudformation-template/aws_cft_generator.rb +++ b/tools/cloudformation-template/aws_cft_generator.rb @@ -197,8 +197,7 @@ def create_template(perm_list, template_path) # Generate new CloudFormation Template empty_template = File.read(template_path) - final_template = empty_template.gsub("__PLACEHOLDER_FOR_GENERATION_DATETIME__", Time.now.utc.iso8601) - final_template = final_template.gsub("__PLACEHOLDER_FOR_PARAMETER_GROUPS__", parameter_groups) + final_template = empty_template.gsub("__PLACEHOLDER_FOR_PARAMETER_GROUPS__", parameter_groups) final_template = final_template.gsub("__PLACEHOLDER_FOR_PARAMETER_LABELS__", parameter_labels) final_template = final_template.gsub("__PLACEHOLDER_FOR_PARAMETER_GROUP_DEFINITIONS__", parameter_group_definitions) final_template = final_template.gsub("__PLACEHOLDER_FOR_CONDITIONS__", conditions) diff --git a/tools/cloudformation-template/aws_cft_generator.template.txt b/tools/cloudformation-template/aws_cft_generator.template.txt index 4fd2c4dd67..0f630ce090 100644 --- a/tools/cloudformation-template/aws_cft_generator.template.txt +++ b/tools/cloudformation-template/aws_cft_generator.template.txt @@ -1,6 +1,5 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on __PLACEHOLDER_FOR_GENERATION_DATETIME__ # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: diff --git a/tools/cloudformation-template/aws_cft_updater.rb b/tools/cloudformation-template/aws_cft_updater.rb index aa82de117a..6779ff6a0f 100644 --- a/tools/cloudformation-template/aws_cft_updater.rb +++ b/tools/cloudformation-template/aws_cft_updater.rb @@ -6,15 +6,7 @@ # Method to test if two files are identical def files_match?(file1, file2) - lines1 = File.readlines(file1) - lines2 = File.readlines(file2) - - # Remove line 3 since this contains the date the file was generated - lines1.delete_at(2) if lines1.size > 2 - lines2.delete_at(2) if lines2.size > 2 - - # Compare the remaining content - Digest::SHA256.hexdigest(lines1.join) == Digest::SHA256.hexdigest(lines2.join) + Digest::SHA256.file(file1).hexdigest == Digest::SHA256.file(file2).hexdigest end # Define the directory containing the files diff --git a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template index 86ad7edc1a..613b5ccf0f 100644 --- a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template +++ b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template @@ -1,6 +1,5 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template b/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template index 86ad7edc1a..613b5ccf0f 100644 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template @@ -1,6 +1,5 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template b/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template index 6fcef15a5f..731f3fd641 100644 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template +++ b/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template @@ -1,6 +1,5 @@ AWSTemplateFormatVersion: 2010-09-09 Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# Generated by Flexera automation on 2024-12-13T14:14:20Z # For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md Metadata: From 030f52b69858d29f144d50dc85188fefb0dbd7a1 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 09:23:09 -0600 Subject: [PATCH 18/23] update --- tools/cloudformation-template/README.md | 2 ++ tools/cloudformation-template/aws_cft_updater.rb | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/cloudformation-template/README.md b/tools/cloudformation-template/README.md index bea58e3f3a..53b61c8824 100644 --- a/tools/cloudformation-template/README.md +++ b/tools/cloudformation-template/README.md @@ -181,3 +181,5 @@ resource "aws_cloudformation_stack" "FlexeraAutomationAccessRole" { ## For Maintainers New rolling releases are created automatically by the `tools/cloudformation-template/aws_cft_generator.rb` script. This script runs automatically via GitHub Actions whenever a change is made to the master branch. This script uses the permissions file `data/policy_permissions_list/master_policy_permissions_list.json` to obtain the information needed to generate the CloudFormation Template. This file, in turn, is sourced through its own automation that scrapes policy template README files. + +New production releases are created automatically by the `tools/cloudformation-template/aws_cft_updater.rb` script. This script runs on the first of every month and checks whether the most recent rolling release has any changes compared to the current production release. If changes are present, a new minor version is created and stored in the `tools/cloudformation-template/releases` directory, and the `tools/cloudformation-template/FlexeraAutomationPolicies.template` file is updated to match the new release. diff --git a/tools/cloudformation-template/aws_cft_updater.rb b/tools/cloudformation-template/aws_cft_updater.rb index 6779ff6a0f..0ecd0ab22e 100644 --- a/tools/cloudformation-template/aws_cft_updater.rb +++ b/tools/cloudformation-template/aws_cft_updater.rb @@ -30,8 +30,8 @@ def files_match?(file1, file2) most_recent_file, most_recent_version = most_recent most_recent_path = File.join(release_dir, most_recent_file) - new_patch_version = (Integer(most_recent_version.split(".")[2]) + 1).to_s - new_version = most_recent_version.split(".")[0] + "." + most_recent_version.split(".")[1] + "." + new_patch_version + new_minor_version = (Integer(most_recent_version.split(".")[1]) + 1).to_s + new_version = most_recent_version.split(".")[0] + "." + new_minor_version + ".0" new_file_path = release_dir + "/FlexeraAutomationPolicies_v" + new_version + ".template" FileUtils.cp(rolling_path, new_file_path, verbose: true) From 258aefb2be0f6b9405fb384032eb16a411691e3a Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 09:24:56 -0600 Subject: [PATCH 19/23] update --- tools/cloudformation-template/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cloudformation-template/README.md b/tools/cloudformation-template/README.md index 53b61c8824..53e2f5c90f 100644 --- a/tools/cloudformation-template/README.md +++ b/tools/cloudformation-template/README.md @@ -180,6 +180,6 @@ resource "aws_cloudformation_stack" "FlexeraAutomationAccessRole" { ## For Maintainers -New rolling releases are created automatically by the `tools/cloudformation-template/aws_cft_generator.rb` script. This script runs automatically via GitHub Actions whenever a change is made to the master branch. This script uses the permissions file `data/policy_permissions_list/master_policy_permissions_list.json` to obtain the information needed to generate the CloudFormation Template. This file, in turn, is sourced through its own automation that scrapes policy template README files. +New rolling releases are created automatically by the `tools/cloudformation-template/aws_cft_generator.rb` script. This script runs automatically via GitHub Actions whenever a change is made to the master branch. This script uses the permissions file `data/policy_permissions_list/master_policy_permissions_list.json` to obtain the information needed to generate the CloudFormation Template. This file, in turn, is sourced through its [own automation](https://github.com/flexera-public/policy_templates/tree/master/tools/policy_master_permission_generation) that scrapes policy template README files. New production releases are created automatically by the `tools/cloudformation-template/aws_cft_updater.rb` script. This script runs on the first of every month and checks whether the most recent rolling release has any changes compared to the current production release. If changes are present, a new minor version is created and stored in the `tools/cloudformation-template/releases` directory, and the `tools/cloudformation-template/FlexeraAutomationPolicies.template` file is updated to match the new release. From 92c87b6ebfea608b09da68b655123a8888e1bca5 Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 11:17:08 -0600 Subject: [PATCH 20/23] update --- .github/workflows/cfn-test.yaml | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/.github/workflows/cfn-test.yaml b/.github/workflows/cfn-test.yaml index 4abb14d4ef..450f6ed213 100644 --- a/.github/workflows/cfn-test.yaml +++ b/.github/workflows/cfn-test.yaml @@ -19,25 +19,21 @@ jobs: matrix: # matrix.template_files is a list of template files to test template_files: - - ./cost/aws/FlexeraReadOnlyPolicy.template - ./tools/cloudformation-template/FlexeraAutomationPolicies.template - - # TODO: Fix wildcard/dynamic release list - # - ./tools/cloudformation-template/releases/*.template - - # Staticly define release templates for now - - ./tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.1.0.template - - ./tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.1.1.template - - ./tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.2.0.template - - ./tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.2.1.template - - ./tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.3.0.template - - ./tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.4.0.template + - ./tools/cloudformation-template/FlexeraAutomationPoliciesSimple.template + - ./tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template + - ./tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template steps: - name: Checkout uses: actions/checkout@v2 - - name: Setup Cloud Formation Linter with Latest Version - uses: scottbrenner/cfn-lint-action@v2 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install cfn-lint + run: pip install cfn-lint - name: Run Cloudformation Linter id: cfn-lint From 5b6f1f84721b2fe1e240aefdf8270869186fd4bc Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 11:35:49 -0600 Subject: [PATCH 21/23] update --- cost/aws/s3_lifecycle/README.md | 4 ++-- .../master_policy_permissions_list.json | 4 ++-- .../master_policy_permissions_list.yaml | 2 +- .../FlexeraAutomationPolicies.template | 4 ++-- .../releases/FlexeraAutomationPolicies_v0.9.0.template | 4 ++-- .../rolling/FlexeraAutomationPolicies.template | 4 ++-- .../rolling/FlexeraAutomationPoliciesReadOnly.template | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cost/aws/s3_lifecycle/README.md b/cost/aws/s3_lifecycle/README.md index e3d0d6eb68..5d56630454 100644 --- a/cost/aws/s3_lifecycle/README.md +++ b/cost/aws/s3_lifecycle/README.md @@ -34,7 +34,7 @@ For administrators [creating and managing credentials](https://docs.flexera.com/ - `s3:ListAllMyBuckets` - `s3:GetBucketLocation` - `s3:GetBucketTagging` - - `s3:GetBucketLifecycleConfiguration` + - `s3:GetLifecycleConfiguration` - `sts:GetCallerIdentity` Example IAM Permission Policy: @@ -49,7 +49,7 @@ For administrators [creating and managing credentials](https://docs.flexera.com/ "s3:ListAllMyBuckets", "s3:GetBucketLocation", "s3:GetBucketTagging", - "s3:GetBucketLifecycleConfiguration", + "s3:GetLifecycleConfiguration", "sts:GetCallerIdentity" ], "Resource": "*" diff --git a/data/policy_permissions_list/master_policy_permissions_list.json b/data/policy_permissions_list/master_policy_permissions_list.json index 723053add3..e2a84d18c6 100644 --- a/data/policy_permissions_list/master_policy_permissions_list.json +++ b/data/policy_permissions_list/master_policy_permissions_list.json @@ -2537,7 +2537,7 @@ "required": true }, { - "name": "s3:GetBucketLifecycleConfiguration", + "name": "s3:GetLifecycleConfiguration", "read_only": true, "required": true }, @@ -10110,4 +10110,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/data/policy_permissions_list/master_policy_permissions_list.yaml b/data/policy_permissions_list/master_policy_permissions_list.yaml index 1c9bfd628d..ee580fa632 100644 --- a/data/policy_permissions_list/master_policy_permissions_list.yaml +++ b/data/policy_permissions_list/master_policy_permissions_list.yaml @@ -1458,7 +1458,7 @@ - name: s3:GetBucketTagging read_only: true required: true - - name: s3:GetBucketLifecycleConfiguration + - name: s3:GetLifecycleConfiguration read_only: true required: true - name: sts:GetCallerIdentity diff --git a/tools/cloudformation-template/FlexeraAutomationPolicies.template b/tools/cloudformation-template/FlexeraAutomationPolicies.template index 613b5ccf0f..7f96b182b2 100644 --- a/tools/cloudformation-template/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/FlexeraAutomationPolicies.template @@ -1783,7 +1783,7 @@ Mappings: - "rds:ListTagsForResource" - "redshift:DescribeClusters" - "s3:GetBucketAcl" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "s3:GetBucketLocation" - "s3:GetBucketLogging" - "s3:GetBucketPolicy" @@ -2315,7 +2315,7 @@ Mappings: - "s3:ListAllMyBuckets" - "s3:GetBucketLocation" - "s3:GetBucketTagging" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "sts:GetCallerIdentity" action: [] ## AWS S3 Buckets Without MFA Delete Enabled diff --git a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template index 613b5ccf0f..7f96b182b2 100644 --- a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template +++ b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template @@ -1783,7 +1783,7 @@ Mappings: - "rds:ListTagsForResource" - "redshift:DescribeClusters" - "s3:GetBucketAcl" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "s3:GetBucketLocation" - "s3:GetBucketLogging" - "s3:GetBucketPolicy" @@ -2315,7 +2315,7 @@ Mappings: - "s3:ListAllMyBuckets" - "s3:GetBucketLocation" - "s3:GetBucketTagging" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "sts:GetCallerIdentity" action: [] ## AWS S3 Buckets Without MFA Delete Enabled diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template b/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template index 613b5ccf0f..7f96b182b2 100644 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template @@ -1783,7 +1783,7 @@ Mappings: - "rds:ListTagsForResource" - "redshift:DescribeClusters" - "s3:GetBucketAcl" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "s3:GetBucketLocation" - "s3:GetBucketLogging" - "s3:GetBucketPolicy" @@ -2315,7 +2315,7 @@ Mappings: - "s3:ListAllMyBuckets" - "s3:GetBucketLocation" - "s3:GetBucketTagging" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "sts:GetCallerIdentity" action: [] ## AWS S3 Buckets Without MFA Delete Enabled diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template b/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template index 731f3fd641..e9483da78f 100644 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template +++ b/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template @@ -1667,7 +1667,7 @@ Mappings: - "rds:ListTagsForResource" - "redshift:DescribeClusters" - "s3:GetBucketAcl" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "s3:GetBucketLocation" - "s3:GetBucketLogging" - "s3:GetBucketPolicy" @@ -2136,7 +2136,7 @@ Mappings: - "s3:ListAllMyBuckets" - "s3:GetBucketLocation" - "s3:GetBucketTagging" - - "s3:GetBucketLifecycleConfiguration" + - "s3:GetLifecycleConfiguration" - "sts:GetCallerIdentity" action: [] ## AWS S3 Buckets Without MFA Delete Enabled From 0750bd78c5df9bf54581dc2541695e946f95736e Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 13:44:04 -0600 Subject: [PATCH 22/23] update --- .../generate-aws-cloudformation-template.yaml | 2 +- .../update-aws-cloudformation-template.yaml | 16 +- .../FlexeraAutomationPolicies.template | 2 +- ...FlexeraAutomationPoliciesReadOnly.template | 2 +- tools/cloudformation-template/README.md | 14 +- .../aws_cft_generator.rb | 7 +- .../aws_cft_new_release.rb | 37 + .../aws_cft_updater.rb | 39 - .../FlexeraAutomationPolicies_v0.9.0.template | 2 +- .../FlexeraAutomationPolicies.template | 4756 ----------------- 10 files changed, 59 insertions(+), 4818 deletions(-) rename tools/cloudformation-template/{rolling => }/FlexeraAutomationPoliciesReadOnly.template (100%) create mode 100644 tools/cloudformation-template/aws_cft_new_release.rb delete mode 100644 tools/cloudformation-template/aws_cft_updater.rb delete mode 100644 tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template diff --git a/.github/workflows/generate-aws-cloudformation-template.yaml b/.github/workflows/generate-aws-cloudformation-template.yaml index 614a16826b..40bad365d1 100644 --- a/.github/workflows/generate-aws-cloudformation-template.yaml +++ b/.github/workflows/generate-aws-cloudformation-template.yaml @@ -1,4 +1,4 @@ -name: Generate Meta Parent Policy Templates +name: Generate AWS CloudFormation Template on: # Trigger this workflow on pushes to master diff --git a/.github/workflows/update-aws-cloudformation-template.yaml b/.github/workflows/update-aws-cloudformation-template.yaml index 41078f1ec2..90f2dd8c76 100644 --- a/.github/workflows/update-aws-cloudformation-template.yaml +++ b/.github/workflows/update-aws-cloudformation-template.yaml @@ -1,4 +1,4 @@ -name: Update Meta Parent Policy Templates +name: Update AWS CloudFormation Template Release on: schedule: @@ -11,8 +11,8 @@ on: # │ │ │ │ │ # │ │ │ │ │ # * * * * * - # At 01:00 UTC on Sundays - - cron: "0 0 1 * *" + # At 12am daily + - cron: "0 0 * * *" # Workflow dispatch trigger allows manually running workflow workflow_dispatch: {} @@ -31,16 +31,16 @@ jobs: - name: Update AWS CloudFormation Template working-directory: tools/cloudformation-template run: | - ruby aws_cft_updater.rb + ruby aws_cft_new_release.rb - name: Create Pull Request id: cpr uses: peter-evans/create-pull-request@v4 with: - commit-message: "Update AWS CloudFormation Template" - title: "Update AWS CloudFormation Template" - body: "Update AWS CloudFormation Template from GitHub Actions Workflow [${{ github.workflow }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" - branch: "task/update-aws-cloudformation-template" + commit-message: "Update AWS CloudFormation Template Release" + title: "Update AWS CloudFormation Template Release" + body: "Update AWS CloudFormation Template Release from GitHub Actions Workflow [${{ github.workflow }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" + branch: "task/update-aws-cloudformation-template-release" delete-branch: true labels: "automation" diff --git a/tools/cloudformation-template/FlexeraAutomationPolicies.template b/tools/cloudformation-template/FlexeraAutomationPolicies.template index 7f96b182b2..c0a7adb02e 100644 --- a/tools/cloudformation-template/FlexeraAutomationPolicies.template +++ b/tools/cloudformation-template/FlexeraAutomationPolicies.template @@ -1783,7 +1783,6 @@ Mappings: - "rds:ListTagsForResource" - "redshift:DescribeClusters" - "s3:GetBucketAcl" - - "s3:GetLifecycleConfiguration" - "s3:GetBucketLocation" - "s3:GetBucketLogging" - "s3:GetBucketPolicy" @@ -1792,6 +1791,7 @@ Mappings: - "s3:GetBucketVersioning" - "s3:GetEncryptionConfiguration" - "s3:GetIntelligentTieringConfiguration" + - "s3:GetLifecycleConfiguration" - "s3:GetObject" - "s3:ListAllMyBuckets" - "s3:ListBucketMultipartUploads" diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template b/tools/cloudformation-template/FlexeraAutomationPoliciesReadOnly.template similarity index 100% rename from tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template rename to tools/cloudformation-template/FlexeraAutomationPoliciesReadOnly.template index e9483da78f..d26ddbea29 100644 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template +++ b/tools/cloudformation-template/FlexeraAutomationPoliciesReadOnly.template @@ -1667,7 +1667,6 @@ Mappings: - "rds:ListTagsForResource" - "redshift:DescribeClusters" - "s3:GetBucketAcl" - - "s3:GetLifecycleConfiguration" - "s3:GetBucketLocation" - "s3:GetBucketLogging" - "s3:GetBucketPolicy" @@ -1676,6 +1675,7 @@ Mappings: - "s3:GetBucketVersioning" - "s3:GetEncryptionConfiguration" - "s3:GetIntelligentTieringConfiguration" + - "s3:GetLifecycleConfiguration" - "s3:GetObject" - "s3:ListAllMyBuckets" - "s3:ListBucketMultipartUploads" diff --git a/tools/cloudformation-template/README.md b/tools/cloudformation-template/README.md index 53e2f5c90f..6f8276b453 100644 --- a/tools/cloudformation-template/README.md +++ b/tools/cloudformation-template/README.md @@ -4,16 +4,12 @@ Template to create a CloudFormation Stack with IAM Role and Permission Policy resources required by [Flexera Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm). -Two supported versions are provided as options: +Three supported versions are provided as options: -- [FlexeraAutomationPolicies.template](https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/FlexeraAutomationPolicies.template): Current approved/stable version of the template. Recommended for most use cases. +- [FlexeraAutomationPolicies.template](https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/FlexeraAutomationPolicies.template): Current production version of the template. Recommended for most use cases. +- [FlexeraAutomationPoliciesReadOnly.template](https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template): Identical to the above but with only read-only permissions. Recommended when there are concerns over the template having options for more than just read-only access. - [FlexeraAutomationPoliciesSimple.template](https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/FlexeraAutomationPoliciesSimple.template): Template that simply attaches the built-in `arn:aws:iam::aws:policy/ReadOnlyAccess` AWS policy by default with the option to add other policies by name manually via parameter. Recommended when custom inline policies are not desired. Note that this grants more access than simply applying [FlexeraAutomationPolicies.template](https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/FlexeraAutomationPolicies.template) with the default options, since this provides read-only access to everything in the AWS account rather than just to the resources needed for Flexera automation. -Additionally, two automatically generated rolling release versions are provided but are **not recommended** or supported for production use. These will be used as the basis for the stable releases above. - -- [rolling/FlexeraAutomationPolicies.template](https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template): Template to add either read or read/action permissions for either all Flexera automation templates or per-Flexera automation template. -- [rolling/FlexeraAutomationPoliciesReadOnly.template](https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template): Identical to the above but with only read-only permissions. Recommended when there are concerns over the template having options for more than just read-only access. - ## Amazon S3 Template URL **`https://flexera-cloudformation-public.s3.us-east-2.amazonaws.com/FlexeraAutomationPolicies_latest.template`** @@ -180,6 +176,6 @@ resource "aws_cloudformation_stack" "FlexeraAutomationAccessRole" { ## For Maintainers -New rolling releases are created automatically by the `tools/cloudformation-template/aws_cft_generator.rb` script. This script runs automatically via GitHub Actions whenever a change is made to the master branch. This script uses the permissions file `data/policy_permissions_list/master_policy_permissions_list.json` to obtain the information needed to generate the CloudFormation Template. This file, in turn, is sourced through its [own automation](https://github.com/flexera-public/policy_templates/tree/master/tools/policy_master_permission_generation) that scrapes policy template README files. +New versions of `tools/cloudformation-template/FlexeraAutomationPolicies.template` are created automatically by the `tools/cloudformation-template/aws_cft_generator.rb` script. This script runs automatically via GitHub Actions whenever a change is made to the master branch. This script uses the permissions file `data/policy_permissions_list/master_policy_permissions_list.json` to obtain the information needed to generate the CloudFormation Template. This file, in turn, is sourced through its [own automation](https://github.com/flexera-public/policy_templates/tree/master/tools/policy_master_permission_generation) that scrapes policy template README files. -New production releases are created automatically by the `tools/cloudformation-template/aws_cft_updater.rb` script. This script runs on the first of every month and checks whether the most recent rolling release has any changes compared to the current production release. If changes are present, a new minor version is created and stored in the `tools/cloudformation-template/releases` directory, and the `tools/cloudformation-template/FlexeraAutomationPolicies.template` file is updated to match the new release. +New releases are created automatically by the `tools/cloudformation-template/aws_cft_new_release.rb` script. This script runs daily and checks whether the most recent version has any changes compared to the latest release. If changes are present, a new minor version is created and stored in the `tools/cloudformation-template/releases` directory. diff --git a/tools/cloudformation-template/aws_cft_generator.rb b/tools/cloudformation-template/aws_cft_generator.rb index a4f895cc70..8db4631b33 100644 --- a/tools/cloudformation-template/aws_cft_generator.rb +++ b/tools/cloudformation-template/aws_cft_generator.rb @@ -1,5 +1,8 @@ require "json" require "time" +require "pathname" +require "digest" +require "fileutils" # Method for generating permission list def create_permissions(perm_json, deprecated, perm_type = "action") @@ -211,8 +214,8 @@ def create_template(perm_list, template_path) activepolicy_json_filepath = "../../data/active_policy_list/active_policy_list.json" permission_json_filepath = "../../data/policy_permissions_list/master_policy_permissions_list.json" template_filepath = "./aws_cft_generator.template.txt" -output_filepath = "./rolling/FlexeraAutomationPolicies.template" -output_readonly_filepath = "./rolling/FlexeraAutomationPoliciesReadOnly.template" +output_filepath = "./FlexeraAutomationPolicies.template" +output_readonly_filepath = "./FlexeraAutomationPoliciesReadOnly.template" # Get list of deprecated policies activepolicy_json = JSON.parse(File.read(activepolicy_json_filepath)) diff --git a/tools/cloudformation-template/aws_cft_new_release.rb b/tools/cloudformation-template/aws_cft_new_release.rb new file mode 100644 index 0000000000..a4ccba0cce --- /dev/null +++ b/tools/cloudformation-template/aws_cft_new_release.rb @@ -0,0 +1,37 @@ +require "json" +require "time" +require "pathname" +require "digest" +require "fileutils" + +# Method to test if two files are identical +def files_match?(file1, file2) + Digest::SHA256.file(file1).hexdigest == Digest::SHA256.file(file2).hexdigest +end + +# Define the directory containing the files +release_dir = "./releases" +local_file_path = "./FlexeraAutomationPolicies.template" + +# Get a list of all template files in the directory +files = Dir.entries(release_dir).select { |file| file =~ /FlexeraAutomationPolicies_v(\d+\.\d+\.\d+)\.template$/ } + +# Extract version numbers and map them to their corresponding files +file_versions = files.map do |file| + match = file.match(/v(\d+\.\d+\.\d+)/) + [file, match[1]] if match +end.compact + +# Find the most recent version +most_recent = file_versions.max_by { |_, version| Gem::Version.new(version) } +most_recent_file, most_recent_version = most_recent +most_recent_path = File.join(release_dir, most_recent_file) + +# Unless the files are identical, create a new version. +unless files_match?(local_file_path, most_recent_path) + new_minor_version = (Integer(most_recent_version.split(".")[1]) + 1).to_s + new_version = most_recent_version.split(".")[0] + "." + new_minor_version + ".0" + new_file_path = release_dir + "/FlexeraAutomationPolicies_v" + new_version + ".template" + + FileUtils.cp(local_file_path, new_file_path, verbose: true) +end diff --git a/tools/cloudformation-template/aws_cft_updater.rb b/tools/cloudformation-template/aws_cft_updater.rb deleted file mode 100644 index 0ecd0ab22e..0000000000 --- a/tools/cloudformation-template/aws_cft_updater.rb +++ /dev/null @@ -1,39 +0,0 @@ -require "json" -require "time" -require "pathname" -require "digest" -require "fileutils" - -# Method to test if two files are identical -def files_match?(file1, file2) - Digest::SHA256.file(file1).hexdigest == Digest::SHA256.file(file2).hexdigest -end - -# Define the directory containing the files -release_dir = "./releases" -rolling_path = "./rolling/FlexeraAutomationPolicies.template" -local_file_path = "./FlexeraAutomationPolicies.template" - -# Unless the files are identical, create a new version. -unless files_match?(rolling_path, local_file_path) - # Get a list of all template files in the directory - files = Dir.entries(release_dir).select { |file| file =~ /FlexeraAutomationPolicies_v(\d+\.\d+\.\d+)\.template$/ } - - # Extract version numbers and map them to their corresponding files - file_versions = files.map do |file| - match = file.match(/v(\d+\.\d+\.\d+)/) - [file, match[1]] if match - end.compact - - # Find the most recent version - most_recent = file_versions.max_by { |_, version| Gem::Version.new(version) } - most_recent_file, most_recent_version = most_recent - most_recent_path = File.join(release_dir, most_recent_file) - - new_minor_version = (Integer(most_recent_version.split(".")[1]) + 1).to_s - new_version = most_recent_version.split(".")[0] + "." + new_minor_version + ".0" - new_file_path = release_dir + "/FlexeraAutomationPolicies_v" + new_version + ".template" - - FileUtils.cp(rolling_path, new_file_path, verbose: true) - FileUtils.cp(rolling_path, local_file_path, verbose: true) -end diff --git a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template index 7f96b182b2..c0a7adb02e 100644 --- a/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template +++ b/tools/cloudformation-template/releases/FlexeraAutomationPolicies_v0.9.0.template @@ -1783,7 +1783,6 @@ Mappings: - "rds:ListTagsForResource" - "redshift:DescribeClusters" - "s3:GetBucketAcl" - - "s3:GetLifecycleConfiguration" - "s3:GetBucketLocation" - "s3:GetBucketLogging" - "s3:GetBucketPolicy" @@ -1792,6 +1791,7 @@ Mappings: - "s3:GetBucketVersioning" - "s3:GetEncryptionConfiguration" - "s3:GetIntelligentTieringConfiguration" + - "s3:GetLifecycleConfiguration" - "s3:GetObject" - "s3:ListAllMyBuckets" - "s3:ListBucketMultipartUploads" diff --git a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template b/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template deleted file mode 100644 index 7f96b182b2..0000000000 --- a/tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template +++ /dev/null @@ -1,4756 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Description: "CloudFormation Stack with IAM Role and IAM Permission Policy used by Flexera Automation. Official Docs: https://docs.flexera.com/" -# For more details, see: https://github.com/flexera-public/policy_templates/blob/master/tools/cloudformation-template/README.md - -Metadata: - # AWS::CloudFormation::Interface is a metadata key that defines how parameters are grouped and sorted in the AWS CloudFormation console. - # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html - AWS::CloudFormation::Interface: - # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-parametergroup.html - ParameterGroups: - # ParameterGroup with paramFlexeraOrgId should be first. - # paramFlexeraOrgId only param that is actually required (if Org is on app.flexera.com) - - Label: - default: "Parameters related to your Organization on the Flexera Platform" - Parameters: - - paramFlexeraOrgId - - paramFlexeraZone - - Label: - default: "Parameters related to the IAM Role that is created" - Parameters: - - paramRoleName - - paramRolePath - - Label: - default: "Parameters related to Policy Template permissions on the IAM Role that is created" - Parameters: - ## All AWS Policy Templates - - paramPermsAllAWSPolicyTemplates - ## AWS Account Credentials - - paramPermsAWSAccountCredentials - ## AWS Accounts Missing Service Control Policies - - paramPermsAWSAccountsMissingServiceControlPolicies - ## AWS Burstable EC2 Instances - - paramPermsAWSBurstableEC2Instances - ## AWS CloudTrail Not Enabled In All Regions - - paramPermsAWSCloudTrailNotEnabledInAllRegions - ## AWS CloudTrail S3 Buckets Without Access Logging - - paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging - ## AWS CloudTrails Not Integrated With CloudWatch - - paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch - ## AWS CloudTrails With Read Logging Enabled - - paramPermsAWSCloudTrailsWithReadLoggingEnabled - ## AWS CloudTrails Without Encrypted Logs - - paramPermsAWSCloudTrailsWithoutEncryptedLogs - ## AWS CloudTrails Without Log File Validation Enabled - - paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled - ## AWS CloudTrails Without Object-level Events Logging Enabled - - paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled - ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled - - paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled - ## AWS Disallowed Regions - - paramPermsAWSDisallowedRegions - ## AWS EC2 Compute Optimizer Recommendations - - paramPermsAWSEC2ComputeOptimizerRecommendations - ## AWS EC2 Instances Time Stopped Report - - paramPermsAWSEC2InstancesTimeStoppedReport - ## AWS EC2 Instances not running FlexNet Inventory Agent - - paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent - ## AWS EKS Clusters Without Spot Instances - - paramPermsAWSEKSClustersWithoutSpotInstances - ## AWS Elastic Load Balancers With Unencrypted Listeners - - paramPermsAWSElasticLoadBalancersWithUnencryptedListeners - ## AWS Expiring Savings Plans - - paramPermsAWSExpiringSavingsPlans - ## AWS IAM Account Missing Support Role - - paramPermsAWSIAMAccountMissingSupportRole - ## AWS IAM Attached Admin Policies - - paramPermsAWSIAMAttachedAdminPolicies - ## AWS IAM Expired SSL/TLS Certificates - - paramPermsAWSIAMExpiredSSLTLSCertificates - ## AWS IAM Insufficient Required Password Length - - paramPermsAWSIAMInsufficientRequiredPasswordLength - ## AWS IAM Password Policy Not Restricting Password Reuse - - paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse - ## AWS IAM Role Audit - - paramPermsAWSIAMRoleAudit - ## AWS IAM Root Account Access Keys - - paramPermsAWSIAMRootAccountAccessKeys - ## AWS IAM Root User Account Without Hardware MFA - - paramPermsAWSIAMRootUserAccountWithoutHardwareMFA - ## AWS IAM Root User Account Without MFA - - paramPermsAWSIAMRootUserAccountWithoutMFA - ## AWS IAM Root User Doing Everyday Tasks - - paramPermsAWSIAMRootUserDoingEverydayTasks - ## AWS IAM User Accounts Without MFA - - paramPermsAWSIAMUserAccountsWithoutMFA - ## AWS IAM Users With Directly-Attached Policies - - paramPermsAWSIAMUsersWithDirectlyAttachedPolicies - ## AWS IAM Users With Multiple Active Access Keys - - paramPermsAWSIAMUsersWithMultipleActiveAccessKeys - ## AWS IAM Users With Old Access Keys - - paramPermsAWSIAMUsersWithOldAccessKeys - ## AWS Idle NAT Gateways - - paramPermsAWSIdleNATGateways - ## AWS Internet-Accessible Elastic Load Balancers - - paramPermsAWSInternetAccessibleElasticLoadBalancers - ## AWS Lambda Functions With High Error Rate - - paramPermsAWSLambdaFunctionsWithHighErrorRate - ## AWS Lambda Functions Without Provisioned Concurrency - - paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency - ## AWS Long Running Instances - - paramPermsAWSLongRunningInstances - ## AWS Long Stopped EC2 Instances - - paramPermsAWSLongStoppedEC2Instances - ## AWS Missing Regions - - paramPermsAWSMissingRegions - ## AWS Old Snapshots - - paramPermsAWSOldSnapshots - ## AWS Open S3 Buckets - - paramPermsAWSOpenS3Buckets - ## AWS Oversized S3 Buckets - - paramPermsAWSOversizedS3Buckets - ## AWS Publicly Accessible CloudTrail S3 Buckets - - paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets - ## AWS Publicly Accessible RDS Instances - - paramPermsAWSPubliclyAccessibleRDSInstances - ## AWS RDS Instances With Unapproved Backup Settings - - paramPermsAWSRDSInstancesWithUnapprovedBackupSettings - ## AWS Regions Without Access Analyzer Enabled - - paramPermsAWSRegionsWithoutAccessAnalyzerEnabled - ## AWS Regions Without Config Fully Enabled - - paramPermsAWSRegionsWithoutConfigFullyEnabled - ## AWS Regions Without Default EBS Encryption - - paramPermsAWSRegionsWithoutDefaultEBSEncryption - ## AWS Reserved Instances Coverage - - paramPermsAWSReservedInstancesCoverage - ## AWS Reserved Instances Recommendations - - paramPermsAWSReservedInstancesRecommendations - ## AWS Rightsize EBS Volumes - - paramPermsAWSRightsizeEBSVolumes - ## AWS Rightsize EC2 Instances - - paramPermsAWSRightsizeEC2Instances - ## AWS Rightsize ElastiCache - - paramPermsAWSRightsizeElastiCache - ## AWS Rightsize RDS Instances - - paramPermsAWSRightsizeRDSInstances - ## AWS Rightsize Redshift - - paramPermsAWSRightsizeRedshift - ## AWS S3 Buckets Accepting HTTP Requests - - paramPermsAWSS3BucketsAcceptingHTTPRequests - ## AWS S3 Buckets Without Default Encryption Configuration - - paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration - ## AWS S3 Buckets Without Intelligent Tiering - - paramPermsAWSS3BucketsWithoutIntelligentTiering - ## AWS S3 Buckets Without Lifecycle Configuration - - paramPermsAWSS3BucketsWithoutLifecycleConfiguration - ## AWS S3 Buckets Without MFA Delete Enabled - - paramPermsAWSS3BucketsWithoutMFADeleteEnabled - ## AWS S3 Buckets Without Public Access Blocked - - paramPermsAWSS3BucketsWithoutPublicAccessBlocked - ## AWS S3 Buckets Without Server Access Logging - - paramPermsAWSS3BucketsWithoutServerAccessLogging - ## AWS S3 Incomplete Multi-Part Uploads - - paramPermsAWSS3IncompleteMultiPartUploads - ## AWS Savings Plan Recommendations - - paramPermsAWSSavingsPlanRecommendations - ## AWS Savings Plan Utilization - - paramPermsAWSSavingsPlanUtilization - ## AWS Schedule Instance - - paramPermsAWSScheduleInstance - ## AWS Scheduled EC2 Events - - paramPermsAWSScheduledEC2Events - ## AWS Superseded EBS Volumes - - paramPermsAWSSupersededEBSVolumes - ## AWS Superseded EC2 Instances - - paramPermsAWSSupersededEC2Instances - ## AWS Tag Cardinality Report - - paramPermsAWSTagCardinalityReport - ## AWS Unencrypted EBS Volumes - - paramPermsAWSUnencryptedEBSVolumes - ## AWS Unencrypted RDS Instances - - paramPermsAWSUnencryptedRDSInstances - ## AWS Untagged Resources - - paramPermsAWSUntaggedResources - ## AWS Unused Application Load Balancers - - paramPermsAWSUnusedApplicationLoadBalancers - ## AWS Unused Classic Load Balancers - - paramPermsAWSUnusedClassicLoadBalancers - ## AWS Unused ECS Clusters - - paramPermsAWSUnusedECSClusters - ## AWS Unused IAM Credentials - - paramPermsAWSUnusedIAMCredentials - ## AWS Unused IP Addresses - - paramPermsAWSUnusedIPAddresses - ## AWS Unused Network Load Balancers - - paramPermsAWSUnusedNetworkLoadBalancers - ## AWS VPCs Without FlowLogs Enabled - - paramPermsAWSVPCsWithoutFlowLogsEnabled - ## Common Bill Ingestion from AWS S3 Object Storage - - paramPermsCommonBillIngestionfromAWSS3ObjectStorage - - # End for each policy template - - paramPermsAttachExistingPolicies - # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-parameterlabel.html - ParameterLabels: - paramRoleName: - # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-interface-label.html - # The default label that the CloudFormation console uses to name a parameter group or parameter. - default: "IAM Role Name" - paramRolePath: - default: "IAM Role Path" - paramFlexeraOrgId: - default: "Flexera Organization ID" - paramFlexeraZone: - default: "Flexera Zone" - ## All AWS Policy Templates - paramPermsAllAWSPolicyTemplates: - default: "Permissions for all AWS Policy Templates" - ## AWS Account Credentials - paramPermsAWSAccountCredentials: - default: "Permissions for Policy Template: AWS Account Credentials" - ## AWS Accounts Missing Service Control Policies - paramPermsAWSAccountsMissingServiceControlPolicies: - default: "Permissions for Policy Template: AWS Accounts Missing Service Control Policies" - ## AWS Burstable EC2 Instances - paramPermsAWSBurstableEC2Instances: - default: "Permissions for Policy Template: AWS Burstable EC2 Instances" - ## AWS CloudTrail Not Enabled In All Regions - paramPermsAWSCloudTrailNotEnabledInAllRegions: - default: "Permissions for Policy Template: AWS CloudTrail Not Enabled In All Regions" - ## AWS CloudTrail S3 Buckets Without Access Logging - paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging: - default: "Permissions for Policy Template: AWS CloudTrail S3 Buckets Without Access Logging" - ## AWS CloudTrails Not Integrated With CloudWatch - paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch: - default: "Permissions for Policy Template: AWS CloudTrails Not Integrated With CloudWatch" - ## AWS CloudTrails With Read Logging Enabled - paramPermsAWSCloudTrailsWithReadLoggingEnabled: - default: "Permissions for Policy Template: AWS CloudTrails With Read Logging Enabled" - ## AWS CloudTrails Without Encrypted Logs - paramPermsAWSCloudTrailsWithoutEncryptedLogs: - default: "Permissions for Policy Template: AWS CloudTrails Without Encrypted Logs" - ## AWS CloudTrails Without Log File Validation Enabled - paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled: - default: "Permissions for Policy Template: AWS CloudTrails Without Log File Validation Enabled" - ## AWS CloudTrails Without Object-level Events Logging Enabled - paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: - default: "Permissions for Policy Template: AWS CloudTrails Without Object-level Events Logging Enabled" - ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled - paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled: - default: "Permissions for Policy Template: AWS Customer Managed Keys (CMKs) Without Rotation Enabled" - ## AWS Disallowed Regions - paramPermsAWSDisallowedRegions: - default: "Permissions for Policy Template: AWS Disallowed Regions" - ## AWS EC2 Compute Optimizer Recommendations - paramPermsAWSEC2ComputeOptimizerRecommendations: - default: "Permissions for Policy Template: AWS EC2 Compute Optimizer Recommendations" - ## AWS EC2 Instances Time Stopped Report - paramPermsAWSEC2InstancesTimeStoppedReport: - default: "Permissions for Policy Template: AWS EC2 Instances Time Stopped Report" - ## AWS EC2 Instances not running FlexNet Inventory Agent - paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent: - default: "Permissions for Policy Template: AWS EC2 Instances not running FlexNet Inventory Agent" - ## AWS EKS Clusters Without Spot Instances - paramPermsAWSEKSClustersWithoutSpotInstances: - default: "Permissions for Policy Template: AWS EKS Clusters Without Spot Instances" - ## AWS Elastic Load Balancers With Unencrypted Listeners - paramPermsAWSElasticLoadBalancersWithUnencryptedListeners: - default: "Permissions for Policy Template: AWS Elastic Load Balancers With Unencrypted Listeners" - ## AWS Expiring Savings Plans - paramPermsAWSExpiringSavingsPlans: - default: "Permissions for Policy Template: AWS Expiring Savings Plans" - ## AWS IAM Account Missing Support Role - paramPermsAWSIAMAccountMissingSupportRole: - default: "Permissions for Policy Template: AWS IAM Account Missing Support Role" - ## AWS IAM Attached Admin Policies - paramPermsAWSIAMAttachedAdminPolicies: - default: "Permissions for Policy Template: AWS IAM Attached Admin Policies" - ## AWS IAM Expired SSL/TLS Certificates - paramPermsAWSIAMExpiredSSLTLSCertificates: - default: "Permissions for Policy Template: AWS IAM Expired SSL/TLS Certificates" - ## AWS IAM Insufficient Required Password Length - paramPermsAWSIAMInsufficientRequiredPasswordLength: - default: "Permissions for Policy Template: AWS IAM Insufficient Required Password Length" - ## AWS IAM Password Policy Not Restricting Password Reuse - paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse: - default: "Permissions for Policy Template: AWS IAM Password Policy Not Restricting Password Reuse" - ## AWS IAM Role Audit - paramPermsAWSIAMRoleAudit: - default: "Permissions for Policy Template: AWS IAM Role Audit" - ## AWS IAM Root Account Access Keys - paramPermsAWSIAMRootAccountAccessKeys: - default: "Permissions for Policy Template: AWS IAM Root Account Access Keys" - ## AWS IAM Root User Account Without Hardware MFA - paramPermsAWSIAMRootUserAccountWithoutHardwareMFA: - default: "Permissions for Policy Template: AWS IAM Root User Account Without Hardware MFA" - ## AWS IAM Root User Account Without MFA - paramPermsAWSIAMRootUserAccountWithoutMFA: - default: "Permissions for Policy Template: AWS IAM Root User Account Without MFA" - ## AWS IAM Root User Doing Everyday Tasks - paramPermsAWSIAMRootUserDoingEverydayTasks: - default: "Permissions for Policy Template: AWS IAM Root User Doing Everyday Tasks" - ## AWS IAM User Accounts Without MFA - paramPermsAWSIAMUserAccountsWithoutMFA: - default: "Permissions for Policy Template: AWS IAM User Accounts Without MFA" - ## AWS IAM Users With Directly-Attached Policies - paramPermsAWSIAMUsersWithDirectlyAttachedPolicies: - default: "Permissions for Policy Template: AWS IAM Users With Directly-Attached Policies" - ## AWS IAM Users With Multiple Active Access Keys - paramPermsAWSIAMUsersWithMultipleActiveAccessKeys: - default: "Permissions for Policy Template: AWS IAM Users With Multiple Active Access Keys" - ## AWS IAM Users With Old Access Keys - paramPermsAWSIAMUsersWithOldAccessKeys: - default: "Permissions for Policy Template: AWS IAM Users With Old Access Keys" - ## AWS Idle NAT Gateways - paramPermsAWSIdleNATGateways: - default: "Permissions for Policy Template: AWS Idle NAT Gateways" - ## AWS Internet-Accessible Elastic Load Balancers - paramPermsAWSInternetAccessibleElasticLoadBalancers: - default: "Permissions for Policy Template: AWS Internet-Accessible Elastic Load Balancers" - ## AWS Lambda Functions With High Error Rate - paramPermsAWSLambdaFunctionsWithHighErrorRate: - default: "Permissions for Policy Template: AWS Lambda Functions With High Error Rate" - ## AWS Lambda Functions Without Provisioned Concurrency - paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency: - default: "Permissions for Policy Template: AWS Lambda Functions Without Provisioned Concurrency" - ## AWS Long Running Instances - paramPermsAWSLongRunningInstances: - default: "Permissions for Policy Template: AWS Long Running Instances" - ## AWS Long Stopped EC2 Instances - paramPermsAWSLongStoppedEC2Instances: - default: "Permissions for Policy Template: AWS Long Stopped EC2 Instances" - ## AWS Missing Regions - paramPermsAWSMissingRegions: - default: "Permissions for Policy Template: AWS Missing Regions" - ## AWS Old Snapshots - paramPermsAWSOldSnapshots: - default: "Permissions for Policy Template: AWS Old Snapshots" - ## AWS Open S3 Buckets - paramPermsAWSOpenS3Buckets: - default: "Permissions for Policy Template: AWS Open S3 Buckets" - ## AWS Oversized S3 Buckets - paramPermsAWSOversizedS3Buckets: - default: "Permissions for Policy Template: AWS Oversized S3 Buckets" - ## AWS Publicly Accessible CloudTrail S3 Buckets - paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets: - default: "Permissions for Policy Template: AWS Publicly Accessible CloudTrail S3 Buckets" - ## AWS Publicly Accessible RDS Instances - paramPermsAWSPubliclyAccessibleRDSInstances: - default: "Permissions for Policy Template: AWS Publicly Accessible RDS Instances" - ## AWS RDS Instances With Unapproved Backup Settings - paramPermsAWSRDSInstancesWithUnapprovedBackupSettings: - default: "Permissions for Policy Template: AWS RDS Instances With Unapproved Backup Settings" - ## AWS Regions Without Access Analyzer Enabled - paramPermsAWSRegionsWithoutAccessAnalyzerEnabled: - default: "Permissions for Policy Template: AWS Regions Without Access Analyzer Enabled" - ## AWS Regions Without Config Fully Enabled - paramPermsAWSRegionsWithoutConfigFullyEnabled: - default: "Permissions for Policy Template: AWS Regions Without Config Fully Enabled" - ## AWS Regions Without Default EBS Encryption - paramPermsAWSRegionsWithoutDefaultEBSEncryption: - default: "Permissions for Policy Template: AWS Regions Without Default EBS Encryption" - ## AWS Reserved Instances Coverage - paramPermsAWSReservedInstancesCoverage: - default: "Permissions for Policy Template: AWS Reserved Instances Coverage" - ## AWS Reserved Instances Recommendations - paramPermsAWSReservedInstancesRecommendations: - default: "Permissions for Policy Template: AWS Reserved Instances Recommendations" - ## AWS Rightsize EBS Volumes - paramPermsAWSRightsizeEBSVolumes: - default: "Permissions for Policy Template: AWS Rightsize EBS Volumes" - ## AWS Rightsize EC2 Instances - paramPermsAWSRightsizeEC2Instances: - default: "Permissions for Policy Template: AWS Rightsize EC2 Instances" - ## AWS Rightsize ElastiCache - paramPermsAWSRightsizeElastiCache: - default: "Permissions for Policy Template: AWS Rightsize ElastiCache" - ## AWS Rightsize RDS Instances - paramPermsAWSRightsizeRDSInstances: - default: "Permissions for Policy Template: AWS Rightsize RDS Instances" - ## AWS Rightsize Redshift - paramPermsAWSRightsizeRedshift: - default: "Permissions for Policy Template: AWS Rightsize Redshift" - ## AWS S3 Buckets Accepting HTTP Requests - paramPermsAWSS3BucketsAcceptingHTTPRequests: - default: "Permissions for Policy Template: AWS S3 Buckets Accepting HTTP Requests" - ## AWS S3 Buckets Without Default Encryption Configuration - paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration: - default: "Permissions for Policy Template: AWS S3 Buckets Without Default Encryption Configuration" - ## AWS S3 Buckets Without Intelligent Tiering - paramPermsAWSS3BucketsWithoutIntelligentTiering: - default: "Permissions for Policy Template: AWS S3 Buckets Without Intelligent Tiering" - ## AWS S3 Buckets Without Lifecycle Configuration - paramPermsAWSS3BucketsWithoutLifecycleConfiguration: - default: "Permissions for Policy Template: AWS S3 Buckets Without Lifecycle Configuration" - ## AWS S3 Buckets Without MFA Delete Enabled - paramPermsAWSS3BucketsWithoutMFADeleteEnabled: - default: "Permissions for Policy Template: AWS S3 Buckets Without MFA Delete Enabled" - ## AWS S3 Buckets Without Public Access Blocked - paramPermsAWSS3BucketsWithoutPublicAccessBlocked: - default: "Permissions for Policy Template: AWS S3 Buckets Without Public Access Blocked" - ## AWS S3 Buckets Without Server Access Logging - paramPermsAWSS3BucketsWithoutServerAccessLogging: - default: "Permissions for Policy Template: AWS S3 Buckets Without Server Access Logging" - ## AWS S3 Incomplete Multi-Part Uploads - paramPermsAWSS3IncompleteMultiPartUploads: - default: "Permissions for Policy Template: AWS S3 Incomplete Multi-Part Uploads" - ## AWS Savings Plan Recommendations - paramPermsAWSSavingsPlanRecommendations: - default: "Permissions for Policy Template: AWS Savings Plan Recommendations" - ## AWS Savings Plan Utilization - paramPermsAWSSavingsPlanUtilization: - default: "Permissions for Policy Template: AWS Savings Plan Utilization" - ## AWS Schedule Instance - paramPermsAWSScheduleInstance: - default: "Permissions for Policy Template: AWS Schedule Instance" - ## AWS Scheduled EC2 Events - paramPermsAWSScheduledEC2Events: - default: "Permissions for Policy Template: AWS Scheduled EC2 Events" - ## AWS Superseded EBS Volumes - paramPermsAWSSupersededEBSVolumes: - default: "Permissions for Policy Template: AWS Superseded EBS Volumes" - ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - default: "Permissions for Policy Template: AWS Superseded EC2 Instances" - ## AWS Tag Cardinality Report - paramPermsAWSTagCardinalityReport: - default: "Permissions for Policy Template: AWS Tag Cardinality Report" - ## AWS Unencrypted EBS Volumes - paramPermsAWSUnencryptedEBSVolumes: - default: "Permissions for Policy Template: AWS Unencrypted EBS Volumes" - ## AWS Unencrypted RDS Instances - paramPermsAWSUnencryptedRDSInstances: - default: "Permissions for Policy Template: AWS Unencrypted RDS Instances" - ## AWS Untagged Resources - paramPermsAWSUntaggedResources: - default: "Permissions for Policy Template: AWS Untagged Resources" - ## AWS Unused Application Load Balancers - paramPermsAWSUnusedApplicationLoadBalancers: - default: "Permissions for Policy Template: AWS Unused Application Load Balancers" - ## AWS Unused Classic Load Balancers - paramPermsAWSUnusedClassicLoadBalancers: - default: "Permissions for Policy Template: AWS Unused Classic Load Balancers" - ## AWS Unused ECS Clusters - paramPermsAWSUnusedECSClusters: - default: "Permissions for Policy Template: AWS Unused ECS Clusters" - ## AWS Unused IAM Credentials - paramPermsAWSUnusedIAMCredentials: - default: "Permissions for Policy Template: AWS Unused IAM Credentials" - ## AWS Unused IP Addresses - paramPermsAWSUnusedIPAddresses: - default: "Permissions for Policy Template: AWS Unused IP Addresses" - ## AWS Unused Network Load Balancers - paramPermsAWSUnusedNetworkLoadBalancers: - default: "Permissions for Policy Template: AWS Unused Network Load Balancers" - ## AWS VPCs Without FlowLogs Enabled - paramPermsAWSVPCsWithoutFlowLogsEnabled: - default: "Permissions for Policy Template: AWS VPCs Without FlowLogs Enabled" - ## Common Bill Ingestion from AWS S3 Object Storage - paramPermsCommonBillIngestionfromAWSS3ObjectStorage: - default: "Permissions for Policy Template: Common Bill Ingestion from AWS S3 Object Storage" - - # End for each policy template - paramPermsAttachExistingPolicies: - default: "Additional IAM Permission Policies for IAM Role" - -Parameters: - # ParameterGroup: Parameters related to your Organization on the Flexera Platform - paramFlexeraOrgId: - Description: >- - The Organization ID in Flexera which trust will be granted to use the IAM Role that will be created - Type: String - AllowedPattern: "[0-9]+" - MinLength: 1 - ConstraintDescription: Organization ID must be provided and match regex [0-9]+ - paramFlexeraZone: - Description: >- - The Flexera Zone which trust will be granted to. The Organization ID should be located in this Flexera Zone. - Type: String - Default: app.flexera.com - AllowedValues: - - app.flexera.com - - app.flexera.eu - - app.flexera.au - - app.flexeratest.com - - # ParameterGroup: Parameters for the IAM Role that is created - paramRoleName: - Description: Name of the the IAM Role that will be created. If you plan to create more than one IAM Role (i.e. one for each Policy Template, or to trust multiple Orgs) you will need to modify this to prevent naming conflict. - Type: String - Default: FlexeraAutomationAccessRole - # IAM Role Name Max Length is 64chars - MaxLength: 64 - paramRolePath: - Description: Path for the IAM Role that will be created. Generally does not need to be modified. - Type: String - Default: / - - # ParameterGroup: Parameters to define Policy Template permissions on the IAM Role that is created - ## All AWS Policy Templates - paramPermsAllAWSPolicyTemplates: - Description: 'What permissions for all AWS Policy Templates should be granted on the AWS Role that will be created? Note that the more granular permissions below only need to be enabled if this option is disabled or you want to grant access to take actions only for specific policy templates.' - Type: String - Default: Read Only - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Account Credentials - paramPermsAWSAccountCredentials: - Description: 'What permissions for the "AWS Account Credentials" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Accounts Missing Service Control Policies - paramPermsAWSAccountsMissingServiceControlPolicies: - Description: 'What permissions for the "AWS Accounts Missing Service Control Policies" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Burstable EC2 Instances - paramPermsAWSBurstableEC2Instances: - Description: 'What permissions for the "AWS Burstable EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS CloudTrail Not Enabled In All Regions - paramPermsAWSCloudTrailNotEnabledInAllRegions: - Description: 'What permissions for the "AWS CloudTrail Not Enabled In All Regions" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS CloudTrail S3 Buckets Without Access Logging - paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging: - Description: 'What permissions for the "AWS CloudTrail S3 Buckets Without Access Logging" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS CloudTrails Not Integrated With CloudWatch - paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch: - Description: 'What permissions for the "AWS CloudTrails Not Integrated With CloudWatch" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS CloudTrails With Read Logging Enabled - paramPermsAWSCloudTrailsWithReadLoggingEnabled: - Description: 'What permissions for the "AWS CloudTrails With Read Logging Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS CloudTrails Without Encrypted Logs - paramPermsAWSCloudTrailsWithoutEncryptedLogs: - Description: 'What permissions for the "AWS CloudTrails Without Encrypted Logs" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS CloudTrails Without Log File Validation Enabled - paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled: - Description: 'What permissions for the "AWS CloudTrails Without Log File Validation Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS CloudTrails Without Object-level Events Logging Enabled - paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: - Description: 'What permissions for the "AWS CloudTrails Without Object-level Events Logging Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled - paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled: - Description: 'What permissions for the "AWS Customer Managed Keys (CMKs) Without Rotation Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Disallowed Regions - paramPermsAWSDisallowedRegions: - Description: 'What permissions for the "AWS Disallowed Regions" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS EC2 Compute Optimizer Recommendations - paramPermsAWSEC2ComputeOptimizerRecommendations: - Description: 'What permissions for the "AWS EC2 Compute Optimizer Recommendations" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS EC2 Instances Time Stopped Report - paramPermsAWSEC2InstancesTimeStoppedReport: - Description: 'What permissions for the "AWS EC2 Instances Time Stopped Report" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS EC2 Instances not running FlexNet Inventory Agent - paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent: - Description: 'What permissions for the "AWS EC2 Instances not running FlexNet Inventory Agent" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS EKS Clusters Without Spot Instances - paramPermsAWSEKSClustersWithoutSpotInstances: - Description: 'What permissions for the "AWS EKS Clusters Without Spot Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Elastic Load Balancers With Unencrypted Listeners - paramPermsAWSElasticLoadBalancersWithUnencryptedListeners: - Description: 'What permissions for the "AWS Elastic Load Balancers With Unencrypted Listeners" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Expiring Savings Plans - paramPermsAWSExpiringSavingsPlans: - Description: 'What permissions for the "AWS Expiring Savings Plans" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Account Missing Support Role - paramPermsAWSIAMAccountMissingSupportRole: - Description: 'What permissions for the "AWS IAM Account Missing Support Role" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Attached Admin Policies - paramPermsAWSIAMAttachedAdminPolicies: - Description: 'What permissions for the "AWS IAM Attached Admin Policies" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Expired SSL/TLS Certificates - paramPermsAWSIAMExpiredSSLTLSCertificates: - Description: 'What permissions for the "AWS IAM Expired SSL/TLS Certificates" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Insufficient Required Password Length - paramPermsAWSIAMInsufficientRequiredPasswordLength: - Description: 'What permissions for the "AWS IAM Insufficient Required Password Length" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Password Policy Not Restricting Password Reuse - paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse: - Description: 'What permissions for the "AWS IAM Password Policy Not Restricting Password Reuse" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Role Audit - paramPermsAWSIAMRoleAudit: - Description: 'What permissions for the "AWS IAM Role Audit" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Root Account Access Keys - paramPermsAWSIAMRootAccountAccessKeys: - Description: 'What permissions for the "AWS IAM Root Account Access Keys" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Root User Account Without Hardware MFA - paramPermsAWSIAMRootUserAccountWithoutHardwareMFA: - Description: 'What permissions for the "AWS IAM Root User Account Without Hardware MFA" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Root User Account Without MFA - paramPermsAWSIAMRootUserAccountWithoutMFA: - Description: 'What permissions for the "AWS IAM Root User Account Without MFA" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Root User Doing Everyday Tasks - paramPermsAWSIAMRootUserDoingEverydayTasks: - Description: 'What permissions for the "AWS IAM Root User Doing Everyday Tasks" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM User Accounts Without MFA - paramPermsAWSIAMUserAccountsWithoutMFA: - Description: 'What permissions for the "AWS IAM User Accounts Without MFA" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Users With Directly-Attached Policies - paramPermsAWSIAMUsersWithDirectlyAttachedPolicies: - Description: 'What permissions for the "AWS IAM Users With Directly-Attached Policies" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Users With Multiple Active Access Keys - paramPermsAWSIAMUsersWithMultipleActiveAccessKeys: - Description: 'What permissions for the "AWS IAM Users With Multiple Active Access Keys" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS IAM Users With Old Access Keys - paramPermsAWSIAMUsersWithOldAccessKeys: - Description: 'What permissions for the "AWS IAM Users With Old Access Keys" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Idle NAT Gateways - paramPermsAWSIdleNATGateways: - Description: 'What permissions for the "AWS Idle NAT Gateways" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Internet-Accessible Elastic Load Balancers - paramPermsAWSInternetAccessibleElasticLoadBalancers: - Description: 'What permissions for the "AWS Internet-Accessible Elastic Load Balancers" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Lambda Functions With High Error Rate - paramPermsAWSLambdaFunctionsWithHighErrorRate: - Description: 'What permissions for the "AWS Lambda Functions With High Error Rate" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Lambda Functions Without Provisioned Concurrency - paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency: - Description: 'What permissions for the "AWS Lambda Functions Without Provisioned Concurrency" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Long Running Instances - paramPermsAWSLongRunningInstances: - Description: 'What permissions for the "AWS Long Running Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Long Stopped EC2 Instances - paramPermsAWSLongStoppedEC2Instances: - Description: 'What permissions for the "AWS Long Stopped EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Missing Regions - paramPermsAWSMissingRegions: - Description: 'What permissions for the "AWS Missing Regions" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Old Snapshots - paramPermsAWSOldSnapshots: - Description: 'What permissions for the "AWS Old Snapshots" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Open S3 Buckets - paramPermsAWSOpenS3Buckets: - Description: 'What permissions for the "AWS Open S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Oversized S3 Buckets - paramPermsAWSOversizedS3Buckets: - Description: 'What permissions for the "AWS Oversized S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Publicly Accessible CloudTrail S3 Buckets - paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets: - Description: 'What permissions for the "AWS Publicly Accessible CloudTrail S3 Buckets" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Publicly Accessible RDS Instances - paramPermsAWSPubliclyAccessibleRDSInstances: - Description: 'What permissions for the "AWS Publicly Accessible RDS Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS RDS Instances With Unapproved Backup Settings - paramPermsAWSRDSInstancesWithUnapprovedBackupSettings: - Description: 'What permissions for the "AWS RDS Instances With Unapproved Backup Settings" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Regions Without Access Analyzer Enabled - paramPermsAWSRegionsWithoutAccessAnalyzerEnabled: - Description: 'What permissions for the "AWS Regions Without Access Analyzer Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Regions Without Config Fully Enabled - paramPermsAWSRegionsWithoutConfigFullyEnabled: - Description: 'What permissions for the "AWS Regions Without Config Fully Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Regions Without Default EBS Encryption - paramPermsAWSRegionsWithoutDefaultEBSEncryption: - Description: 'What permissions for the "AWS Regions Without Default EBS Encryption" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Reserved Instances Coverage - paramPermsAWSReservedInstancesCoverage: - Description: 'What permissions for the "AWS Reserved Instances Coverage" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Reserved Instances Recommendations - paramPermsAWSReservedInstancesRecommendations: - Description: 'What permissions for the "AWS Reserved Instances Recommendations" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Rightsize EBS Volumes - paramPermsAWSRightsizeEBSVolumes: - Description: 'What permissions for the "AWS Rightsize EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Rightsize EC2 Instances - paramPermsAWSRightsizeEC2Instances: - Description: 'What permissions for the "AWS Rightsize EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Rightsize ElastiCache - paramPermsAWSRightsizeElastiCache: - Description: 'What permissions for the "AWS Rightsize ElastiCache" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Rightsize RDS Instances - paramPermsAWSRightsizeRDSInstances: - Description: 'What permissions for the "AWS Rightsize RDS Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Rightsize Redshift - paramPermsAWSRightsizeRedshift: - Description: 'What permissions for the "AWS Rightsize Redshift" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS S3 Buckets Accepting HTTP Requests - paramPermsAWSS3BucketsAcceptingHTTPRequests: - Description: 'What permissions for the "AWS S3 Buckets Accepting HTTP Requests" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS S3 Buckets Without Default Encryption Configuration - paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration: - Description: 'What permissions for the "AWS S3 Buckets Without Default Encryption Configuration" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS S3 Buckets Without Intelligent Tiering - paramPermsAWSS3BucketsWithoutIntelligentTiering: - Description: 'What permissions for the "AWS S3 Buckets Without Intelligent Tiering" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS S3 Buckets Without Lifecycle Configuration - paramPermsAWSS3BucketsWithoutLifecycleConfiguration: - Description: 'What permissions for the "AWS S3 Buckets Without Lifecycle Configuration" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS S3 Buckets Without MFA Delete Enabled - paramPermsAWSS3BucketsWithoutMFADeleteEnabled: - Description: 'What permissions for the "AWS S3 Buckets Without MFA Delete Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS S3 Buckets Without Public Access Blocked - paramPermsAWSS3BucketsWithoutPublicAccessBlocked: - Description: 'What permissions for the "AWS S3 Buckets Without Public Access Blocked" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS S3 Buckets Without Server Access Logging - paramPermsAWSS3BucketsWithoutServerAccessLogging: - Description: 'What permissions for the "AWS S3 Buckets Without Server Access Logging" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS S3 Incomplete Multi-Part Uploads - paramPermsAWSS3IncompleteMultiPartUploads: - Description: 'What permissions for the "AWS S3 Incomplete Multi-Part Uploads" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Savings Plan Recommendations - paramPermsAWSSavingsPlanRecommendations: - Description: 'What permissions for the "AWS Savings Plan Recommendations" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Savings Plan Utilization - paramPermsAWSSavingsPlanUtilization: - Description: 'What permissions for the "AWS Savings Plan Utilization" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Schedule Instance - paramPermsAWSScheduleInstance: - Description: 'What permissions for the "AWS Schedule Instance" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Scheduled EC2 Events - paramPermsAWSScheduledEC2Events: - Description: 'What permissions for the "AWS Scheduled EC2 Events" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Superseded EBS Volumes - paramPermsAWSSupersededEBSVolumes: - Description: 'What permissions for the "AWS Superseded EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Superseded EC2 Instances - paramPermsAWSSupersededEC2Instances: - Description: 'What permissions for the "AWS Superseded EC2 Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Tag Cardinality Report - paramPermsAWSTagCardinalityReport: - Description: 'What permissions for the "AWS Tag Cardinality Report" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Unencrypted EBS Volumes - paramPermsAWSUnencryptedEBSVolumes: - Description: 'What permissions for the "AWS Unencrypted EBS Volumes" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Unencrypted RDS Instances - paramPermsAWSUnencryptedRDSInstances: - Description: 'What permissions for the "AWS Unencrypted RDS Instances" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Untagged Resources - paramPermsAWSUntaggedResources: - Description: 'What permissions for the "AWS Untagged Resources" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Unused Application Load Balancers - paramPermsAWSUnusedApplicationLoadBalancers: - Description: 'What permissions for the "AWS Unused Application Load Balancers" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Unused Classic Load Balancers - paramPermsAWSUnusedClassicLoadBalancers: - Description: 'What permissions for the "AWS Unused Classic Load Balancers" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Unused ECS Clusters - paramPermsAWSUnusedECSClusters: - Description: 'What permissions for the "AWS Unused ECS Clusters" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Unused IAM Credentials - paramPermsAWSUnusedIAMCredentials: - Description: 'What permissions for the "AWS Unused IAM Credentials" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## AWS Unused IP Addresses - paramPermsAWSUnusedIPAddresses: - Description: 'What permissions for the "AWS Unused IP Addresses" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS Unused Network Load Balancers - paramPermsAWSUnusedNetworkLoadBalancers: - Description: 'What permissions for the "AWS Unused Network Load Balancers" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - Read and Take Action - ## AWS VPCs Without FlowLogs Enabled - paramPermsAWSVPCsWithoutFlowLogsEnabled: - Description: 'What permissions for the "AWS VPCs Without FlowLogs Enabled" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - ## Common Bill Ingestion from AWS S3 Object Storage - paramPermsCommonBillIngestionfromAWSS3ObjectStorage: - Description: 'What permissions for the "Common Bill Ingestion from AWS S3 Object Storage" Policy Template should be granted on the AWS Role that will be created?' - Type: String - Default: None - AllowedValues: - - None - - Read Only - - # End for each policy template - paramPermsAttachExistingPolicies: - Description: 'Existing IAM Permission Policies to attach to the IAM Role that will be created. Optional, comma separated list of IAM Policy ARNs -- i.e. arn:aws:iam::aws:policy/ReadOnlyAccess' - Type: String - # AWS Managed Policy ARN: arn:aws:iam::aws:policy/ReadOnlyAccess - # Customer Managed Policy ARN: arn:aws:iam::123456789012:policy/CustomPolicy - AllowedPattern: '^((arn:aws:iam::(\d{12}|aws)?:policy\/[\w+=,.@-]{1,128})(,)?)*$' - ConstraintDescription: 'Malformed IAM Policy ARN. Must match pattern ^((arn:aws:iam::(\d{12}|aws)?:policy\/[\w+=,.@-]{1,128})(,)?)*$' - -Conditions: - ## All AWS Policy Templates - CreatePolicyAllAWSPolicyTemplatesRead: !Not - - !Equals - - !Ref paramPermsAllAWSPolicyTemplates - - None - CreatePolicyAllAWSPolicyTemplatesAction: !Equals - - !Ref paramPermsAllAWSPolicyTemplates - - Read and Take Action - ## AWS Account Credentials - CreatePolicyAWSAccountCredentialsRead: !Not - - !Equals - - !Ref paramPermsAWSAccountCredentials - - None - ## AWS Accounts Missing Service Control Policies - CreatePolicyAWSAccountsMissingServiceControlPoliciesRead: !Not - - !Equals - - !Ref paramPermsAWSAccountsMissingServiceControlPolicies - - None - ## AWS Burstable EC2 Instances - CreatePolicyAWSBurstableEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSBurstableEC2Instances - - None - CreatePolicyAWSBurstableEC2InstancesAction: !Equals - - !Ref paramPermsAWSBurstableEC2Instances - - Read and Take Action - ## AWS CloudTrail Not Enabled In All Regions - CreatePolicyAWSCloudTrailNotEnabledInAllRegionsRead: !Not - - !Equals - - !Ref paramPermsAWSCloudTrailNotEnabledInAllRegions - - None - ## AWS CloudTrail S3 Buckets Without Access Logging - CreatePolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead: !Not - - !Equals - - !Ref paramPermsAWSCloudTrailS3BucketsWithoutAccessLogging - - None - ## AWS CloudTrails Not Integrated With CloudWatch - CreatePolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead: !Not - - !Equals - - !Ref paramPermsAWSCloudTrailsNotIntegratedWithCloudWatch - - None - ## AWS CloudTrails With Read Logging Enabled - CreatePolicyAWSCloudTrailsWithReadLoggingEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSCloudTrailsWithReadLoggingEnabled - - None - CreatePolicyAWSCloudTrailsWithReadLoggingEnabledAction: !Equals - - !Ref paramPermsAWSCloudTrailsWithReadLoggingEnabled - - Read and Take Action - ## AWS CloudTrails Without Encrypted Logs - CreatePolicyAWSCloudTrailsWithoutEncryptedLogsRead: !Not - - !Equals - - !Ref paramPermsAWSCloudTrailsWithoutEncryptedLogs - - None - ## AWS CloudTrails Without Log File Validation Enabled - CreatePolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSCloudTrailsWithoutLogFileValidationEnabled - - None - ## AWS CloudTrails Without Object-level Events Logging Enabled - CreatePolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled - - None - ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled - CreatePolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSCustomerManagedKeysCMKsWithoutRotationEnabled - - None - ## AWS Disallowed Regions - CreatePolicyAWSDisallowedRegionsRead: !Not - - !Equals - - !Ref paramPermsAWSDisallowedRegions - - None - CreatePolicyAWSDisallowedRegionsAction: !Equals - - !Ref paramPermsAWSDisallowedRegions - - Read and Take Action - ## AWS EC2 Compute Optimizer Recommendations - CreatePolicyAWSEC2ComputeOptimizerRecommendationsRead: !Not - - !Equals - - !Ref paramPermsAWSEC2ComputeOptimizerRecommendations - - None - CreatePolicyAWSEC2ComputeOptimizerRecommendationsAction: !Equals - - !Ref paramPermsAWSEC2ComputeOptimizerRecommendations - - Read and Take Action - ## AWS EC2 Instances Time Stopped Report - CreatePolicyAWSEC2InstancesTimeStoppedReportRead: !Not - - !Equals - - !Ref paramPermsAWSEC2InstancesTimeStoppedReport - - None - CreatePolicyAWSEC2InstancesTimeStoppedReportAction: !Equals - - !Ref paramPermsAWSEC2InstancesTimeStoppedReport - - Read and Take Action - ## AWS EC2 Instances not running FlexNet Inventory Agent - CreatePolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead: !Not - - !Equals - - !Ref paramPermsAWSEC2InstancesnotrunningFlexNetInventoryAgent - - None - ## AWS EKS Clusters Without Spot Instances - CreatePolicyAWSEKSClustersWithoutSpotInstancesRead: !Not - - !Equals - - !Ref paramPermsAWSEKSClustersWithoutSpotInstances - - None - ## AWS Elastic Load Balancers With Unencrypted Listeners - CreatePolicyAWSElasticLoadBalancersWithUnencryptedListenersRead: !Not - - !Equals - - !Ref paramPermsAWSElasticLoadBalancersWithUnencryptedListeners - - None - ## AWS Expiring Savings Plans - CreatePolicyAWSExpiringSavingsPlansRead: !Not - - !Equals - - !Ref paramPermsAWSExpiringSavingsPlans - - None - ## AWS IAM Account Missing Support Role - CreatePolicyAWSIAMAccountMissingSupportRoleRead: !Not - - !Equals - - !Ref paramPermsAWSIAMAccountMissingSupportRole - - None - ## AWS IAM Attached Admin Policies - CreatePolicyAWSIAMAttachedAdminPoliciesRead: !Not - - !Equals - - !Ref paramPermsAWSIAMAttachedAdminPolicies - - None - ## AWS IAM Expired SSL/TLS Certificates - CreatePolicyAWSIAMExpiredSSLTLSCertificatesRead: !Not - - !Equals - - !Ref paramPermsAWSIAMExpiredSSLTLSCertificates - - None - ## AWS IAM Insufficient Required Password Length - CreatePolicyAWSIAMInsufficientRequiredPasswordLengthRead: !Not - - !Equals - - !Ref paramPermsAWSIAMInsufficientRequiredPasswordLength - - None - ## AWS IAM Password Policy Not Restricting Password Reuse - CreatePolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead: !Not - - !Equals - - !Ref paramPermsAWSIAMPasswordPolicyNotRestrictingPasswordReuse - - None - ## AWS IAM Role Audit - CreatePolicyAWSIAMRoleAuditRead: !Not - - !Equals - - !Ref paramPermsAWSIAMRoleAudit - - None - ## AWS IAM Root Account Access Keys - CreatePolicyAWSIAMRootAccountAccessKeysRead: !Not - - !Equals - - !Ref paramPermsAWSIAMRootAccountAccessKeys - - None - ## AWS IAM Root User Account Without Hardware MFA - CreatePolicyAWSIAMRootUserAccountWithoutHardwareMFARead: !Not - - !Equals - - !Ref paramPermsAWSIAMRootUserAccountWithoutHardwareMFA - - None - ## AWS IAM Root User Account Without MFA - CreatePolicyAWSIAMRootUserAccountWithoutMFARead: !Not - - !Equals - - !Ref paramPermsAWSIAMRootUserAccountWithoutMFA - - None - ## AWS IAM Root User Doing Everyday Tasks - CreatePolicyAWSIAMRootUserDoingEverydayTasksRead: !Not - - !Equals - - !Ref paramPermsAWSIAMRootUserDoingEverydayTasks - - None - ## AWS IAM User Accounts Without MFA - CreatePolicyAWSIAMUserAccountsWithoutMFARead: !Not - - !Equals - - !Ref paramPermsAWSIAMUserAccountsWithoutMFA - - None - ## AWS IAM Users With Directly-Attached Policies - CreatePolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead: !Not - - !Equals - - !Ref paramPermsAWSIAMUsersWithDirectlyAttachedPolicies - - None - ## AWS IAM Users With Multiple Active Access Keys - CreatePolicyAWSIAMUsersWithMultipleActiveAccessKeysRead: !Not - - !Equals - - !Ref paramPermsAWSIAMUsersWithMultipleActiveAccessKeys - - None - ## AWS IAM Users With Old Access Keys - CreatePolicyAWSIAMUsersWithOldAccessKeysRead: !Not - - !Equals - - !Ref paramPermsAWSIAMUsersWithOldAccessKeys - - None - ## AWS Idle NAT Gateways - CreatePolicyAWSIdleNATGatewaysRead: !Not - - !Equals - - !Ref paramPermsAWSIdleNATGateways - - None - CreatePolicyAWSIdleNATGatewaysAction: !Equals - - !Ref paramPermsAWSIdleNATGateways - - Read and Take Action - ## AWS Internet-Accessible Elastic Load Balancers - CreatePolicyAWSInternetAccessibleElasticLoadBalancersRead: !Not - - !Equals - - !Ref paramPermsAWSInternetAccessibleElasticLoadBalancers - - None - CreatePolicyAWSInternetAccessibleElasticLoadBalancersAction: !Equals - - !Ref paramPermsAWSInternetAccessibleElasticLoadBalancers - - Read and Take Action - ## AWS Lambda Functions With High Error Rate - CreatePolicyAWSLambdaFunctionsWithHighErrorRateRead: !Not - - !Equals - - !Ref paramPermsAWSLambdaFunctionsWithHighErrorRate - - None - ## AWS Lambda Functions Without Provisioned Concurrency - CreatePolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead: !Not - - !Equals - - !Ref paramPermsAWSLambdaFunctionsWithoutProvisionedConcurrency - - None - ## AWS Long Running Instances - CreatePolicyAWSLongRunningInstancesRead: !Not - - !Equals - - !Ref paramPermsAWSLongRunningInstances - - None - CreatePolicyAWSLongRunningInstancesAction: !Equals - - !Ref paramPermsAWSLongRunningInstances - - Read and Take Action - ## AWS Long Stopped EC2 Instances - CreatePolicyAWSLongStoppedEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSLongStoppedEC2Instances - - None - CreatePolicyAWSLongStoppedEC2InstancesAction: !Equals - - !Ref paramPermsAWSLongStoppedEC2Instances - - Read and Take Action - ## AWS Missing Regions - CreatePolicyAWSMissingRegionsRead: !Not - - !Equals - - !Ref paramPermsAWSMissingRegions - - None - ## AWS Old Snapshots - CreatePolicyAWSOldSnapshotsRead: !Not - - !Equals - - !Ref paramPermsAWSOldSnapshots - - None - CreatePolicyAWSOldSnapshotsAction: !Equals - - !Ref paramPermsAWSOldSnapshots - - Read and Take Action - ## AWS Open S3 Buckets - CreatePolicyAWSOpenS3BucketsRead: !Not - - !Equals - - !Ref paramPermsAWSOpenS3Buckets - - None - ## AWS Oversized S3 Buckets - CreatePolicyAWSOversizedS3BucketsRead: !Not - - !Equals - - !Ref paramPermsAWSOversizedS3Buckets - - None - ## AWS Publicly Accessible CloudTrail S3 Buckets - CreatePolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead: !Not - - !Equals - - !Ref paramPermsAWSPubliclyAccessibleCloudTrailS3Buckets - - None - ## AWS Publicly Accessible RDS Instances - CreatePolicyAWSPubliclyAccessibleRDSInstancesRead: !Not - - !Equals - - !Ref paramPermsAWSPubliclyAccessibleRDSInstances - - None - CreatePolicyAWSPubliclyAccessibleRDSInstancesAction: !Equals - - !Ref paramPermsAWSPubliclyAccessibleRDSInstances - - Read and Take Action - ## AWS RDS Instances With Unapproved Backup Settings - CreatePolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead: !Not - - !Equals - - !Ref paramPermsAWSRDSInstancesWithUnapprovedBackupSettings - - None - ## AWS Regions Without Access Analyzer Enabled - CreatePolicyAWSRegionsWithoutAccessAnalyzerEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSRegionsWithoutAccessAnalyzerEnabled - - None - ## AWS Regions Without Config Fully Enabled - CreatePolicyAWSRegionsWithoutConfigFullyEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSRegionsWithoutConfigFullyEnabled - - None - ## AWS Regions Without Default EBS Encryption - CreatePolicyAWSRegionsWithoutDefaultEBSEncryptionRead: !Not - - !Equals - - !Ref paramPermsAWSRegionsWithoutDefaultEBSEncryption - - None - ## AWS Reserved Instances Coverage - CreatePolicyAWSReservedInstancesCoverageRead: !Not - - !Equals - - !Ref paramPermsAWSReservedInstancesCoverage - - None - ## AWS Reserved Instances Recommendations - CreatePolicyAWSReservedInstancesRecommendationsRead: !Not - - !Equals - - !Ref paramPermsAWSReservedInstancesRecommendations - - None - ## AWS Rightsize EBS Volumes - CreatePolicyAWSRightsizeEBSVolumesRead: !Not - - !Equals - - !Ref paramPermsAWSRightsizeEBSVolumes - - None - CreatePolicyAWSRightsizeEBSVolumesAction: !Equals - - !Ref paramPermsAWSRightsizeEBSVolumes - - Read and Take Action - ## AWS Rightsize EC2 Instances - CreatePolicyAWSRightsizeEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSRightsizeEC2Instances - - None - CreatePolicyAWSRightsizeEC2InstancesAction: !Equals - - !Ref paramPermsAWSRightsizeEC2Instances - - Read and Take Action - ## AWS Rightsize ElastiCache - CreatePolicyAWSRightsizeElastiCacheRead: !Not - - !Equals - - !Ref paramPermsAWSRightsizeElastiCache - - None - CreatePolicyAWSRightsizeElastiCacheAction: !Equals - - !Ref paramPermsAWSRightsizeElastiCache - - Read and Take Action - ## AWS Rightsize RDS Instances - CreatePolicyAWSRightsizeRDSInstancesRead: !Not - - !Equals - - !Ref paramPermsAWSRightsizeRDSInstances - - None - CreatePolicyAWSRightsizeRDSInstancesAction: !Equals - - !Ref paramPermsAWSRightsizeRDSInstances - - Read and Take Action - ## AWS Rightsize Redshift - CreatePolicyAWSRightsizeRedshiftRead: !Not - - !Equals - - !Ref paramPermsAWSRightsizeRedshift - - None - CreatePolicyAWSRightsizeRedshiftAction: !Equals - - !Ref paramPermsAWSRightsizeRedshift - - Read and Take Action - ## AWS S3 Buckets Accepting HTTP Requests - CreatePolicyAWSS3BucketsAcceptingHTTPRequestsRead: !Not - - !Equals - - !Ref paramPermsAWSS3BucketsAcceptingHTTPRequests - - None - ## AWS S3 Buckets Without Default Encryption Configuration - CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead: !Not - - !Equals - - !Ref paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration - - None - CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction: !Equals - - !Ref paramPermsAWSS3BucketsWithoutDefaultEncryptionConfiguration - - Read and Take Action - ## AWS S3 Buckets Without Intelligent Tiering - CreatePolicyAWSS3BucketsWithoutIntelligentTieringRead: !Not - - !Equals - - !Ref paramPermsAWSS3BucketsWithoutIntelligentTiering - - None - ## AWS S3 Buckets Without Lifecycle Configuration - CreatePolicyAWSS3BucketsWithoutLifecycleConfigurationRead: !Not - - !Equals - - !Ref paramPermsAWSS3BucketsWithoutLifecycleConfiguration - - None - ## AWS S3 Buckets Without MFA Delete Enabled - CreatePolicyAWSS3BucketsWithoutMFADeleteEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSS3BucketsWithoutMFADeleteEnabled - - None - ## AWS S3 Buckets Without Public Access Blocked - CreatePolicyAWSS3BucketsWithoutPublicAccessBlockedRead: !Not - - !Equals - - !Ref paramPermsAWSS3BucketsWithoutPublicAccessBlocked - - None - ## AWS S3 Buckets Without Server Access Logging - CreatePolicyAWSS3BucketsWithoutServerAccessLoggingRead: !Not - - !Equals - - !Ref paramPermsAWSS3BucketsWithoutServerAccessLogging - - None - CreatePolicyAWSS3BucketsWithoutServerAccessLoggingAction: !Equals - - !Ref paramPermsAWSS3BucketsWithoutServerAccessLogging - - Read and Take Action - ## AWS S3 Incomplete Multi-Part Uploads - CreatePolicyAWSS3IncompleteMultiPartUploadsRead: !Not - - !Equals - - !Ref paramPermsAWSS3IncompleteMultiPartUploads - - None - CreatePolicyAWSS3IncompleteMultiPartUploadsAction: !Equals - - !Ref paramPermsAWSS3IncompleteMultiPartUploads - - Read and Take Action - ## AWS Savings Plan Recommendations - CreatePolicyAWSSavingsPlanRecommendationsRead: !Not - - !Equals - - !Ref paramPermsAWSSavingsPlanRecommendations - - None - ## AWS Savings Plan Utilization - CreatePolicyAWSSavingsPlanUtilizationRead: !Not - - !Equals - - !Ref paramPermsAWSSavingsPlanUtilization - - None - ## AWS Schedule Instance - CreatePolicyAWSScheduleInstanceRead: !Not - - !Equals - - !Ref paramPermsAWSScheduleInstance - - None - ## AWS Scheduled EC2 Events - CreatePolicyAWSScheduledEC2EventsRead: !Not - - !Equals - - !Ref paramPermsAWSScheduledEC2Events - - None - ## AWS Superseded EBS Volumes - CreatePolicyAWSSupersededEBSVolumesRead: !Not - - !Equals - - !Ref paramPermsAWSSupersededEBSVolumes - - None - CreatePolicyAWSSupersededEBSVolumesAction: !Equals - - !Ref paramPermsAWSSupersededEBSVolumes - - Read and Take Action - ## AWS Superseded EC2 Instances - CreatePolicyAWSSupersededEC2InstancesRead: !Not - - !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - None - CreatePolicyAWSSupersededEC2InstancesAction: !Equals - - !Ref paramPermsAWSSupersededEC2Instances - - Read and Take Action - ## AWS Tag Cardinality Report - CreatePolicyAWSTagCardinalityReportRead: !Not - - !Equals - - !Ref paramPermsAWSTagCardinalityReport - - None - ## AWS Unencrypted EBS Volumes - CreatePolicyAWSUnencryptedEBSVolumesRead: !Not - - !Equals - - !Ref paramPermsAWSUnencryptedEBSVolumes - - None - ## AWS Unencrypted RDS Instances - CreatePolicyAWSUnencryptedRDSInstancesRead: !Not - - !Equals - - !Ref paramPermsAWSUnencryptedRDSInstances - - None - CreatePolicyAWSUnencryptedRDSInstancesAction: !Equals - - !Ref paramPermsAWSUnencryptedRDSInstances - - Read and Take Action - ## AWS Untagged Resources - CreatePolicyAWSUntaggedResourcesRead: !Not - - !Equals - - !Ref paramPermsAWSUntaggedResources - - None - CreatePolicyAWSUntaggedResourcesAction: !Equals - - !Ref paramPermsAWSUntaggedResources - - Read and Take Action - ## AWS Unused Application Load Balancers - CreatePolicyAWSUnusedApplicationLoadBalancersRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedApplicationLoadBalancers - - None - CreatePolicyAWSUnusedApplicationLoadBalancersAction: !Equals - - !Ref paramPermsAWSUnusedApplicationLoadBalancers - - Read and Take Action - ## AWS Unused Classic Load Balancers - CreatePolicyAWSUnusedClassicLoadBalancersRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedClassicLoadBalancers - - None - CreatePolicyAWSUnusedClassicLoadBalancersAction: !Equals - - !Ref paramPermsAWSUnusedClassicLoadBalancers - - Read and Take Action - ## AWS Unused ECS Clusters - CreatePolicyAWSUnusedECSClustersRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedECSClusters - - None - CreatePolicyAWSUnusedECSClustersAction: !Equals - - !Ref paramPermsAWSUnusedECSClusters - - Read and Take Action - ## AWS Unused IAM Credentials - CreatePolicyAWSUnusedIAMCredentialsRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedIAMCredentials - - None - ## AWS Unused IP Addresses - CreatePolicyAWSUnusedIPAddressesRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedIPAddresses - - None - CreatePolicyAWSUnusedIPAddressesAction: !Equals - - !Ref paramPermsAWSUnusedIPAddresses - - Read and Take Action - ## AWS Unused Network Load Balancers - CreatePolicyAWSUnusedNetworkLoadBalancersRead: !Not - - !Equals - - !Ref paramPermsAWSUnusedNetworkLoadBalancers - - None - CreatePolicyAWSUnusedNetworkLoadBalancersAction: !Equals - - !Ref paramPermsAWSUnusedNetworkLoadBalancers - - Read and Take Action - ## AWS VPCs Without FlowLogs Enabled - CreatePolicyAWSVPCsWithoutFlowLogsEnabledRead: !Not - - !Equals - - !Ref paramPermsAWSVPCsWithoutFlowLogsEnabled - - None - ## Common Bill Ingestion from AWS S3 Object Storage - CreatePolicyCommonBillIngestionfromAWSS3ObjectStorageRead: !Not - - !Equals - - !Ref paramPermsCommonBillIngestionfromAWSS3ObjectStorage - - None - - # End for each policy template - ValueProvidedparamPermsAttachExistingPolicies: !Not - - !Equals - - !Ref paramPermsAttachExistingPolicies - - "" - -Mappings: - TrustedRoleMap: - app.flexera.com: - roleArn: "arn:aws:iam::451234325714:role/production_customer_access" - app.flexera.eu: - roleArn: "arn:aws:iam::451234325714:role/production_eu_customer_access" - app.flexera.au: - roleArn: "arn:aws:iam::451234325714:role/production_apac_customer_access" - app.flexeratest.com: - roleArn: "arn:aws:iam::274571843445:role/staging_customer_access" - PermissionMap: - # Begin IAM Permissions Map - # Expect 2 lists for each Policy Template (read and action) - ## All AWS Policy Templates - AllAWSPolicyTemplates: - read: - - "access-analyzer:ListAnalyzers" - - "ce:GetReservationCoverage" - - "ce:GetReservationPurchaseRecommendation" - - "ce:GetSavingsPlansPurchaseRecommendation" - - "ce:GetSavingsPlansUtilization" - - "cloudtrail:DescribeTrails" - - "cloudtrail:GetEventSelectors" - - "cloudtrail:GetTrailStatus" - - "cloudtrail:LookupEvents" - - "cloudwatch:GetMetricData" - - "cloudwatch:GetMetricStatistics" - - "cloudwatch:ListMetrics" - - "compute-optimizer:GetEC2InstanceRecommendations" - - "config:DescribeConfigurationRecorderStatus" - - "ec2:CreateTags" - - "ec2:DeleteTags" - - "ec2:DescribeAddresses" - - "ec2:DescribeFlowLogs" - - "ec2:DescribeImages" - - "ec2:DescribeInstanceStatus" - - "ec2:DescribeInstances" - - "ec2:DescribeNatGateways" - - "ec2:DescribeRegions" - - "ec2:DescribeSnapshots" - - "ec2:DescribeTags" - - "ec2:DescribeVolumes" - - "ec2:DescribeVpcs" - - "ec2:GetEbsEncryptionByDefault" - - "ec2:StartInstances" - - "ec2:StopInstances" - - "ec2:TerminateInstances" - - "ecs:DescribeClusters" - - "ecs:ListClusters" - - "eks:DescribeCluster" - - "eks:DescribeNodegroup" - - "eks:ListClusters" - - "eks:ListNodegroups" - - "elasticache:DescribeCacheClusters" - - "elasticache:ListTagsForResource" - - "elasticloadbalancing:DescribeInstanceHealth" - - "elasticloadbalancing:DescribeListeners" - - "elasticloadbalancing:DescribeLoadBalancers" - - "elasticloadbalancing:DescribeTags" - - "elasticloadbalancing:DescribeTargetGroups" - - "elasticloadbalancing:DescribeTargetHealth" - - "iam:GenerateCredentialReport" - - "iam:GetAccountPasswordPolicy" - - "iam:GetAccountSummary" - - "iam:GetCredentialReport" - - "iam:GetPolicyVersion" - - "iam:ListAccessKeys" - - "iam:ListAttachedUserPolicies" - - "iam:ListEntitiesForPolicy" - - "iam:ListPolicies" - - "iam:ListRoleTags" - - "iam:ListRoles" - - "iam:ListServerCertificates" - - "iam:ListUserPolicies" - - "iam:ListUsers" - - "iam:ListVirtualMFADevices" - - "kms:CreateGrant" - - "kms:Decrypt" - - "kms:GetKeyRotationStatus" - - "kms:ListKeys" - - "lambda:ListFunctions" - - "lambda:ListProvisionedConcurrencyConfigs" - - "lambda:ListTags" - - "lambda:ListVersionsByFunction" - - "organizations:ListAccounts" - - "organizations:ListPolicies" - - "organizations:ListPoliciesForTarget" - - "organizations:ListTagsForResource" - - "pricing:GetProducts" - - "rds:DescribeDBClusterSnapshots" - - "rds:DescribeDBClusters" - - "rds:DescribeDBInstances" - - "rds:DescribeDBSnapshots" - - "rds:DescribeOrderableDBInstanceOptions" - - "rds:ListTagsForResource" - - "redshift:DescribeClusters" - - "s3:GetBucketAcl" - - "s3:GetLifecycleConfiguration" - - "s3:GetBucketLocation" - - "s3:GetBucketLogging" - - "s3:GetBucketPolicy" - - "s3:GetBucketPublicAccessBlock" - - "s3:GetBucketTagging" - - "s3:GetBucketVersioning" - - "s3:GetEncryptionConfiguration" - - "s3:GetIntelligentTieringConfiguration" - - "s3:GetObject" - - "s3:ListAllMyBuckets" - - "s3:ListBucketMultipartUploads" - - "s3:ListMultipartUploadParts" - - "savingsplans:DescribeSavingsPlans" - - "sts:GetCallerIdentity" - - "tag:GetResources" - action: - - "cloudtrail:PutEventSelectors" - - "ec2:DeleteNatGateway" - - "ec2:DeleteSnapshot" - - "ec2:DeregisterImage" - - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:ModifyVolume" - - "ec2:ReleaseAddress" - - "ec2:StartInstances" - - "ec2:StopInstances" - - "ec2:TerminateInstances" - - "ecs:DeleteCluster" - - "elasticache:ModifyCacheCluster" - - "elasticloadbalancing:DeleteLoadBalancer" - - "organizations:TagResource" - - "rds:DeleteDBClusterSnapshot" - - "rds:DeleteDBInstance" - - "rds:DeleteDBSnapshot" - - "rds:ModifyDBInstance" - - "redshift:ModifyCluster" - - "s3:AbortMultipartUpload" - - "s3:DeleteBucket" - - "s3:PutBucketLogging" - - "s3:PutEncryptionConfiguration" - - "tag:TagResources" - ## AWS Account Credentials - AWSAccountCredentials: - read: - - "sts:GetCallerIdentity" - action: [] - ## AWS Accounts Missing Service Control Policies - AWSAccountsMissingServiceControlPolicies: - read: - - "organizations:ListPolicies" - - "organizations:ListAccounts" - - "organizations:ListPoliciesForTarget" - action: [] - ## AWS Burstable EC2 Instances - AWSBurstableEC2Instances: - read: - - "sts:GetCallerIdentity" - - "cloudwatch:GetMetricData" - - "cloudwatch:ListMetrics" - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "ec2:DescribeTags" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - - "ec2:StopInstances" - ## AWS CloudTrail Not Enabled In All Regions - AWSCloudTrailNotEnabledInAllRegions: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - - "cloudtrail:GetTrailStatus" - - "cloudtrail:GetEventSelectors" - action: [] - ## AWS CloudTrail S3 Buckets Without Access Logging - AWSCloudTrailS3BucketsWithoutAccessLogging: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - - "s3:GetBucketLocation" - - "s3:GetBucketLogging" - action: [] - ## AWS CloudTrails Not Integrated With CloudWatch - AWSCloudTrailsNotIntegratedWithCloudWatch: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - - "cloudtrail:GetTrailStatus" - action: [] - ## AWS CloudTrails With Read Logging Enabled - AWSCloudTrailsWithReadLoggingEnabled: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - - "cloudtrail:GetEventSelectors" - action: - - "cloudtrail:PutEventSelectors" - ## AWS CloudTrails Without Encrypted Logs - AWSCloudTrailsWithoutEncryptedLogs: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - action: [] - ## AWS CloudTrails Without Log File Validation Enabled - AWSCloudTrailsWithoutLogFileValidationEnabled: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - action: [] - ## AWS CloudTrails Without Object-level Events Logging Enabled - AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - - "cloudtrail:GetEventSelectors" - action: [] - ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled - AWSCustomerManagedKeysCMKsWithoutRotationEnabled: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "kms:ListKeys" - - "kms:GetKeyRotationStatus" - action: [] - ## AWS Disallowed Regions - AWSDisallowedRegions: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - action: - - "ec2:StopInstances" - - "ec2:TerminateInstances" - ## AWS EC2 Compute Optimizer Recommendations - AWSEC2ComputeOptimizerRecommendations: - read: - - "sts:GetCallerIdentity" - - "compute-optimizer:GetEC2InstanceRecommendations" - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - action: - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - - "ec2:StopInstances" - ## AWS EC2 Instances Time Stopped Report - AWSEC2InstancesTimeStoppedReport: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:StopInstances" - - "ec2:TerminateInstances" - ## AWS EC2 Instances not running FlexNet Inventory Agent - AWSEC2InstancesnotrunningFlexNetInventoryAgent: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - action: [] - ## AWS EKS Clusters Without Spot Instances - AWSEKSClustersWithoutSpotInstances: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "eks:ListClusters" - - "eks:ListNodegroups" - - "eks:DescribeCluster" - - "eks:DescribeNodegroup" - action: [] - ## AWS Elastic Load Balancers With Unencrypted Listeners - AWSElasticLoadBalancersWithUnencryptedListeners: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "elasticloadbalancing:DescribeLoadBalancers" - - "elasticloadbalancing:DescribeTags" - - "elasticloadbalancing:DescribeListeners" - action: [] - ## AWS Expiring Savings Plans - AWSExpiringSavingsPlans: - read: - - "savingsplans:DescribeSavingsPlans" - action: [] - ## AWS IAM Account Missing Support Role - AWSIAMAccountMissingSupportRole: - read: - - "sts:GetCallerIdentity" - - "iam:ListPolicies" - - "iam:ListEntitiesForPolicy" - action: [] - ## AWS IAM Attached Admin Policies - AWSIAMAttachedAdminPolicies: - read: - - "sts:GetCallerIdentity" - - "iam:ListPolicies" - - "iam:GetPolicyVersion" - action: [] - ## AWS IAM Expired SSL/TLS Certificates - AWSIAMExpiredSSLTLSCertificates: - read: - - "sts:GetCallerIdentity" - - "iam:ListServerCertificates" - action: [] - ## AWS IAM Insufficient Required Password Length - AWSIAMInsufficientRequiredPasswordLength: - read: - - "sts:GetCallerIdentity" - - "iam:GetAccountPasswordPolicy" - action: [] - ## AWS IAM Password Policy Not Restricting Password Reuse - AWSIAMPasswordPolicyNotRestrictingPasswordReuse: - read: - - "sts:GetCallerIdentity" - - "iam:GetAccountPasswordPolicy" - action: [] - ## AWS IAM Role Audit - AWSIAMRoleAudit: - read: - - "sts:GetCallerIdentity" - - "iam:ListRoles" - - "iam:ListRoleTags" - action: [] - ## AWS IAM Root Account Access Keys - AWSIAMRootAccountAccessKeys: - read: - - "sts:GetCallerIdentity" - - "iam:GetAccountSummary" - action: [] - ## AWS IAM Root User Account Without Hardware MFA - AWSIAMRootUserAccountWithoutHardwareMFA: - read: - - "sts:GetCallerIdentity" - - "iam:GetAccountSummary" - - "iam:ListVirtualMFADevices" - action: [] - ## AWS IAM Root User Account Without MFA - AWSIAMRootUserAccountWithoutMFA: - read: - - "sts:GetCallerIdentity" - - "iam:GetAccountSummary" - - "iam:ListVirtualMFADevices" - action: [] - ## AWS IAM Root User Doing Everyday Tasks - AWSIAMRootUserDoingEverydayTasks: - read: - - "sts:GetCallerIdentity" - - "iam:GenerateCredentialReport" - - "iam:GetCredentialReport" - action: [] - ## AWS IAM User Accounts Without MFA - AWSIAMUserAccountsWithoutMFA: - read: - - "sts:GetCallerIdentity" - - "iam:GenerateCredentialReport" - - "iam:GetCredentialReport" - action: [] - ## AWS IAM Users With Directly-Attached Policies - AWSIAMUsersWithDirectlyAttachedPolicies: - read: - - "sts:GetCallerIdentity" - - "iam:ListUsers" - - "iam:ListUserPolicies" - - "iam:ListAttachedUserPolicies" - action: [] - ## AWS IAM Users With Multiple Active Access Keys - AWSIAMUsersWithMultipleActiveAccessKeys: - read: - - "sts:GetCallerIdentity" - - "iam:ListUsers" - - "iam:ListAccessKeys" - action: [] - ## AWS IAM Users With Old Access Keys - AWSIAMUsersWithOldAccessKeys: - read: - - "sts:GetCallerIdentity" - - "iam:GenerateCredentialReport" - - "iam:GetCredentialReport" - action: [] - ## AWS Idle NAT Gateways - AWSIdleNATGateways: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeNatGateways" - - "sts:GetCallerIdentity" - action: - - "ec2:DeleteNatGateway" - ## AWS Internet-Accessible Elastic Load Balancers - AWSInternetAccessibleElasticLoadBalancers: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "elasticloadbalancing:DescribeLoadBalancers" - - "elasticloadbalancing:DescribeTags" - - "elasticloadbalancing:DescribeListeners" - action: - - "elasticloadbalancing:DeleteLoadBalancer" - ## AWS Lambda Functions With High Error Rate - AWSLambdaFunctionsWithHighErrorRate: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "lambda:ListFunctions" - - "lambda:ListTags" - - "cloudwatch:ListMetrics" - - "cloudwatch:GetMetricData" - action: [] - ## AWS Lambda Functions Without Provisioned Concurrency - AWSLambdaFunctionsWithoutProvisionedConcurrency: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "lambda:ListFunctions" - - "lambda:ListTags" - - "lambda:ListProvisionedConcurrencyConfigs" - - "lambda:ListVersionsByFunction" - action: [] - ## AWS Long Running Instances - AWSLongRunningInstances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:StopInstances" - - "ec2:TerminateInstances" - ## AWS Long Stopped EC2 Instances - AWSLongStoppedEC2Instances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "cloudwatch:GetMetricStatistics" - - "cloudwatch:GetMetricData" - - "cloudwatch:ListMetrics" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:TerminateInstances" - ## AWS Missing Regions - AWSMissingRegions: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "sts:GetCallerIdentity" - action: [] - ## AWS Old Snapshots - AWSOldSnapshots: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeImages" - - "ec2:DescribeSnapshots" - - "rds:DescribeDBInstances" - - "rds:DescribeDBSnapshots" - - "rds:DescribeDBClusters" - - "rds:DescribeDBClusterSnapshots" - - "sts:GetCallerIdentity" - - "cloudtrail:LookupEvents" - action: - - "ec2:DeregisterImage" - - "ec2:DeleteSnapshot" - - "rds:DeleteDBClusterSnapshot" - - "rds:DeleteDBSnapshot" - ## AWS Open S3 Buckets - AWSOpenS3Buckets: - read: - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketAcl" - - "sts:GetCallerIdentity" - action: [] - ## AWS Oversized S3 Buckets - AWSOversizedS3Buckets: - read: - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "cloudwatch:ListMetrics" - - "cloudwatch:GetMetricData" - - "sts:GetCallerIdentity" - action: [] - ## AWS Publicly Accessible CloudTrail S3 Buckets - AWSPubliclyAccessibleCloudTrailS3Buckets: - read: - - "sts:GetCallerIdentity" - - "cloudtrail:DescribeTrails" - - "s3:GetBucketLocation" - - "s3:GetBucketAcl" - - "s3:GetBucketPolicy" - action: [] - ## AWS Publicly Accessible RDS Instances - AWSPubliclyAccessibleRDSInstances: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "rds:DescribeDBInstances" - - "rds:ListTagsForResource" - action: - - "rds:ModifyDBInstance" - - "rds:DeleteDBInstance" - ## AWS RDS Instances With Unapproved Backup Settings - AWSRDSInstancesWithUnapprovedBackupSettings: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "rds:DescribeDBInstances" - - "rds:ListTagsForResource" - action: [] - ## AWS Regions Without Access Analyzer Enabled - AWSRegionsWithoutAccessAnalyzerEnabled: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "access-analyzer:ListAnalyzers" - action: [] - ## AWS Regions Without Config Fully Enabled - AWSRegionsWithoutConfigFullyEnabled: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "config:DescribeConfigurationRecorderStatus" - action: [] - ## AWS Regions Without Default EBS Encryption - AWSRegionsWithoutDefaultEBSEncryption: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "ec2:GetEbsEncryptionByDefault" - action: [] - ## AWS Reserved Instances Coverage - AWSReservedInstancesCoverage: - read: - - "ce:GetReservationCoverage" - action: [] - ## AWS Reserved Instances Recommendations - AWSReservedInstancesRecommendations: - read: - - "ce:GetReservationPurchaseRecommendation" - action: [] - ## AWS Rightsize EBS Volumes - AWSRightsizeEBSVolumes: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeVolumes" - - "pricing:GetProducts" - action: - - "ec2:ModifyVolume" - ## AWS Rightsize EC2 Instances - AWSRightsizeEC2Instances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "ec2:DescribeTags" - - "cloudwatch:GetMetricStatistics" - - "cloudwatch:GetMetricData" - - "cloudwatch:ListMetrics" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - - "ec2:StopInstances" - - "ec2:TerminateInstances" - ## AWS Rightsize ElastiCache - AWSRightsizeElastiCache: - read: - - "sts:GetCallerIdentity" - - "cloudwatch:GetMetricData" - - "ec2:DescribeRegions" - - "elasticache:DescribeCacheClusters" - - "elasticache:ListTagsForResource" - action: - - "elasticache:ModifyCacheCluster" - ## AWS Rightsize RDS Instances - AWSRightsizeRDSInstances: - read: - - "sts:GetCallerIdentity" - - "cloudwatch:GetMetricStatistics" - - "cloudwatch:GetMetricData" - - "ec2:DescribeRegions" - - "rds:DescribeDBInstances" - - "rds:ListTagsForResource" - - "rds:DescribeOrderableDBInstanceOptions" - action: - - "rds:ModifyDBInstance" - - "rds:DeleteDBInstance" - ## AWS Rightsize Redshift - AWSRightsizeRedshift: - read: - - "sts:GetCallerIdentity" - - "cloudwatch:GetMetricData" - - "ec2:DescribeRegions" - - "redshift:DescribeClusters" - action: - - "redshift:ModifyCluster" - ## AWS S3 Buckets Accepting HTTP Requests - AWSS3BucketsAcceptingHTTPRequests: - read: - - "sts:GetCallerIdentity" - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:GetBucketPolicy" - action: [] - ## AWS S3 Buckets Without Default Encryption Configuration - AWSS3BucketsWithoutDefaultEncryptionConfiguration: - read: - - "sts:GetCallerIdentity" - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:GetEncryptionConfiguration" - action: - - "s3:PutEncryptionConfiguration" - - "s3:DeleteBucket" - ## AWS S3 Buckets Without Intelligent Tiering - AWSS3BucketsWithoutIntelligentTiering: - read: - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:GetIntelligentTieringConfiguration" - - "sts:GetCallerIdentity" - action: [] - ## AWS S3 Buckets Without Lifecycle Configuration - AWSS3BucketsWithoutLifecycleConfiguration: - read: - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:GetLifecycleConfiguration" - - "sts:GetCallerIdentity" - action: [] - ## AWS S3 Buckets Without MFA Delete Enabled - AWSS3BucketsWithoutMFADeleteEnabled: - read: - - "sts:GetCallerIdentity" - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:GetBucketVersioning" - action: [] - ## AWS S3 Buckets Without Public Access Blocked - AWSS3BucketsWithoutPublicAccessBlocked: - read: - - "sts:GetCallerIdentity" - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:GetBucketPublicAccessBlock" - action: [] - ## AWS S3 Buckets Without Server Access Logging - AWSS3BucketsWithoutServerAccessLogging: - read: - - "sts:GetCallerIdentity" - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:GetBucketLogging" - action: - - "s3:PutBucketLogging" - ## AWS S3 Incomplete Multi-Part Uploads - AWSS3IncompleteMultiPartUploads: - read: - - "sts:GetCallerIdentity" - - "s3:ListAllMyBuckets" - - "s3:GetBucketLocation" - - "s3:GetBucketTagging" - - "s3:ListBucketMultipartUploads" - - "s3:ListMultipartUploadParts" - action: - - "s3:AbortMultipartUpload" - ## AWS Savings Plan Recommendations - AWSSavingsPlanRecommendations: - read: - - "ce:GetSavingsPlansPurchaseRecommendation" - action: [] - ## AWS Savings Plan Utilization - AWSSavingsPlanUtilization: - read: - - "ce:GetSavingsPlansUtilization" - - "savingsplans:DescribeSavingsPlans" - action: [] - ## AWS Schedule Instance - AWSScheduleInstance: - read: - - "ec2:DescribeInstances" - - "ec2:StartInstances" - - "ec2:StopInstances" - - "ec2:DeleteTags" - - "ec2:DescribeRegions" - - "kms:CreateGrant" - - "kms:Decrypt" - - "ec2:CreateTags" - - "ec2:TerminateInstances" - action: [] - ## AWS Scheduled EC2 Events - AWSScheduledEC2Events: - read: - - "ec2:DescribeInstances" - - "ec2:DescribeInstanceStatus" - - "ec2:DescribeRegions" - - "sts:GetCallerIdentity" - action: [] - ## AWS Superseded EBS Volumes - AWSSupersededEBSVolumes: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "ec2:DescribeVolumes" - - "pricing:GetProducts" - action: - - "ec2:ModifyVolume" - ## AWS Superseded EC2 Instances - AWSSupersededEC2Instances: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeInstances" - - "ec2:DescribeTags" - - "sts:GetCallerIdentity" - action: - - "ec2:DescribeInstanceStatus" - - "ec2:ModifyInstanceAttribute" - - "ec2:StartInstances" - - "ec2:StopInstances" - ## AWS Tag Cardinality Report - AWSTagCardinalityReport: - read: - - "tag:GetResources" - - "ec2:DescribeRegions" - - "organizations:ListAccounts" - - "organizations:ListTagsForResource" - action: [] - ## AWS Unencrypted EBS Volumes - AWSUnencryptedEBSVolumes: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "ec2:DescribeVolumes" - action: [] - ## AWS Unencrypted RDS Instances - AWSUnencryptedRDSInstances: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "rds:DescribeDBInstances" - - "rds:ListTagsForResource" - action: - - "rds:DeleteDBInstance" - ## AWS Untagged Resources - AWSUntaggedResources: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "tag:GetResources" - action: - - "tag:TagResources" - - "organizations:TagResource" - ## AWS Unused Application Load Balancers - AWSUnusedApplicationLoadBalancers: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "elasticloadbalancing:DescribeLoadBalancers" - - "elasticloadbalancing:DescribeListeners" - - "elasticloadbalancing:DescribeTags" - - "elasticloadbalancing:DescribeTargetGroups" - - "elasticloadbalancing:DescribeTargetHealth" - action: - - "elasticloadbalancing:DeleteLoadBalancer" - ## AWS Unused Classic Load Balancers - AWSUnusedClassicLoadBalancers: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "elasticloadbalancing:DescribeLoadBalancers" - - "elasticloadbalancing:DescribeInstanceHealth" - - "elasticloadbalancing:DescribeTags" - action: - - "elasticloadbalancing:DeleteLoadBalancer" - ## AWS Unused ECS Clusters - AWSUnusedECSClusters: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "ecs:ListClusters" - - "ecs:DescribeClusters" - action: - - "ecs:DeleteCluster" - ## AWS Unused IAM Credentials - AWSUnusedIAMCredentials: - read: - - "sts:GetCallerIdentity" - - "iam:GenerateCredentialReport" - - "iam:GetCredentialReport" - action: [] - ## AWS Unused IP Addresses - AWSUnusedIPAddresses: - read: - - "ec2:DescribeRegions" - - "ec2:DescribeAddresses" - - "sts:GetCallerIdentity" - - "cloudtrail:LookupEvents" - action: - - "ec2:ReleaseAddress" - ## AWS Unused Network Load Balancers - AWSUnusedNetworkLoadBalancers: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "elasticloadbalancing:DescribeLoadBalancers" - - "elasticloadbalancing:DescribeListeners" - - "elasticloadbalancing:DescribeTags" - - "elasticloadbalancing:DescribeTargetGroups" - - "elasticloadbalancing:DescribeTargetHealth" - action: - - "elasticloadbalancing:DeleteLoadBalancer" - ## AWS VPCs Without FlowLogs Enabled - AWSVPCsWithoutFlowLogsEnabled: - read: - - "sts:GetCallerIdentity" - - "ec2:DescribeRegions" - - "ec2:DescribeVpcs" - - "ec2:DescribeFlowLogs" - action: [] - ## Common Bill Ingestion from AWS S3 Object Storage - CommonBillIngestionfromAWSS3ObjectStorage: - read: - - "s3:GetObject" - action: [] - - # End for each policy template - -Resources: - # IAM Role Resource - iamRole: - Type: "AWS::IAM::Role" - Properties: - RoleName: !Ref paramRoleName - Description: !Join - - " " - - - "Allows access from Flexera Platform. This IAM Role and the attached permission policies were created and are managed by CloudFormation Stack:" - - !Ref AWS::StackId - Path: !Ref paramRolePath - AssumeRolePolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Principal: - AWS: !FindInMap - - TrustedRoleMap - - !Ref paramFlexeraZone - - roleArn - Action: "sts:AssumeRole" - Condition: - StringEquals: - "sts:ExternalId": !Ref paramFlexeraOrgId - # ManagedPolicyArns value is conditional based on input paramPermsAttachExistingPolicies - ManagedPolicyArns: !If - - ValueProvidedparamPermsAttachExistingPolicies - # If value is provided for paramPermsAttachExistingPolicies, split that comma-separated list into a list object - - !Split [ ",", !Ref paramPermsAttachExistingPolicies ] - # Provide a null value if nothing provided for paramPermsAttachExistingPolicies - - !Ref AWS::NoValue - # Begin IAM Permission Policy Resources - # 1 or 2 Permission Policies per Policy Template (read and action) - # Policy create/attachment is conditional based on parameter input for each policy - ## All AWS Policy Templates - iamPolicyAllAWSPolicyTemplatesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAllAWSPolicyTemplatesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AllAWSPolicyTemplatesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AllAWSPolicyTemplates - - read - Resource: "*" - iamPolicyAllAWSPolicyTemplatesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAllAWSPolicyTemplatesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AllAWSPolicyTemplatesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AllAWSPolicyTemplates - - action - Resource: "*" - ## AWS Account Credentials - iamPolicyAWSAccountCredentialsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSAccountCredentialsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSAccountCredentialsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSAccountCredentials - - read - Resource: "*" - ## AWS Accounts Missing Service Control Policies - iamPolicyAWSAccountsMissingServiceControlPoliciesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSAccountsMissingServiceControlPoliciesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSAccountsMissingServiceControlPoliciesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSAccountsMissingServiceControlPolicies - - read - Resource: "*" - ## AWS Burstable EC2 Instances - iamPolicyAWSBurstableEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSBurstableEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSBurstableEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSBurstableEC2Instances - - read - Resource: "*" - iamPolicyAWSBurstableEC2InstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSBurstableEC2InstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSBurstableEC2InstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSBurstableEC2Instances - - action - Resource: "*" - ## AWS CloudTrail Not Enabled In All Regions - iamPolicyAWSCloudTrailNotEnabledInAllRegionsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailNotEnabledInAllRegionsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailNotEnabledInAllRegionsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailNotEnabledInAllRegions - - read - Resource: "*" - ## AWS CloudTrail S3 Buckets Without Access Logging - iamPolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailS3BucketsWithoutAccessLoggingRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailS3BucketsWithoutAccessLoggingReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailS3BucketsWithoutAccessLogging - - read - Resource: "*" - ## AWS CloudTrails Not Integrated With CloudWatch - iamPolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailsNotIntegratedWithCloudWatchRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailsNotIntegratedWithCloudWatchReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailsNotIntegratedWithCloudWatch - - read - Resource: "*" - ## AWS CloudTrails With Read Logging Enabled - iamPolicyAWSCloudTrailsWithReadLoggingEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailsWithReadLoggingEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailsWithReadLoggingEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailsWithReadLoggingEnabled - - read - Resource: "*" - iamPolicyAWSCloudTrailsWithReadLoggingEnabledAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailsWithReadLoggingEnabledAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailsWithReadLoggingEnabledActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailsWithReadLoggingEnabled - - action - Resource: "*" - ## AWS CloudTrails Without Encrypted Logs - iamPolicyAWSCloudTrailsWithoutEncryptedLogsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailsWithoutEncryptedLogsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailsWithoutEncryptedLogsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailsWithoutEncryptedLogs - - read - Resource: "*" - ## AWS CloudTrails Without Log File Validation Enabled - iamPolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailsWithoutLogFileValidationEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailsWithoutLogFileValidationEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailsWithoutLogFileValidationEnabled - - read - Resource: "*" - ## AWS CloudTrails Without Object-level Events Logging Enabled - iamPolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCloudTrailsWithoutObjectlevelEventsLoggingEnabled - - read - Resource: "*" - ## AWS Customer Managed Keys (CMKs) Without Rotation Enabled - iamPolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSCustomerManagedKeysCMKsWithoutRotationEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSCustomerManagedKeysCMKsWithoutRotationEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSCustomerManagedKeysCMKsWithoutRotationEnabled - - read - Resource: "*" - ## AWS Disallowed Regions - iamPolicyAWSDisallowedRegionsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSDisallowedRegionsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSDisallowedRegionsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSDisallowedRegions - - read - Resource: "*" - iamPolicyAWSDisallowedRegionsAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSDisallowedRegionsAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSDisallowedRegionsActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSDisallowedRegions - - action - Resource: "*" - ## AWS EC2 Compute Optimizer Recommendations - iamPolicyAWSEC2ComputeOptimizerRecommendationsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSEC2ComputeOptimizerRecommendationsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSEC2ComputeOptimizerRecommendationsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSEC2ComputeOptimizerRecommendations - - read - Resource: "*" - iamPolicyAWSEC2ComputeOptimizerRecommendationsAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSEC2ComputeOptimizerRecommendationsAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSEC2ComputeOptimizerRecommendationsActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSEC2ComputeOptimizerRecommendations - - action - Resource: "*" - ## AWS EC2 Instances Time Stopped Report - iamPolicyAWSEC2InstancesTimeStoppedReportRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSEC2InstancesTimeStoppedReportRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSEC2InstancesTimeStoppedReportReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSEC2InstancesTimeStoppedReport - - read - Resource: "*" - iamPolicyAWSEC2InstancesTimeStoppedReportAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSEC2InstancesTimeStoppedReportAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSEC2InstancesTimeStoppedReportActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSEC2InstancesTimeStoppedReport - - action - Resource: "*" - ## AWS EC2 Instances not running FlexNet Inventory Agent - iamPolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSEC2InstancesnotrunningFlexNetInventoryAgentRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSEC2InstancesnotrunningFlexNetInventoryAgentReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSEC2InstancesnotrunningFlexNetInventoryAgent - - read - Resource: "*" - ## AWS EKS Clusters Without Spot Instances - iamPolicyAWSEKSClustersWithoutSpotInstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSEKSClustersWithoutSpotInstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSEKSClustersWithoutSpotInstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSEKSClustersWithoutSpotInstances - - read - Resource: "*" - ## AWS Elastic Load Balancers With Unencrypted Listeners - iamPolicyAWSElasticLoadBalancersWithUnencryptedListenersRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSElasticLoadBalancersWithUnencryptedListenersRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSElasticLoadBalancersWithUnencryptedListenersReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSElasticLoadBalancersWithUnencryptedListeners - - read - Resource: "*" - ## AWS Expiring Savings Plans - iamPolicyAWSExpiringSavingsPlansRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSExpiringSavingsPlansRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSExpiringSavingsPlansReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSExpiringSavingsPlans - - read - Resource: "*" - ## AWS IAM Account Missing Support Role - iamPolicyAWSIAMAccountMissingSupportRoleRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMAccountMissingSupportRoleRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMAccountMissingSupportRoleReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMAccountMissingSupportRole - - read - Resource: "*" - ## AWS IAM Attached Admin Policies - iamPolicyAWSIAMAttachedAdminPoliciesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMAttachedAdminPoliciesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMAttachedAdminPoliciesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMAttachedAdminPolicies - - read - Resource: "*" - ## AWS IAM Expired SSL/TLS Certificates - iamPolicyAWSIAMExpiredSSLTLSCertificatesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMExpiredSSLTLSCertificatesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMExpiredSSLTLSCertificatesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMExpiredSSLTLSCertificates - - read - Resource: "*" - ## AWS IAM Insufficient Required Password Length - iamPolicyAWSIAMInsufficientRequiredPasswordLengthRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMInsufficientRequiredPasswordLengthRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMInsufficientRequiredPasswordLengthReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMInsufficientRequiredPasswordLength - - read - Resource: "*" - ## AWS IAM Password Policy Not Restricting Password Reuse - iamPolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMPasswordPolicyNotRestrictingPasswordReuseRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMPasswordPolicyNotRestrictingPasswordReuseReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMPasswordPolicyNotRestrictingPasswordReuse - - read - Resource: "*" - ## AWS IAM Role Audit - iamPolicyAWSIAMRoleAuditRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMRoleAuditRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMRoleAuditReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMRoleAudit - - read - Resource: "*" - ## AWS IAM Root Account Access Keys - iamPolicyAWSIAMRootAccountAccessKeysRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMRootAccountAccessKeysRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMRootAccountAccessKeysReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMRootAccountAccessKeys - - read - Resource: "*" - ## AWS IAM Root User Account Without Hardware MFA - iamPolicyAWSIAMRootUserAccountWithoutHardwareMFARead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMRootUserAccountWithoutHardwareMFARead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMRootUserAccountWithoutHardwareMFAReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMRootUserAccountWithoutHardwareMFA - - read - Resource: "*" - ## AWS IAM Root User Account Without MFA - iamPolicyAWSIAMRootUserAccountWithoutMFARead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMRootUserAccountWithoutMFARead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMRootUserAccountWithoutMFAReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMRootUserAccountWithoutMFA - - read - Resource: "*" - ## AWS IAM Root User Doing Everyday Tasks - iamPolicyAWSIAMRootUserDoingEverydayTasksRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMRootUserDoingEverydayTasksRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMRootUserDoingEverydayTasksReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMRootUserDoingEverydayTasks - - read - Resource: "*" - ## AWS IAM User Accounts Without MFA - iamPolicyAWSIAMUserAccountsWithoutMFARead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMUserAccountsWithoutMFARead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMUserAccountsWithoutMFAReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMUserAccountsWithoutMFA - - read - Resource: "*" - ## AWS IAM Users With Directly-Attached Policies - iamPolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMUsersWithDirectlyAttachedPoliciesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMUsersWithDirectlyAttachedPoliciesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMUsersWithDirectlyAttachedPolicies - - read - Resource: "*" - ## AWS IAM Users With Multiple Active Access Keys - iamPolicyAWSIAMUsersWithMultipleActiveAccessKeysRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMUsersWithMultipleActiveAccessKeysRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMUsersWithMultipleActiveAccessKeysReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMUsersWithMultipleActiveAccessKeys - - read - Resource: "*" - ## AWS IAM Users With Old Access Keys - iamPolicyAWSIAMUsersWithOldAccessKeysRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIAMUsersWithOldAccessKeysRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIAMUsersWithOldAccessKeysReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIAMUsersWithOldAccessKeys - - read - Resource: "*" - ## AWS Idle NAT Gateways - iamPolicyAWSIdleNATGatewaysRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIdleNATGatewaysRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIdleNATGatewaysReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIdleNATGateways - - read - Resource: "*" - iamPolicyAWSIdleNATGatewaysAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSIdleNATGatewaysAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSIdleNATGatewaysActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSIdleNATGateways - - action - Resource: "*" - ## AWS Internet-Accessible Elastic Load Balancers - iamPolicyAWSInternetAccessibleElasticLoadBalancersRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSInternetAccessibleElasticLoadBalancersRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSInternetAccessibleElasticLoadBalancersReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSInternetAccessibleElasticLoadBalancers - - read - Resource: "*" - iamPolicyAWSInternetAccessibleElasticLoadBalancersAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSInternetAccessibleElasticLoadBalancersAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSInternetAccessibleElasticLoadBalancersActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSInternetAccessibleElasticLoadBalancers - - action - Resource: "*" - ## AWS Lambda Functions With High Error Rate - iamPolicyAWSLambdaFunctionsWithHighErrorRateRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSLambdaFunctionsWithHighErrorRateRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSLambdaFunctionsWithHighErrorRateReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSLambdaFunctionsWithHighErrorRate - - read - Resource: "*" - ## AWS Lambda Functions Without Provisioned Concurrency - iamPolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSLambdaFunctionsWithoutProvisionedConcurrencyRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSLambdaFunctionsWithoutProvisionedConcurrencyReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSLambdaFunctionsWithoutProvisionedConcurrency - - read - Resource: "*" - ## AWS Long Running Instances - iamPolicyAWSLongRunningInstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSLongRunningInstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSLongRunningInstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSLongRunningInstances - - read - Resource: "*" - iamPolicyAWSLongRunningInstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSLongRunningInstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSLongRunningInstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSLongRunningInstances - - action - Resource: "*" - ## AWS Long Stopped EC2 Instances - iamPolicyAWSLongStoppedEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSLongStoppedEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSLongStoppedEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSLongStoppedEC2Instances - - read - Resource: "*" - iamPolicyAWSLongStoppedEC2InstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSLongStoppedEC2InstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSLongStoppedEC2InstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSLongStoppedEC2Instances - - action - Resource: "*" - ## AWS Missing Regions - iamPolicyAWSMissingRegionsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSMissingRegionsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSMissingRegionsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSMissingRegions - - read - Resource: "*" - ## AWS Old Snapshots - iamPolicyAWSOldSnapshotsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSOldSnapshotsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSOldSnapshotsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSOldSnapshots - - read - Resource: "*" - iamPolicyAWSOldSnapshotsAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSOldSnapshotsAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSOldSnapshotsActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSOldSnapshots - - action - Resource: "*" - ## AWS Open S3 Buckets - iamPolicyAWSOpenS3BucketsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSOpenS3BucketsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSOpenS3BucketsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSOpenS3Buckets - - read - Resource: "*" - ## AWS Oversized S3 Buckets - iamPolicyAWSOversizedS3BucketsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSOversizedS3BucketsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSOversizedS3BucketsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSOversizedS3Buckets - - read - Resource: "*" - ## AWS Publicly Accessible CloudTrail S3 Buckets - iamPolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSPubliclyAccessibleCloudTrailS3BucketsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSPubliclyAccessibleCloudTrailS3BucketsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSPubliclyAccessibleCloudTrailS3Buckets - - read - Resource: "*" - ## AWS Publicly Accessible RDS Instances - iamPolicyAWSPubliclyAccessibleRDSInstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSPubliclyAccessibleRDSInstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSPubliclyAccessibleRDSInstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSPubliclyAccessibleRDSInstances - - read - Resource: "*" - iamPolicyAWSPubliclyAccessibleRDSInstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSPubliclyAccessibleRDSInstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSPubliclyAccessibleRDSInstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSPubliclyAccessibleRDSInstances - - action - Resource: "*" - ## AWS RDS Instances With Unapproved Backup Settings - iamPolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRDSInstancesWithUnapprovedBackupSettingsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRDSInstancesWithUnapprovedBackupSettingsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRDSInstancesWithUnapprovedBackupSettings - - read - Resource: "*" - ## AWS Regions Without Access Analyzer Enabled - iamPolicyAWSRegionsWithoutAccessAnalyzerEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRegionsWithoutAccessAnalyzerEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRegionsWithoutAccessAnalyzerEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRegionsWithoutAccessAnalyzerEnabled - - read - Resource: "*" - ## AWS Regions Without Config Fully Enabled - iamPolicyAWSRegionsWithoutConfigFullyEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRegionsWithoutConfigFullyEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRegionsWithoutConfigFullyEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRegionsWithoutConfigFullyEnabled - - read - Resource: "*" - ## AWS Regions Without Default EBS Encryption - iamPolicyAWSRegionsWithoutDefaultEBSEncryptionRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRegionsWithoutDefaultEBSEncryptionRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRegionsWithoutDefaultEBSEncryptionReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRegionsWithoutDefaultEBSEncryption - - read - Resource: "*" - ## AWS Reserved Instances Coverage - iamPolicyAWSReservedInstancesCoverageRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSReservedInstancesCoverageRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSReservedInstancesCoverageReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSReservedInstancesCoverage - - read - Resource: "*" - ## AWS Reserved Instances Recommendations - iamPolicyAWSReservedInstancesRecommendationsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSReservedInstancesRecommendationsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSReservedInstancesRecommendationsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSReservedInstancesRecommendations - - read - Resource: "*" - ## AWS Rightsize EBS Volumes - iamPolicyAWSRightsizeEBSVolumesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEBSVolumesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeEBSVolumesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeEBSVolumes - - read - Resource: "*" - iamPolicyAWSRightsizeEBSVolumesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEBSVolumesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeEBSVolumesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeEBSVolumes - - action - Resource: "*" - ## AWS Rightsize EC2 Instances - iamPolicyAWSRightsizeEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeEC2Instances - - read - Resource: "*" - iamPolicyAWSRightsizeEC2InstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeEC2InstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeEC2InstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeEC2Instances - - action - Resource: "*" - ## AWS Rightsize ElastiCache - iamPolicyAWSRightsizeElastiCacheRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeElastiCacheRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeElastiCacheReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeElastiCache - - read - Resource: "*" - iamPolicyAWSRightsizeElastiCacheAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeElastiCacheAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeElastiCacheActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeElastiCache - - action - Resource: "*" - ## AWS Rightsize RDS Instances - iamPolicyAWSRightsizeRDSInstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeRDSInstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeRDSInstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeRDSInstances - - read - Resource: "*" - iamPolicyAWSRightsizeRDSInstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeRDSInstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeRDSInstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeRDSInstances - - action - Resource: "*" - ## AWS Rightsize Redshift - iamPolicyAWSRightsizeRedshiftRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeRedshiftRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeRedshiftReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeRedshift - - read - Resource: "*" - iamPolicyAWSRightsizeRedshiftAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSRightsizeRedshiftAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSRightsizeRedshiftActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSRightsizeRedshift - - action - Resource: "*" - ## AWS S3 Buckets Accepting HTTP Requests - iamPolicyAWSS3BucketsAcceptingHTTPRequestsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsAcceptingHTTPRequestsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsAcceptingHTTPRequestsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsAcceptingHTTPRequests - - read - Resource: "*" - ## AWS S3 Buckets Without Default Encryption Configuration - iamPolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutDefaultEncryptionConfigurationReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutDefaultEncryptionConfiguration - - read - Resource: "*" - iamPolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutDefaultEncryptionConfigurationAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutDefaultEncryptionConfigurationActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutDefaultEncryptionConfiguration - - action - Resource: "*" - ## AWS S3 Buckets Without Intelligent Tiering - iamPolicyAWSS3BucketsWithoutIntelligentTieringRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutIntelligentTieringRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutIntelligentTieringReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutIntelligentTiering - - read - Resource: "*" - ## AWS S3 Buckets Without Lifecycle Configuration - iamPolicyAWSS3BucketsWithoutLifecycleConfigurationRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutLifecycleConfigurationRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutLifecycleConfigurationReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutLifecycleConfiguration - - read - Resource: "*" - ## AWS S3 Buckets Without MFA Delete Enabled - iamPolicyAWSS3BucketsWithoutMFADeleteEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutMFADeleteEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutMFADeleteEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutMFADeleteEnabled - - read - Resource: "*" - ## AWS S3 Buckets Without Public Access Blocked - iamPolicyAWSS3BucketsWithoutPublicAccessBlockedRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutPublicAccessBlockedRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutPublicAccessBlockedReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutPublicAccessBlocked - - read - Resource: "*" - ## AWS S3 Buckets Without Server Access Logging - iamPolicyAWSS3BucketsWithoutServerAccessLoggingRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutServerAccessLoggingRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutServerAccessLoggingReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutServerAccessLogging - - read - Resource: "*" - iamPolicyAWSS3BucketsWithoutServerAccessLoggingAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3BucketsWithoutServerAccessLoggingAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3BucketsWithoutServerAccessLoggingActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3BucketsWithoutServerAccessLogging - - action - Resource: "*" - ## AWS S3 Incomplete Multi-Part Uploads - iamPolicyAWSS3IncompleteMultiPartUploadsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3IncompleteMultiPartUploadsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3IncompleteMultiPartUploadsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3IncompleteMultiPartUploads - - read - Resource: "*" - iamPolicyAWSS3IncompleteMultiPartUploadsAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSS3IncompleteMultiPartUploadsAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSS3IncompleteMultiPartUploadsActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSS3IncompleteMultiPartUploads - - action - Resource: "*" - ## AWS Savings Plan Recommendations - iamPolicyAWSSavingsPlanRecommendationsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSavingsPlanRecommendationsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSavingsPlanRecommendationsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSavingsPlanRecommendations - - read - Resource: "*" - ## AWS Savings Plan Utilization - iamPolicyAWSSavingsPlanUtilizationRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSavingsPlanUtilizationRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSavingsPlanUtilizationReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSavingsPlanUtilization - - read - Resource: "*" - ## AWS Schedule Instance - iamPolicyAWSScheduleInstanceRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSScheduleInstanceRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSScheduleInstanceReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSScheduleInstance - - read - Resource: "*" - ## AWS Scheduled EC2 Events - iamPolicyAWSScheduledEC2EventsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSScheduledEC2EventsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSScheduledEC2EventsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSScheduledEC2Events - - read - Resource: "*" - ## AWS Superseded EBS Volumes - iamPolicyAWSSupersededEBSVolumesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEBSVolumesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEBSVolumesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEBSVolumes - - read - Resource: "*" - iamPolicyAWSSupersededEBSVolumesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEBSVolumesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEBSVolumesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEBSVolumes - - action - Resource: "*" - ## AWS Superseded EC2 Instances - iamPolicyAWSSupersededEC2InstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - read - Resource: "*" - iamPolicyAWSSupersededEC2InstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSSupersededEC2InstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSSupersededEC2InstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSSupersededEC2Instances - - action - Resource: "*" - ## AWS Tag Cardinality Report - iamPolicyAWSTagCardinalityReportRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSTagCardinalityReportRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSTagCardinalityReportReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSTagCardinalityReport - - read - Resource: "*" - ## AWS Unencrypted EBS Volumes - iamPolicyAWSUnencryptedEBSVolumesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnencryptedEBSVolumesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnencryptedEBSVolumesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnencryptedEBSVolumes - - read - Resource: "*" - ## AWS Unencrypted RDS Instances - iamPolicyAWSUnencryptedRDSInstancesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnencryptedRDSInstancesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnencryptedRDSInstancesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnencryptedRDSInstances - - read - Resource: "*" - iamPolicyAWSUnencryptedRDSInstancesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnencryptedRDSInstancesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnencryptedRDSInstancesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnencryptedRDSInstances - - action - Resource: "*" - ## AWS Untagged Resources - iamPolicyAWSUntaggedResourcesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUntaggedResourcesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUntaggedResourcesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUntaggedResources - - read - Resource: "*" - iamPolicyAWSUntaggedResourcesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUntaggedResourcesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUntaggedResourcesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUntaggedResources - - action - Resource: "*" - ## AWS Unused Application Load Balancers - iamPolicyAWSUnusedApplicationLoadBalancersRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedApplicationLoadBalancersRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedApplicationLoadBalancersReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedApplicationLoadBalancers - - read - Resource: "*" - iamPolicyAWSUnusedApplicationLoadBalancersAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedApplicationLoadBalancersAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedApplicationLoadBalancersActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedApplicationLoadBalancers - - action - Resource: "*" - ## AWS Unused Classic Load Balancers - iamPolicyAWSUnusedClassicLoadBalancersRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedClassicLoadBalancersRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedClassicLoadBalancersReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedClassicLoadBalancers - - read - Resource: "*" - iamPolicyAWSUnusedClassicLoadBalancersAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedClassicLoadBalancersAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedClassicLoadBalancersActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedClassicLoadBalancers - - action - Resource: "*" - ## AWS Unused ECS Clusters - iamPolicyAWSUnusedECSClustersRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedECSClustersRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedECSClustersReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedECSClusters - - read - Resource: "*" - iamPolicyAWSUnusedECSClustersAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedECSClustersAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedECSClustersActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedECSClusters - - action - Resource: "*" - ## AWS Unused IAM Credentials - iamPolicyAWSUnusedIAMCredentialsRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedIAMCredentialsRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedIAMCredentialsReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedIAMCredentials - - read - Resource: "*" - ## AWS Unused IP Addresses - iamPolicyAWSUnusedIPAddressesRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedIPAddressesRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedIPAddressesReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedIPAddresses - - read - Resource: "*" - iamPolicyAWSUnusedIPAddressesAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedIPAddressesAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedIPAddressesActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedIPAddresses - - action - Resource: "*" - ## AWS Unused Network Load Balancers - iamPolicyAWSUnusedNetworkLoadBalancersRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedNetworkLoadBalancersRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedNetworkLoadBalancersReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedNetworkLoadBalancers - - read - Resource: "*" - iamPolicyAWSUnusedNetworkLoadBalancersAction: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSUnusedNetworkLoadBalancersAction - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSUnusedNetworkLoadBalancersActionPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSUnusedNetworkLoadBalancers - - action - Resource: "*" - ## AWS VPCs Without FlowLogs Enabled - iamPolicyAWSVPCsWithoutFlowLogsEnabledRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyAWSVPCsWithoutFlowLogsEnabledRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - AWSVPCsWithoutFlowLogsEnabledReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - AWSVPCsWithoutFlowLogsEnabled - - read - Resource: "*" - ## Common Bill Ingestion from AWS S3 Object Storage - iamPolicyCommonBillIngestionfromAWSS3ObjectStorageRead: - Type: "AWS::IAM::Policy" - Condition: CreatePolicyCommonBillIngestionfromAWSS3ObjectStorageRead - Properties: - PolicyName: !Join - - "_" - - - !Ref paramRoleName - - CommonBillIngestionfromAWSS3ObjectStorageReadPermissionPolicy - Roles: - - !Ref iamRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: !FindInMap - - PermissionMap - - CommonBillIngestionfromAWSS3ObjectStorage - - read - Resource: "*" - - # End for each policy template - - # End IAM Permission Policy Resources - -Outputs: - iamRoleArn: - Description: The ARN of the IAM Role that was created - Value: !GetAtt - - iamRole - - Arn From 8c221a837cac4492966867da9c6f419927de19dc Mon Sep 17 00:00:00 2001 From: Shawn Huckabay Date: Fri, 13 Dec 2024 13:48:48 -0600 Subject: [PATCH 23/23] update --- .github/workflows/cfn-test.yaml | 3 +-- tools/cloudformation-template/README.md | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cfn-test.yaml b/.github/workflows/cfn-test.yaml index 450f6ed213..1bd6c82a62 100644 --- a/.github/workflows/cfn-test.yaml +++ b/.github/workflows/cfn-test.yaml @@ -20,9 +20,8 @@ jobs: # matrix.template_files is a list of template files to test template_files: - ./tools/cloudformation-template/FlexeraAutomationPolicies.template + - ./tools/cloudformation-template/FlexeraAutomationPoliciesReadOnly.template - ./tools/cloudformation-template/FlexeraAutomationPoliciesSimple.template - - ./tools/cloudformation-template/rolling/FlexeraAutomationPolicies.template - - ./tools/cloudformation-template/rolling/FlexeraAutomationPoliciesReadOnly.template steps: - name: Checkout uses: actions/checkout@v2 diff --git a/tools/cloudformation-template/README.md b/tools/cloudformation-template/README.md index 6f8276b453..0b7da290a0 100644 --- a/tools/cloudformation-template/README.md +++ b/tools/cloudformation-template/README.md @@ -176,6 +176,6 @@ resource "aws_cloudformation_stack" "FlexeraAutomationAccessRole" { ## For Maintainers -New versions of `tools/cloudformation-template/FlexeraAutomationPolicies.template` are created automatically by the `tools/cloudformation-template/aws_cft_generator.rb` script. This script runs automatically via GitHub Actions whenever a change is made to the master branch. This script uses the permissions file `data/policy_permissions_list/master_policy_permissions_list.json` to obtain the information needed to generate the CloudFormation Template. This file, in turn, is sourced through its [own automation](https://github.com/flexera-public/policy_templates/tree/master/tools/policy_master_permission_generation) that scrapes policy template README files. +New versions of `tools/cloudformation-template/FlexeraAutomationPolicies.template` and `tools/cloudformation-template/FlexeraAutomationPoliciesReadOnly.template` are created automatically by the `tools/cloudformation-template/aws_cft_generator.rb` script. This script runs automatically via GitHub Actions whenever a change is made to the master branch. This script uses the permissions file `data/policy_permissions_list/master_policy_permissions_list.json` to obtain the information needed to generate the CloudFormation Template. This file, in turn, is sourced through its [own automation](https://github.com/flexera-public/policy_templates/tree/master/tools/policy_master_permission_generation) that scrapes policy template README files. -New releases are created automatically by the `tools/cloudformation-template/aws_cft_new_release.rb` script. This script runs daily and checks whether the most recent version has any changes compared to the latest release. If changes are present, a new minor version is created and stored in the `tools/cloudformation-template/releases` directory. +New releases are created automatically by the `tools/cloudformation-template/aws_cft_new_release.rb` script. This script runs daily and checks whether the most recent version of `tools/cloudformation-template/FlexeraAutomationPolicies.template` has any changes compared to the latest release. If changes are present, a new minor version is created and stored in the `tools/cloudformation-template/releases` directory.