Problem/Motivation

We have a sensor that checks users with higher privileges.

Assigning the higher privileges to the roles anonymous or authenticated also is a problem.

Proposed resolution

Check the roles and if any permission with "restrict access" is assigned. If so, escalate:
- warn for authenticated users, if registration is admin only
- critical for authenticated users, if they can register on their own
- critical for anonymous users

AddMessage for the cases to explain the reason.

User interface changes

The existing sensors have extra reasons to escalate to critical and warning.

Comments

miro_dietiker created an issue. See original summary.

giancarlosotelo’s picture

Status: Active » Needs review
StatusFileSize
new4.41 KB

First patch. I am checking the roles and permission to show a message. I also added test and modify some of them because of the changes in the sensor.

Status: Needs review » Needs work

The last submitted patch, 2: check_user_privileges-2577187-2.patch, failed testing.

The last submitted patch, 2: check_user_privileges-2577187-2.patch, failed testing.

miro_dietiker’s picture

Good progress, but some aspects have been misunderstood.

  1. +++ b/src/Plugin/monitoring/SensorPlugin/UserIntegritySensorPlugin.php
    @@ -74,6 +74,18 @@ class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfo
    +      if ($role->id() != 'anonymous' && !$role->hasPermission('administer account settings')) {
    +        $sensor_result->addStatusMessage($role->label() . ' has privileged access but not for registration');
    ...
    +      elseif (!$role->isAdmin()) {
    +        $sensor_result->addStatusMessage($role->label() . ' has privileged access including registration');
    

    These checks need to be completely refactored. See below.

  2. +++ b/src/Tests/MonitoringCoreWebTest.php
    @@ -155,31 +156,47 @@ class MonitoringCoreWebTest extends MonitoringTestBase {
    +    $this->assertTrue(strpos($result->getMessage(), '1 privileged user(s)') !== FALSE);
    ...
    +    $this->assertTrue(strpos($result->getMessage(), '2 privileged user(s), 1 new user(s)') !== FALSE);
    ...
    +    $this->assertTrue(strpos($result->getMessage(), '2 privileged user(s)') !== FALSE);
    ...
    +    $this->assertTrue(strpos($result->getMessage(), '2 privileged user(s), 1 changed user(s)') !== FALSE);
    ...
    +    $this->assertTrue(strpos($result->getMessage(), '2 privileged user(s)') !== FALSE);
    

    Please assert the whole message with Equal. No partial checks.

  3. +++ b/src/Tests/MonitoringCoreWebTest.php
    @@ -155,31 +156,47 @@ class MonitoringCoreWebTest extends MonitoringTestBase {
    +      'administer account settings',
    

    That's not the point.
    I was referring to the site setting at admin/config/people/accounts:
    Radio "Who can register accounts?"
    A value "visitors" for user_register means they can register... (and possibly have a super privileged user = authenticated)
    We really only want to check the roles authenticated and anonymous. Not all others. Because these permissions a user can gain on his own.
    - as anonymous by just accessing the site and having super power
    - as authenticated by self registering and having super power
    And the third case is just to avoid bad practice to close registration and assign super privileged roles to all (authenticated) users. Thus warn. The admin should create a dedicated role for these cases.

giancarlosotelo’s picture

Status: Needs work » Needs review
StatusFileSize
new5.37 KB
new3.34 KB

Ok I hope this is closer.

Now I am checking the value of the 'user_register' and only for authenticated and anonymous users to set the status and show the message. About tests I am checking the complete message.

While I was working on this I found some problems, but I don't know if they are relevant so I will list them and you can tell me if I should create follow ups.

1. When every user have NO role(yeah its possible), we get a fatal error.
Recoverable fatal error: Argument 1 passed to Drupal\monitoring\Plugin\monitoring\SensorPlugin\UserIntegritySensorPlugin::getUserChanges() must be of the type array, null given....
Because we are loading current users depending on the role. This situation is very strange to happen so I don't know.

2. In the description of the User integrity sensor said: Monitors name and e-mail changes of users with access to restricted permissions.
So I think this is for any user but this only works if the user has an administrator role.

I tested manually with an authenticated user with some restricted permissions and the changes are not showed by the sensor, so should we fix this or is a correct behavior?. And also we are testing this just with admin users thats why is passing?.

3. Now that we are also checking privileges in the sensor, should we change the description of the sensor?

Status: Needs review » Needs work

The last submitted patch, 6: check_user_privileges-2577187-6.patch, failed testing.

Status: Needs work » Needs review
giancarlosotelo’s picture

StatusFileSize
new6.81 KB

Logic changed to fix problem in 2, description updated and better test coverage.

About 1 its not necessary to delete a user to get the fatal error we just have to remove the administrator permission from the admin after run the sensor.

This is going to change some of the logic of the resultVerbose function so maybe is better to create a followup for that.

giancarlosotelo’s picture

StatusFileSize
new6.82 KB

Patch here

Status: Needs review » Needs work

The last submitted patch, 10: check_user_privileges-2577187-9.patch, failed testing.

The last submitted patch, 10: check_user_privileges-2577187-9.patch, failed testing.

miro_dietiker’s picture

From discussion with Sascha, we need to decide if monitoring all (authenticated) users in case of privileged access assigned makes sense. For accidental assignment, this (loading all and managing them) will kill the system. If the main purpose of this sensor is to identify risky accidental assignments, then we failed to reach the goal.

We should
- apply a strict order of authenticated users
- limit them to 500 in loading
- make a separate count query for the numbers (which needs API changes, because counting the array size does not work for this case.)

As a result, both a small set of authenticated users are well monitorable, and we have a meaningful warning if it was accidental in environments with a huge user base.

giancarlosotelo’s picture

Status: Needs work » Needs review
StatusFileSize
new4.7 KB
new10.15 KB
new39.99 KB

Well I order users by last accessed time and limit them to 500. About the separate query its not necessary, we are counting users in the right way.

Then I discussed with @berdir and it was ok without adding the list of authenticated users in the verbose output, its just fine saying the number in the message but I am adding a description in the table and a message if there is no result.

I also added a new column of last accessed time, its necessary?. Attaching a picture of how it looks now.

miro_dietiker’s picture

Status: Needs review » Needs work

Last accessed column shows a "0" if a user never logged in.

You add a title "Table shows new and changed users who have privileged access."
I would shorten that to "New and changed users with privileged access"

And then below add a second table:
"Users with privileged access"
And yeah, list them. :-)

  1. +++ b/src/Plugin/monitoring/SensorPlugin/UserIntegritySensorPlugin.php
    @@ -34,6 +34,13 @@ class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfo
    +  protected $list_size =500;
    

    code style. Please also check the full diff for style again.

  2. +++ b/src/Plugin/monitoring/SensorPlugin/UserIntegritySensorPlugin.php
    @@ -74,6 +81,30 @@ class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfo
    +    $role_ids = array_intersect($role_ids, ['authenticated', 'anonymous']);
    

    Do not overwrite this variable. Pick a new name.

  3. +++ b/src/Plugin/monitoring/SensorPlugin/UserIntegritySensorPlugin.php
    @@ -74,6 +81,30 @@ class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfo
    +    $role_labels = [];
    ...
    +      $role_labels[$role->id()] = $role->label();
    +      $sensor_result->addStatusMessage($role->label() . ' has privileged access');
    

    The idea of creating the $role_labels array here is to add one addStatusMessage statement if the list is !empty() and a comma implode.
    I think the language works best with changing the sentence to
    "Privileged access for roles @roles" and @roles is "Authenticated user", "Anonymous user" or both "Authenticated user, Anonymous user"

  4. +++ b/src/Plugin/monitoring/SensorPlugin/UserIntegritySensorPlugin.php
    @@ -74,6 +81,30 @@ class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfo
    +    if (!empty($role_labels['anonymous'])) {
    ...
    +    if (!empty($role_labels['authenticated']) && $user_register != USER_REGISTER_ADMINISTRATORS_ONLY) {
    

    These checks should stay on the original $rold_ids

  5. +++ b/src/Plugin/monitoring/SensorPlugin/UserIntegritySensorPlugin.php
    @@ -89,9 +120,23 @@ class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfo
    +      ->range(0, $this->list_size);
    

    Add a comment about why we limit here. (See our issue discussion above.)

  6. +++ b/src/Tests/MonitoringCoreWebTest.php
    @@ -180,6 +181,48 @@ class MonitoringCoreWebTest extends MonitoringTestBase {
    +    $this->assertEqual($result->getMessage(), '3 privileged user(s), Anonymous user has privileged access, Authenticated user has privileged access');
    

    As a result of the dumb loop above the message is redundant.
    Monitoring messages should be well crafted and minimalistically right to the point.
    Merge the two sentences as proposed above.
    Also it is plural: anonymous users and authenticated users.

miro_dietiker’s picture

Oh sorry about the feedback you added:

Yeah i also first thought the double dates are redundant, but last access really matters somehow, and change does.

About the discussion with berdir and not listing the users...
Well yeah, if we don't fully agree we could move this discussion into a followup.
But in general, verbose output is pretty OK to be verbose and if the sensor is on WARNING or ERROR and there are no change records, i really want to see relevant verbose information. With aggregator sensors, we display the unaggregated result for investigation. Here, i really think we should list all users that are privileged to have an idea.
Fetching these users through other channels (sql, code) for debugging is complex. We should create awareness.

Now that i think about it, we should even have a separate verbose output item that lists the roles (comma separated) that are considered to be highly privileged.

berdir’s picture

Users I'm not sure. The sensor doesn't care how many you have, just the changes, so that's what we show. As a second table, yes, maybe.

Same for roles, yes, *that* would be very good, with the permissions that are restricted for each.

But both tasks have nothing in common with the original goal of this issue (Various changes already don't ;)). So, lets do separate issues, or we'll iterate forever on this one.

giancarlosotelo’s picture

Status: Needs work » Needs review
StatusFileSize
new5.91 KB
new10.29 KB

Changed to 'Never' if a user never logged in instead of 0.
Addressed all points in #26 and I will create follow ups for the other tasks.

Status: Needs review » Needs work

The last submitted patch, 18: check_user_privileges-2577187-18.patch, failed testing.

giancarlosotelo’s picture

Status: Needs work » Needs review
StatusFileSize
new1.54 KB
new10.27 KB

Changed a bit the logic of last accessed

The last submitted patch, 18: check_user_privileges-2577187-18.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 20: check_user_privileges-2577187-19.patch, failed testing.

The last submitted patch, 20: check_user_privileges-2577187-19.patch, failed testing.

miro_dietiker’s picture

Status: Needs review » Fixed
StatusFileSize
new3.64 KB
+++ b/src/Plugin/monitoring/SensorPlugin/UserIntegritySensorPlugin.php
@@ -74,6 +81,33 @@ class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfo
+      $role_labels[$role->id()] = $role->label() . 's';

We always try to avoid technical character mangling of natural language.
Removed the "s" and committed. :-)

I don't get that error above. It passed green and still indicated some 8 fails?

giancarlosotelo’s picture

Those errors were before the fix on the failing tests #2581697: Test are failing because of recent core changes. but I forgot to retest sorry.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.