3 namespace Drupal\security_review;
5 use Drupal\Core\Config\ConfigFactoryInterface;
6 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
8 use Drupal\Core\Logger\RfcLogLevel;
9 use Drupal\Core\Session\AccountProxyInterface;
10 use Drupal\Core\State\StateInterface;
13 * A class containing static methods regarding the module's configuration.
15 class SecurityReview {
17 use DependencySerializationTrait;
20 * Temporary logging setting.
24 protected static $temporaryLogging = NULL;
29 * @var \Drupal\Core\Config\ConfigFactoryInterface
31 protected $configFactory;
36 * @var \Drupal\Core\Config\Config
43 * @var \Drupal\Core\State\StateInterface
50 * @var \Drupal\Core\Extension\ModuleHandlerInterface
52 protected $moduleHandler;
57 * @var \Drupal\Core\Session\AccountProxyInterface
59 protected $currentUser;
62 * Constructs a SecurityReview instance.
64 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
66 * @param \Drupal\Core\State\StateInterface $state
68 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
70 * @param \Drupal\Core\Session\AccountProxyInterface $current_user
73 public function __construct(ConfigFactoryInterface $config_factory, StateInterface $state, ModuleHandlerInterface $module_handler, AccountProxyInterface $current_user) {
74 // Store the dependencies.
75 $this->configFactory = $config_factory;
76 $this->config = $config_factory->getEditable('security_review.settings');
77 $this->state = $state;
78 $this->moduleHandler = $module_handler;
79 $this->currentUser = $current_user;
83 * Returns whether the module has been configured.
85 * If the module has been configured on the settings page this function
86 * returns true. Otherwise it returns false.
89 * A boolean indicating whether the module has been configured.
91 public function isConfigured() {
92 return $this->config->get('configured') === TRUE;
96 * Returns true if logging is enabled, otherwise returns false.
99 * A boolean indicating whether logging is enabled.
101 public function isLogging() {
102 // Check for temporary logging.
103 if (static::$temporaryLogging !== NULL) {
104 return static::$temporaryLogging;
107 return $this->config->get('log') === TRUE;
111 * Returns the last time Security Review has been run.
114 * The last time Security Review has been run.
116 public function getLastRun() {
117 return $this->state->get('last_run', 0);
121 * Returns the IDs of the stored untrusted roles.
124 * Stored untrusted roles' IDs.
126 public function getUntrustedRoles() {
127 return $this->config->get('untrusted_roles');
131 * Sets the 'configured' flag.
133 * @param bool $configured
134 * The new value of the 'configured' setting.
136 public function setConfigured($configured) {
137 $this->config->set('configured', $configured);
138 $this->config->save();
142 * Sets the 'logging' flag.
144 * @param bool $logging
145 * The new value of the 'logging' setting.
146 * @param bool $temporary
147 * Whether to set only temporarily.
149 public function setLogging($logging, $temporary = FALSE) {
151 $this->config->set('log', $logging);
152 $this->config->save();
155 static::$temporaryLogging = ($logging == TRUE);
160 * Sets the 'last_run' value.
162 * @param int $last_run
163 * The new value for 'last_run'.
165 public function setLastRun($last_run) {
166 $this->state->set('last_run', $last_run);
170 * Stores the given 'untrusted_roles' setting.
172 * @param string[] $untrusted_roles
173 * The new untrusted roles' IDs.
175 public function setUntrustedRoles(array $untrusted_roles) {
176 $this->config->set('untrusted_roles', $untrusted_roles);
177 $this->config->save();
183 * @param \Drupal\security_review\Check $check
184 * The Check the message is about.
185 * @param string $message
187 * @param array $context
188 * The context of the message.
190 * Severity (RfcLogLevel).
192 public function log(Check $check, $message, array $context, $level) {
193 if (static::isLogging()) {
194 $this->moduleHandler->invokeAll(
195 'security_review_log',
198 'message' => $message,
199 'context' => $context,
207 * Logs a check result.
209 * @param \Drupal\security_review\CheckResult $result
212 public function logCheckResult(CheckResult $result = NULL) {
213 if ($this->isLogging()) {
214 if ($result == NULL) {
215 $check = $result->check();
217 '@check' => $check->getTitle(),
218 '@namespace' => $check->getNamespace(),
220 $this->log($check, '@check of @namespace produced a null result', $context, RfcLogLevel::CRITICAL);
224 $check = $result->check();
226 // Fallback log message.
227 $level = RfcLogLevel::NOTICE;
228 $message = '@name check invalid result';
230 // Set log message and level according to result.
231 switch ($result->result()) {
232 case CheckResult::SUCCESS:
233 $level = RfcLogLevel::INFO;
234 $message = '@name check succeeded';
237 case CheckResult::FAIL:
238 $level = RfcLogLevel::ERROR;
239 $message = '@name check failed';
242 case CheckResult::WARN:
243 $level = RfcLogLevel::WARNING;
244 $message = '@name check raised a warning';
247 case CheckResult::INFO:
248 $level = RfcLogLevel::INFO;
249 $message = '@name check returned info';
253 $context = ['@name' => $check->getTitle()];
254 $this->log($check, $message, $context, $level);
259 * Deletes orphaned check data.
261 public function cleanStorage() {
262 /** @var \Drupal\security_review\Checklist $checklist */
263 $checklist = \Drupal::service('security_review.checklist');
265 // Get list of check configuration names.
266 $orphaned = $this->configFactory->listAll('security_review.check.');
268 // Remove items that are used by the checks.
269 foreach ($checklist->getChecks() as $check) {
270 $key = array_search('security_review.check.' . $check->id(), $orphaned);
271 if ($key !== FALSE) {
272 unset($orphaned[$key]);
276 // Delete orphaned configuration data.
277 foreach ($orphaned as $config_name) {
278 $config = $this->configFactory->getEditable($config_name);
284 * Stores information about the server into the State system.
286 public function setServerData() {
287 if (!static::isServerPosix() || PHP_SAPI === 'cli') {
290 // Determine web server's uid and groups.
291 $uid = posix_getuid();
292 $groups = posix_getgroups();
294 // Store the data in the State system.
295 $this->state->set('security_review.server.uid', $uid);
296 $this->state->set('security_review.server.groups', $groups);
300 * Returns whether the server is POSIX.
303 * Whether the web server is POSIX based.
305 public function isServerPosix() {
306 return function_exists('posix_getuid');
310 * Returns the UID of the web server.
313 * UID of the web server's user.
315 public function getServerUid() {
316 return $this->state->get('security_review.server.uid');
320 * Returns the GIDs of the web server.
323 * GIDs of the web server's user.
325 public function getServerGids() {
326 return $this->state->get('security_review.server.groups');