Project

General

Profile

Actions

Bug #24547

open

Puppet Configuration Error reports not delivered anymore when Role with hostgroup filtering exists

Added by Oliver Freyermuth over 5 years ago. Updated almost 5 years ago.

Status:
New
Priority:
High
Assignee:
-
Category:
E-Mail
Target version:
-
Difficulty:
Triaged:
Yes
Fixed in Releases:
Found in Releases:

Description

I created a role with the following filter on the ressource "Host":

hostgroup_fullname = Linux/Desktop/Stationary/Ubuntu or hostgroup_fullname = Linux/Desktop/Mobile/Ubuntu

The role is assigned to a group, and the group owns all desktop machines.

After doing so, if an erroneous puppet report from a machine not in those hostgroups arrives (e.g. a "Server"), I see the following in production.log:

2018-08-06T18:02:41 cf3ff439 [app] [I] Started POST "/api/config_reports" for my_puppet_master_ip at 2018-08-06 18:02:41 +0200
2018-08-06T18:02:41 cf3ff439 [app] [I] Processing by Api::V2::ConfigReportsController#create as JSON
2018-08-06T18:02:41 cf3ff439 [app] [I]   Parameters: {"config_report"=>"[FILTERED]", "apiv"=>"v2"}
2018-08-06T18:02:41 cf3ff439 [app] [I] Current user: foreman_api_admin (administrator)
2018-08-06T18:02:42 cf3ff439 [app] [I] Couldn't find Host::Managed with 'id'=176 [WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu')))] (ActiveRecord::RecordNotFound)
2018-08-06T18:02:42 cf3ff439 [app] [I]   Rendering api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout
2018-08-06T18:02:42 cf3ff439 [app] [I]   Rendered api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout (0.9ms)
2018-08-06T18:02:42 cf3ff439 [app] [I] Completed 404 Not Found in 266ms (Views: 2.1ms | ActiveRecord: 139.4ms)

No error report is sent.

Of course, the server with the erroneous report is owned by a different user group which does not have this role assigned.

Actions #1

Updated by Oliver Freyermuth over 5 years ago

Issue persists after upgrade to 1.18.0, with slightly changed log:

2018-08-06T20:59:41 [I|app|e37b8] Processing by Api::V2::ConfigReportsController#create as JSON
2018-08-06T20:59:41 [I|app|e37b8]   Parameters: {"config_report"=>"[FILTERED]", "apiv"=>"v2"}
2018-08-06T20:59:41 [I|app|e37b8] Current user: foreman_api_admin (administrator)
2018-08-06T20:59:41 [I|app|e37b8] Scanning report with: Foreman::PuppetReportScanner
2018-08-06T20:59:42 [I|app|e37b8] Couldn't find Host::Managed with 'id'=177 [WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu')))] (ActiveRecord::RecordNotFound)
2018-08-06T20:59:42 [I|app|e37b8]   Rendering api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout
2018-08-06T20:59:42 [I|app|e37b8]   Rendered api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout (1.5ms)
2018-08-06T20:59:42 [I|app|e37b8] Completed 404 Not Found in 442ms (Views: 4.6ms | ActiveRecord: 234.7ms)

Actions #2

Updated by Oliver Freyermuth over 5 years ago

I've managed to pin it down using debug logs.

The following is needed for reproduction:
- A role with a filter on resource "Host", filtering by Hostgroup, e.g. `hostgroup_fullname = Linux/Desktop/Stationary/Ubuntu`.
In the following log snippet, that role has id 19.
- A usergroup with that role assigned, i.e. they can only "view_hosts" for that hostgroup.
- A user, let's call him/her "A", in that usergroup. In the following log snippet, that user has id "11".
- User "A" having set-up configuration error reports for "my hosts" or "all hosts".
- A second, completely different usergroup with user "B". That usergroup has id "3" in the following example log snippet, and contains users with ids 4 and 5.
- A host "C" owned by "B", and not in the hostgroup which is part of the filter above.

Then the following happens:

2018-08-06T21:35:41 [D|sql|7862b]   Usergroup Load (0.8ms)  SELECT  "usergroups".* FROM "usergroups" WHERE "usergroups"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
2018-08-06T21:35:41 [D|sql|7862b]   Usergroup Load (0.8ms)  SELECT "usergroups".* FROM "usergroups" INNER JOIN "usergroup_members" ON "usergroups"."id" = "usergroup_members"."member_id" WHERE "usergroup_members"."usergroup_id" = $1 AND "usergroup_members"."member_type" = $2 ORDER BY usergroups.name  [["usergroup_id", 3], ["member_type", "Usergroup"]]
2018-08-06T21:35:41 [D|sql|7862b]   User Load (0.9ms)  SELECT "users".* FROM "users" INNER JOIN "usergroup_members" ON "users"."id" = "usergroup_members"."member_id" WHERE "usergroup_members"."usergroup_id" = $1 AND "usergroup_members"."member_type" = $2 ORDER BY firstname  [["usergroup_id", 3], ["member_type", "User"]]
2018-08-06T21:35:41 [D|sql|7862b]   MailNotification Load (0.9ms)  SELECT  "mail_notifications".* FROM "mail_notifications" WHERE "mail_notifications"."name" = $1 ORDER BY mail_notifications.name LIMIT $2  [["name", "config_error_state"], ["LIMIT", 1]]
2018-08-06T21:35:41 [D|sql|7862b]   MailNotification Exists (1.2ms)  SELECT  1 AS one FROM "mail_notifications" INNER JOIN "user_mail_notifications" ON "mail_notifications"."id" = "user_mail_notifications"."mail_notification_id" WHERE "user_mail_notifications"."user_id" = $1 AND "mail_notifications"."id" = $2 LIMIT $3  [["user_id", 5], ["id", 6], ["LIMIT", 1]]
2018-08-06T21:35:41 [D|sql|7862b]   CACHE MailNotification Load (0.0ms)  SELECT  "mail_notifications".* FROM "mail_notifications" WHERE "mail_notifications"."name" = $1 ORDER BY mail_notifications.name LIMIT $2  [["name", "config_error_state"], ["LIMIT", 1]]
2018-08-06T21:35:41 [D|sql|7862b]   MailNotification Exists (0.9ms)  SELECT  1 AS one FROM "mail_notifications" INNER JOIN "user_mail_notifications" ON "mail_notifications"."id" = "user_mail_notifications"."mail_notification_id" WHERE "user_mail_notifications"."user_id" = $1 AND "mail_notifications"."id" = $2 LIMIT $3  [["user_id", 4], ["id", 6], ["LIMIT", 1]]
2018-08-06T21:35:41 [D|sql|7862b]   SQL (1.0ms)  SELECT "mail_notifications"."id" AS t0_r0, "mail_notifications"."name" AS t0_r1, "mail_notifications"."description" AS t0_r2, "mail_notifications"."mailer" AS t0_r3, "mail_notifications"."method" AS t0_r4, "mail_notifications"."subscriptable" AS t0_r5, "mail_notifications"."default_interval" AS t0_r6, "mail_notifications"."created_at" AS t0_r7, "mail_notifications"."updated_at" AS t0_r8, "mail_notifications"."subscription_type" AS t0_r9, "mail_notifications"."queryable" AS t0_r10, "mail_notifications"."type" AS t0_r11, "user_mail_notifications"."id" AS t1_r0, "user_mail_notifications"."user_id" AS t1_r1, "user_mail_notifications"."mail_notification_id" AS t1_r2, "user_mail_notifications"."last_sent" AS t1_r3, "user_mail_notifications"."interval" AS t1_r4, "user_mail_notifications"."created_at" AS t1_r5, "user_mail_notifications"."updated_at" AS t1_r6, "user_mail_notifications"."mail_query" AS t1_r7 FROM "mail_notifications" LEFT OUTER JOIN "user_mail_notifications" ON "user_mail_notifications"."mail_notification_id" = "mail_notifications"."id" WHERE "mail_notifications"."type" IN ('ConfigManagementError') AND "user_mail_notifications"."interval" = $1 ORDER BY mail_notifications.name  [["interval", "Subscribe to all hosts"]]
2018-08-06T21:35:41 [D|sql|7862b]   User Load (0.9ms)  SELECT "users".* FROM "users" INNER JOIN "user_mail_notifications" ON "users"."id" = "user_mail_notifications"."user_id" WHERE "user_mail_notifications"."mail_notification_id" = $1 ORDER BY firstname  [["mail_notification_id", 6]]
2018-08-06T21:35:41 [D|sql|7862b]   Usergroup Load (1.1ms)  SELECT "usergroups".* FROM "usergroups" INNER JOIN "cached_usergroup_members" ON "usergroups"."id" = "cached_usergroup_members"."usergroup_id" WHERE "cached_usergroup_members"."user_id" = $1 ORDER BY usergroups.name  [["user_id", 11]]
2018-08-06T21:35:41 [D|per|7862b] checking permission view_hosts for class Host::Managed
2018-08-06T21:35:41 [D|sql|7862b]   Filter Load (3.0ms)  SELECT "filters".* FROM "filters" INNER JOIN "filterings" ON "filterings"."filter_id" = "filters"."id" INNER JOIN "permissions" ON "permissions"."id" = "filterings"."permission_id" INNER JOIN "roles" ON "filters"."role_id" = "roles"."id" INNER JOIN "cached_user_roles" ON "roles"."id" = "cached_user_roles"."role_id" WHERE "cached_user_roles"."user_id" = $1 AND (permissions.resource_type = 'Host') AND (permissions.name = 'view_hosts')  [["user_id", 11]]
2018-08-06T21:35:41 [D|per|7862b] filter with role_id: 19 limited: true search: hostgroup_fullname = Linux/Desktop/Stationary/Ubuntu or hostgroup_fullname = Linux/Desktop/Mobile/Ubuntu taxonomy_search: 
2018-08-06T21:35:41 [D|sql|7862b]   SQL (2.4ms)  SELECT  "hosts"."id" AS t0_r0, "hosts"."name" AS t0_r1, "hosts"."last_compile" AS t0_r2, "hosts"."last_report" AS t0_r3, "hosts"."updated_at" AS t0_r4, "hosts"."created_at" AS t0_r5, "hosts"."root_pass" AS t0_r6, "hosts"."architecture_id" AS t0_r7, "hosts"."operatingsystem_id" AS t0_r8, "hosts"."environment_id" AS t0_r9, "hosts"."ptable_id" AS t0_r10, "hosts"."medium_id" AS t0_r11, "hosts"."build" AS t0_r12, "hosts"."comment" AS t0_r13, "hosts"."disk" AS t0_r14, "hosts"."installed_at" AS t0_r15, "hosts"."model_id" AS t0_r16, "hosts"."hostgroup_id" AS t0_r17, "hosts"."owner_id" AS t0_r18, "hosts"."owner_type" AS t0_r19, "hosts"."enabled" AS t0_r20, "hosts"."puppet_ca_proxy_id" AS t0_r21, "hosts"."managed" AS t0_r22, "hosts"."use_image" AS t0_r23, "hosts"."image_file" AS t0_r24, "hosts"."uuid" AS t0_r25, "hosts"."compute_resource_id" AS t0_r26, "hosts"."puppet_proxy_id" AS t0_r27, "hosts"."certname" AS t0_r28, "hosts"."image_id" AS t0_r29, "hosts"."organization_id" AS t0_r30, "hosts"."location_id" AS t0_r31, "hosts"."type" AS t0_r32, "hosts"."otp" AS t0_r33, "hosts"."realm_id" AS t0_r34, "hosts"."compute_profile_id" AS t0_r35, "hosts"."provision_method" AS t0_r36, "hosts"."grub_pass" AS t0_r37, "hosts"."global_status" AS t0_r38, "hosts"."lookup_value_matcher" AS t0_r39, "hosts"."pxe_loader" AS t0_r40, "hosts"."discovery_rule_id" AS t0_r41, "hostgroups"."id" AS t1_r0, "hostgroups"."name" AS t1_r1, "hostgroups"."created_at" AS t1_r2, "hostgroups"."updated_at" AS t1_r3, "hostgroups"."environment_id" AS t1_r4, "hostgroups"."operatingsystem_id" AS t1_r5, "hostgroups"."architecture_id" AS t1_r6, "hostgroups"."medium_id" AS t1_r7, "hostgroups"."ptable_id" AS t1_r8, "hostgroups"."root_pass" AS t1_r9, "hostgroups"."puppet_ca_proxy_id" AS t1_r10, "hostgroups"."use_image" AS t1_r11, "hostgroups"."image_file" AS t1_r12, "hostgroups"."ancestry" AS t1_r13, "hostgroups"."vm_defaults" AS t1_r14, "hostgroups"."subnet_id" AS t1_r15, "hostgroups"."domain_id" AS t1_r16, "hostgroups"."puppet_proxy_id" AS t1_r17, "hostgroups"."title" AS t1_r18, "hostgroups"."realm_id" AS t1_r19, "hostgroups"."compute_profile_id" AS t1_r20, "hostgroups"."grub_pass" AS t1_r21, "hostgroups"."lookup_value_matcher" AS t1_r22, "hostgroups"."subnet6_id" AS t1_r23, "hostgroups"."pxe_loader" AS t1_r24, "hostgroups"."description" AS t1_r25, "hostgroups"."compute_resource_id" AS t1_r26 FROM "hosts" LEFT OUTER JOIN "hostgroups" ON "hostgroups"."id" = "hosts"."hostgroup_id" WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu'))) AND "hosts"."id" = $1 LIMIT $2  [["id", 177], ["LIMIT", 1]]
2018-08-06T21:35:41 [I|app|7862b] Couldn't find Host::Managed with 'id'=177 [WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu')))] (ActiveRecord::RecordNotFound)
2018-08-06T21:35:41 [I|app|7862b]   Rendering api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout
2018-08-06T21:35:41 [I|app|7862b]   Rendered api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout (1.6ms)

I.e.: Some users not amongst the host owners are thrown into the "to be notified" list, and then the filtering rules for those users are applied, and we get "RecordNotFound".

Actions #3

Updated by Oliver Freyermuth over 5 years ago

I wondered why it fails both if the user "A" has set-up configuration error reports for "my hosts" or "all hosts".

Checking app/services/report_importer.rb and modifying "notify_on_report_error" to contain:

      owners = host.owner.present? ? host.owner.recipients_for(:config_error_state) : []
      users = ConfigManagementError.all_hosts.flat_map(&:users)
      logger.info "considering subscribers to be #{users.map(&:login).join(',')}" 

The logger-info message outputs all users which either have subscribed to "all hosts", or subscribed to "my hosts".
Seems like there's a bug hidden somewhere, maybe it can be understood from the debug logs in the previous comment with more ruby knowledge.

Actions #4

Updated by Oliver Freyermuth over 5 years ago

So in total, I think there are at least two bugs in app/services/report_importer => notify_on_report_error.

1) The following code somehow collects both ALL users subscribed to "all hosts" and to "my hosts".
Since that is done independent of the host, that's wrong.

users = ConfigManagementError.all_hosts.flat_map(&:users)

2) The following code appears to fail if any of the users is not authorized (view_hosts), so finally, no user is notified.

users.select { |user| Host.authorized_as(user, :view_hosts).find(host.id).present? }

Actions #5

Updated by Oliver Freyermuth over 5 years ago

  • Category set to Notifications
  • Found in Releases 1.18.0 added
Actions #6

Updated by Tomer Brisker over 5 years ago

  • Category changed from Notifications to Users, Roles and Permissions
  • Target version set to 1.18.2
  • Triaged changed from No to Yes
Actions #7

Updated by Tomer Brisker over 5 years ago

  • Category changed from Users, Roles and Permissions to Notifications
Actions #8

Updated by Tomer Brisker over 5 years ago

  • Category changed from Notifications to E-Mail
  • Target version deleted (1.18.2)
Actions #9

Updated by Oliver Freyermuth over 5 years ago

I see that the "targeted" version has been removed - and recently, 1.20 was released.
Is this bug still on somebody's radar?

Actions #10

Updated by Oliver Freyermuth over 5 years ago

  • Found in Releases 1.18.1, 1.18.2, 1.18.3 added

Added additional, tested releases.
Seem all still broken :-(.

Actions #11

Updated by Marek Hulán over 5 years ago

I'm trying to think of why

users.select { |user| Host.authorized_as(user, :view_hosts).find(host.id).present? }

would fail if at least one user is not authorized. This should collect those users who are authrorized to view the given host. Could you try replacing with

users.select { |user| user.can?(:view_hosts, host) }

Another idea is, trying

users.select { |user| Host.authorized_as(user, :view_hosts, Host).find(host.id).present? }

since this resource uses STI.

Actions #12

Updated by Oliver Freyermuth over 5 years ago

I'm not the Ruby expert, but here's what I get.
I've modified the code as follows:

      owners = host.owner.present? ? host.owner.recipients_for(:config_error_state) : []
      logger.debug "found owners #{owners.map(&:login).join(',')}" 
      users = ConfigManagementError.all_hosts.flat_map(&:users)
      logger.debug "found users_all #{users.map(&:login).join(',')}" 
      #users.select { |user| Host.authorized_as(user, :view_hosts).find(host.id).present? }
      users.select { |user| user.can?(:view_hosts, host) }
      #users.select { |user| Host.authorized_as(user, :view_hosts, Host).find(host.id).present? }
      logger.debug "found users #{users.map(&:login).join(',')}" 

i.e. we will always get extra debug output for "owners", "users_all" and the filtered users "found users").

For vanilla:

users.select { |user| Host.authorized_as(user, :view_hosts).find(host.id).present? }

I get:
2018-12-22T17:56:42 [D|app|42e64] found owners
2018-12-22T17:56:42 [D|sql|42e64]   SQL (5.1ms)  SELECT "mail_notifications"."id" AS t0_r0, "mail_notifications"."name" AS t0_r1, "mail_notifications"."description" AS t0_r2, "mail_notifications"."mailer" AS t0_r3, "mail_notifications"."method" AS t0_r4, "mail_notifications"."subscriptable" AS t0_r5, "mail_notifications"."default_interval" AS t0_r6, "mail_notifications"."created_at" AS t0_r7, "mail_notifications"."updated_at" AS t0_r8, "mail_notifications"."subscription_type" AS t0_r9, "mail_notifications"."queryable" AS t0_r10, "mail_notifications"."type" AS t0_r11, "user_mail_notifications"."id" AS t1_r0, "user_mail_notifications"."user_id" AS t1_r1, "user_mail_notifications"."mail_notification_id" AS t1_r2, "user_mail_notifications"."last_sent" AS t1_r3, "user_mail_notifications"."interval" AS t1_r4, "user_mail_notifications"."created_at" AS t1_r5, "user_mail_notifications"."updated_at" AS t1_r6, "user_mail_notifications"."mail_query" AS t1_r7 FROM "mail_notifications" LEFT OUTER JOIN "user_mail_notifications" ON "user_mail_notifications"."mail_notification_id" = "mail_notifications"."id" WHERE "mail_notifications"."type" IN ('ConfigManagementError') AND "user_mail_notifications"."interval" = $1 ORDER BY mail_notifications.name  [["interval", "Subscribe to all hosts"]]
2018-12-22T17:56:42 [D|sql|42e64]   User Load (1.1ms)  SELECT "users".* FROM "users" INNER JOIN "user_mail_notifications" ON "users"."id" = "user_mail_notifications"."user_id" WHERE "user_mail_notifications"."mail_notification_id" = $1 ORDER BY firstname  [["mail_notification_id", 6]]
2018-12-22T17:56:42 [D|app|42e64] found users_all admin1,admin2,testuser2
2018-12-22T17:56:42 [D|sql|42e64]   Host::Managed Load (4.7ms)  SELECT  "hosts".* FROM "hosts" WHERE "hosts"."type" IN ('Host::Managed') AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:56:42 [D|sql|42e64]   CACHE Host::Managed Load (0.1ms)  SELECT  "hosts".* FROM "hosts" WHERE "hosts"."type" IN ('Host::Managed') AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:56:42 [D|sql|42e64]   CACHE Host::Managed Load (0.0ms)  SELECT  "hosts".* FROM "hosts" WHERE "hosts"."type" IN ('Host::Managed') AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:56:42 [D|sql|42e64]   Usergroup Load (1.0ms)  SELECT "usergroups".* FROM "usergroups" INNER JOIN "cached_usergroup_members" ON "usergroups"."id" = "cached_usergroup_members"."usergroup_id" WHERE "cached_usergroup_members"."user_id" = $1 ORDER BY usergroups.name  [["user_id", 12]]
2018-12-22T17:56:42 [D|per|42e64] checking permission view_hosts for class Host::Managed
2018-12-22T17:56:42 [D|sql|42e64]   Filter Load (8.2ms)  SELECT "filters".* FROM "filters" INNER JOIN "filterings" ON "filterings"."filter_id" = "filters"."id" INNER JOIN "permissions" ON "permissions"."id" = "filterings"."permission_id" INNER JOIN "roles" ON "filters"."role_id" = "roles"."id" INNER JOIN "cached_user_roles" ON "roles"."id" = "cached_user_roles"."role_id" WHERE "cached_user_roles"."user_id" = $1 AND (permissions.resource_type = 'Host') AND (permissions.name = 'view_hosts')  [["user_id", 12]]
2018-12-22T17:56:42 [D|per|42e64] filter with role_id: 19 limited: true search: hostgroup_fullname = Linux/Desktop/Stationary/Ubuntu or hostgroup_fullname = Linux/Desktop/Mobile/Ubuntu taxonomy_search:
2018-12-22T17:56:42 [D|sql|42e64]   SQL (2.5ms)  SELECT  "hosts"."id" AS t0_r0, "hosts"."name" AS t0_r1, "hosts"."last_compile" AS t0_r2, "hosts"."last_report" AS t0_r3, "hosts"."updated_at" AS t0_r4, "hosts"."created_at" AS t0_r5, "hosts"."root_pass" AS t0_r6, "hosts"."architecture_id" AS t0_r7, "hosts"."operatingsystem_id" AS t0_r8, "hosts"."environment_id" AS t0_r9, "hosts"."ptable_id" AS t0_r10, "hosts"."medium_id" AS t0_r11, "hosts"."build" AS t0_r12, "hosts"."comment" AS t0_r13, "hosts"."disk" AS t0_r14, "hosts"."installed_at" AS t0_r15, "hosts"."model_id" AS t0_r16, "hosts"."hostgroup_id" AS t0_r17, "hosts"."owner_id" AS t0_r18, "hosts"."owner_type" AS t0_r19, "hosts"."enabled" AS t0_r20, "hosts"."puppet_ca_proxy_id" AS t0_r21, "hosts"."managed" AS t0_r22, "hosts"."use_image" AS t0_r23, "hosts"."image_file" AS t0_r24, "hosts"."uuid" AS t0_r25, "hosts"."compute_resource_id" AS t0_r26, "hosts"."puppet_proxy_id" AS t0_r27, "hosts"."certname" AS t0_r28, "hosts"."image_id" AS t0_r29, "hosts"."organization_id" AS t0_r30, "hosts"."location_id" AS t0_r31, "hosts"."type" AS t0_r32, "hosts"."otp" AS t0_r33, "hosts"."realm_id" AS t0_r34, "hosts"."compute_profile_id" AS t0_r35, "hosts"."provision_method" AS t0_r36, "hosts"."grub_pass" AS t0_r37, "hosts"."global_status" AS t0_r38, "hosts"."lookup_value_matcher" AS t0_r39, "hosts"."pxe_loader" AS t0_r40, "hosts"."discovery_rule_id" AS t0_r41, "hostgroups"."id" AS t1_r0, "hostgroups"."name" AS t1_r1, "hostgroups"."created_at" AS t1_r2, "hostgroups"."updated_at" AS t1_r3, "hostgroups"."environment_id" AS t1_r4, "hostgroups"."operatingsystem_id" AS t1_r5, "hostgroups"."architecture_id" AS t1_r6, "hostgroups"."medium_id" AS t1_r7, "hostgroups"."ptable_id" AS t1_r8, "hostgroups"."root_pass" AS t1_r9, "hostgroups"."puppet_ca_proxy_id" AS t1_r10, "hostgroups"."use_image" AS t1_r11, "hostgroups"."image_file" AS t1_r12, "hostgroups"."ancestry" AS t1_r13, "hostgroups"."vm_defaults" AS t1_r14, "hostgroups"."subnet_id" AS t1_r15, "hostgroups"."domain_id" AS t1_r16, "hostgroups"."puppet_proxy_id" AS t1_r17, "hostgroups"."title" AS t1_r18, "hostgroups"."realm_id" AS t1_r19, "hostgroups"."compute_profile_id" AS t1_r20, "hostgroups"."grub_pass" AS t1_r21, "hostgroups"."lookup_value_matcher" AS t1_r22, "hostgroups"."subnet6_id" AS t1_r23, "hostgroups"."pxe_loader" AS t1_r24, "hostgroups"."description" AS t1_r25, "hostgroups"."compute_resource_id" AS t1_r26 FROM "hosts" LEFT OUTER JOIN "hostgroups" ON "hostgroups"."id" = "hosts"."hostgroup_id" WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu'))) AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:56:42 [I|app|42e64] Couldn't find Host::Managed with 'id'=94 [WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu')))] (ActiveRecord::RecordNotFound)
2018-12-22T17:56:42 [I|app|42e64]   Rendering api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout
2018-12-22T17:56:42 [I|app|42e64]   Rendered api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout (1.2ms)
2018-12-22T17:56:42 [I|app|42e64] Completed 404 Not Found in 940ms (Views: 4.3ms | ActiveRecord: 484.2ms)

Note that testuser2 has no permission to view_hosts for the host. So he is found with the first query (since that person has subscribed to notifications for all hosts).
My understanding why:
users.select { |user| Host.authorized_as(user, :view_hosts).find(host.id).present? }

fails is that:
Host.authorized_as(user, :view_hosts)

yields no result when stumbling across the unauthorized user and subsequently "find(host.id)" fails since it is called upon an empty recordset, then the whole thing blows up and a 404 is shown. That appears to be what the debug information above suggests, and matches observation.

Trying out:

users.select { |user| user.can?(:view_hosts, host) }

yields the following:
2018-12-22T17:59:23 [D|app|67c6e] found owners
2018-12-22T17:59:23 [D|sql|67c6e]   SQL (1.4ms)  SELECT "mail_notifications"."id" AS t0_r0, "mail_notifications"."name" AS t0_r1, "mail_notifications"."description" AS t0_r2, "mail_notifications"."mailer" AS t0_r3, "mail_notifications"."method" AS t0_r4, "mail_notifications"."subscriptable" AS t0_r5, "mail_notifications"."default_interval" AS t0_r6, "mail_notifications"."created_at" AS t0_r7, "mail_notifications"."updated_at" AS t0_r8, "mail_notifications"."subscription_type" AS t0_r9, "mail_notifications"."queryable" AS t0_r10, "mail_notifications"."type" AS t0_r11, "user_mail_notifications"."id" AS t1_r0, "user_mail_notifications"."user_id" AS t1_r1, "user_mail_notifications"."mail_notification_id" AS t1_r2, "user_mail_notifications"."last_sent" AS t1_r3, "user_mail_notifications"."interval" AS t1_r4, "user_mail_notifications"."created_at" AS t1_r5, "user_mail_notifications"."updated_at" AS t1_r6, "user_mail_notifications"."mail_query" AS t1_r7 FROM "mail_notifications" LEFT OUTER JOIN "user_mail_notifications" ON "user_mail_notifications"."mail_notification_id" = "mail_notifications"."id" WHERE "mail_notifications"."type" IN ('ConfigManagementError') AND "user_mail_notifications"."interval" = $1 ORDER BY mail_notifications.name  [["interval", "Subscribe to all hosts"]]
2018-12-22T17:59:23 [D|sql|67c6e]   User Load (1.1ms)  SELECT "users".* FROM "users" INNER JOIN "user_mail_notifications" ON "users"."id" = "user_mail_notifications"."user_id" WHERE "user_mail_notifications"."mail_notification_id" = $1 ORDER BY firstname  [["mail_notification_id", 6]]
2018-12-22T17:59:23 [D|app|67c6e] found users_all admin1,admin2,testuser2
2018-12-22T17:59:23 [D|sql|67c6e]   Usergroup Load (1.5ms)  SELECT "usergroups".* FROM "usergroups" INNER JOIN "cached_usergroup_members" ON "usergroups"."id" = "cached_usergroup_members"."usergroup_id" WHERE "cached_usergroup_members"."user_id" = $1 ORDER BY usergroups.name  [["user_id", 12]]
2018-12-22T17:59:23 [D|per|67c6e] checking permission view_hosts for class Host::Managed
2018-12-22T17:59:23 [D|sql|67c6e]   Filter Load (3.4ms)  SELECT "filters".* FROM "filters" INNER JOIN "filterings" ON "filterings"."filter_id" = "filters"."id" INNER JOIN "permissions" ON "permissions"."id" = "filterings"."permission_id" INNER JOIN "roles" ON "filters"."role_id" = "roles"."id" INNER JOIN "cached_user_roles" ON "roles"."id" = "cached_user_roles"."role_id" WHERE "cached_user_roles"."user_id" = $1 AND (permissions.resource_type = 'Host') AND (permissions.name = 'view_hosts')  [["user_id", 12]]
2018-12-22T17:59:23 [D|per|67c6e] filter with role_id: 19 limited: true search: hostgroup_fullname = Linux/Desktop/Stationary/Ubuntu or hostgroup_fullname = Linux/Desktop/Mobile/Ubuntu taxonomy_search:
2018-12-22T17:59:23 [D|sql|67c6e]   SQL (6.4ms)  SELECT "hosts"."id" AS t0_r0, "hosts"."name" AS t0_r1, "hosts"."last_compile" AS t0_r2, "hosts"."last_report" AS t0_r3, "hosts"."updated_at" AS t0_r4, "hosts"."created_at" AS t0_r5, "hosts"."root_pass" AS t0_r6, "hosts"."architecture_id" AS t0_r7, "hosts"."operatingsystem_id" AS t0_r8, "hosts"."environment_id" AS t0_r9, "hosts"."ptable_id" AS t0_r10, "hosts"."medium_id" AS t0_r11, "hosts"."build" AS t0_r12, "hosts"."comment" AS t0_r13, "hosts"."disk" AS t0_r14, "hosts"."installed_at" AS t0_r15, "hosts"."model_id" AS t0_r16, "hosts"."hostgroup_id" AS t0_r17, "hosts"."owner_id" AS t0_r18, "hosts"."owner_type" AS t0_r19, "hosts"."enabled" AS t0_r20, "hosts"."puppet_ca_proxy_id" AS t0_r21, "hosts"."managed" AS t0_r22, "hosts"."use_image" AS t0_r23, "hosts"."image_file" AS t0_r24, "hosts"."uuid" AS t0_r25, "hosts"."compute_resource_id" AS t0_r26, "hosts"."puppet_proxy_id" AS t0_r27, "hosts"."certname" AS t0_r28, "hosts"."image_id" AS t0_r29, "hosts"."organization_id" AS t0_r30, "hosts"."location_id" AS t0_r31, "hosts"."type" AS t0_r32, "hosts"."otp" AS t0_r33, "hosts"."realm_id" AS t0_r34, "hosts"."compute_profile_id" AS t0_r35, "hosts"."provision_method" AS t0_r36, "hosts"."grub_pass" AS t0_r37, "hosts"."global_status" AS t0_r38, "hosts"."lookup_value_matcher" AS t0_r39, "hosts"."pxe_loader" AS t0_r40, "hosts"."discovery_rule_id" AS t0_r41, "hostgroups"."id" AS t1_r0, "hostgroups"."name" AS t1_r1, "hostgroups"."created_at" AS t1_r2, "hostgroups"."updated_at" AS t1_r3, "hostgroups"."environment_id" AS t1_r4, "hostgroups"."operatingsystem_id" AS t1_r5, "hostgroups"."architecture_id" AS t1_r6, "hostgroups"."medium_id" AS t1_r7, "hostgroups"."ptable_id" AS t1_r8, "hostgroups"."root_pass" AS t1_r9, "hostgroups"."puppet_ca_proxy_id" AS t1_r10, "hostgroups"."use_image" AS t1_r11, "hostgroups"."image_file" AS t1_r12, "hostgroups"."ancestry" AS t1_r13, "hostgroups"."vm_defaults" AS t1_r14, "hostgroups"."subnet_id" AS t1_r15, "hostgroups"."domain_id" AS t1_r16, "hostgroups"."puppet_proxy_id" AS t1_r17, "hostgroups"."title" AS t1_r18, "hostgroups"."realm_id" AS t1_r19, "hostgroups"."compute_profile_id" AS t1_r20, "hostgroups"."grub_pass" AS t1_r21, "hostgroups"."lookup_value_matcher" AS t1_r22, "hostgroups"."subnet6_id" AS t1_r23, "hostgroups"."pxe_loader" AS t1_r24, "hostgroups"."description" AS t1_r25, "hostgroups"."compute_resource_id" AS t1_r26 FROM "hosts" LEFT OUTER JOIN "hostgroups" ON "hostgroups"."id" = "hosts"."hostgroup_id" WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu')))
2018-12-22T17:59:23 [D|app|67c6e] found users admin1,admin2,testuser2
2018-12-22T17:59:23 [D|app|67c6e] sending alert to admin1,admin2,testuser2

I don't understand why exactly, but now all users are getting the notification, also testuser2 who does not have view_hosts privilege for the host in question!
The host in question is not in the listed hostgroups.

Now finally, the third version:

users.select { |user| Host.authorized_as(user, :view_hosts, Host).find(host.id).present? }

yields:
2018-12-22T17:53:01 [D|app|b41f8] found owners
2018-12-22T17:53:01 [D|sql|b41f8]   SQL (1.1ms)  SELECT "mail_notifications"."id" AS t0_r0, "mail_notifications"."name" AS t0_r1, "mail_notifications"."description" AS t0_r2, "mail_notifications"."mailer" AS t0_r3, "mail_notifications"."method" AS t0_r4, "mail_notifications"."subscriptable" AS t0_r5, "mail_notifications"."default_interval" AS t0_r6, "mail_notifications"."created_at" AS t0_r7, "mail_notifications"."updated_at" AS t0_r8, "mail_notifications"."subscription_type" AS t0_r9, "mail_notifications"."queryable" AS t0_r10, "mail_notifications"."type" AS t0_r11, "user_mail_notifications"."id" AS t1_r0, "user_mail_notifications"."user_id" AS t1_r1, "user_mail_notifications"."mail_notification_id" AS t1_r2, "user_mail_notifications"."last_sent" AS t1_r3, "user_mail_notifications"."interval" AS t1_r4, "user_mail_notifications"."created_at" AS t1_r5, "user_mail_notifications"."updated_at" AS t1_r6, "user_mail_notifications"."mail_query" AS t1_r7 FROM "mail_notifications" LEFT OUTER JOIN "user_mail_notifications" ON "user_mail_notifications"."mail_notification_id" = "mail_notifications"."id" WHERE "mail_notifications"."type" IN ('ConfigManagementError') AND "user_mail_notifications"."interval" = $1 ORDER BY mail_notifications.name  [["interval", "Subscribe to all hosts"]]
2018-12-22T17:53:01 [D|sql|b41f8]   User Load (1.1ms)  SELECT "users".* FROM "users" INNER JOIN "user_mail_notifications" ON "users"."id" = "user_mail_notifications"."user_id" WHERE "user_mail_notifications"."mail_notification_id" = $1 ORDER BY firstname  [["mail_notification_id", 6]]
2018-12-22T17:53:01 [D|app|b41f8] found users_all admin1,admin2,testuser2
2018-12-22T17:53:01 [D|sql|b41f8]   Host::Managed Load (0.9ms)  SELECT  "hosts".* FROM "hosts" WHERE "hosts"."type" IN ('Host::Managed') AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:53:01 [D|sql|b41f8]   CACHE Host::Managed Load (0.1ms)  SELECT  "hosts".* FROM "hosts" WHERE "hosts"."type" IN ('Host::Managed') AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:53:01 [D|sql|b41f8]   CACHE Host::Managed Load (0.0ms)  SELECT  "hosts".* FROM "hosts" WHERE "hosts"."type" IN ('Host::Managed') AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:53:01 [D|sql|b41f8]   Usergroup Load (0.9ms)  SELECT "usergroups".* FROM "usergroups" INNER JOIN "cached_usergroup_members" ON "usergroups"."id" = "cached_usergroup_members"."usergroup_id" WHERE "cached_usergroup_members"."user_id" = $1 ORDER BY usergroups.name  [["user_id", 12]]
2018-12-22T17:53:01 [D|per|b41f8] checking permission view_hosts for class Host
2018-12-22T17:53:01 [D|sql|b41f8]   Filter Load (3.6ms)  SELECT "filters".* FROM "filters" INNER JOIN "filterings" ON "filterings"."filter_id" = "filters"."id" INNER JOIN "permissions" ON "permissions"."id" = "filterings"."permission_id" INNER JOIN "roles" ON "filters"."role_id" = "roles"."id" INNER JOIN "cached_user_roles" ON "roles"."id" = "cached_user_roles"."role_id" WHERE "cached_user_roles"."user_id" = $1 AND (permissions.resource_type = 'Host') AND (permissions.name = 'view_hosts')  [["user_id", 12]]
2018-12-22T17:53:01 [D|per|b41f8] filter with role_id: 19 limited: true search: hostgroup_fullname = Linux/Desktop/Stationary/Ubuntu or hostgroup_fullname = Linux/Desktop/Mobile/Ubuntu taxonomy_search:
2018-12-22T17:53:01 [D|sql|b41f8]   SQL (2.5ms)  SELECT  "hosts"."id" AS t0_r0, "hosts"."name" AS t0_r1, "hosts"."last_compile" AS t0_r2, "hosts"."last_report" AS t0_r3, "hosts"."updated_at" AS t0_r4, "hosts"."created_at" AS t0_r5, "hosts"."root_pass" AS t0_r6, "hosts"."architecture_id" AS t0_r7, "hosts"."operatingsystem_id" AS t0_r8, "hosts"."environment_id" AS t0_r9, "hosts"."ptable_id" AS t0_r10, "hosts"."medium_id" AS t0_r11, "hosts"."build" AS t0_r12, "hosts"."comment" AS t0_r13, "hosts"."disk" AS t0_r14, "hosts"."installed_at" AS t0_r15, "hosts"."model_id" AS t0_r16, "hosts"."hostgroup_id" AS t0_r17, "hosts"."owner_id" AS t0_r18, "hosts"."owner_type" AS t0_r19, "hosts"."enabled" AS t0_r20, "hosts"."puppet_ca_proxy_id" AS t0_r21, "hosts"."managed" AS t0_r22, "hosts"."use_image" AS t0_r23, "hosts"."image_file" AS t0_r24, "hosts"."uuid" AS t0_r25, "hosts"."compute_resource_id" AS t0_r26, "hosts"."puppet_proxy_id" AS t0_r27, "hosts"."certname" AS t0_r28, "hosts"."image_id" AS t0_r29, "hosts"."organization_id" AS t0_r30, "hosts"."location_id" AS t0_r31, "hosts"."type" AS t0_r32, "hosts"."otp" AS t0_r33, "hosts"."realm_id" AS t0_r34, "hosts"."compute_profile_id" AS t0_r35, "hosts"."provision_method" AS t0_r36, "hosts"."grub_pass" AS t0_r37, "hosts"."global_status" AS t0_r38, "hosts"."lookup_value_matcher" AS t0_r39, "hosts"."pxe_loader" AS t0_r40, "hosts"."discovery_rule_id" AS t0_r41, "hostgroups"."id" AS t1_r0, "hostgroups"."name" AS t1_r1, "hostgroups"."created_at" AS t1_r2, "hostgroups"."updated_at" AS t1_r3, "hostgroups"."environment_id" AS t1_r4, "hostgroups"."operatingsystem_id" AS t1_r5, "hostgroups"."architecture_id" AS t1_r6, "hostgroups"."medium_id" AS t1_r7, "hostgroups"."ptable_id" AS t1_r8, "hostgroups"."root_pass" AS t1_r9, "hostgroups"."puppet_ca_proxy_id" AS t1_r10, "hostgroups"."use_image" AS t1_r11, "hostgroups"."image_file" AS t1_r12, "hostgroups"."ancestry" AS t1_r13, "hostgroups"."vm_defaults" AS t1_r14, "hostgroups"."subnet_id" AS t1_r15, "hostgroups"."domain_id" AS t1_r16, "hostgroups"."puppet_proxy_id" AS t1_r17, "hostgroups"."title" AS t1_r18, "hostgroups"."realm_id" AS t1_r19, "hostgroups"."compute_profile_id" AS t1_r20, "hostgroups"."grub_pass" AS t1_r21, "hostgroups"."lookup_value_matcher" AS t1_r22, "hostgroups"."subnet6_id" AS t1_r23, "hostgroups"."pxe_loader" AS t1_r24, "hostgroups"."description" AS t1_r25, "hostgroups"."compute_resource_id" AS t1_r26 FROM "hosts" LEFT OUTER JOIN "hostgroups" ON "hostgroups"."id" = "hosts"."hostgroup_id" WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu'))) AND "hosts"."id" = $1 LIMIT $2  [["id", 94], ["LIMIT", 1]]
2018-12-22T17:53:01 [I|app|b41f8] Couldn't find Host::Managed with 'id'=94 [WHERE "hosts"."type" IN ('Host::Managed') AND ((("hostgroups"."title" = 'Linux/Desktop/Stationary/Ubuntu') OR ("hostgroups"."title" = 'Linux/Desktop/Mobile/Ubuntu')))] (ActiveRecord::RecordNotFound)
2018-12-22T17:53:01 [I|app|b41f8]   Rendering api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout
2018-12-22T17:53:01 [I|app|b41f8]   Rendered api/v2/errors/not_found.json.rabl within api/v2/layouts/error_layout (2.4ms)
2018-12-22T17:53:01 [I|app|b41f8] Completed 404 Not Found in 655ms (Views: 6.6ms | ActiveRecord: 271.0ms)

That looks very similar to the "vanilla" version.

Cheers and hope that helps,
Oliver

Actions #13

Updated by Oliver Freyermuth almost 5 years ago

  • Found in Releases 1.21.2 added

Sorry to bump this, but since the new year has arrived...
Any update on this from someone more experienced in Ruby than I am?
I still see this in 1.21.2.

Actions

Also available in: Atom PDF