Allow /dev/health to be public
As per the readme, /dev/health should be a public URL which returns a status code and Site is available. For security reasons it should not contain details about the checks run.
This commit is contained in:
parent
b9bfacf223
commit
1cda4e0afc
|
@ -1,10 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package environmentcheck
|
||||
*/
|
||||
|
||||
class DevCheckController extends Controller {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $allowed_actions = array(
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'index'
|
||||
);
|
||||
|
||||
|
@ -22,7 +24,7 @@ class DevCheckController extends Controller {
|
|||
*
|
||||
* @throws SS_HTTPResponse_Exception
|
||||
*/
|
||||
function index($request) {
|
||||
public function index($request) {
|
||||
$suite = 'check';
|
||||
|
||||
if ($name = $request->param('Suite')) {
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* A public URL which requires no authenication which returns a simple Ok, Fail
|
||||
* check.
|
||||
*
|
||||
* For a more detailed check, see {@link DevCheckController}
|
||||
*
|
||||
* @package environmentcheck
|
||||
*/
|
||||
class DevHealthController extends Controller {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $allowed_actions = array(
|
||||
private static $allowed_actions = array(
|
||||
'index'
|
||||
);
|
||||
|
||||
/**
|
||||
* @return EnvironmentChecker
|
||||
*
|
||||
* @throws SS_HTTPResponse_Exception
|
||||
*/
|
||||
function index() {
|
||||
// health check does not require permission to run
|
||||
public function index() {
|
||||
Config::inst()->update('EnvironmentChecker', 'template', 'DevHealthController');
|
||||
|
||||
$checker = new EnvironmentChecker('health', 'Site health');
|
||||
$checker->init('');
|
||||
$checker->setErrorCode(404);
|
||||
$e = new EnvironmentChecker('health', 'Site health');
|
||||
$e->init(''); //empty permission check, the "health" check does not require a permission check to run
|
||||
$e->setErrorCode(500);
|
||||
|
||||
return $checker;
|
||||
return $e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ class EnvironmentChecker extends RequestHandler {
|
|||
* @param string $checkSuiteName
|
||||
* @param string $title
|
||||
*/
|
||||
private static $template = 'EnvironmentChecker';
|
||||
|
||||
function __construct($checkSuiteName, $title) {
|
||||
parent::__construct();
|
||||
|
||||
|
@ -56,8 +58,8 @@ class EnvironmentChecker extends RequestHandler {
|
|||
* @param string $permission
|
||||
*
|
||||
* @throws SS_HTTPResponse_Exception
|
||||
*/
|
||||
function init($permission = 'ADMIN') {
|
||||
*/
|
||||
public function init($permission = 'ADMIN') {
|
||||
// if the environment supports it, provide a basic auth challenge and see if it matches configured credentials
|
||||
if(defined('ENVCHECK_BASICAUTH_USERNAME') && defined('ENVCHECK_BASICAUTH_PASSWORD')) {
|
||||
if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
|
||||
|
@ -101,7 +103,7 @@ class EnvironmentChecker extends RequestHandler {
|
|||
$member = Member::currentUser();
|
||||
}
|
||||
|
||||
if(!$member) {
|
||||
if(!$member && $permission) {
|
||||
$member = BasicAuth::requireLogin('Environment Checker', $permission, false);
|
||||
}
|
||||
|
||||
|
@ -132,7 +134,7 @@ class EnvironmentChecker extends RequestHandler {
|
|||
* @return SS_HTTPResponse
|
||||
*/
|
||||
function index() {
|
||||
$response = new SS_HTTPResponse;
|
||||
$response = new SS_HTTPResponse();
|
||||
$result = EnvironmentCheckSuite::inst($this->checkSuiteName)->run();
|
||||
|
||||
if(!$result->ShouldPass()) {
|
||||
|
@ -144,10 +146,15 @@ class EnvironmentChecker extends RequestHandler {
|
|||
"Title" => $this->title,
|
||||
"Name" => $this->checkSuiteName,
|
||||
"ErrorCode" => $this->errorCode,
|
||||
))->renderWith("EnvironmentChecker");
|
||||
))->renderWith($this->config()->template);
|
||||
|
||||
if (self::$email_results && !$result->ShouldPass()) {
|
||||
$email = new Email(self::$from_email_address, self::$to_email_address, $this->title, $resultText);
|
||||
$email = new Email(
|
||||
self::$from_email_address,
|
||||
self::$to_email_address,
|
||||
$this->title,
|
||||
$resultText
|
||||
);
|
||||
$email->send();
|
||||
}
|
||||
|
||||
|
|
49
readme.md
49
readme.md
|
@ -8,28 +8,40 @@
|
|||
|
||||
This module adds an API for running environment checks to your API.
|
||||
|
||||
* `dev/health` - A public URL that performs a quick check that this environment is functioning. This could be tied to a load balancer, for example.
|
||||
* `dev/check` - An admin-only URL that performs a more comprehensive set of checks. This could be tied to a deployment system, for example.
|
||||
* `dev/health` - A public URL that performs a quick check that this environment is functioning. This could be tied to
|
||||
a load balancer, for example.
|
||||
* `dev/check` - An admin-only URL that performs a more comprehensive set of checks. This could be tied to a deployment
|
||||
system, for example.
|
||||
* `dev/check/<suite>` - Check a specific suite (admin only)
|
||||
|
||||
## Aren't these just unit tests?
|
||||
|
||||
Almost, but not really. Environment checks differ from unit tests in two important ways:
|
||||
|
||||
* **They test environment specific settings.** Unit tests are designed to use dummy data and mock interfaces to external system. Environment checks check the real systems and data that the given environment is actually connected to.
|
||||
* **They can't modify data.** Because these checks will run using production databases, they can't go modifying the data in there. This is the biggest reason why we haven't used the same base class as a unit test for writing environment checks - we wanted to make it impossible to accidentally plug a unit test into the environment checker!
|
||||
* **They test environment specific settings.** Unit tests are designed to use dummy data and mock interfaces to
|
||||
external system. Environment checks check the real systems and data that the given environment is actually connected
|
||||
to.
|
||||
* **They can't modify data.** Because these checks will run using production databases, they can't go modifying the
|
||||
data in there. This is the biggest reason why we haven't used the same base class as a unit test for writing
|
||||
environment checks - we wanted to make it impossible to accidentally plug a unit test into the environment checker!
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ composer require silverstripe/environmentalcheck
|
||||
$ composer require silverstripe/environmentcheck
|
||||
```
|
||||
|
||||
You'll also need to run `/dev/build`.
|
||||
|
||||
## Registering Checks
|
||||
|
||||
There are two ways to register your checks, both can be used at the same time. The checks will be appended to the suite.
|
||||
>>>>>>> Allow /dev/health to be public:README.md
|
||||
|
||||
### Activating Directly
|
||||
|
||||
Register checks in your own `_config.php` - see the `_config.php` in this module for some defaults.
|
||||
Register checks in your own `_config.php` - see the `_config.php` in this
|
||||
module for some defaults.
|
||||
|
||||
```php
|
||||
EnvironmentCheckSuite::register('health', 'DatabaseCheck', "Can we connect to the database?");
|
||||
|
@ -85,6 +97,8 @@ EnvironmentCheckSuite:
|
|||
|
||||
## Authentication
|
||||
|
||||
`dev/health` is public and requires no authentication.
|
||||
|
||||
By default, accessing the `dev/check` URL will not require authentication on CLI and dev environments, but if you're
|
||||
trying to access it on a live or test environment, it will respond with a 403 HTTP status unless you're logged in as
|
||||
an administrator on the site.
|
||||
|
@ -106,18 +120,26 @@ To add more checks, you should put additional `EnvironmentCheckSuite::register`
|
|||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("curl_init")', "Does PHP have CURL support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("imagecreatetruecolor")', "Does PHP have GD2 support?");
|
||||
|
||||
The first argument is the name of the check suite. There are two built-in check suites, "health", and "check", corresponding to the `dev/health` and `dev/check` URLs. If you wish, you can create your own check suites and execute them on other URLs. You can also add a check to more than one suite by passing the first argument as an array.
|
||||
The first argument is the name of the check suite. There are two built-in check suites, "health", and "check",
|
||||
corresponding to the `dev/health` and `dev/check` URLs. If you wish, you can create your own check suites and execute
|
||||
them on other URLs. You can also add a check to more than one suite by passing the first argument as an array.
|
||||
|
||||
The module comes bundled with a few checks in `DefaultHealthChecks.php`. However, to test your own application, you probably want to write custom checks.
|
||||
The module comes bundled with a few checks in `DefaultHealthChecks.php`. However, to test your own application, you
|
||||
probably want to write custom checks.
|
||||
|
||||
* Implement the `EnvironmentCheck` interface
|
||||
* Define the `check()` function, which returns a 2 element array:
|
||||
* The first element is one of `EnvironmentCheck::OK`, `EnvironmentCheck::WARNING`, `EnvironmentCheck::ERROR`, depending on the status of the check
|
||||
* The first element is one of `EnvironmentCheck::OK`, `EnvironmentCheck::WARNING`, `EnvironmentCheck::ERROR`,
|
||||
depending on the status of the check.
|
||||
* The second element is a string describing the response.
|
||||
|
||||
Here is a simple example of how you might create a check to test your own code. In this example, we are checking that an instance of the `MyGateway` class will return "foo" when `call()` is called on it. Testing interfaces with 3rd party systems is a common use case for custom environment checks.
|
||||
Here is a simple example of how you might create a check to test your own code. In this example, we are checking that
|
||||
an instance of the `MyGateway` class will return "foo" when `call()` is called on it. Testing interfaces with 3rd
|
||||
party systems is a common use case for custom environment checks.
|
||||
|
||||
:::php
|
||||
<?php
|
||||
|
||||
class MyGatewayCheck implements EnvironmentCheck {
|
||||
protected $checkTable;
|
||||
|
||||
|
@ -144,9 +166,14 @@ Once you have created your custom check class, don't forget to register it in a
|
|||
|
||||
### Using other environment check suites
|
||||
|
||||
If you want to use the same UI as dev/health and dev/check, you can create an `EnvironmentChecker` object. This class is a `RequestHandler` and so can be returned from an action handler. The first argument to the `EnvironmentChecker` constructor is the suite name. For example:
|
||||
If you want to use the same UI as dev/health and dev/check, you can create an `EnvironmentChecker` object. This class
|
||||
is a `RequestHandler` and so can be returned from an action handler. The first argument to the `EnvironmentChecker`
|
||||
constructor is the suite name. For example:
|
||||
|
||||
<?php
|
||||
|
||||
class DevHealth extends Controller {
|
||||
|
||||
function index() {
|
||||
$e = new EnvironmentChecker('health', 'Site health');
|
||||
return $e;
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title><% if ShouldPass %>Site is available<% else %>Site is unavailable<% end_if %></title>
|
||||
<style>
|
||||
* {
|
||||
font-family: Helvetica, Arial;
|
||||
font-size: 12px;
|
||||
}
|
||||
.subtext {
|
||||
margin-top: -10px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
margin-bottom: 3px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
margin: 2px 0 10px 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th {
|
||||
color: white;
|
||||
background-color: #777;
|
||||
/*border: 1px #aaa solid;*/
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
table td {
|
||||
background-color: #eee;
|
||||
/*border: 1px #ddd solid;*/
|
||||
padding: 5px 10px;
|
||||
}
|
||||
table tr:nth-child(odd) td {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.OK {
|
||||
color: green;
|
||||
}
|
||||
.WARNING {
|
||||
color: orange;
|
||||
font-weight: bold;
|
||||
}
|
||||
.ERROR {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<% if ShouldPass %>
|
||||
<p>Site is available</p>
|
||||
<p class="subtext">(you may check for the presence of the text 'Site is available' rather than an HTTP $ErrorCode error on this page, if you prefer.)</p>
|
||||
<% else %>
|
||||
<% if Name == check %>
|
||||
<p><b>A subsystem of the site is unavailable, but the site remains operational</b></p>
|
||||
<% else %>
|
||||
<p><b>Site is not available</b></p>
|
||||
<% end_if %>
|
||||
<% end_if %>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue