Coder Social home page Coder Social logo

silverstripe / silverstripe-environmentcheck Goto Github PK

View Code? Open in Web Editor NEW
32.0 17.0 24.0 242 KB

A Silverstripe module that provides an API for creating environment checks

License: BSD 3-Clause "New" or "Revised" License

PHP 96.77% Scheme 3.23%
hacktoberfest

silverstripe-environmentcheck's Introduction

Silverstripe Environment Checker Module

CI Silverstripe supported module

This module adds an API for running environment checks to your API.

  • health/check - 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!

Installation

composer require silverstripe/environmentcheck

Activating Directly

Register checks in your own _config.php - see the _config.php in this module for some defaults. Don't forget to either use a fully-qualified (namespaced) class name for EnvironmentCheckSuite, or use (import) the namespaced class first.

EnvironmentCheckSuite::register('health', 'DatabaseCheck', 'Can we connect to the database?');
EnvironmentCheckSuite::register('check', 'URLCheck("")', 'Is the homepage accessible?');

Activating Via Config

Register your checks on the EnvironmentCheckSuite. The same named check may be used multiple times.

SilverStripe\EnvironmentCheck\EnvironmentCheckSuite:
  registered_checks:
    db:
      definition: 'DatabaseCheck("Page")'
      title: 'Is the database accessible?'
    url:
      definition: 'URLCheck()'
      title: 'Is the homepage accessible?'
  registered_suites:
    check:
      - db
    health:
      - db
      - url

You can also disable checks configured this way. This is handy if you want to override a check imposed on your project by some other module. Just set the "state" property of the check to "disabled" like this:

SilverStripe\EnvironmentCheck\EnvironmentCheckSuite:
  registered_checks:
    db:
      state: disabled

Available checks

  • DatabaseCheck: Check that the connection to the database is working, by ensuring that the table exists and that the table contain some records.
  • URLCheck: Check that a given URL is functioning, by default, the homepage.
  • HasFunctionCheck: Check that the given function exists. This can be used to check that PHP modules or features are installed.
  • HasClassCheck: Check that the given class exists. This can be used to check that PHP modules or features are installed.
  • FileWriteableCheck: Check that the given file is writeable.
  • FileAccessibilityAndValidationCheck: Check that a given file is accessible and optionally matches a given format.
  • FileAgeCheck: Checks for the maximum age of one or more files or folders. Useful for files which should be frequently auto-generated, like static caches, as well as for backup files and folders.
  • ExternalURLCheck: Checks that one or more URLs are reachable via HTTP.
  • SMTPConnectCheck: Checks if the SMTP connection configured through PHP.ini works as expected.
  • SolrIndexCheck: Checks if the Solr cores of given class are available.
  • SessionCheck: Checks that a given URL does not generate a session.
  • CacheHeadersCheck: Check cache headers in response for directives that must either be included or excluded as well checking for existence of ETag.
  • EnvTypeCheck: Checks environment type, dev and test should not be used on production environments.

Monitoring Checks

Checks will return an appropriate HTTP status code, so are easy to hook into common uptime montoring solutions like pingdom.com.

You can also have the environment checker email results with the following configuration:

SilverStripe\EnvironmentCheck\EnvironmentChecker:
  email_results: true
  to_email_address: [email protected]
  from_email_address: [email protected]

Errors can be logged via the standard Silverstripe PSR-3 compatible logging. Each check will cause an individual log entry. You can choose to enable logging separately for warnings and errors, identified through the result of EnvironmentCheck->check().

SilverStripe\EnvironmentCheck\EnvironmentChecker:
  log_results_warning: true
  log_results_error: true

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.

You may wish to have an automated service check dev/check periodically, but not want to open it up for public access. You can enable basic authentication by defining the following in your environment (.env file):

ENVCHECK_BASICAUTH_USERNAME="test"
ENVCHECK_BASICAUTH_PASSWORD="password"

Now if you access dev/check in a browser it will pop up a basic auth popup, and if the submitted username and password match the ones defined the username and password defined in the environment, access will be granted to the page.

Adding more checks

To add more checks, you should put additional EnvironmentCheckSuite::register calls into your _config.php. See the _config.php file of this module for examples.

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 health/check 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.

To test your own application, you probably want to write custom checks:

  • Implement the SilverStripe\EnvironmentCheck\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 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.

use SilverStripe\EnvironmentCheck\EnvironmentCheck;

class MyGatewayCheck implements EnvironmentCheck
{
    protected $checkTable;

    function check()
    {
        $g = new \MyGateway;

        $response = $g->call();
        $expectedResponse = 'foo';

        if($response == null) {
            return array(EnvironmentCheck::ERROR, "MyGateway didn't return a response");
        } else if($response != $expectedResponse) {
            return array(EnvironmentCheck::WARNING, "MyGateway returned unexpected response $response");
        }
        return array(EnvironmentCheck::OK, '');
    }
}

Once you have created your custom check class, don't forget to register it in a check suite

EnvironmentCheckSuite::register('check', 'MyGatewayCheck', 'Can I connect to the gateway?');

Using other environment check suites

If you want to use the same UI as health/check 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:

use SilverStripe\Control\Controller;

class DevHealth extends Controller
{
    function index()
    {
        $e = new EnvironmentChecker('health', 'Site health');
        return $e;
    }
}

If you wish to embed an environment check suite in another, you can use the following call:

$result = EnvironmentCheckSuite::inst('health')->run();

$result will contain a EnvironmentCheckSuiteResult object

  • $result->ShouldPass(): Return a boolean of whether or not the tests passed.
  • $result->Status(): The string "OK", "WARNING", or "ERROR", depending on the worst failure.
  • $result->Details(): A DataObjectSet of details about the result of each check in the suite.

See EnvironmentChecker.ss to see how these can be used to build a UI.

Versioning

This library follows Semver. According to Semver, you will be able to upgrade to any minor or patch version of this library without any breaking changes to the public API. Semver also requires that we clearly define the public API for this library.

All methods, with public visibility, are part of the public API. All other methods are not part of the public API. Where possible, we'll try to keep protected methods backwards-compatible in minor/patch versions, but if you're overriding methods then please test your work before upgrading.

Reporting Issues

Please create an issue for any bugs you've found, or features you're missing.

silverstripe-environmentcheck's People

Contributors

andrewandante avatar anotheredward avatar assertchris avatar chillu avatar dhensby avatar dnsl48 avatar emteknetnz avatar frankmullenger avatar guysartorelli avatar halkyon avatar mateusz avatar maxime-rainville avatar michalkleiner avatar nightjar avatar patbolo avatar robbieaverill avatar sabina-talipova avatar scopeynz avatar scott1702 avatar sminnee avatar tractorcow avatar wilr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

silverstripe-environmentcheck's Issues

Issues when using HTTP BASIC Auth on EnvironmentChecker.php

Hi there,

I've found 2 issues in this module touching the BASIC AUTH.

Details about environment

Running this module on;

  • PHP 7.2
  • Apache

Readme

  1. The example in the README does not work. In the original README there are double-quotes added.
    But the double-quotes are not needed, the example below is the right way to add this environment variables;
ENVCHECK_BASICAUTH_USERNAME=test
ENVCHECK_BASICAUTH_PASSWORD=password

For some reason Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME') returns "test" and Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME') will return "password".

In the README update PR I've created, there was a comment mentioning https://github.com/m1/Env#env-example. Quotes around .env variables should be allowed.

Wierd issue, needs further investigation.

$_SERVER['PHP_AUTH_PW'] and $_SERVER['PHP_AUTH_USER']

  1. $_SERVER['PHP_AUTH_PW'] and $_SERVER['PHP_AUTH_USER'] checks in EnvironmentChecker.php -> init method are not working

For some reason, when I check on the variables above, I've keep getting the "basic auth form" and logging in.
Did some investigation, and the variables are just not available.

When I'm adding a $request = $this->getRequest(); and then use $request->getHeader('PHP_AUTH_USER') and $request->getHeader('PHP_AUTH_PW') the basic login works.

And now?

I'm willing to create a PR later, but right now I just don't have time to fix this and create a PR.
Because I've found this issue and I think its important to fix this, I've created a Issue to make sure this is documented somewhere.

Work-around;
For now, I've created a custom HealthCheck controller that doesn't involve the init method on the EnvironentChecker.
This way I can use my own basic authentication logic in my own controller.

URLCheck fails if running via command line

if you run a URLCheck() via command line, it returns the redirect HTML, instead of a success/ failure code:

<p>Redirecting to <a href="*URL HERE*" title="Click this link if your browser does not redirect you"*URL HERE*... (output started on C:\xampp\htdocs\op\framework\dev\TaskRunner.php, line 67)</a></p>

Class EnvTypeCheck does not exist

Perhaps I'm doing something wrong. Other checks are working fine using latest version (2.1.2), but when trying to implement the EnvTypeCheck, the class cannot be found.

Uncaught SilverStripe\Core\Injector\InjectorNotFoundException: ReflectionException: Class EnvTypeCheck does not exist in /var/www/html/vendor/silverstripe/framework/src/Core/Injector/InjectionCreator.php:17

...

SilverStripe\Core\Injector\InjectionCreator->create(EnvTypeCheck, Array)
Injector.php:594
SilverStripe\Core\Injector\Injector->instantiate(Array, EnvTypeCheck, prototype)
Injector.php:1002
SilverStripe\Core\Injector\Injector->getNamedService(EnvTypeCheck, , Array)
Injector.php:955
SilverStripe\Core\Injector\Injector->get(EnvTypeCheck, , Array)
Injector.php:1125
SilverStripe\Core\Injector\Injector->createWithArgs(EnvTypeCheck, Array)
Injector.php:1113
SilverStripe\Core\Injector\Injector->create(EnvTypeCheck)
EnvironmentCheckSuite.php:137
SilverStripe\EnvironmentCheck\EnvironmentCheckSuite->checkInstances()
EnvironmentCheckSuite.php:110
SilverStripe\EnvironmentCheck\EnvironmentCheckSuite->run()
EnvironmentChecker.php:169

environmentcheck.yml

---
Name: my-environmentcheck
---
SilverStripe\EnvironmentCheck\EnvironmentCheckSuite:
  registered_checks:
    db:
      definition: 'DatabaseCheck("SiteTree")'
      title: 'Database'
    url:
      definition: 'URLCheck("/")'
      title: 'Site'
    external:
      definition: 'ExternalURLCheck("https://www.google.com")'
      title: 'Internet'
    env:
      definition: 'EnvTypeCheck' # tried with EnvTypeCheck() and EnvTypeCheck("live")
      title: 'Environment'
  registered_suites:
    health:
      - db
      - url
      - external
      - env
    check:
      - db
      - url
      - external
      - env

Add ability to return a warning instead of error when checks fail

Description

CacheHeadersCheck::check() method checks that correct caching headers are present. Method should return EnvironmentCheck::WARNING if validation result messageType is ValidationResult::TYPE_WARNING. Necessary to add additional check for message type.

See:

// @todo Ability to return a warning
return [
EnvironmentCheck::ERROR,
$this->getMessage(),
];

DatabaseCheck gives an PHP error when the table is not present

When the module is used to test a table/view and the table/view is not in the database it returns a PHP error.

Couldn't run query: SELECT COUNT(*) FROM "bar" Table 'ssdev.bar' doesn't exist

Instead we would expect to get an ERROR response from the environmentcheck module.

Should the DatabaseCheck verify if the table is present and then do what we said we would expect, or do you see this as part of a custom check?

I am happy to come up with a fix if that's the case

health route is a reserved URL

We have a client who is unable to publish a page called "Health" with the URL "health" because the default configuration of the environmentcheck module uses /health/check as a defacto reserved word. As far as I can tell there's no way to unset it without resetting the entire Director::rules array

It would be nice if the responsibility of defining a route was left to the developer as part of the initial setup and configuration of the module, or if a different route could be used by default instead

Using basic auth credentials to access /dev/check still triggers the site login

Since 2.6, /health/check doesn't show full check results - /dev/check does, but requires authentication when in live mode - that was an intended change. https://github.com/silverstripe/silverstripe-environmentcheck#authentication discusses configuring HTTP Basic Auth for this as a way for automated monitoring to access /dev/check.

This doesn't seem to work however - on a fresh SS5 installation (and also in our SS4 installs) configuring the ENV variables and loading /dev/check still redirects the user to the login flow instead of serving a 401. After logging in and being redirected back to /dev/check, we get the 401 and http auth flow as expected.

Working on debugging this as I suspect it's to do with the bypass added in yaml to avoid the /dev/confirm redirect. Oddly, copying over the rule below from environmentcheck to my test site's mysite.yml means this starts working as expected - I can't see why this workaround works though.

SilverStripe\Control\Director:
  rules:
    'dev/check/$Suite': 'Silverstripe\EnvironmentCheck\Controllers\DevCheckController'

Before:

➜  silverstripe-5-template git:(main) ✗ curl -I https://site-template.localhost.direct/dev/check -u "test:password"
HTTP/2 302 
[..]
location: https://site-template.localhost.direct/Security/login?BackURL=%2Fdev%2Fcheck

After:

➜  silverstripe-5-template git:(main) ✗ curl -I https://site-template.localhost.direct/dev/check -u "test:password"
HTTP/2 200 
[...]

URL in documentation.

In the documentation the url for health is said to be:

/dev/health

However that does not work and complains about a missing controller

The URL should be:

/health/check

/dev/check fails with BasicAuth is protecting the site

[Emergency] Uncaught TypeError: Argument 1 passed to SilverStripe\Security\BasicAuth::requireLogin() must be an instance of SilverStripe\Control\HTTPRequest, string given, called in /Users/robbieaverill/dev/mywebsite/environmentcheck/src/EnvironmentChecker.php on line 150
GET /dev/check

Line 80 in /Users/robbieaverill/dev/mywebsite/vendor/silverstripe/framework/src/Security/BasicAuth.php

Trace

SilverStripe\Security\BasicAuth::requireLogin(Environment Checker, ADMIN, ) 
EnvironmentChecker.php:150
SilverStripe\EnvironmentCheck\EnvironmentChecker->canAccess(, ADMIN) 
EnvironmentChecker.php:129
SilverStripe\EnvironmentCheck\EnvironmentChecker->init(ADMIN) 
DevCheckController.php:45
SilverStripe\EnvironmentCheck\Controllers\DevCheckController->index(SilverStripe\Control\HTTPRequest) 
RequestHandler.php:320

Use codecov.io for code coverage

#38 removed some old configuration from .scrutinizer.yml for external code coverage since Travis was not configured to provide it.

We should switch to using Codecov.io instead.

4.x compat (with PSR-3)

#29 introduced logging for the 3.x compatible version of this module. This should be adjusted to use PSR-3 instead of SS_Log, with the current code moved into a 3.x compatible 1.0 branch.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.