diff --git a/lib/NGCP/Panel.pm b/lib/NGCP/Panel.pm index c57cb73ed5..551a07f50a 100644 --- a/lib/NGCP/Panel.pm +++ b/lib/NGCP/Panel.pm @@ -153,6 +153,21 @@ __PACKAGE__->config( }, use_session => 0, }, + api_admin_system => { + credential => { + class => 'HTTP', + type => 'basic', + username_field => 'login', + password_field => 'password', + password_type => 'clear', + }, + store => { + class => '+NGCP::Panel::AuthenticationStore::System', + file => '/etc/default/ngcp-api', + group => 'auth_system', + }, + use_session => 0, + }, subscriber => { credential => { class => 'Password', diff --git a/lib/NGCP/Panel/AuthenticationStore/System.pm b/lib/NGCP/Panel/AuthenticationStore/System.pm new file mode 100644 index 0000000000..e3986d9175 --- /dev/null +++ b/lib/NGCP/Panel/AuthenticationStore/System.pm @@ -0,0 +1,87 @@ +package NGCP::Panel::AuthenticationStore::System; +use Sipwise::Base; +use Moose; +use namespace::autoclean; +use NGCP::Panel::AuthenticationStore::SystemRole; +use Config::Tiny; + +with 'MooseX::Emulate::Class::Accessor::Fast'; +use Scalar::Util qw( blessed ); + +__PACKAGE__->mk_accessors(qw/acl port user_class/); + +sub new { + my ( $class, $config, $app) = @_; + + my $group = $config->{group} + or die $class.": group is undefined in the config"; + my $file = delete $config->{file} + or die $class.": file is not specified in the config"; + my $api_cfg = Config::Tiny->read($file) + or die "Cannot read $file: $!"; + + my %data; + foreach my $key (keys %{$api_cfg->{_}}) { + my $val = $api_cfg->{_}{$key}; + next unless $key =~ s/^(${group}|NGCP_API)_//i; + $key = lc $key; + foreach my $t (qw(login password roles port)) { + $key eq $t and $data{$key} = $val; + } + } + + foreach my $key (qw(login password roles port)) { + die $class.": undefined $group $key parameter" unless $data{$key}; + } + + my $self = bless { + acl => { $data{login} => + { + login => $data{login}, + password => $data{password}, + roles => $data{roles}, + } }, + port => $data{port}, + user_class => $config->{user_class} || + "NGCP::Panel::AuthenticationStore::SystemRole", + }, $class; + + return $self; +} + +sub find_user { + my ( $self, $authinfo, $c ) = @_; + + return unless $self->port eq $c->request->env->{SERVER_PORT}; + + my $user = $authinfo->{stored} || + $self->acl->{$authinfo->{login}} || return; + my $username = $user->{login} || return; + + return unless exists $self->acl->{$username}; + + if (ref($user) eq "HASH") { + return $self->user_class->new($user); + } elsif (ref($user) && blessed($user) && + $user->isa('NGCP::Panel::AuthenticationStore::SystemRole')) { + return $user; + } else { + Catalyst::Exception->throw( + "The user '$username' must be a hash reference or an " . + "object of class NGCP::Panel::AuthenticationStore::SystemRole"); + } + + return; +} + +sub from_session { + my ( $self, $c, $stored ) = @_; + + return $self->find_user( { stored => $stored } ); +} + +__PACKAGE__->meta->make_immutable(inline_constructor => 0); + +1; + +# vim ts=4 sw=4 et diff --git a/lib/NGCP/Panel/AuthenticationStore/SystemRole.pm b/lib/NGCP/Panel/AuthenticationStore/SystemRole.pm new file mode 100644 index 0000000000..faef286d18 --- /dev/null +++ b/lib/NGCP/Panel/AuthenticationStore/SystemRole.pm @@ -0,0 +1,15 @@ +package NGCP::Panel::AuthenticationStore::SystemRole; +use Sipwise::Base; +use base 'Catalyst::Authentication::User::Hash'; + +sub roles { + my $self = shift; + + # return only first role for now + return ref($self->{roles}) eq "ARRAY" ? $self->{roles}[0] + : $self->{roles}; +} + +1; + +# vim ts=4 sw=4 et diff --git a/lib/NGCP/Panel/Controller/Root.pm b/lib/NGCP/Panel/Controller/Root.pm index fe8d44cb9c..ae1a43157f 100644 --- a/lib/NGCP/Panel/Controller/Root.pm +++ b/lib/NGCP/Panel/Controller/Root.pm @@ -103,8 +103,19 @@ sub auto :Private { } $self->api_apply_fake_time($c); return 1; + } elsif ($c->req->headers->header("NGCP-UserAgent") && + $c->req->headers->header("NGCP-UserAgent") eq "NGCP::API::Client") { + $c->log->debug("++++++ Root::auto API request with system auth"); + my $realm = "api_admin_system"; + my $res = $c->authenticate({}, $realm); + unless ($c->user_exists) { + $c->log->debug("+++++ invalid api admin system login"); + $c->log->warn("invalid api system login from '".$c->req->address."'"); + } + $self->api_apply_fake_time($c); + return 1; } else { $c->log->debug("++++++ Root::auto API request with http auth"); my $realm = "api_admin_http";