5 * Contains \Drupal\security_review\SecurityReview.
8 namespace Drupal\security_review;
10 use Drupal\Core\Config\ConfigFactoryInterface;
11 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
12 use Drupal\Core\Extension\ModuleHandlerInterface;
13 use Drupal\Core\Logger\RfcLogLevel;
14 use Drupal\Core\Session\AccountProxyInterface;
15 use Drupal\Core\State\StateInterface;
18 * A class containing static methods regarding the module's configuration.
20 class SecurityReview {
22 use DependencySerializationTrait;
25 * Temporary logging setting.
29 protected static $temporaryLogging = NULL;
34 * @var \Drupal\Core\Config\ConfigFactoryInterface
36 protected $configFactory;
41 * @var \Drupal\Core\Config\Config
48 * @var \Drupal\Core\State\StateInterface
55 * @var \Drupal\Core\Extension\ModuleHandlerInterface
57 protected $moduleHandler;
62 * @var \Drupal\Core\Session\AccountProxyInterface
64 protected $currentUser;
67 * Constructs a SecurityReview instance.
69 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
71 * @param \Drupal\Core\State\StateInterface $state
73 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
75 * @param \Drupal\Core\Session\AccountProxyInterface $current_user
78 public function __construct(ConfigFactoryInterface $config_factory, StateInterface $state, ModuleHandlerInterface $module_handler, AccountProxyInterface $current_user) {
79 // Store the dependencies.
80 $this->configFactory = $config_factory;
81 $this->config = $config_factory->getEditable('security_review.settings');
82 $this->state = $state;
83 $this->moduleHandler = $module_handler;
84 $this->currentUser = $current_user;
88 * Returns whether the module has been configured.
90 * If the module has been configured on the settings page this function
91 * returns true. Otherwise it returns false.
94 * A boolean indicating whether the module has been configured.
96 public function isConfigured() {
97 return $this->config->get('configured') === TRUE;
101 * Returns true if logging is enabled, otherwise returns false.
104 * A boolean indicating whether logging is enabled.
106 public function isLogging() {
107 // Check for temporary logging.
108 if (static::$temporaryLogging !== NULL) {
109 return static::$temporaryLogging;
112 return $this->config->get('log') === TRUE;
116 * Returns the last time Security Review has been run.
119 * The last time Security Review has been run.
121 public function getLastRun() {
122 return $this->config->get('last_run');
126 * Returns the IDs of the stored untrusted roles.
129 * Stored untrusted roles' IDs.
131 public function getUntrustedRoles() {
132 return $this->config->get('untrusted_roles');
136 * Sets the 'configured' flag.
138 * @param bool $configured
139 * The new value of the 'configured' setting.
141 public function setConfigured($configured) {
142 $this->config->set('configured', $configured);
143 $this->config->save();
147 * Sets the 'logging' flag.
149 * @param bool $logging
150 * The new value of the 'logging' setting.
151 * @param bool $temporary
152 * Whether to set only temporarily.
154 public function setLogging($logging, $temporary = FALSE) {
156 $this->config->set('log', $logging);
157 $this->config->save();
160 static::$temporaryLogging = ($logging == TRUE);
165 * Sets the 'last_run' value.
167 * @param int $last_run
168 * The new value for 'last_run'.
170 public function setLastRun($last_run) {
171 $this->config->set('last_run', $last_run);
172 $this->config->save();
176 * Stores the given 'untrusted_roles' setting.
178 * @param string[] $untrusted_roles
179 * The new untrusted roles' IDs.
181 public function setUntrustedRoles(array $untrusted_roles) {
182 $this->config->set('untrusted_roles', $untrusted_roles);
183 $this->config->save();
189 * @param \Drupal\security_review\Check $check
190 * The Check the message is about.
191 * @param string $message
193 * @param array $context
194 * The context of the message.
196 * Severity (RfcLogLevel).
198 public function log(Check $check, $message, array $context, $level) {
199 if (static::isLogging()) {
200 $this->moduleHandler->invokeAll(
201 'security_review_log',
204 'message' => $message,
205 'context' => $context,
213 * Logs a check result.
215 * @param \Drupal\security_review\CheckResult $result
218 public function logCheckResult(CheckResult $result = NULL) {
219 if ($this->isLogging()) {
220 if ($result == NULL) {
221 $check = $result->check();
223 '@check' => $check->getTitle(),
224 '@namespace' => $check->getNamespace(),
226 $this->log($check, '@check of @namespace produced a null result', $context, RfcLogLevel::CRITICAL);
230 $check = $result->check();
232 // Fallback log message.
233 $level = RfcLogLevel::NOTICE;
234 $message = '@name check invalid result';
236 // Set log message and level according to result.
237 switch ($result->result()) {
238 case CheckResult::SUCCESS:
239 $level = RfcLogLevel::INFO;
240 $message = '@name check succeeded';
243 case CheckResult::FAIL:
244 $level = RfcLogLevel::ERROR;
245 $message = '@name check failed';
248 case CheckResult::WARN:
249 $level = RfcLogLevel::WARNING;
250 $message = '@name check raised a warning';
253 case CheckResult::INFO:
254 $level = RfcLogLevel::INFO;
255 $message = '@name check returned info';
259 $context = ['@name' => $check->getTitle()];
260 $this->log($check, $message, $context, $level);
265 * Deletes orphaned check data.
267 public function cleanStorage() {
268 /** @var \Drupal\security_review\Checklist $checklist */
269 $checklist = \Drupal::service('security_review.checklist');
271 // Get list of check configuration names.
272 $orphaned = $this->configFactory->listAll('security_review.check.');
274 // Remove items that are used by the checks.
275 foreach ($checklist->getChecks() as $check) {
276 $key = array_search('security_review.check.' . $check->id(), $orphaned);
277 if ($key !== FALSE) {
278 unset($orphaned[$key]);
282 // Delete orphaned configuration data.
283 foreach ($orphaned as $config_name) {
284 $config = $this->configFactory->getEditable($config_name);
290 * Stores information about the server into the State system.
292 public function setServerData() {
293 if (!static::isServerPosix() || PHP_SAPI === 'cli') {
296 // Determine web server's uid and groups.
297 $uid = posix_getuid();
298 $groups = posix_getgroups();
300 // Store the data in the State system.
301 $this->state->set('security_review.server.uid', $uid);
302 $this->state->set('security_review.server.groups', $groups);
306 * Returns whether the server is POSIX.
309 * Whether the web server is POSIX based.
311 public function isServerPosix() {
312 return function_exists('posix_getuid');
316 * Returns the UID of the web server.
319 * UID of the web server's user.
321 public function getServerUid() {
322 return $this->state->get('security_review.server.uid');
326 * Returns the GIDs of the web server.
329 * GIDs of the web server's user.
331 public function getServerGids() {
332 return $this->state->get('security_review.server.groups');