You are here

security_review.drush.inc in Security Review 8

Same filename and directory in other branches
  1. 6 security_review.drush.inc
  2. 7 security_review.drush.inc

Drush commands for Security Review module.

File

security_review.drush.inc
View source
<?php

/**
 * @file
 * Drush commands for Security Review module.
 */
use Drupal\security_review\CheckResult;

/**
 * Implements hook_drush_command().
 */
function security_review_drush_command() {
  $items = [];
  $items['security-review'] = [
    'aliases' => [
      '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;
}

Functions

Namesort descending Description
security_review_drush Runs a checklist and displays results.
security_review_drush_command Implements hook_drush_command().
security_review_drush_help Implements hook_drush_help().
_security_review_drush_format_results Helper function to compile Security Review results.
_security_review_drush_get_check Helper function for parsing input check name strings.