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 16, 2024
1 parent 579890c commit 188b16a
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 76 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
50 changes: 31 additions & 19 deletions lib/Thruk/Backend/Peer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,13 @@ sub cmd {
$background_options->{"cmd"} = $cmd;
}
if($self->{'type'} eq 'http') {
if($self->{'federation'} && scalar @{$self->{'fed_info'}->{'type'}} >= 2 && $self->{'fed_info'}->{'type'}->[1] eq 'http') {
# is the machine reachable by 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 All @@ -359,7 +363,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 +372,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], { 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);
}

return($rc, $out);
Expand All @@ -413,7 +425,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 +492,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
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
16 changes: 14 additions & 2 deletions lib/Thruk/Controller/proxy.pm
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,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 +115,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
129 changes: 104 additions & 25 deletions lib/Thruk/Utils.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ returns url with optional proxy prepended
sub proxifiy_me {
my($c, $peer_id) = @_;
return unless $peer_id;
my $thruk_url = get_remote_thruk_url($c, $peer_id);
my $thruk_url = get_remote_thruk_url_path($c, $peer_id);
return unless $thruk_url;
my $url = $c->req->uri;
$url =~ s|^https?://[^/]+/|/|mx;
Expand All @@ -1314,61 +1314,140 @@ sub proxifiy_me {

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

=head2 get_remote_thruk_url
=head2 get_remote_thruk_url_path
get_remote_thruk_url($c, $peer_key, [$full])
get_remote_thruk_url_path($c, $peer_key)
return url for remote thruk installation
returns path of last http address/thruk instance in chain
=cut
sub get_remote_thruk_url {
sub get_remote_thruk_url_path {
my($c, $id, $full) = @_;
my $peer = $c->db->get_peer_by_key($id);
confess("got no peer for id: ".$id) unless $peer;
my $url = "";
if($peer->{'fed_info'} && $peer->{'fed_info'}->{'addr'}) {
# use last address which starts with http
for my $u (reverse @{$peer->{'fed_info'}->{'addr'}}) {
if($u =~ m|^https?:|mx) {
if($u =~ m%^https?:%mx) {
$url = $u;
last;
}
}
}
if($peer->{'type'} eq 'http' && (!$url || $url !~ /^https?:/mx)) {
$url = $peer->{'addr'};
if(!$url || $url !~ m/^https?:\/\//mx) {
for my $u (reverse @{$peer->peer_list()}) {
if($u =~ m%^https?:%mx) {
$url = $u;
last;
}
}
}
return($url || "") if $full;
if($url) {
if($url !~ m/^https?:\/\//mx) {
return("");
if(!$url || $url !~ m/^https?:\/\//mx) {
return("");
}

$url =~ s|^https?://[^/]*/?|/|gmx;
$url =~ s|cgi-bin\/remote\.cgi$||gmx;
$url =~ s|thruk/?$||gmx;
$url =~ s|/$||gmx;
$url = $url.'/thruk/';

return($url);
}

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

=head2 get_remote_thruk_hostname
get_remote_thruk_hostname($c, $peer_key)
returns hostname and url of last none-local address
=cut
sub get_remote_thruk_hostname {
my($c, $id) = @_;

my $peer = $c->db->get_peer_by_key($id);
confess("got no peer for id: ".$id) unless $peer;

my $url = "";
if($peer->{'fed_info'} && $peer->{'fed_info'}->{'addr'}) {
for my $u (reverse @{$peer->{'fed_info'}->{'addr'}}) {
next if $u =~ m%(127\.0\.0\.|localhost|::1|^/)%mx;
if($u =~ m%^(https?:|.*:\d+)%mx) {
$url = $u;
last;
}
}
}

if(!$url) {
for my $u (reverse @{$peer->peer_list()}) {
next if $u =~ m%(127\.0\.0\.|localhost|::1|^/)%mx;
if($u =~ m%^(https?:|.*:\d+)%mx) {
$url = $u;
last;
}
}
$url =~ s|^https?://[^/]*/?|/|gmx;
$url =~ s|cgi-bin\/remote\.cgi$||gmx;
$url =~ s|thruk/?$||gmx;
$url =~ s|/$||gmx;
$url = $url.'/thruk/';
}
return($url || "");

return unless $url;

if($url =~ m|^(https?)://([^/]+)/([^/]+)/|gmx) {
return($2, $url);
}

if($url =~ m|^(.*):(\d+)|gmx) {
return($1, $url);
}

return;
}

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

=head2 get_remote_thruk_url_full
=head2 get_remote_thruk_site_name
get_remote_thruk_url_full($c, $peer_key)
get_remote_thruk_site_name($c, $peer_key)
returns ($proto, $hostname, $site)
returns site name of peer
=cut
sub get_remote_thruk_url_full {
sub get_remote_thruk_site_name {
my($c, $id) = @_;
my $url = get_remote_thruk_url($c, $id, 1);

my $peer = $c->db->get_peer_by_key($id);
confess("got no peer for id: ".$id) unless $peer;

my $url = "";
if($peer->{'fed_info'} && $peer->{'fed_info'}->{'addr'}) {
for my $u (reverse @{$peer->{'fed_info'}->{'addr'}}) {
if($u =~ m%^(https?:|/omd/sites/)%mx) {
$url = $u;
last;
}
}
}

if(!$url) {
for my $u (reverse @{$peer->peer_list()}) {
if($u =~ m%^(https?:|/omd/sites/)%mx) {
$url = $u;
last;
}
}
}

return unless $url;

if($url =~ m|^(https?)://([^/]+)/([^/]+)/|gmx) {
return($1, $2, $3);
return($3);
}

if($url =~ m|^/omd/sites/([^/]+)/|gmx) {
return($1);
}

return;
}

Expand Down
16 changes: 16 additions & 0 deletions lib/Thruk/Utils/CLI.pm
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,22 @@ sub _internal_request {
delete $Thruk::thruk->{'TRANSFER_USER'} if $app->{'thruk'};
$Thruk::thruk->{'TRANSFER_USER'} = $user if defined $user;

# serve static files internally
if($url =~ m%/thruk/(vendor|javascript|themes)/%mx) {
my $file = Thruk->config->{home}.'/root'.$url;
if(-f $file) {
require Plack::MIME;
my $content_type = Plack::MIME->mime_type($file) || 'text/plain';
return(undef, undef,
HTTP::Response->new(
200, "OK",
HTTP::Headers->new( Content_Type => $content_type ),
Thruk::Utils::IO::read($file),
),
);
}
}

my $request = HTTP::Request->new($method, $url);
$request->method(uc($method));
if($postdata) {
Expand Down
Loading

0 comments on commit 188b16a

Please sign in to comment.