NAME
Catalyst::Controller::ElasticSearch - Thin proxy for ElasticSearch with some protection
VERSION
version 0.1.0
DESCRIPTION
This controller base class provides some basic protection for your ElasticSearch server. This will allow you to publish individual indices and types through your Catalyst application. The controller will prevent malicious requests such as huge size parameters or scripts.
ElasticSearch's _search
endpoint is very powerful. And with power comes great responsibility. Instead of providing the vanilla search endpoint, it is recommeded that you predefine searches that process only certain parameters. See "DISABLING FEATURES".
Exposing ElasticSearch to the Internet is dangerous. MetaCPAN is doing it, and this module is the result of what we've learned so far.
SYNOPSIS
package MyApp::Model::ElasticSearch;
use Moose;
use ElasticSearch
extends 'Catalyst::Model';
has es => (
is => "ro",
default => sub { ElasticSearch->new },
);
package MyApp::Controller::Twitter;
use Moose;
extends "Catalyst::Controller::ElasticSearch";
__PACKAGE__->config(
model_class => "ElasticSearch",
index => "twitter",
);
package MyApp::Controller::Twitter::Tweet;
use Moose;
extends "MyApp::Controller::Twitter";
__PACKAGE__->config(
type => "tweet",
# defaults
max_size => 5000,
allow_scripts => 0,
get_raw => 1,
);
CONFIGURATION
model_class
The name of your model class that connects to ElasticSearch. Basically the name you would use to access it via "model" in Catalyst.
This controller is very flexible and accepts any model class that provides a _es
or es
method that returns a ElasticSearch instance.
If you want to use ElasticSearchX::Model classes in the controller, provide a esxmodel
method in your model that will return an instance of ElasticSearchX::Model.
index
The ElasticSearch index this controller will handle. "index" and "type" can also be ArrayRefs or _all
. See ElasticSearch for more information.
type
The ElasticSearch type this controller will handle. The type is optional.
max_size
Defaults to 5000. A http status 416 is returned in case the user exceed the size limit. The size parameter is evaluated both from the query parameter as well as in the request body.
Setting max_size to 0
will disabled the check.
raw_get
Disable to only retrieve the _source
or fields
key if requesting a resource by its ID (i.e. no searching). This might be more convenient because the client doesn't has to traverse to the actual data but it also breaks clients that expect the ElasticSearch format that includes type and index information.
allow_scripts
Malicious scripts for scoring can cause the ElasticSearch server to spin or even execute commands on the server. By default, scripts are not enabled.
DISABLING FEATURES
If you want to disable certain features such as search, get or mapping, feel free to override the corresponding methods.
sub search {
my ($self, $c) = @_;
$c->detach("error", [403, "Disabled _search"]);
}
sub by_color : Path : Args(1) {
my ($self, $c, $color) = @_;
my $model = $self->model($c); # does security checks
eval { $c->stash(
$model->es->search(
index => $self->index,
type => $self->type,
size => $model->size,
) );
} or do { $c->detach("error", [500, $@]) };
}
ENDPOINTS
By default, this controller will create the following endpoints for a controller named MyApp::Controller::Tweet
.
mapping
/twitter/tweet/_mapping
This will return the ElasticSearch mapping.
get
/twitter/tweet/$id
Will return the document $id
. If "raw_get" is set to false, the returned JSON will not include the ElasticSearch metadata. Instead the _source
or fields
property is returned.
all
/twitter/tweet
This endpoint is equivalent to /tweet/_search?q=*
.
search
/twitter/tweet/_search
This endpoint proxies to the search endpoint of ElasticSearch. However, it will sanitize the query first.
ACCESS CONTROL
As with other controllers, you would do the access control in the auto
action.
sub auto : Private {
my ($self, $c) = @_;
return $c->detach("error", [403, "Unauthorized"])
unless $c->user->is_admin;
return 1; # return 1 to proceed
}
PRIVATE ACTIONS
error
$c->detach("error", [404, "Not found"]);
$c->detach("error", [$code, $message]);
This helper action can be used to return a error message to the client. The client will receive a JSON response that includes the message and the error code. If the message is a ElasticSearch::Error, the corresponding error message will be retrieved from the object.
AUTHOR
Moritz Onken <onken@netcubed.de>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2013 by Moritz Onken.
This is free software, licensed under:
The MIT (X11) License