Skip to content

Commit

Permalink
unify remote.cgi and proxy.cgi
Browse files Browse the repository at this point in the history
  • Loading branch information
sni committed Sep 18, 2024
1 parent f82714a commit 5e39b76
Show file tree
Hide file tree
Showing 17 changed files with 382 additions and 120 deletions.
3 changes: 2 additions & 1 deletion lib/Thruk.pm
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ sub startup {
$app = Plack::Middleware::Static->wrap($app,
path => sub {
my $p = Thruk::Context::translate_request_path($_, config());
return if $p =~ m%^/thruk/cgi\-bin/proxy\.cgi%mx;
return if $p =~ m%^/thruk/cgi\-bin/(remote|proxy)\.cgi%mx;
$p =~ /\.(css|png|js|gif|jpg|ico|html|wav|mp3|ogg|ttf|svg|woff|woff2|eot|map)$/mx;
},
root => './root/',
Expand Down Expand Up @@ -190,6 +190,7 @@ sub _build_app {
[ '^/thruk/r/v1.*' ,'Thruk::Controller::rest_v1::index' ],
[ '^/thruk/r/.*' ,'Thruk::Controller::rest_v1::index' ],
[ '^/thruk/cgi-bin/proxy.cgi/.*' ,'Thruk::Controller::proxy::index' ],
[ '^/thruk/cgi-bin/remote.cgi/.*' ,'Thruk::Controller::remote::index' ],
];

Thruk::Utils::Status::add_view({'group' => 'Main',
Expand Down
92 changes: 71 additions & 21 deletions lib/Thruk/Backend/Peer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -327,22 +327,27 @@ return result of cmd
=cut
sub cmd {
my($self, $c, $cmd, $background_options) = @_;
my($self, $c, $cmd, $background_options, $env) = @_;
my($rc, $out) = (0, "");
if($background_options) {
$background_options->{"background"} = 1;
$background_options->{"cmd"} = $cmd;
$background_options->{"env"} = $env;
}
if($self->{'type'} eq 'http') {
if($self->{'federation'} && scalar @{$self->{'fed_info'}->{'type'}} >= 2 && $self->{'fed_info'}->{'type'}->[1] eq 'http') {
# forward by http federation
if($self->{'federation'}
&& scalar @{$self->{'fed_info'}->{'type'}} >= 2
&& $self->{'fed_info'}->{'type'}->[1] eq 'http'
) {
require Thruk::Utils;
my $url = Thruk::Utils::get_remote_thruk_url($c, $self->{'key'});
my $url = Thruk::Utils::get_remote_thruk_url_path($c, $self->{'key'});

my $options = {
'action' => 'raw',
'sub' => 'Thruk::Utils::IO::cmd',
'remote_name' => $self->{'class'}->{'remote_name'},
'args' => [$cmd],
'args' => [$cmd, { env => $env }],
};
if($background_options) {
$options->{'sub'} = 'Thruk::Utils::External::cmd';
Expand All @@ -359,7 +364,7 @@ sub cmd {
my $req = HTTP::Request->new('POST', $url.'cgi-bin/remote.cgi', $header, $postdata);

require Thruk::Controller::proxy;
my $res = Thruk::Controller::proxy::proxy_request($c, $self->{'key'}, $url.'cgi-bin/remote.cgi', $req);
my $res = Thruk::Controller::proxy::proxy_request($c, $self->{'key'}, $url.'cgi-bin/remote.cgi', $req);
my $result;
eval {
$result = Cpanel::JSON::XS::decode_json($res->content());
Expand All @@ -368,31 +373,39 @@ sub cmd {
if($err) {
die(Thruk::Utils::http_response_error($res));
}
if(ref $result->{'output'} ne 'ARRAY') {
$out = $result->{'output'};
$rc = -1;
return($rc, $out);
}
($rc, $out) = @{$result->{'output'}};
if($background_options) {
($out) = @{$result->{'output'}};
}
return($rc, $out);
}

if($background_options) {
($out) = @{$self->{'class'}->request("Thruk::Utils::External::cmd", ['Thruk::Context', $background_options], { timeout => 120 })};
} else {
if($background_options) {
($out) = @{$self->{'class'}->request("Thruk::Utils::External::cmd", ['Thruk::Context', $background_options], { timeout => 120 })};
} else {
($rc, $out) = @{$self->{'class'}->request("Thruk::Utils::IO::cmd", [$cmd], { timeout => 120 })};
}
($rc, $out) = @{$self->{'class'}->request("Thruk::Utils::IO::cmd", [$cmd, { env => $env }], { timeout => 120 })};
}
return($rc, $out);

} elsif(my $http_peer = $self->get_http_fallback_peer()) {
}

if(my $http_peer = $self->get_http_fallback_peer()) {
my @args = @_;
shift @args;
return($http_peer->cmd(@args));
}
else {
if($background_options) {
require Thruk::Utils::External;
$out = Thruk::Utils::External::cmd($c, $background_options);
} else {
require Thruk::Utils::IO;
($rc, $out) = Thruk::Utils::IO::cmd($cmd);
}

if($background_options) {
require Thruk::Utils::External;
$out = Thruk::Utils::External::cmd($c, $background_options);
} else {
require Thruk::Utils::IO;
($rc, $out) = Thruk::Utils::IO::cmd($cmd, { env => $env });
}

return($rc, $out);
Expand All @@ -413,7 +426,7 @@ sub rpc {
if($self->{'type'} eq 'http') {
if($self->{'federation'} && scalar @{$self->{'fed_info'}->{'type'}} >= 2 && $self->{'fed_info'}->{'type'}->[1] eq 'http') {
require Thruk::Utils;
my $url = Thruk::Utils::get_remote_thruk_url($c, $self->{'key'});
my $url = Thruk::Utils::get_remote_thruk_url_path($c, $self->{'key'});

my $options = {
'action' => 'raw',
Expand Down Expand Up @@ -480,7 +493,7 @@ sub job_data {
if($self->{'type'} eq 'http') {
if($self->{'federation'} && scalar @{$self->{'fed_info'}->{'type'}} >= 2 && $self->{'fed_info'}->{'type'}->[1] eq 'http') {
require Thruk::Utils;
my $url = Thruk::Utils::get_remote_thruk_url($c, $self->{'key'});
my $url = Thruk::Utils::get_remote_thruk_url_path($c, $self->{'key'});

my $options = {
'action' => 'raw',
Expand Down Expand Up @@ -514,4 +527,41 @@ sub job_data {

##########################################################

=head2 is_peer_machine_reachable_by_http
is_peer_machine_reachable_by_http()
returns true if there is a thruk instance reachable by http for this peer
=cut
sub is_peer_machine_reachable_by_http {
my($self) = @_;

return if $self->is_local();

# check the last/final address in a federation setup and check whether it connects locally or not
if($self->{'federation'}) {
my $final_addr = $self->{'fed_info'}->{'addr'}->[scalar @{$self->{'fed_info'}->{'addr'}} - 1];
if($final_addr =~ m%^https?:%mx) {
return 1; # a final http address is ok
}
if($final_addr =~ m%:%mx) {
return; # final tcp connection does not work
}
# probably a final local unix address
return 1;
}

# nonlocal http connection
if($self->{'type'} eq 'http') {
return 1;
}

# TODO: what if there is a fallback http peer

return;
}

##########################################################

1;
2 changes: 1 addition & 1 deletion lib/Thruk/Config.pm
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ sub get_toolkit_config {
'get_broadcasts' => \&Thruk::Utils::Broadcast::get_broadcasts,
'command_disabled' => \&Thruk::Utils::command_disabled,
'proxifiy_url' => \&Thruk::Utils::proxifiy_url,
'get_remote_thruk_url' => \&Thruk::Utils::get_remote_thruk_url,
'get_remote_thruk_url_path' => \&Thruk::Utils::get_remote_thruk_url_path,
'basename' => \&Thruk::Base::basename,
'debug_details' => \&get_debug_details,
'format_date' => \&Thruk::Utils::format_date,
Expand Down
19 changes: 17 additions & 2 deletions lib/Thruk/Controller/proxy.pm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ sub index {
return $c->redirect_to($url);
}

$c->authenticate() unless $c->user_exists();
return $c->detach('/error/index/100') unless $c->user_exists();

my $res = proxy_request($c, $site, $url, $c->req);

$c->res->status($res->code);
Expand Down Expand Up @@ -81,13 +84,21 @@ sub proxy_request {
my $request_url = Thruk::Utils::absolute_url($peer->{'addr'}, $url, 1);

# federated peers forward to the next hop
my $passthrough;
my($passthrough, $add_key);
if($peer->{'federation'} && scalar @{$peer->{'fed_info'}->{'type'}} >= 2 && $peer->{'fed_info'}->{'type'}->[1] eq 'http') {
$request_url = $peer->{'addr'};
$request_url =~ s|/cgi\-bin/remote\.cgi$||gmx;
$request_url =~ s|/thruk/?$||gmx;
$request_url = $request_url.'/thruk/cgi-bin/proxy.cgi/'.$peer->{'key'};
$request_url = $request_url.'/thruk/cgi-bin/remote.cgi/'.$peer->{'key'};
$passthrough = '/thruk/cgi-bin/proxy.cgi/'.$peer->{'key'}.$url;
} else {
## TODO: only if normal http request fails or so...
#$request_url = $peer->{'addr'};
#$request_url =~ s|/cgi\-bin/remote\.cgi$||gmx;
#$request_url =~ s|/thruk/?$||gmx;
#$request_url = $request_url.'/thruk/cgi-bin/remote.cgi';
#$passthrough = $url;
#$add_key = 1;
}

if($base_req->{'env'}->{'QUERY_STRING'}) {
Expand All @@ -107,6 +118,10 @@ sub proxy_request {
if($passthrough) {
$req->header('X-Thruk-Passthrough', $passthrough);
}
if($add_key) {
$req->header('X-Thruk-Auth-Key', $peer->{'class'}->{'auth'});
$req->header('X-Thruk-Auth-User', $c->user->{'username'}) if $c->user_exists;
}
my $ua = Thruk::UserAgent->new({}, $c->config);
$ua->max_redirect(0);
Thruk::UserAgent::disable_verify_hostname_by_url($ua, $request_url);
Expand Down
26 changes: 25 additions & 1 deletion lib/Thruk/Controller/remote.pm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,31 @@ Thruk Controller.

##########################################################
sub index {
my($c) = @_;
my($c, $path_info) = @_;

# proxy request
if($c->req->header('X-Thruk-Passthrough')) {
if(!$c->user_exists) {
$c->authenticate(skip_db_access => 1);
}
if(!$c->user_exists) {
$c->res->code(401);
return $c->render("text" => 'not authorized');
}
# TODO: check why changes constantly
$c->user->set_dynamic_attributes($c);
require Thruk::Context;
require Thruk::Utils::CLI;
my $url = Thruk::Context::translate_request_path($c->req->header('X-Thruk-Passthrough'), $c->config);
my @res = Thruk::Utils::CLI::request_url($c, $url, undef, $c->req->method, $c->req->parameters);
if($res[1] && $res[1]->{'headers'}) {
$c->res->headers($res[1]->{'headers'}->clone());
}
$c->res->body($res[1]->{'result'} // $res[2]);
$c->res->code($res[0]);
$c->{'rendered'} = 1;
return;
}

Thruk::Utils::check_pid_file($c);

Expand Down
Loading

0 comments on commit 5e39b76

Please sign in to comment.