From 1c2c8cf4fd69f670b5f9a124c492d7a67bd70c3e Mon Sep 17 00:00:00 2001 From: Gerhard Jungwirth Date: Thu, 12 May 2016 13:00:38 +0200 Subject: [PATCH] MT#19765 add subscriberlogin for API in line with the web-login, a domain can be specified or defaults to the request host. because validating the format "username@domain" is not supported natively by the catalyst HTTP auth plugin, the domain is checked manually at the appropriate place. Change-Id: Ifcc86234bc27598244788d1b4b07c2611c2e593b --- lib/NGCP/Panel.pm | 17 +++++++++ .../AuthenticationStore/RoleFromRealm.pm | 2 +- lib/NGCP/Panel/Controller/API/RtcSessions.pm | 4 +-- .../Panel/Controller/API/RtcSessionsItem.pm | 2 +- lib/NGCP/Panel/Controller/Root.pm | 35 ++++++++++++++++++- lib/NGCP/Panel/Role/API/RtcSessions.pm | 6 ++++ 6 files changed, 61 insertions(+), 5 deletions(-) diff --git a/lib/NGCP/Panel.pm b/lib/NGCP/Panel.pm index 2627f02867..a3c840b33d 100644 --- a/lib/NGCP/Panel.pm +++ b/lib/NGCP/Panel.pm @@ -153,6 +153,23 @@ __PACKAGE__->config( }, use_session => 0, }, + api_subscriber_http => { + credential => { + class => 'HTTP', + #type => 'digest', + type => 'basic', + username_field => 'webusername', + password_field => 'webpassword', + password_type => 'clear', + }, + store => { + class => 'DBIx::Class', + user_model => 'DB::provisioning_voip_subscribers', + store_user_class => 'NGCP::Panel::AuthenticationStore::RoleFromRealm', + # use_userdata_from_session => 1, + }, + use_session => 0, + }, api_admin_system => { credential => { class => 'HTTP', diff --git a/lib/NGCP/Panel/AuthenticationStore/RoleFromRealm.pm b/lib/NGCP/Panel/AuthenticationStore/RoleFromRealm.pm index defde4f1e6..938577689f 100644 --- a/lib/NGCP/Panel/AuthenticationStore/RoleFromRealm.pm +++ b/lib/NGCP/Panel/AuthenticationStore/RoleFromRealm.pm @@ -12,7 +12,7 @@ sub roles { : return "reseller"; } } - foreach my $auth_type (qw/subscriber api_subscriber/) { + foreach my $auth_type (qw/subscriber api_subscriber_http/) { if ($auth_type eq $self->auth_realm) { $self->_user->admin ? return "subscriberadmin" : return "subscriber"; diff --git a/lib/NGCP/Panel/Controller/API/RtcSessions.pm b/lib/NGCP/Panel/Controller/API/RtcSessions.pm index 7062ea248e..3c76ca4ab9 100644 --- a/lib/NGCP/Panel/Controller/API/RtcSessions.pm +++ b/lib/NGCP/Panel/Controller/API/RtcSessions.pm @@ -41,7 +41,7 @@ __PACKAGE__->config( action => { map { $_ => { ACLDetachTo => '/api/root/invalid_user', - AllowedRole => [qw/admin reseller/], + AllowedRole => [qw/admin reseller subscriber subscriberadmin/], Args => 0, Does => [qw(ACL CheckTrailingSlash RequireSSL)], Method => $_, @@ -143,7 +143,7 @@ sub POST :Allow { } elsif($c->user->roles eq "reseller") { $resource->{reseller_id} = $c->user->reseller_id; # TODO: ? } else { - $resource->{subscriber_id} = $c->user->id; + $resource->{subscriber_id} = $c->user->voip_subscriber->id; } my $subscriber_item = $c->model('DB')->resultset('voip_subscribers')->search_rs({ diff --git a/lib/NGCP/Panel/Controller/API/RtcSessionsItem.pm b/lib/NGCP/Panel/Controller/API/RtcSessionsItem.pm index 78787a85ed..805521e601 100644 --- a/lib/NGCP/Panel/Controller/API/RtcSessionsItem.pm +++ b/lib/NGCP/Panel/Controller/API/RtcSessionsItem.pm @@ -39,7 +39,7 @@ __PACKAGE__->config( action => { (map { $_ => { ACLDetachTo => '/api/root/invalid_user', - AllowedRole => [qw/admin reseller/], + AllowedRole => [qw/admin reseller subscriber subscriberadmin/], Args => 1, Does => [qw(ACL RequireSSL)], Method => $_, diff --git a/lib/NGCP/Panel/Controller/Root.pm b/lib/NGCP/Panel/Controller/Root.pm index c900d9fd5e..19624d62f0 100644 --- a/lib/NGCP/Panel/Controller/Root.pm +++ b/lib/NGCP/Panel/Controller/Root.pm @@ -68,6 +68,7 @@ sub auto :Private { $c->log->debug("++++++ Root::auto unauthenticated API request"); my $ssl_dn = $c->request->env->{SSL_CLIENT_M_DN} // ""; my $ssl_sn = hex ($c->request->env->{SSL_CLIENT_M_SERIAL} // 0); + my $ngcp_api_realm = $c->request->env->{NGCP_API_REALM} // ""; if($ssl_sn) { $c->log->debug("++++++ Root::auto API request with client auth sn '$ssl_sn'"); unless($ssl_dn eq "/CN=Sipwise NGCP API client certificate") { @@ -113,10 +114,42 @@ sub auto :Private { $c->log->warn("invalid api system login from '".$c->req->address."'"); } + $self->api_apply_fake_time($c); + return 1; + } elsif ($ngcp_api_realm eq "subscriber") { + $c->log->debug("++++++ Root::auto API subscriber request with http auth"); + my $realm = "api_subscriber_http"; + my ($username,$password) = $c->req->headers->authorization_basic; + my ($u,$d) = split(/\@/,$username); + if ($d) { + $c->req->headers->authorization_basic($u,$password); + } + my $res = $c->authenticate({}, $realm); + + if($c->user_exists) { + $d //= $c->req->uri->host; + $c->log->debug("++++++ checking '".$c->user->domain->domain."' against '$d'"); + if ($c->user->domain->domain ne $d) { + $c->user->logout; + $c->log->debug("+++++ invalid api subscriber http login (domain check failed)"); + $c->log->warn("invalid api http login from '".$c->req->address."'"); + my $r = $c->get_auth_realm($realm); + $r->credential->authorization_required_response($c, $r); + return; + } + $c->log->debug("++++++ subscriber '".$c->user->webusername."' authenticated via api_subscriber_http"); + } else { + $c->user->logout if($c->user); + $c->log->debug("+++++ invalid api subscriber http login"); + $c->log->warn("invalid api http login from '".$c->req->address."'"); + my $r = $c->get_auth_realm($realm); + $r->credential->authorization_required_response($c, $r); + return; + } $self->api_apply_fake_time($c); return 1; } else { - $c->log->debug("++++++ Root::auto API request with http auth"); + $c->log->debug("++++++ Root::auto API admin request with http auth"); my $realm = "api_admin_http"; my $res = $c->authenticate({}, $realm); diff --git a/lib/NGCP/Panel/Role/API/RtcSessions.pm b/lib/NGCP/Panel/Role/API/RtcSessions.pm index 5ae06a1437..390f58e3cc 100644 --- a/lib/NGCP/Panel/Role/API/RtcSessions.pm +++ b/lib/NGCP/Panel/Role/API/RtcSessions.pm @@ -75,6 +75,12 @@ sub item_rs { },{ join => {subscriber => { voip_subscriber => { contract => 'contact' }}}, }); + } else { + $item_rs = $item_rs->search({ + 'subscriber.id' => $c->user->id, + },{ + join => 'subscriber', + }); } return $item_rs;