From 57d2e1a027b56b5731ae611648a072a713babb03 Mon Sep 17 00:00:00 2001 From: Devin Lyons Date: Thu, 15 Jun 2023 13:17:10 -0800 Subject: [PATCH 1/4] Add ability to name namespace sensitive objects. --- README.md | 21 +++++++++++++++------ libraries/helpers.rb | 32 ++++++++++++++++++-------------- resources/asset.rb | 1 + resources/check.rb | 1 + resources/entity.rb | 1 + resources/filter.rb | 1 + resources/handler.rb | 1 + resources/hook.rb | 1 + resources/mutator.rb | 1 + resources/role.rb | 1 + resources/role_binding.rb | 1 + resources/search.rb | 1 + resources/secret.rb | 1 + 13 files changed, 44 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e9572446..acfc46be 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,7 @@ The sensu_check resource is used to define check objects. * `interval` The frequency in seconds the check is executed. * `low_flap_threshold` The flap detection low threshold, in percent * `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `check_name` The name to give the check in Sensu, default: *resource id* * `proxy_entity_name` Used to create a proxy entity for an external resource * `proxy_requests` A [Sensu Proxy Request](https://docs.sensu.io/sensu-go/latest/reference/checks/#proxy-requests-attributes), representing Sensu entity attributes to match entities in the registry. * `publish` If check requests are published for the check @@ -338,7 +339,8 @@ end * `filters` an array of Sensu event filter names to use * `handlers` an array of Sensu event handler names to use for events * `mutator` mutator to use to mutate event data for the handler -* `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `namespace` the Sensu RBAC namespace that this handler belongs to, default: *default* +* `handler_name` The name to give the handler in Sensu, default: *resource id* * `runtime_assets` An array of [Sensu assets](https://docs.sensu.io/sensu-go/latest/reference/assets/) required at runtime for the execution of the `command` * `secrets` an array of hashes of name/secret pairs to use with command execution * `socket` the socket definition scope, used to configure the TCP/UDP handler socket @@ -364,7 +366,8 @@ Used to define hooks for sensu checks #### Properties * `command` **required** command to be executed -* `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `namespace` the Sensu RBAC namespace that this filter belongs to, default: *default* +* `hook_name` The name to give the hook in Sensu, default: *resource id* * `timeout` duration timeout in seconds (hard stop) * `stdin` If the Sensu agent writes JSON serialized Sensu entity and check data to the command process’ STDIN. The command must expect the JSON data via STDIN, read it, and close STDIN. This attribute cannot be used with existing Sensu check plugins, nor Nagios plugins etc, as Sensu agent will wait indefinitely for the hook process to read and close STDIN @@ -394,7 +397,8 @@ Used to define filters for sensu checks * `filter_action` **required** action to take with the event if the filter statements match. One of: `allow`, `deny` * `expressions` **required** filter expressions to be compared with event data. -* `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `namespace` the Sensu RBAC namespace that this filter belongs to, default: *default* +* `filter_name` The name to give the filter in Sensu, default: *resource id* * `when` the [when definition scope](https://docs.sensu.io/sensu-go/latest/reference/filters/#when-attributes), used to determine when a filter is applied with time windows #### Examples @@ -425,7 +429,8 @@ A handler can specify a mutator to transform event data. This resource can defin * `command` **required** the command to run * `env_vars` an array of environment variables to use with command execution -* `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `namespace` the Sensu RBAC namespace that this mutator belongs to, default: *default* +* `mutator_name` The name to give the mutator in Sensu, default: *resource id* * `secrets` an array of hashes of name/secret pairs to use with command execution * `timeout` the execution duration timeout in seconds @@ -450,6 +455,7 @@ At runtime the agent can sequentially fetch assets and store them in its local c * `sha512` **required** the checksum of the asset. * `url` **required** the URL location of the asset. * `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `asset_name` The name to give the asset in Sensu, default: *resource id* * `builds` List, defines multiple artifacts that provide the named asset. * `headers` Optional HTTP headers to apply to dynamic runtime asset retrieval @@ -486,7 +492,8 @@ An entity is a representation of anything that needs to be monitored. From Sensu * `entity_class` **required** the entity type, should be either `agent` or `proxy`. * `deregister` Whether or not the entity should be removed from Sensu once the Sensu agent process's keepalive dies. Not needed for proxy entities. * `deregistration` Hash of handlers for use when the entity is deregistered. Not needed for proxy entities. -* `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `namespace` the Sensu RBAC namespace that this entity belongs to, default: *default* +* `entity_name` The name to give the entity in Sensu, default: *resource id* * `redact` List of items to redact from log messages and dashboard. If a value is provided, it overwrites the default list of items to be redacted. * `sensu_agent_version` Version of the agent entity running on the machine. Not needed for proxy entities. * `subscriptions` An array of subscriptions. If no subscriptions are provided, it defaults to an entity-specific subscription list: `[entity:{ID}]`. @@ -707,7 +714,8 @@ Create a secret that Sensu can grab from a secret provider so that sensitive inf #### Properties * `id` **required** The key to use to retrive the secret. For the Env secrets provider, this is the environment variable. For the Vault secrets provider, this is the path and key in the form of `secret/path#key`. Currently, the Vault secrets provider does not support any base engine paths other than "secret/" for v2 K/V secrets engine. -* `namespace` the Sensu RBAC namespace that this check belongs to, default: *default* +* `namespace` the Sensu RBAC namespace that this secret belongs to, default: *default* +* `secret_name` The name to give the secret in Sensu, default: *resource id* * `secrets_provider` **required** Name of the provider, all in lowercase, ex: `'env'`, `'vault'` #### Examples @@ -827,6 +835,7 @@ Create a save search that can be used in the Sensu web interface (commercial fea #### Properties * `namespace` namespace for the save search +* `search_name` The name to give the search in Sensu, default: *resource id* * `parameters` **required** parameters the search will apply * `resource` **required** fully qualified name of the resource diff --git a/libraries/helpers.rb b/libraries/helpers.rb index 8259003c..81596a37 100644 --- a/libraries/helpers.rb +++ b/libraries/helpers.rb @@ -20,11 +20,16 @@ def object_file(plural = true) ::File.join(object_dir(plural), new_resource.name) + '.json' end - def base_resource(new_resource, spec = Mash.new, api_version = 'core/v2') + def base_resource(new_resource, spec = Mash.new, api_version = 'core/v2', override_name = nil) obj = Mash.new meta = Mash.new - meta['name'] = new_resource.name + if override_name == nil + meta['name'] = new_resource.name + else + meta['name'] = override_name + end + meta['labels'] = new_resource.labels if new_resource.labels meta['annotations'] = new_resource.annotations if new_resource.annotations @@ -64,7 +69,7 @@ def check_from_resource spec['output_metric_format'] = new_resource.output_metric_format if new_resource.output_metric_format spec['output_metric_handlers'] = new_resource.output_metric_handlers if new_resource.output_metric_handlers - c = base_resource(new_resource, spec) + c = base_resource(new_resource, spec, override_name = new_resource.check_name) c['metadata']['namespace'] = new_resource.namespace c end @@ -79,8 +84,7 @@ def asset_from_resource spec['builds'] = new_resource.builds end spec['headers'] = new_resource.headers if new_resource.headers - a = base_resource(new_resource, spec) - a['metadata']['namespace'] = new_resource.namespace + a = base_resource(new_resource, spec, override_name = new_resource.asset_name) a end @@ -97,7 +101,7 @@ def handler_from_resource spec['timeout'] = new_resource.timeout if new_resource.timeout spec['type'] = new_resource.type - h = base_resource(new_resource, spec) + h = base_resource(new_resource, spec, override_name = new_resource.handler_name) h['metadata']['namespace'] = new_resource.namespace h end @@ -108,7 +112,7 @@ def hook_from_resource spec['timeout'] = new_resource.timeout if new_resource.timeout spec['stdin'] = new_resource.stdin if new_resource.stdin - h = base_resource(new_resource, spec) + h = base_resource(new_resource, spec, override_name = new_resource.hook_name) h['metadata']['namespace'] = new_resource.namespace h end @@ -120,7 +124,7 @@ def filter_from_resource spec['when'] = new_resource.when if new_resource.when spec['runtime_assets'] = new_resource.runtime_assets if new_resource.runtime_assets - f = base_resource(new_resource, spec) + f = base_resource(new_resource, spec, override_name = new_resource.filter_name) f['type'] = 'Event' + type_from_name f['metadata']['namespace'] = new_resource.namespace f @@ -133,7 +137,7 @@ def mutator_from_resource spec['secrets'] = new_resource.secrets if new_resource.secrets spec['timeout'] = new_resource.timeout if new_resource.timeout - m = base_resource(new_resource, spec) + m = base_resource(new_resource, spec, override_name = new_resource.mutator_name) m['metadata']['namespace'] = new_resource.namespace m end @@ -149,7 +153,7 @@ def entity_from_resource spec['system'] = new_resource.system if new_resource.system spec['user'] = new_resource.user if new_resource.user - e = base_resource(new_resource, spec) + e = base_resource(new_resource, spec, override_name = new_resource.entity_name) e['metadata']['namespace'] = new_resource.namespace e end @@ -166,7 +170,7 @@ def role_from_resource 'rules' => new_resource.rules, } - role = base_resource(new_resource, spec) + role = base_resource(new_resource, spec, override_name = new_resource.role_name) role['metadata']['namespace'] = new_resource.namespace role end @@ -187,7 +191,7 @@ def role_binding_from_resource 'subjects' => new_resource.subjects, } - binding = base_resource(new_resource, spec) + binding = base_resource(new_resource, spec, override_name = new_resource.role_binding_name) binding['metadata']['namespace'] = new_resource.namespace binding end @@ -243,7 +247,7 @@ def secret_from_resource spec = {} spec['id'] = new_resource.id spec['provider'] = new_resource.secrets_provider - secret = base_resource(new_resource, spec, 'secrets/v1') + secret = base_resource(new_resource, spec, 'secrets/v1', override_name = new_resource.secret_name) secret['metadata']['namespace'] = new_resource.namespace secret end @@ -283,7 +287,7 @@ def search_from_resource spec = {} spec['parameters'] = new_resource.parameters spec['resource'] = new_resource.resource - search = base_resource(new_resource, spec, 'searches/v1') + search = base_resource(new_resource, spec, 'searches/v1', override_name = new_resource.search_name) search['metadata']['namespace'] = new_resource.namespace search end diff --git a/resources/asset.rb b/resources/asset.rb index 3665b545..847ef2ad 100644 --- a/resources/asset.rb +++ b/resources/asset.rb @@ -58,6 +58,7 @@ } property :namespace, String, default: 'default' property :headers, Hash, default: {} +property :asset_name, String action_class do include SensuCookbook::Helpers diff --git a/resources/check.rb b/resources/check.rb index 94721ef1..ef9365e3 100644 --- a/resources/check.rb +++ b/resources/check.rb @@ -51,6 +51,7 @@ property :output_metric_format, String property :output_metric_handlers, Array property :namespace, String, default: 'default' +property :check_name, String action_class do include SensuCookbook::Helpers diff --git a/resources/entity.rb b/resources/entity.rb index 68d5a3a5..47869c84 100644 --- a/resources/entity.rb +++ b/resources/entity.rb @@ -42,6 +42,7 @@ property :system, Hash property :user, String property :namespace, String, default: 'default' +property :entity_name, String action :create do directory object_dir do diff --git a/resources/filter.rb b/resources/filter.rb index ad2ae99d..27b2d7a1 100644 --- a/resources/filter.rb +++ b/resources/filter.rb @@ -35,6 +35,7 @@ property :when, Hash property :runtime_assets, Array property :namespace, String, default: 'default' +property :filter_name, String action_class do include SensuCookbook::Helpers diff --git a/resources/handler.rb b/resources/handler.rb index 994d5cce..83bd30a8 100644 --- a/resources/handler.rb +++ b/resources/handler.rb @@ -41,6 +41,7 @@ property :timeout, Integer property :type, String, equal_to: %w(pipe tcp udp set), required: true property :namespace, String, default: 'default' +property :handler_name, String action_class do include SensuCookbook::Helpers diff --git a/resources/hook.rb b/resources/hook.rb index ff74c199..eb22f789 100644 --- a/resources/hook.rb +++ b/resources/hook.rb @@ -33,6 +33,7 @@ property :timeout, Integer property :stdin, [true, false] property :namespace, String, default: 'default' +property :hook_name, String action_class do include SensuCookbook::Helpers diff --git a/resources/mutator.rb b/resources/mutator.rb index 454c7b2f..4b1123b7 100644 --- a/resources/mutator.rb +++ b/resources/mutator.rb @@ -35,6 +35,7 @@ property :secrets, Array property :timeout, Integer property :namespace, String, default: 'default' +property :mutator_name, String action_class do include SensuCookbook::Helpers diff --git a/resources/role.rb b/resources/role.rb index 04eb9235..add5d30c 100644 --- a/resources/role.rb +++ b/resources/role.rb @@ -30,6 +30,7 @@ provides :sensu_role property :namespace, String, default: 'default' +property :role_name, String # rubocop:disable Style/TrailingCommaInHashLiteral property :rules, Array, required: true, callbacks: { 'should be an array of hashes' => lambda do |arry| diff --git a/resources/role_binding.rb b/resources/role_binding.rb index a64c0cf8..3bc5d01b 100644 --- a/resources/role_binding.rb +++ b/resources/role_binding.rb @@ -30,6 +30,7 @@ provides :sensu_role_binding property :namespace, String, default: 'default' +property :role_binding_name, String property :role_name, String, required: true property :role_type, String, required: true, equal_to: %w(Role ClusterRole) # rubocop:disable Style/TrailingCommaInHashLiteral diff --git a/resources/search.rb b/resources/search.rb index 69ceece4..e3978382 100644 --- a/resources/search.rb +++ b/resources/search.rb @@ -30,6 +30,7 @@ provides :sensu_search property :namespace, String, default: 'default' +property :search_name, String property :parameters, Array, required: true, callbacks: { 'List can only contain valid sensu search parameters' => lambda do |arry| arry.all? do |e| diff --git a/resources/secret.rb b/resources/secret.rb index 1ad71851..b0754fd4 100644 --- a/resources/secret.rb +++ b/resources/secret.rb @@ -36,6 +36,7 @@ property :id, String, required: true property :secrets_provider, String, required: true property :namespace, String, default: 'default' +property :secret_name, String action :create do directory object_dir do From 6308801f1353e7604a4effd818ae7c3ee5035d90 Mon Sep 17 00:00:00 2001 From: Devin Lyons Date: Thu, 15 Jun 2023 13:25:29 -0800 Subject: [PATCH 2/4] Update change log. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 980aa94f..26a34897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ This CHANGELOG follows the format located [here](https://github.com/sensu-plugin ## [Unreleased] +### Added + +- Added ability to name namespace-sensitive assets in Sensu (@devinlyons) + ## [1.4.0] - 2020-03-10 ### Fixed From 8328bef05a8da77091c490c5e079f829c89b1645 Mon Sep 17 00:00:00 2001 From: Devin Lyons Date: Thu, 29 Jun 2023 13:58:35 -0800 Subject: [PATCH 3/4] Made delete actions namespace aware. --- resources/asset.rb | 4 ++-- resources/check.rb | 4 ++-- resources/filter.rb | 4 ++-- resources/handler.rb | 4 ++-- resources/hook.rb | 4 ++-- resources/role.rb | 4 ++-- resources/role_binding.rb | 4 ++-- resources/secret.rb | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/resources/asset.rb b/resources/asset.rb index 847ef2ad..38805fae 100644 --- a/resources/asset.rb +++ b/resources/asset.rb @@ -87,10 +87,10 @@ action :update do file object_file do action :delete - notifies :run, "execute[sensuctl asset update #{new_resource.name}]" + notifies :run, "execute[sensuctl asset update #{new_resource.name} --namespace #{new_resource.namespace}]" end - execute "sensuctl asset update #{new_resource.name}" do + execute "sensuctl asset update #{new_resource.name} --namespace #{new_resource.namespace}" do command sensuctl_asset_update_cmd action :nothing end diff --git a/resources/check.rb b/resources/check.rb index ef9365e3..421af790 100644 --- a/resources/check.rb +++ b/resources/check.rb @@ -76,10 +76,10 @@ action :delete do file object_file do action :delete - notifies :run, "execute[sensuctl check delete #{new_resource.name} --skip-confirm]" + notifies :run, "execute[sensuctl check delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm]" end - execute "sensuctl check delete #{new_resource.name} --skip-confirm" do + execute "sensuctl check delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" do action :nothing end end diff --git a/resources/filter.rb b/resources/filter.rb index 27b2d7a1..5c7a27de 100644 --- a/resources/filter.rb +++ b/resources/filter.rb @@ -60,10 +60,10 @@ action :delete do file object_file do action :delete - notifies :run, "execute[sensuctl filter delete #{new_resource.name} --skip-confirm]" + notifies :run, "execute[sensuctl filter delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm]" end - execute "sensuctl filter delete #{new_resource.name} --skip-confirm" do + execute "sensuctl filter delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" do action :nothing end end diff --git a/resources/handler.rb b/resources/handler.rb index 83bd30a8..9fc4eb39 100644 --- a/resources/handler.rb +++ b/resources/handler.rb @@ -66,10 +66,10 @@ action :delete do file object_file do action :delete - notifies :run, "execute[sensuctl handler delete #{new_resource.name} --skip-confirm]" + notifies :run, "execute[sensuctl handler delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm]" end - execute "sensuctl handler delete #{new_resource.name} --skip-confirm" do + execute "sensuctl handler delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" do action :nothing end end diff --git a/resources/hook.rb b/resources/hook.rb index eb22f789..9f41ab51 100644 --- a/resources/hook.rb +++ b/resources/hook.rb @@ -58,10 +58,10 @@ action :delete do file object_file do action :delete - notifies :run, "execute[sensu hook delete #{new_resource.name} --skip-confirm" + notifies :run, "execute[sensu hook delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" end - execute "sensuctl hook delete #{new_resource.name} --skip-confirm" do + execute "sensuctl hook delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" do action :nothing end end diff --git a/resources/role.rb b/resources/role.rb index add5d30c..55754d38 100644 --- a/resources/role.rb +++ b/resources/role.rb @@ -64,10 +64,10 @@ action :delete do file object_file do action :delete - notifies :run, "execute[sensu role delete #{new_resource.name} --skip-confirm" + notifies :run, "execute[sensu role delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" end - execute "sensuctl role delete #{new_resource.name} --skip-confirm" do + execute "sensuctl role delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" do action :nothing end end diff --git a/resources/role_binding.rb b/resources/role_binding.rb index 3bc5d01b..895e613a 100644 --- a/resources/role_binding.rb +++ b/resources/role_binding.rb @@ -66,10 +66,10 @@ action :delete do file object_file do action :delete - notifies :run, "execute[sensu role-binding delete #{new_resource.name} --skip-confirm" + notifies :run, "execute[sensu role-binding delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" end - execute "sensuctl role-binding delete #{new_resource.name} --skip-confirm" do + execute "sensuctl role-binding delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" do action :nothing end end diff --git a/resources/secret.rb b/resources/secret.rb index b0754fd4..77c4eb01 100644 --- a/resources/secret.rb +++ b/resources/secret.rb @@ -57,10 +57,10 @@ action :delete do file object_file do action :delete - notifies :run, "execute[sensuctl secret delete #{new_resource.name} --skip-confirm]" + notifies :run, "execute[sensuctl secret delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm]" end - execute "sensuctl secret delete #{new_resource.name} --skip-confirm" do + execute "sensuctl secret delete #{new_resource.name} --namespace #{new_resource.namespace} --skip-confirm" do action :nothing end end From d13dae15d4430954c0511c31c2409845fd1aa872 Mon Sep 17 00:00:00 2001 From: Devin Lyons Date: Fri, 30 Jun 2023 13:43:36 -0800 Subject: [PATCH 4/4] Save configuration files in a namespace sensitive way. --- libraries/helpers.rb | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/libraries/helpers.rb b/libraries/helpers.rb index 81596a37..b2e9ab68 100644 --- a/libraries/helpers.rb +++ b/libraries/helpers.rb @@ -9,15 +9,29 @@ def type_from_name # Pluralize object directory name def object_dir(plural = true) dirname = new_resource.declared_type.to_s.gsub(/^sensu_/, '') + + base_path = ::File.join(new_resource.config_home, dirname) if plural - ::File.join(new_resource.config_home, dirname) + 's' + base_path += 's' + else + + prop_name = dirname + "_name" + if !new_resource[prop_name].nil? && !new_resource["namespace"].nil? + ::File.join(base_path, new_resource.namespace) else - ::File.join(new_resource.config_home, dirname) + base_path end end def object_file(plural = true) - ::File.join(object_dir(plural), new_resource.name) + '.json' + prop_name = new_resource.declared_type.to_s.gsub(/^sensu_/, '') + '_name' + file_name = new_resource.name + + if !new_resource[prop_name].nil? && !new_resource["namespace"].nil? + file_name = new_resource[prop_name] + end + + ::File.join(object_dir(plural), file_name) + '.json' end def base_resource(new_resource, spec = Mash.new, api_version = 'core/v2', override_name = nil)