#!/usr/bin/php
<?php
/*
TICKET: 10131633
AUTOR: Otávio Honório
CRIADO EM: 23/01/2019 14:20:00

REVISÕES:
--
*/

include_once('/usr/local/opmon/libexec/php-nagios-plugins/Nagios_Plugin.php');
include_once('/usr/local/opmon/share/modelgroups/incapsula/manager/Incapsula.php');

ini_set('error_reporting', 'E_NOTICE & ~ E_DEPRECATED');

define(VERSION, '1.0');

/*
* Show manual of script
*/
function getGuideLine()
{
    print <<<EOF
-------------------------------------------------------------------------------
                            Manual de exemplo.
-------------------------------------------------------------------------------

Descrição do plugin:
    Este plugin monitora o crédito disponível na conta do zenvia.

Dependências:
    php
    php-xml

Funcionamento:
    O plugin recebe a conta, usuário e senha, acessa o site da zenvia e pega o
    crédito exibido na tela inicial

Exemplos de execução e retorno do comando:
    ./check_incapsula --id 12345 --key xxx-xyzw-xxx -m bandwidth -w 20 -c 30

EOF;

    exit(OK);
}

/*
* get options from command line
*/
function getOptions()
{
    global $np;

    $np = new Nagios_Plugin(
        array(
            'version' => VERSION. "[www.opservices.com.br/suporte]",
            'blurb' => "Developed by:\n\tOpServices\n",
            'Author' => "Otávio Honório - otavio.honorio@opservices.com.br",
            'usage' => "Usage:\n\t%s --id <api_id> --key <api_key> -m <metric> -w <warning> -c <critical>"
        )
    );

    $np->add_arg("id=i", "ID for access API", true);
    $np->add_arg("key=s", "Key for access API", true);
    $np->add_arg("site=i", "Site id", true);
    $np->add_arg("metric|m=s", "Metric name", true);
    $np->add_arg(
        "warning|w=i",
        "Warning value. If there is more than one metric, use the comma separator"
    );
    $np->add_arg(
        "critical|c=i",
        "Critical value. If there is more than one metric, use the comma separator"
    );
    $np->add_arg("man", "Show guideline");

    $np->getopts();
}

function convertions($value, $from, $to)
{
    if ($from === 'bytes') {
        //return round($value / 1e+6, 3);
        return round($value / 1000, 3);
    }
    if ($from === 'bits') {
        //return round($value / 8e+6, 3);
        return round($value / 8000, 3);
    }

    return $value;
}

function getLastValue($data)
{
    usort($data, function ($a, $b) {
        if ($a[0] === $b[0]) return 0;
        return ($a[0] > $b[0]) ? -1 : 1;
    });

    return $data[0][1];
}

function getMetrics($data, $stat)
{
    if ($stat['type'] === 'timeseries') {
        return getTimeseriesMetrics($data, $stat);
    }
    if ($stat['type'] === 'threats') {
        return getThreatsMetrics($data, $stat);
    }
    return array();
}

function getThreatsMetrics($data, $stat)
{
    foreach ($data->{$stat['property']} as $item) {
        if ($item->name === $stat['key']) {
            return array(
                $item->name => $item->incidents
            );
        }
    }
    return array();
}

function getTimeseriesMetrics($data, $stat)
{
    $metrics = array();
    foreach ($data->{$stat['property']} as $item) {
        $metrics[$item->name] = getLastValue($item->data);
    }
    return $metrics;
}

function getStatus()
{
    global $np;

    $incapsula = new Incapsula();
    $data = $incapsula->doRequest(
        $incapsula::URL.'/api/prov/v1/sites/status',
        array(
            'api_id' => $np->opts['id'],
            'api_key' => $np->opts['key'],
            'site_id' => $np->opts['site']
        )
    );

    $code = 0;
    $message = "Site OK - ";
    if ($data->status !== 'fully-configured') {
        $code = 2;
        $message = "Site Critical - ";
    }

    $np->nagios_exit(
        $code,
        $message.$data->status
    );
}

global $np;
getOptions();

if (isset($np->opts['man'])) {
    getGuideLine();
}

if ($np->opts['metric'] === 'status') {
    getStatus();
}

$warnings = explode(',', $np->opts['warning']);
$criticals = explode(',', $np->opts['critical']);

$stats = array(
    'bandwidth' => array(
        'property' => 'bandwidth_timeseries',
        'type' => 'timeseries',
        'unit' => array(
            'Bandwidth' => 'kb',
            'Bits per second' => 'kbps'
        ),
        'convert' => array(
            'Bandwidth' => 'bytes',
            'Bits per second' => 'bits'
        )
    ),
    'visits' => array(
        'property' => 'visits_timeseries',
        'type' => 'timeseries'
    ),
    'hits' => array(
        'property' => 'hits_timeseries',
        'type' => 'timeseries'
    ),
    'caching' => array(
        'property' => 'caching_timeseries',
        'type' => 'timeseries',
        'unit' => array(
            'Standard Bandwidth Caching' => 'kb',
            'Advanced Bandwidth Caching' => 'kb',
            'Total bandwidth' => 'kb'
        ),
        'convert' => array(
            'Standard Bandwidth Caching' => 'bytes',
            'Advanced Bandwidth Caching' => 'bytes',
            'Total bandwidth' => 'bytes'
        )
    ),
    'sql-injection' => array(
        'property' => 'threats',
        'key' => 'SQL Injection',
        'type' => 'threats'
    ),
    'ddos' => array(
        'property' => 'threats',
        'key' => 'DDoS',
        'type' => 'threats'
    ),
    'bot-access-control' => array(
        'property' => 'threats',
        'key' => 'Bot Access Control',
        'type' => 'threats'
    ),
    'illegal-resource-access' => array(
        'property' => 'threats',
        'key' => 'Illegal Resource Access',
        'type' => 'threats'
    ),
    'remote-file-inclusion' => array(
        'property' => 'threats',
        'key' => 'Remote File Inclusion',
        'type' => 'threats'
    ),
    'visitors-from-blacklisted-countries' => array(
        'property' => 'threats',
        'key' => 'Visitors from blacklisted Countries',
        'type' => 'threats'
    ),
    'backdoor-protect' => array(
        'property' => 'threats',
        'key' => 'Backdoor Protect',
        'type' => 'threats'
    ),
    'cross-site-scripting' => array(
        'property' => 'threats',
        'key' => 'Cross Site Scripting',
        'type' => 'threats'
    ),
    'visitors-from-blacklisted-urls' => array(
        'property' => 'threats',
        'key' => 'Visitors from blacklisted URLs',
        'type' => 'threats'
    ),
    'visitors-from-blacklisted-ips' => array(
        'property' => 'threats',
        'key' => 'Visitors from blacklisted IPs',
        'type' => 'threats'
    ),
    'suspected-bots' => array(
        'property' => 'threats',
        'key' => 'Suspected Bots',
        'type' => 'threats'
    ),
);

$incapsula = new Incapsula();
$data = $incapsula->doRequest(
    $incapsula::URL.'/api/stats/v1',
    array(
        'api_id' => $np->opts['id'],
        'api_key' => $np->opts['key'],
        'site_id' => $np->opts['site'],
        'time_range' => 'today',
        'stats' => $stats[$np->opts['metric']]['property']
    )
);

$metrics = getMetrics($data, $stats[$np->opts['metric']]);

$index = 0;
foreach ($metrics as $metric => $value) {
    $np->set_thresholds($warnings[$index], $criticals[$index], 0);

    $np->add_perfdata(
        $metric,
        convertions(
            $value,
            $stats[$np->opts['metric']]['convert'][$metric],
            $stats[$np->opts['metric']]['unit'][$metric]
        ),
        $stats[$np->opts['metric']]['unit'][$metric],
        $np->threshold()
    );

    $messages[] = sprintf(
        '%s: %s%s',
        $metric,
        convertions(
            $value,
            $stats[$np->opts['metric']]['convert'][$metric],
            $stats[$np->opts['metric']]['unit'][$metric]
        ),
        $stats[$np->opts['metric']]['unit'][$metric]
    );

    $codes[] = $np->check_threshold($value);
    $index++;
}
$message = implode($messages, ' / ');
arsort($codes);

$np->nagios_exit(
    $codes[0],
    $message
);
