X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fmodules%2Fcontrib%2Fsecurity_review%2Fsecurity_review.drush.inc;fp=web%2Fmodules%2Fcontrib%2Fsecurity_review%2Fsecurity_review.drush.inc;h=6931887083bb92b82db6db37621710193ad98866;hp=0000000000000000000000000000000000000000;hb=ba1b5c55c66590c41ccc9844d3e62391b0399abb;hpb=93ef30d42f68e55d11d97312531118bbcd4cf318 diff --git a/web/modules/contrib/security_review/security_review.drush.inc b/web/modules/contrib/security_review/security_review.drush.inc new file mode 100644 index 000000000..693188708 --- /dev/null +++ b/web/modules/contrib/security_review/security_review.drush.inc @@ -0,0 +1,251 @@ + ['secrev'], + 'callback' => 'security_review_drush', + 'description' => "Run the Security Review checklist", + 'options' => [ + 'store' => 'Write results to the database', + 'log' => 'Log results of each check to watchdog, defaults to off', + 'lastrun' => 'Do not run the checklist, just print last results', + 'check' => 'Comma-separated list of specified checks to run. See README.txt for list of options', + 'skip' => 'Comma-separated list of specified checks not to run. This takes precedence over --check.', + 'short' => "Short result messages instead of full description (e.g. 'Text formats')", + 'results' => 'Show the incorrect settings for failed checks', + ], + 'examples' => [ + 'secrev' => 'Run the checklist and output the results', + 'secrev --store' => 'Run the checklist, store, and output the results', + 'secrev --lastrun' => 'Output the stored results from the last run of the checklist', + ], + 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, + 'outputformat' => [ + 'default' => 'table', + 'pipe-format' => 'csv', + 'fields-default' => ['message', 'status'], + 'field-labels' => [ + 'message' => 'Message', + 'status' => 'Status', + 'findings' => 'Findings', + ], + 'output-data-type' => 'format-table', + ], + ]; + + return $items; +} + +/** + * Implements hook_drush_help(). + */ +function security_review_drush_help($section) { + switch ($section) { + case 'drush:security-review': + return dt("Run configuration security checks on your Drupal site."); + } +} + +/** + * Runs a checklist and displays results. + */ +function security_review_drush() { + /** @var \Drupal\security_review\SecurityReview $security_review */ + $security_review = Drupal::service('security_review'); + + /** @var \Drupal\security_review\Checklist $checklist */ + $checklist = Drupal::service('security_review.checklist'); + + $store = drush_get_option('store'); + $log = drush_get_option('log'); + $last_run = drush_get_option('lastrun'); + $run_checks = drush_get_option_list('check'); + $skip_checks = drush_get_option_list('skip'); + $short_titles = drush_get_option('short'); + $show_findings = drush_get_option('results'); + + // Set temporary logging. + $log = in_array($log, [TRUE, 1, 'TRUE']); + $security_review->setLogging($log, TRUE); + + if (!empty($short_titles)) { + $short_titles = TRUE; + } + else { + $short_titles = FALSE; + } + + $results = []; + if (!$last_run) { + // Do a normal security review run. + /** @var \Drupal\security_review\Check[] $checks */ + $checks = []; + /** @var \Drupal\security_review\Check[] $to_skip */ + $to_skip = []; + + // Fill the $checks array. + if (!empty($run_checks)) { + // Get explicitly specified checks. + foreach ($run_checks as $check) { + $checks[] = _security_review_drush_get_check($check); + } + } + else { + // Get the whole checklist. + $checks = $checklist->getChecks(); + } + + // Mark checks listed after --skip for removal. + if (!empty($skip_checks)) { + foreach ($skip_checks as $skip_check) { + $to_skip[] = _security_review_drush_get_check($skip_check); + } + } + + // If storing, mark skipped checks for removal. + if ($store) { + foreach ($checks as $check) { + if ($check->isSkipped()) { + $to_skip[] = $check; + } + } + } + + // Remove the skipped checks from $checks. + foreach ($to_skip as $skip_check) { + foreach ($checks as $key => $check) { + if ($check->id() == $skip_check->id()) { + unset($checks[$key]); + } + } + } + + // If $checks is empty at this point, return with an error. + if (empty($checks)) { + return drush_set_error('EMPTY_CHECKLIST', dt("No checks to run. Run 'drush help secrev' for option use or consult the drush section of API.txt for further help.")); + } + + // Run the checks. + $results = $checklist->runChecks($checks, TRUE); + + // Store the results. + if ($store) { + $checklist->storeResults($results); + } + } + else { + // Show the latest stored results. + foreach ($checklist->getChecks() as $check) { + $last_result = $check->lastResult($show_findings); + if ($last_result instanceof CheckResult) { + $results[] = $last_result; + } + } + } + + return _security_review_drush_format_results($results, $short_titles, $show_findings); +} + +/** + * Helper function for parsing input check name strings. + * + * @param string $check_name + * The check to get. + * + * @return \Drupal\security_review\Check|null + * The found Check. + */ +function _security_review_drush_get_check($check_name) { + /** @var \Drupal\security_review\Checklist $checklist */ + $checklist = Drupal::service('security_review.checklist'); + + // Default namespace is Security Review. + $namespace = 'security_review'; + $title = $check_name; + + // Set namespace and title if explicitly defined. + if (strpos($check_name, ':') !== FALSE) { + list($namespace, $title) = explode(':', $check_name); + } + + // Return the found check if any. + return $checklist->getCheck($namespace, $title); +} + +/** + * Helper function to compile Security Review results. + * + * @param \Drupal\security_review\CheckResult[] $results + * An array of CheckResults. + * @param bool $short_titles + * Whether to use short message (check title) or full check success or failure + * message. + * @param bool $show_findings + * Whether to print failed check results. + * + * @return array + * The results of the security review checks. + */ +function _security_review_drush_format_results(array $results, $short_titles = FALSE, $show_findings = FALSE) { + $output = []; + + foreach ($results as $result) { + if ($result instanceof CheckResult) { + if (!$result->isVisible()) { + // Continue with the next check. + continue; + } + + $check = $result->check(); + $message = $short_titles ? $check->getTitle() : $result->resultMessage(); + $status = 'notice'; + + // Set log level according to check result. + switch ($result->result()) { + case CheckResult::SUCCESS: + $status = 'success'; + break; + + case CheckResult::FAIL: + $status = 'failed'; + break; + + case CheckResult::WARN: + $status = 'warning'; + break; + + case CheckResult::INFO: + $status = 'info'; + break; + } + + // Attach findings. + if ($show_findings) { + $findings = trim($result->check()->evaluatePlain($result)); + if ($findings != '') { + $message .= "\n" . $findings; + } + } + + $output[$check->id()] = [ + 'message' => (string) $message, + 'status' => $status, + 'findings' => $result->findings(), + ]; + } + } + + return $output; +}