Skip to content

Commit

Permalink
Merge branch 'release/1.8.9' into fix/1934_non_volatile
Browse files Browse the repository at this point in the history
  • Loading branch information
frankiejol committed Apr 19, 2023
2 parents ff0d227 + 041fd6f commit 2a960b8
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 20 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

**Implemented enhancements:**

- LDAP checks [\#1927]
- purge nodes CLI [\#1926]

**Refactors**

**Bugfixes**

- CPU topology when empty model
- Link for Windows virt viewer download wrong [\#1911]
2 changes: 1 addition & 1 deletion lib/Ravada.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package Ravada;
use warnings;
use strict;

our $VERSION = '1.8.8';
our $VERSION = '1.8.9';

use utf8;

Expand Down
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 @@ -739,16 +740,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 @@ -856,6 +869,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 @@ -1029,6 +1043,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
109 changes: 100 additions & 9 deletions script/rvd_back
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ my $REMOVE_DOMAIN;
my $REBASE;
my $RUN_REQUEST;
my $MIGRATE;
my $PURGE_NODES;

my $IMPORT_DOMAIN_OWNER;

Expand Down Expand Up @@ -167,6 +168,8 @@ GetOptions ( help => \$help
,"restore" => \$RESTORE
,"log=s" => \$LOG_FILENAME

,"purge-nodes" => \$PURGE_NODES

,"time-connection=s" => \$TIME_CONNECTION
) or exit;

Expand Down Expand Up @@ -754,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 @@ -762,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 @@ -771,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 Expand Up @@ -971,6 +1013,53 @@ sub _list_domains($rvd_back
return @domains;
}

sub purge_nodes($rvd_back) {
my $sth = $rvd_back->_dbh->prepare(
"SELECT id,name FROM domains WHERE is_base=1"
." ORDER BY name "
);
my $sth_ins = $rvd_back->_dbh->prepare(
"SELECT di.id,di.id_domain, di.id_vm, d.name, vms.name "
." FROM domain_instances di,domains d, vms"
." WHERE di.id_domain = d.id "
." AND d.id_base=?"
." AND d.id_vm <> di.id_vm "
." AND vms.id=di.id_vm "
." AND vms.hostname <> 'localhost'"
." AND vms.hostname <> '127.0.0.1'"
." ORDER by d.name "
);
my $sth_delete = $rvd_back->_dbh->prepare(
"DELETE FROM domain_instances WHERE id=?"
);
$sth->execute();
while ( my ($id_base,$name) = $sth->fetchrow ) {
$sth_ins->execute($id_base);
while (my @row = $sth_ins->fetchrow()) {
next if !@row;
my ($id, $id_domain, $id_vm, $name , $vm_name) = @row;
my $domain = Ravada::Domain->open($id_domain);
my $vm = Ravada::VM->open($id_vm);
if ( !$vm->_connect) {
warn "Node $vm_name unavailable\n";
next;
}
for my $vol ( $domain->list_volumes ) {
next if !$vm->file_exists($vol);
print "Found $name [$id_domain] unused in $vm_name.\n";
print "Remove $vol\n";
print "[y/N] ? ";
my $ok= <stdin>;
next if $ok !~ /y/i;

$vm->remove_file($vol);
}
$sth_delete->execute($id);
}

}
}

sub DESTROY {
}

Expand Down Expand Up @@ -1018,6 +1107,8 @@ clean_db_leftovers($rvd_back) if $CLEAN_DB_LEFTOVERS;

backup($rvd_back) if $BACKUP;
restore($rvd_back) if $RESTORE;

purge_nodes($rvd_back) if $PURGE_NODES;
}


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 2a960b8

Please sign in to comment.