253 lines
5.9 KiB
Plaintext
253 lines
5.9 KiB
Plaintext
|
|
#!/usr/bin/env perl
|
||
|
|
use strict;
|
||
|
|
use warnings;
|
||
|
|
|
||
|
|
our $VERSION = '1.1.0';
|
||
|
|
|
||
|
|
use 5.14.2;
|
||
|
|
|
||
|
|
use English qw( $PID );
|
||
|
|
use JSON::PP;
|
||
|
|
use JSON::RPC::Dispatch;
|
||
|
|
use Log::Any qw( $log );
|
||
|
|
use Log::Any::Adapter;
|
||
|
|
use POSIX;
|
||
|
|
use Plack::Builder;
|
||
|
|
use Plack::Response;
|
||
|
|
use Router::Simple::Declare;
|
||
|
|
use Try::Tiny;
|
||
|
|
|
||
|
|
BEGIN {
|
||
|
|
$ENV{PERL_JSON_BACKEND} = 'JSON::PP';
|
||
|
|
undef $ENV{LANGUAGE};
|
||
|
|
};
|
||
|
|
|
||
|
|
use Zonemaster::Backend::RPCAPI;
|
||
|
|
use Zonemaster::Backend::Config;
|
||
|
|
use Zonemaster::Backend::Metrics;
|
||
|
|
|
||
|
|
local $| = 1;
|
||
|
|
|
||
|
|
Log::Any::Adapter->set(
|
||
|
|
'+Zonemaster::Backend::Log',
|
||
|
|
log_level => $ENV{ZM_BACKEND_RPCAPI_LOGLEVEL},
|
||
|
|
json => $ENV{ZM_BACKEND_RPCAPI_LOGJSON},
|
||
|
|
stderr => 1
|
||
|
|
);
|
||
|
|
|
||
|
|
$SIG{__WARN__} = sub {
|
||
|
|
$log->warning(map s/^\s+|\s+$//gr, map s/\n/ /gr, @_);
|
||
|
|
};
|
||
|
|
|
||
|
|
my $config = Zonemaster::Backend::Config->load_config();
|
||
|
|
|
||
|
|
Zonemaster::Backend::Metrics->setup($config->METRICS_statsd_host, $config->METRICS_statsd_port);
|
||
|
|
Zonemaster::Engine::init_engine();
|
||
|
|
|
||
|
|
builder {
|
||
|
|
enable sub {
|
||
|
|
my $app = shift;
|
||
|
|
|
||
|
|
# Make sure we can connect to the database
|
||
|
|
$config->new_DB();
|
||
|
|
|
||
|
|
return $app;
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
my $handler = Zonemaster::Backend::RPCAPI->new( { config => $config } );
|
||
|
|
|
||
|
|
my $router = router {
|
||
|
|
############## FRONTEND ####################
|
||
|
|
connect "version_info" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "version_info"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "system_versions" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "system_versions"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "profile_names" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "profile_names"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "conf_profiles" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "conf_profiles"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "get_language_tags" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "get_language_tags"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "conf_languages" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "conf_languages"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "get_host_by_name" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "get_host_by_name"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "lookup_address_records" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "lookup_address_records"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "get_data_from_parent_zone" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "get_data_from_parent_zone"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "lookup_delegation_data" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "lookup_delegation_data"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "start_domain_test" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "start_domain_test"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "job_create" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "job_create"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "test_progress" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "test_progress"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "job_status" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "job_status"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "get_test_params" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "get_test_params"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "job_params" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "job_params"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "get_test_results" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "get_test_results"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "job_results" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "job_results"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "get_test_history" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "get_test_history"
|
||
|
|
};
|
||
|
|
|
||
|
|
# Experimental
|
||
|
|
connect "domain_history" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "domain_history"
|
||
|
|
};
|
||
|
|
|
||
|
|
connect "batch_status" => {
|
||
|
|
handler => $handler,
|
||
|
|
action => "batch_status"
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
if ( $config->RPCAPI_enable_user_create or $config->RPCAPI_enable_add_api_user ) {
|
||
|
|
$log->info('Enabling add_api_user method');
|
||
|
|
$router->connect("add_api_user", {
|
||
|
|
handler => $handler,
|
||
|
|
action => "add_api_user"
|
||
|
|
});
|
||
|
|
$router->connect("user_create", {
|
||
|
|
handler => $handler,
|
||
|
|
action => "user_create"
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( $config->RPCAPI_enable_batch_create or $config->RPCAPI_enable_add_batch_job ) {
|
||
|
|
$log->info('Enabling add_batch_job method');
|
||
|
|
$router->connect("add_batch_job", {
|
||
|
|
handler => $handler,
|
||
|
|
action => "add_batch_job"
|
||
|
|
});
|
||
|
|
$router->connect("batch_create", {
|
||
|
|
handler => $handler,
|
||
|
|
action => "batch_create"
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
my $dispatch = JSON::RPC::Dispatch->new(
|
||
|
|
router => $router,
|
||
|
|
);
|
||
|
|
|
||
|
|
my $rpcapi_app = sub {
|
||
|
|
my $env = shift;
|
||
|
|
my $req = Plack::Request->new($env);
|
||
|
|
my $res = {};
|
||
|
|
my $content = {};
|
||
|
|
my $json_error = '';
|
||
|
|
try {
|
||
|
|
my $json = $req->content;
|
||
|
|
$content = decode_json($json);
|
||
|
|
} catch {
|
||
|
|
$json_error = (split /at \//, $_)[0];
|
||
|
|
};
|
||
|
|
|
||
|
|
if ($json_error eq '') {
|
||
|
|
my $errors = $handler->jsonrpc_validate($content);
|
||
|
|
if ($errors ne '') {
|
||
|
|
$res = Plack::Response->new(200);
|
||
|
|
$res->content_type('application/json');
|
||
|
|
$res->body( encode_json($errors) );
|
||
|
|
$res->finalize;
|
||
|
|
} else {
|
||
|
|
local $log->context->{rpc_method} = $content->{method};
|
||
|
|
$res = $dispatch->handle_psgi($env, $env->{REMOTE_ADDR});
|
||
|
|
my $status = Zonemaster::Backend::Metrics->code_to_status(decode_json(@{@$res[2]}[0])->{error}->{code});
|
||
|
|
Zonemaster::Backend::Metrics::increment("zonemaster.rpcapi.requests.$content->{method}.$status");
|
||
|
|
$res;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
$res = Plack::Response->new(200);
|
||
|
|
$res->content_type('application/json');
|
||
|
|
$res->body( encode_json({
|
||
|
|
jsonrpc => '2.0',
|
||
|
|
id => undef,
|
||
|
|
error => {
|
||
|
|
code => '-32700',
|
||
|
|
message => 'Invalid JSON was received by the server.',
|
||
|
|
data => "$json_error"
|
||
|
|
}}) );
|
||
|
|
$res->finalize;
|
||
|
|
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
builder {
|
||
|
|
enable "Plack::Middleware::ReverseProxy";
|
||
|
|
mount "/" => $rpcapi_app;
|
||
|
|
};
|