psecio / canary
一个输入检测和响应库
Requires (Dev)
- phpunit/phpunit: ^7.0
Suggests
- maknz/slack: Allows for the creation of a Slack notifier (sends to a channel)
- monolog/monolog: Allows for the creation of Monolog-based notifiers
- nmcquay/pagerduty: Used to create PagerDuty notifications
README
术语“canary”(作为一种检测方法)的起源最初是由那些在矿井深处工作的人使用的,他们会带上一只金丝雀(鸟)来检测气体或其他需要离开的原因。如果鸟儿开始行为异常,他们就会知道出了问题。这个概念在安全领域也得到了应用,也被称为“canary”。
同样,Canary
库允许你定义可以用于检测某些数据被使用并使用多种方法通知你的键/值组合,包括默认的PHP错误日志、通过 Monolog
的日志处理以及发送到 Slack
通道的消息。
例如,你可能生成一个特殊的用户名,你希望用作触发器。这个用户名实际上不是你系统中的用户,但你确实希望在尝试使用它进行登录时收到通知。Canary
通过定义带有 if
方法的检查,以及可选的带有 then
方法的处理程序,使这变得简单。例如,假设我们生成了用户名 canary1234@foo.com
,我们想检测它是否被使用。你可以这样定义一个 Canary
表达式
<?php $_POST = [ 'username' => 'canary1234@foo.com', 'password' => 'sup3rs3cr3t' ]; \Psecio\Canary\Instance::build()->if('username', 'canary1234@foo.com')->execute(); // Or you can set multiple match values to look for with an array $matches = [ 'username' => 'canary1234@foo.com', 'password' => 'sup3rs3cr3t' ]; \Psecio\Canary\Instance::build()->if($matches)->execute(); ?>
在这个例子中,我们正在查看当前输入,并检查是否存在值为 canary1234@foo.com
的 username
。在我们的当前 $_POST
值的情况下,有一个匹配。默认情况下(如果没有定义 then
处理程序),匹配的信息会输出到错误中(通过 Psecio\Canary\Notify\ErrorLog
处理程序)。JSON编码的结果如下所示
{"type":"equals","key":"username","value":"canary1234@foo.com"}
注意: Canary 会自动提取
$_GET
和$_POST
超全局值进行评估,因此您不需要手动传递。
使用外部数据源
Canary
还允许您使用一个(静态)类方法来提供评估的 if
部分的数据。要使用它,只需传递类和静态方法名作为字符串
<?php
$classMethod = '\Foo\Bar::criteria';
\Psecio\Canary\Instance::build()->if($classMethod)->execute();
?>
此方法返回必须是数组,否则将抛出异常。
支持的通知方法
目前 Canary
支持以下通知方法
创建自定义处理程序(回调)
如果您不想将结果发送到错误日志,您可以通过 then
方法创建自己的处理程序。目前唯一支持的定制处理程序是可调用方法。所以,如果我们想向使用特殊用户名的用户输出一条消息并终止脚本,我们可能会使用如下代码
<?php $_POST = ['username' => 'canary1234@foo.com']; \Psecio\Canary\Instance::build()->if('username', 'canary1234@foo.com') ->then(function($criteria) { die("You shouldn't have done that!"); }) ->execute(); ?>
在这个处理程序中,当检测到用户名值符合我们的标准时,回调将被执行,并且 die
调用终止脚本。
传递自定义数据
如果您不想自动加载当前的 $_GET
和 $_POST
值,您也可以提供自己的数据集。要传递数据,您可以在配置中使用 data
值
<?php $config = ['data' => [ 'username' => 'foobar@baz.com' ]]; \Psecio\Canary\Instance::build($config)->if('username', 'canary1234@foo.com')->execute(); ?>
使用默认记录器
您可以通过在 build()
配置选项中的 notify
键中将它设置为默认记录器,为所有 if
检查设置它
<?php // create a log channel $log = new Logger('name'); $log->pushHandler(new StreamHandler('/tmp/mylog.log', Logger::WARNING)); $config = [ 'notify' => $log ]; \Psecio\Canary\Instance::build($config)->if('username', 'canary1234@foo.com')->execute(); ?>
注意: 如果您通过
notify
配置提供了默认处理程序,它将覆盖所有其他自定义通知方法。
使用 Monolog
Canary
工具还允许您使用 Monolog 日志库来定义数据结构和输出的一些更详细的定制。和之前一样,我们创建 Canary
实例,但在 then
方法的输入中,我们提供 Monolog\Logger
实例。
<?php use Monolog\Logger; use Monolog\Handler\StreamHandler; require_once 'vendor/autoload.php'; $_GET = ['username' => 'test']; // create a log channel $log = new Logger('name'); $log->pushHandler(new StreamHandler('/tmp/mylog.log', Logger::WARNING)); \Psecio\Canary\Instance::build() ->if('username', 'canary1234@foo.com') ->then($log) ->execute(); ?>
使用 Slack
您还可以使用 Maknz\Slack 库在触发 canary 时向 Slack 发送消息。
<?php $settings = [ 'channel' => '#my-channel-name', 'link_names' => true ]; $slack = new Maknz\Slack\Client('https://hooks.slack.com/services/.....', $settings); \Psecio\Canary\Instance::build($config)->if('username', 'canary1234@foo.com')->then($slack); ?>
您需要设置一个入站 webhook,并用您提供的自定义 URL 替换 Client
创建中的 URL 值。通知的默认名称为 Canary Agent
,输出包括与其他通知方法相同的 JSON 信息。
使用 PagerDuty
Canary
还允许您使用 nmcquay/pagerduty 库向 PagerDuty 服务发送通知。
<?php $pager = new \PagerDuty\Event(); $pager->setServiceKey('[.... your service ID ....]'); \Psecio\Canary\Instance::build($config)->if('username', 'canary1234@foo.com')->then($pager); ?>
您可以通过访问服务页面(https://[your domain].pagerduty.com/services
)并点击您要使用的服务来找到服务 ID。ID 在“集成”选项卡下作为“集成密钥”。