27
Angelos github.com/dann dann 優しいモダンな WAFの作り方 dann [email protected] YAPC::Asia 2009 2009/09/10

優しいWAFの作り方

Embed Size (px)

Citation preview

Page 1: 優しいWAFの作り方

Angelos github.com/dann dann

優しいモダンなWAFの作り方

[email protected]

YAPC::Asia 2009 2009/09/10

Page 3: 優しいWAFの作り方

Angelos github.com/dann dann

Presentation Overview

•モダンなWAFとは•モダンなWAFの基本構成要素の作り方•モダンなWAFの拡張の作り方•まとめ

Page 4: 優しいWAFの作り方

Angelos github.com/dann dann

モダンなWAFとは

•Plaggerのようにプラガブル•WSGIのようなサーバー抽象化•Railsのようにフルスタック ユーザービリティ

拡張性

テスタビリティ

Page 5: 優しいWAFの作り方

Angelos github.com/dann dann

WAFの基本構成要素の作り方

Page 6: 優しいWAFの作り方

Angelos github.com/dann dann

WAFの最小構成要素

ComponentManagerDispatcher

Enginerequestを受けてresponseを返す

(サーバー抽象化 with Plack)

miyagawa++, tokuhirom++

URL to Controller名 コントローラなどのComponentのload & search

Page 7: 優しいWAFの作り方

Angelos github.com/dann dann

WAFの基本処理シーケンス

②①

④⑤

テキスト

Page 8: 優しいWAFの作り方

Angelos github.com/dann dann

Engine - Angelos::Engine

sub build_engine { my $self = shift; my $request_handler = $self->request_handler; $request_handler ||= $self->build_request_handler;

return Angelos::PSGI::Engine->new( interface => { module => $self->server, .... }, psgi_handler => $request_handler, ); }

リクエストを受けて、レスポンスを返すEngine(サーバー抽象化)

Server Gatewayに渡すpsgiのhandler

Server Gatewayの種別

Page 9: 優しいWAFの作り方

Angelos github.com/dann dann

Engine - Angelos::PSGI::Engine

use Mouse;use Angelos::Types qw( ServerGateway ); has 'interface' => (    is => 'ro',    isa => ServerGateway,    coerce => 1,); has 'psgi_handler' => ( is => 'rw', ); sub run {    my $self = shift;    $self->interface->run( $self->psgi_handler );}

Server Gatewayにpsgiのhandler (coderef)

を渡して実行

Server Gateway作成

Page 10: 優しいWAFの作り方

Angelos github.com/dann dann

Server Gatewayの生成

package Angelos::PSGI::ServerGatewayBuilder;use strict;use warnings;use Plack::Loader;

sub build { my ( $class, $module, $args ) = @_; my $server_gateway = Plack::Loader->load( $module, %{$args} ); $server_gateway;}

Plack::LoaderでServerGateway名渡して生成

Plack::Loaderでmodule指定してload

Page 11: 優しいWAFの作り方

Angelos github.com/dann dann

psgi handlerのコード

...sub { my $env = shift; my $req = Angelos::Request->new($env); my $res = $self->handle_request($req); my $psgi_res = $self->finalize_response($res); return $psgi_res;}... PSGIのresponse形式にして返す

PSGIのenvを受け取ってWAFのRequestに

(with Plack::Request)

Page 12: 優しいWAFの作り方

Angelos github.com/dann dann

Request Handler - Angelos::Engine::Base

sub handle_request { my ( $self, $req ) = @_;

eval { $self->DISPATCH($req); }; if ( my $e = Exception::Class->caught() ) { $self->HANDLE_EXCEPTION($e); }

# responseを返す return $self->context->res;}

②reqをDsipatcherでディスパッチ

①リクエスト受信

Page 13: 優しいWAFの作り方

Angelos github.com/dann dann

ディスパッチ処理sub DISPATCH { my ( $self, $req ) = @_;

my $dispatch = $self->dispatcher->dispatch($req); ...

# dispatch処理を実行 $dispatch->run;

# responseを返す $c->res;}

②requestをDispatcherにdispatch

Page 14: 優しいWAFの作り方

Angelos github.com/dann dann

Angelos::Dispatchersub dispatch { my ( $self, $request ) = @_;

my $match = $self->router->match($request);

my $dispatch = $self->dispatch_class->new( match => $match ); return $dispatch;}

③ <URL to Controller>HTTP::Routerでrequestにマッチするrouteを取得 (ikasam_a++)

④ dispatch生成

Page 15: 優しいWAFの作り方

Angelos github.com/dann dann

Angelos::Dispatcher::Dispatch

# matching情報からcontroller名取得my $controller = $match->params->{controller};

my $controller_instance = $self->find_controller_instance( { context => $c, controller => $controller, }); ...

$controller_instance->_dispatch_action( $action, $params );

⑤Component ManagerからController検索

⑥Controllerのaction実行後レスポンスを返す

Page 16: 優しいWAFの作り方

Angelos github.com/dann dann

WAFの基本部分完成

•これで基本部分は完成です•シンプルなWAFは2-3時間あれば作れちゃいます

Page 17: 優しいWAFの作り方

Angelos github.com/dann dann

WAFの拡張部分の作り方(Plugin)

Page 18: 優しいWAFの作り方

Angelos github.com/dann dann

優しいプラグインの作り方

•WAFの拡張性のあるべき姿•プラグインの種類•プラグインの実現方法の種類•Angelosでのプラグインの作り方

Page 19: 優しいWAFの作り方

Angelos github.com/dann dann

WAFの拡張性のあるべき姿

•コアは小さく、何でも拡張/交換可能に•拡張箇所を限定し、適切な箇所を拡張可能に

•Controller, View, Middleware, Request, Response

•Hookポイントを明示的に

Page 20: 優しいWAFの作り方

Angelos github.com/dann dann

プラグインの種類

•大きく分けて二つ•ライフサイクルへのHook系•メソッド生やす系

Page 21: 優しいWAFの作り方

Angelos github.com/dann dann

プラグインの実現方法•ライフサイクルへのHook系•MouseのRole + method modifier•Class::Trigger•MouseX::Object::Pluggable•メソッド生やす系•MouseのRole•Exporter•多重継承

Page 22: 優しいWAFの作り方

Angelos github.com/dann dann

Angelosでのプラグイン機構の作り方•Pluginを Roleに•Plugin(Role)は Component(たとえばController)にwithすることで使う

•HookポイントとしてのModifier•RoleのmodifierでComponentのHook point(メソッド)にHook

•Hook pointの明示をメソッド名の規約(大文字)で

Page 23: 優しいWAFの作り方

Angelos github.com/dann dann

Hookが定義されているControllerのコード

sub _dispatch_action { my ( $self, $action, $params ) = @_; ...

eval { $self->ACTION( $self->context, $action, $params ); }; ...

}

Hookポイントを明示(大文字で)

Page 24: 優しいWAFの作り方

Angelos github.com/dann dann

プラグインのコードbefore 'ACTION' => sub { my ( $self, $c, $action, $params ) = @_; $self->__action_start_time( time() );};

after 'ACTION' => sub { my ( $self, $c, $action, $params ) = @_; $self->__action_end_time( time() );

my $elapsed = $self->__action_end_time - $self->__action_start_time; my $message = "action processing time:\naction: $action \ntime : $elapsed secs\n"; $self->log->info($message);};

Page 25: 優しいWAFの作り方

Angelos github.com/dann dann

拡張を提供したときにセットですべきこと

•適切なデフォルトセットの提供•WAF全体の拡張の推奨セットを用意する•デフォルトセットが無いと...•Unicode化するためのTipsが乱立...•Inflate, DeflateするためのTipsが...

Page 26: 優しいWAFの作り方

Angelos github.com/dann dann

まとめ•WAFの基本構成要素•Engine, Dispatcher, Component Loader

•WAFの拡張(Plugin)•Hook系とメソッド生やす系の二つ•Scopeを限定してComponent毎に用意•Pluginとデフォルトセットはペアで

Page 27: 優しいWAFの作り方

Angelos github.com/dann dann

最後に•WAF作りがかつてないほど簡単に!•次の世代のWAFに興味のある方は開発にも是非ご参加ください :)

•開発はgithubで•http://github.com/dann/angelos/tree/master