Skip to content

Commit

Permalink
Feat: test ldap (#1927)
Browse files Browse the repository at this point in the history
* feat: check ldap permissions in base

* refactor: improved attrs list
  • Loading branch information
frankiejol authored Mar 23, 2023
1 parent f201e27 commit 041fd6f
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 17 deletions.
2 changes: 1 addition & 1 deletion lib/Ravada/Auth/LDAP.pm
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ sub search_user {
}

die "ERROR: ".$mesg->code." : ".$mesg->error
if $mesg->code;
if $mesg->code && $mesg->code != 4 && $mesg->count;

return if !$mesg->count();

Expand Down
4 changes: 2 additions & 2 deletions lib/Ravada/Auth/User.pm
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,6 @@ sub _load_allowed {
my $ldap_entry;
$ldap_entry = $self->ldap_entry if $self->external_auth && $self->external_auth eq 'ldap';


my @domains = $self->_list_domains_access();

for my $id_domain ( @domains ) {
Expand Down Expand Up @@ -433,7 +432,8 @@ sub _load_allowed_groups($self) {
}

$self->{_allowed}->{$id_domain} = 1
if Ravada::Auth::LDAP::is_member($self->ldap_entry, $name);
if $self->ldap_entry
&& Ravada::Auth::LDAP::is_member($self->ldap_entry, $name);
}
}

Expand Down
17 changes: 16 additions & 1 deletion public/js/ravada.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@
$scope.edit = "";
$scope.lock_info = false;
$scope.topology = false;
$scope.searching_ldap_attributes = true;

$scope.getUnixTimeFromDate = function(date) {
date = (date instanceof Date) ? date : date ? new Date(date) : new Date();
Expand Down Expand Up @@ -736,16 +737,28 @@
,'index': index
});
};
$scope.list_ldap_attributes= function() {
$scope.list_ldap_attributes = function() {
$scope.ldap_entries = 0;
$scope.ldap_verified = 0;
$scope.searching_ldap_attributes = true;
if ($scope.cn) {
$http.get('/list_ldap_attributes/'+$scope.cn).then(function(response) {
$scope.ldap_error = response.data.error;
$scope.ldap_attributes = response.data.attributes;
$scope.dn_found = response.data.dn_found;
$scope.values = response.data.values;
$scope.searching_ldap_attributes = false;
$scope.user_name = response.data.name;
$scope.check_access();
});
}
};
$scope.check_access = function() {
$http.get('/machine/check_access/'+$scope.showmachine.id+"/"+$scope.user_name).then(function(response) {
$scope.check_allowed=response.data.ok;
});
};

$scope.count_ldap_entries = function() {
$scope.ldap_verifying = true;
$http.get('/count_ldap_entries/'+$scope.ldap_attribute+'/'+$scope.ldap_attribute_value)
Expand Down Expand Up @@ -853,6 +866,7 @@
$scope.ldap_attributes_domain = response.data.list;
$scope.ldap_attributes_default = response.data.default;
});
$scope.check_access();
};
$scope.init_domain_access = function() {
$http.get('/machine/list_access/'+$scope.showmachine.id).then(function(response) {
Expand Down Expand Up @@ -1026,6 +1040,7 @@
$scope.access_last = [ ];

$scope.new_base = undefined;
$scope.cn ='';
$scope.list_ldap_attributes();
$scope.list_caches = ['default','none','writethrough'
,'writeback','directsync','unsafe'];
Expand Down
57 changes: 48 additions & 9 deletions script/rvd_back
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,32 @@ sub _verify_connection {
return 0;
}

sub _dump_ldap_entry($ldap_entry) {
print $ldap_entry->dn."\n";
for my $attrib (sort $ldap_entry->attributes ) {
my @value = $ldap_entry->get_value($attrib);
print "$attrib: ";

$value[0] =~ tr/./*/c
if defined $value[0] && $attrib eq 'unicodePwd';

if (scalar(@value)<2) {
if (!defined $value[0]) {
print "<UNDEF>";
} else {
print $value[0];
}
print "\n";
} else {
print "\n";
for (@value) {
print " - $_\n";
}
}
}
}


sub test_ldap {
my $rvd_back = Ravada->new(%CONFIG);
eval { Ravada::Auth::LDAP::_init_ldap_admin() };
Expand All @@ -765,7 +791,27 @@ sub test_ldap {
print "login: ";
my $name=<STDIN>;
chomp $name;
print "password: ";
my $user = Ravada::Auth::LDAP::search_user($name);
if (!$user) {
my $config = \$Ravada::CONFIG;

my $field = ($$config->{ldap}->{field} or 'cn');

my $filter = '';

$filter = $$config->{ldap}->{filter}
if exists $$config->{ldap}->{filter};

$filter= "filter=$filter " if $filter;

my $base = $$config->{ldap}->{base};

warn "Error: $field=$name not found. base=$base $filter. Either ".$$config->{ldap}->{admin_user}->{dn}." not allowed, or entry does not exist.\n";
} else {
_dump_ldap_entry($user);
}

print "\nType the password if you want to check the user connection or CTRL-C to stop\npassword: ";
my $password = <STDIN>;
chomp $password;
my $ok= Ravada::Auth::LDAP->new(name => $name, password => $password);
Expand All @@ -774,14 +820,7 @@ sub test_ldap {
warn "No LDAP data found ".Dumper($ok->{_data});
} else {
print "LOGIN OK $ok->{_auth}\n";
print $ok->{_ldap_entry}->dn."\n";
for my $attrib (sort $ok->{_ldap_entry}->attributes ) {
my @value = $ok->{_ldap_entry}->get_value($attrib);
print "$attrib: ";
print join(",",@value);
print "\n";
}

_dump_ldap_entry($ok->{_ldap_entry});
}
} else {
print "LOGIN FAILED\n";
Expand Down
52 changes: 50 additions & 2 deletions script/rvd_front
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,27 @@ get '/machine/check_access/(#id_domain)' => sub {
return $c->render( json => { ok => $domain->access_allowed(client => \%client)});
};

get '/machine/check_access/(#id_domain)/(#user)' => sub {
my $c = shift;

return _access_denied($c) if !$USER->is_admin;

my $user_name = $c->stash('user');
my $user = Ravada::Auth::SQL->new(name => $user_name);

if (!$user->id && Ravada::Auth::LDAP::search_user($user_name)) {
Ravada::Auth::SQL::add_user(
name => $user_name
,is_external => 1
,external_auth => 'ldap'
);
$user = Ravada::Auth::SQL->new(name => $user_name);
}

return $c->render( json => { ok => $user->allowed_access($c->stash('id_domain'))});
};


get '/machine/delete_access/(#id_domain)/(#id_access)' => sub {
my $c = shift;

Expand Down Expand Up @@ -1364,7 +1385,11 @@ get '/list_ldap_attributes/(#cn)' => sub {

my $user;
eval {
($user) = Ravada::Auth::LDAP::search_user($cn);
if ($cn =~ /^[a-z0-9\.-_]+/i) {
($user) = Ravada::Auth::LDAP::search_user(name => $cn.'*', escape_username => 0 , sizelimit => 2);
} else {
($user) = Ravada::Auth::LDAP::search_user($cn);
}
};
my $return;
if ( $@ ) {
Expand All @@ -1374,7 +1399,30 @@ get '/list_ldap_attributes/(#cn)' => sub {
} elsif (!$user) {
$return = { error => "User not found" };
} else {
$return = {attributes => [sort $user->attributes]};
my $values;
for my $attribute ( sort $user->attributes ) {
my @values = $user->get_value($attribute);
if ($attribute =~/Password|unicodePwd/i) {
for (@values) {
s/./*/g;
$_='********' if length($_)>8;
}
}
if (scalar(@values)<2) {
$values->{$attribute} = $values[0];
} else {
$values->{$attribute} = \@values;
}
}
my $field = $Ravada::CONFIG->{ldap}->{field};
$field = 'cn' if !defined $field;
my $user_name = $user->get_value($field);
$return = {
dn_found => $user->dn
, name => $user_name
, attributes => [sort { uc($a) cmp uc($b) } $user->attributes]
, values => $values
};
}

$c->session(ldap_attributes_cn => $cn) if $user;
Expand Down
34 changes: 32 additions & 2 deletions templates/main/machine_access_ldap.html.ep
Original file line number Diff line number Diff line change
@@ -1,16 +1,46 @@
<div class="card">
<div class="card-body">
<%=l 'Type a typical LDAP user name to fetch the attribute list' %>
<input type="text" ng-model="cn" ng-change="list_ldap_attributes()"
<input type="text" ng-model="cn" ng-change="dn_found=''"
ng-init="cn='<%= $ldap_attributes_cn %>'">
<div class="alert alert-danger" role="alert" ng-hide="ldap_attributes || !cn">
<button ng-enabled="cn"
ng-click="list_ldap_attributes()">fetch</button>
<div class="alert alert-danger" role="alert" ng-hide="ldap_attributes || !cn || searching_ldap_attributes || dn_found">
<div>
<%=l 'User name' %>&nbsp;<b>{{cn}}</b>&nbsp;<%=l 'not found in LDAP server' %>
</div>
<div>
{{ldap_error}}
</div>
</div>
<div ng-show="searching_ldap_attributes"><i class="fas fa-sync-alt fa-spin"></i></div>
<div ng-show="dn_found">
<div class="container">
<button ng-click="show_values=true" ng-show="!show_values"
type="button" class="badge btn-light"
title="<%=l 'show attributes'%>"
>+</button>
<button ng-click="show_values=false" ng-show="show_values"
type="button" class="badge"
title="<%=l 'hide attributes'%>"
>-</button>

<span
ng-class="{'text-secondary': !show_values, 'text-dark':show_values}"
>{{dn_found}}</span>

<span ng-show="check_allowed==1" class="bg-success text-white"><%=l 'access granted' %></span>
<span ng-show="check_allowed==0" class="bg-danger text-white"><%=l 'access denied' %></span>
</div>
<div ng-show="show_values" class="container m-8 border border-secondary">
<div ng-repeat="name in ldap_attributes" class="row">
<div class="col ml-4">
<span class="text-secondary">{{name}} :</span>
{{values[name]}}
</div>
</div>
</div>
</div>
</div>
<div class="card">
<table class="card-table table-striped">
Expand Down

0 comments on commit 041fd6f

Please sign in to comment.