View source
<?php
namespace Drupal\monitoring\Plugin\monitoring\SensorPlugin;
use Drupal\Core\Form\FormStateInterface;
use Drupal\monitoring\SensorPlugin\ExtendedInfoSensorPluginInterface;
use Drupal\monitoring\SensorPlugin\SensorPluginBase;
use Drupal\user\Entity\User;
use Drupal\monitoring\Result\SensorResultInterface;
use Drupal\user\Entity\Role;
use Drupal\user\UserInterface;
class UserIntegritySensorPlugin extends SensorPluginBase implements ExtendedInfoSensorPluginInterface {
protected $configurableValueType = FALSE;
protected $listSize = 500;
protected $restrictedPermissions = array();
public function runSensor(SensorResultInterface $sensor_result) {
$role_ids = $this
->getRestrictedRoles();
$current_users = $this
->processUsers($this
->loadCurrentUsers($role_ids));
$sensor_result
->addStatusMessage(count($current_users) . ' privileged user(s)');
$sensor_result
->setStatus(SensorResultInterface::STATUS_OK);
$old_users = \Drupal::keyValue('monitoring.users')
->getAll();
if (empty($old_users)) {
foreach ($current_users as $user) {
\Drupal::keyValue('monitoring.users')
->set($user['id'], $user);
}
}
else {
$new_users = array_diff_key($current_users, $old_users);
if (!empty($new_users)) {
$sensor_result
->setStatus(SensorResultInterface::STATUS_WARNING);
$sensor_result
->addStatusMessage(count($new_users) . ' new user(s)');
}
$count = 0;
$changed_users_ids = array_intersect(array_keys($current_users), array_keys($old_users));
foreach ($changed_users_ids as $changed_user_id) {
$changed = $this
->getUserChanges($current_users[$changed_user_id], $old_users[$changed_user_id]);
if (!empty($changed)) {
$count++;
}
}
if ($count > 0) {
$sensor_result
->addStatusMessage($count . ' changed user(s)');
$sensor_result
->setStatus(SensorResultInterface::STATUS_WARNING);
}
}
$user_register = \Drupal::config('user.settings')
->get('register');
$role_ids_after = array_intersect($role_ids, [
'authenticated',
'anonymous',
]);
$role_labels = [];
foreach (Role::loadMultiple($role_ids_after) as $role) {
$role_labels[$role
->id()] = $role
->label();
}
if (!empty($role_labels)) {
$sensor_result
->addStatusMessage('Privileged access for roles @roles', array(
'@roles' => implode(', ', $role_labels),
));
$sensor_result
->setStatus(SensorResultInterface::STATUS_WARNING);
}
if (in_array('anonymous', $role_ids)) {
$sensor_result
->setStatus(SensorResultInterface::STATUS_CRITICAL);
}
if (in_array('authenticated', $role_ids) && $user_register != UserInterface::REGISTER_ADMINISTRATORS_ONLY) {
$sensor_result
->addStatusMessage('Self registration possible.');
$sensor_result
->setStatus(SensorResultInterface::STATUS_CRITICAL);
}
}
protected function loadCurrentUsers(array $role_ids) {
if (!$role_ids) {
return [];
}
$query = \Drupal::entityQuery('user')
->sort('access', 'DESC')
->range(0, $this->listSize);
if (in_array('authenticated', $role_ids)) {
$uids = $query
->condition('uid', '0', '<>')
->execute();
}
else {
$uids = $query
->condition('roles', $role_ids, 'IN')
->execute();
}
return User::loadMultiple($uids);
}
protected function getUserChanges(array $current_values, array $expected_values) {
$changes = array();
if ($current_values['name'] != $expected_values['name']) {
$changes['name']['expected_value'] = $expected_values['name'];
$changes['name']['current_value'] = $current_values['name'];
}
if ($current_values['mail'] != $expected_values['mail']) {
$changes['mail']['expected_value'] = $expected_values['mail'];
$changes['mail']['current_value'] = $current_values['mail'];
}
if ($current_values['password'] != $expected_values['password']) {
$changes['password']['expected_value'] = '';
$changes['password']['current_value'] = t('Password changed');
}
return $changes;
}
protected function getRestrictedRoles() {
$permission_handler = \Drupal::service('user.permissions');
$available_permissions = $permission_handler
->getPermissions();
$this->restrictedPermissions = array();
foreach ($available_permissions as $key => $value) {
if (!empty($value['restrict access'])) {
$this->restrictedPermissions[] = $key;
}
}
$avaliable_roles = Role::loadMultiple();
$restricted_roles = array();
foreach ($avaliable_roles as $role) {
$permissions = $role
->getPermissions();
if ($role
->isAdmin() || array_intersect($permissions, $this->restrictedPermissions)) {
$restricted_roles[] = $role
->id();
}
}
return $restricted_roles;
}
protected function processUsers(array $users) {
$processed_users = array();
foreach ($users as $user) {
$id = $user
->id();
$processed_users[$id]['id'] = $id;
$processed_users[$id]['name'] = $user
->getAccountName();
$processed_users[$id]['mail'] = $user
->getEmail();
$processed_users[$id]['password'] = hash('sha256', $user
->getPassword());
$processed_users[$id]['changed'] = $user
->getChangedTime();
$processed_users[$id]['last_accessed'] = $user
->getLastAccessedTime();
$processed_users[$id]['created'] = $user
->getCreatedTime();
$processed_users[$id]['roles'] = implode(", ", $user
->getRoles());
}
return $processed_users;
}
public function resultVerbose(SensorResultInterface $result) {
$output = [];
$expected_users = \Drupal::keyValue('monitoring.users')
->getAll();
$role_ids = $this
->getRestrictedRoles();
$current_users = $this
->processUsers($this
->loadCurrentUsers($role_ids));
$new_users_id = array_diff(array_keys($current_users), array_keys($expected_users));
$deleted_users = array_diff_key($expected_users, $current_users);
$rows = [];
foreach ($new_users_id as $id) {
$time_stamp = $current_users[$id]['created'];
$last_accessed = $current_users[$id]['last_accessed'];
$user_name = [
'data' => [
'#theme' => 'username',
'#account' => User::load($id),
],
];
$rows[] = [
'user' => $user_name,
'roles' => [
'data' => [
'#markup' => $current_users[$id]['roles'],
],
],
'created' => [
'data' => [
'#markup' => \Drupal::service('date.formatter')
->format($time_stamp, 'short'),
],
],
'last_accessed' => [
'data' => [
'#markup' => $last_accessed != 0 ? \Drupal::service('date.formatter')
->format($last_accessed, 'short') : t('never'),
],
],
];
}
if (count($rows) > 0) {
$header = [
'user' => t('User'),
'roles' => t('Roles'),
'created' => t('Created'),
'last_accessed' => t('Last accessed'),
];
$output['new_table'] = [
'#type' => 'verbose_table_result',
'#title' => t('New users with privileged access'),
'#header' => $header,
'#rows' => $rows,
];
}
$rows = [];
$old_user_ids = array_keys($expected_users);
foreach ($old_user_ids as $id) {
$changes = [];
if (isset($current_users[$id])) {
$changes = $this
->getUserChanges($current_users[$id], $expected_users[$id]);
}
foreach ($changes as $key => $value) {
$time_stamp = $current_users[$id]['changed'];
$last_accessed = $current_users[$id]['last_accessed'];
$user_name = [
'data' => [
'#theme' => 'username',
'#account' => User::load($id),
],
];
$rows[] = [
'user' => $user_name,
'field' => [
'data' => [
'#markup' => $key,
],
],
'current_value' => [
'data' => [
'#markup' => $value['current_value'],
],
],
'expected_value' => [
'data' => [
'#markup' => $value['expected_value'],
],
],
'changed' => [
'data' => [
'#markup' => \Drupal::service('date.formatter')
->format($time_stamp, 'short'),
],
],
'last_accessed' => [
'data' => [
'#markup' => $last_accessed != 0 ? \Drupal::service('date.formatter')
->format($last_accessed, 'short') : t('never'),
],
],
];
}
}
if (count($rows) > 0) {
$header = [
'user' => t('User'),
'Field' => t('Field'),
'current_value' => t('Current value'),
'expected_value' => t('Expected value'),
'changed' => t('Changed'),
'last_accessed' => t('Last accessed'),
];
$output['changes_table'] = [
'#type' => 'verbose_table_result',
'#title' => t('Changed users with privileged access'),
'#header' => $header,
'#rows' => $rows,
];
}
$rows = [];
foreach ($current_users as $user) {
$created = $user['created'];
$user_name = [
'data' => [
'#theme' => 'username',
'#account' => User::load($user['id']),
],
];
$rows[] = [
'user' => $user_name,
'roles' => [
'data' => [
'#markup' => $user['roles'],
],
],
'created' => [
'data' => [
'#markup' => \Drupal::service('date.formatter')
->format($created, 'short'),
],
],
'last_accessed' => [
'data' => [
'#markup' => $user['last_accessed'] != 0 ? \Drupal::service('date.formatter')
->format($user['last_accessed'], 'short') : t('never'),
],
],
];
}
if (count($rows) > 0) {
$header = [
'user' => t('User'),
'roles' => t('Roles'),
'created' => t('Created'),
'last_accessed' => t('Last accessed'),
];
$output['users_privileged'] = [
'#type' => 'verbose_table_result',
'#title' => t('All users with privileged access'),
'#header' => $header,
'#rows' => $rows,
];
}
$rows = [];
foreach ($deleted_users as $user) {
$rows[] = [
'user' => [
'data' => [
'#markup' => $user['name'],
],
],
'roles' => [
'data' => [
'#markup' => $user['roles'],
],
],
'created' => [
'data' => [
'#markup' => \Drupal::service('date.formatter')
->format($user['created'], 'short'),
],
],
'last_accessed' => [
'data' => [
'#markup' => $user['last_accessed'] != 0 ? \Drupal::service('date.formatter')
->format($user['last_accessed'], 'short') : t('never'),
],
],
];
}
if (count($rows) > 0) {
$header = [
'user' => t('User'),
'roles' => t('Roles'),
'created' => t('Created'),
'last_accessed' => t('Last accessed'),
];
$output['deleted_users'] = [
'#type' => 'verbose_table_result',
'#title' => t('Deleted users with privileged access'),
'#header' => $header,
'#rows' => $rows,
];
}
$roles_list = [];
foreach (Role::loadMultiple($role_ids) as $role) {
if (!$role
->isAdmin()) {
$restricted_permissions = array_intersect($this->restrictedPermissions, $role
->getPermissions());
$roles_list[] = $role
->label() . ': ' . implode(", ", $restricted_permissions);
}
}
$output['roles_list'] = [
'#type' => 'fieldset',
'#title' => t('List of roles with restricted permissions'),
[
'#type' => 'item',
'#markup' => !empty($roles_list) ? implode('<br>', $roles_list) : t('None'),
],
];
return $output;
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['reset_users'] = array(
'#type' => 'submit',
'#value' => t('Reset user data'),
'#submit' => array(
array(
$this,
'submitConfirmPrivilegedUsers',
),
),
);
return $form;
}
public function submitConfirmPrivilegedUsers(array $form, FormStateInterface $form_state) {
\Drupal::keyValue('monitoring.users')
->deleteAll();
return $form;
}
}