1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-21 14:50:08 +03:00

Merge branch 'feature-3159'

This commit is contained in:
Ruben S. Montero 2014-09-03 12:57:45 +02:00
commit 0d5e96debf
4 changed files with 228 additions and 18 deletions

View File

@ -83,9 +83,21 @@ begin
end
if ldap.authenticate(user_name, secret)
groups = ldap.get_groups
if groups.empty?
if !server_conf[:mapping_default]
STDERR.puts "User does not belong to a mapped group"
authenticated = false
break
else
groups = [server_conf[:mapping_default]]
end
end
group_list = groups.join(' ')
escaped_user=URI_PARSER.escape(user)
escaped_secret=URI_PARSER.escape(user_name)
puts "ldap #{escaped_user} #{escaped_secret}"
puts "ldap #{escaped_user} #{escaped_secret} #{group_list}"
authenticated=true
break
else

View File

@ -49,6 +49,21 @@ server 1:
# user field that that is in in the group group_field, if not set 'dn' will be used
#:user_group_field: 'dn'
# Generate mapping file from group template info
:mapping_generate: true
# Seconds a mapping file remain untouched until the next regeneration
:mapping_timeout: 300
# Name of the mapping file in OpenNebula var diretory
:mapping_filename: server1.yaml
# Key from the OpenNebula template to map to an AD group
:mapping_key: GROUP_DN
# Default group ID used for users in an AD group not mapped
:mapping_default: 1
# this example server wont be called as it is not in the :order list
server 2:
:auth_method: :simple

View File

@ -15,22 +15,39 @@
# ---------------------------------------------------------------------------- #
require 'rubygems'
require 'opennebula'
require 'net/ldap'
require 'yaml'
if !defined?(ONE_LOCATION)
ONE_LOCATION=ENV["ONE_LOCATION"]
end
if !ONE_LOCATION
VAR_LOCATION="/var/lib/one/"
else
VAR_LOCATION=ONE_LOCATION+"/var/"
end
module OpenNebula; end
class OpenNebula::LdapAuth
def initialize(options)
@options={
:host => 'localhost',
:port => 389,
:user => nil,
:password => nil,
:base => nil,
:auth_method => :simple,
:user_field => 'cn',
:user_group_field => 'dn',
:group_field => 'member'
:host => 'localhost',
:port => 389,
:user => nil,
:password => nil,
:base => nil,
:auth_method => :simple,
:user_field => 'cn',
:user_group_field => 'dn',
:group_field => 'member',
:mapping_generate => true,
:mapping_timeout => 300,
:mapping_filename => 'server1.yaml',
:mapping_key => 'GROUP_DN',
:mapping_default => 1
}.merge(options)
ops={}
@ -47,9 +64,61 @@ class OpenNebula::LdapAuth
ops[:port]=@options[:port].to_i if @options[:port]
ops[:encryption]=@options[:encryption] if @options[:encryption]
@options[:mapping_file_path] = VAR_LOCATION + @options[:mapping_filename]
generate_mapping if @options[:mapping_generate]
load_mapping
@ldap=Net::LDAP.new(ops)
end
def generate_mapping
file=@options[:mapping_file_path]
generate = false
if File.exists?(file)
stat = File.stat(file)
age = Time.now.to_i - stat.mtime.to_i
generate = true if age > @options[:mapping_timeout]
else
generate = true
end
return if !generate
client = OpenNebula::Client.new
group_pool = OpenNebula::GroupPool.new(client)
group_pool.info
groups = group_pool.to_hash['']
groups=[group_pool.get_hash['GROUP_POOL']['GROUP']].flatten
yaml={}
groups.each do |group|
if group['TEMPLATE'] && group['TEMPLATE'][@options[:mapping_key]]
yaml[group['TEMPLATE'][@options[:mapping_key]]] = group['ID']
end
end
File.open(file, 'w') do |f|
f.write(yaml.to_yaml)
end
end
def load_mapping
file=@options[:mapping_file_path]
@mapping = {}
if File.exists?(file)
@mapping = YAML.load(File.read(file))
end
if @mapping.class != Hash
@mapping = {}
end
end
def find_user(name)
begin
result=@ldap.search(
@ -57,12 +126,14 @@ class OpenNebula::LdapAuth
:filter => "#{@options[:user_field]}=#{name}")
if result && result.first
[result.first.dn, result.first[@options[:user_group_field]]]
@user = result.first
[@user.dn, @user[@options[:user_group_field]]]
else
result=@ldap.search(:base => name)
if result && result.first
[name, result.first[@options[:user_group_field]]]
@user = result.first
[name, @user[@options[:user_group_field]]]
else
[nil, nil]
end
@ -99,5 +170,20 @@ class OpenNebula::LdapAuth
false
end
end
def get_groups
groups = []
[@user['memberOf']].flatten.each do |group|
if @mapping[group]
groups << @mapping[group]
else
groups << @options[:mapping_default]
end
end
groups.delete(false)
groups.compact
end
end

View File

@ -686,10 +686,18 @@ bool UserPool::authenticate_external(const string& username,
string mad_name;
string mad_pass;
string error_str;
string tmp_str;
Nebula& nd = Nebula::instance();
AuthManager * authm = nd.get_authm();
GroupPool * gpool = nd.get_gpool();
User* user;
Group* group;
int gid = -1;
set<int>::iterator it;
set<int> empty_set;
AuthRequest ar(-1,empty_set);
@ -714,6 +722,11 @@ bool UserPool::authenticate_external(const string& username,
user_id = -1;
//--------------------------------------------------------------------------
// Parse driver response format is:
// <driver> <username> <passwd> [gid...]
//--------------------------------------------------------------------------
if ( is.good() )
{
is >> driver_name >> ws;
@ -726,15 +739,69 @@ bool UserPool::authenticate_external(const string& username,
if ( !is.fail() )
{
getline(is, mad_pass);
is >> mad_pass >> ws;
}
while ( is.good() )
{
int tmp_gid;
is >> tmp_gid >> ws;
if ( is.fail() )
{
error_str = "One or more group IDs are malformed";
goto auth_failure_user;
}
if ( gpool->get(tmp_gid, false) == 0 )
{
error_str = "One or more group IDs do not exist";
goto auth_failure_user;
}
if ( gid == -1 ) //Keep the first id for primary group
{
gid = tmp_gid;
}
group_ids.insert(tmp_gid);
}
//--------------------------------------------------------------------------
// Create the user, and set primary group
//--------------------------------------------------------------------------
if ( gid == -1 )
{
group_id = GroupPool::USERS_ID;
gname = GroupPool::USERS_NAME;
group_ids.insert( group_id );
}
else
{
group_id = gid;
group = gpool->get(group_id, true);
if( group == 0 )
{
error_str = "Primary Group no longer exist";
goto auth_failure_user;
}
gname = group->get_name();
group->unlock();
}
if ( !is.fail() )
{
allocate(&user_id,
GroupPool::USERS_ID,
group_id,
mad_name,
GroupPool::USERS_NAME,
gname,
mad_pass,
driver_name,
true,
@ -746,11 +813,41 @@ bool UserPool::authenticate_external(const string& username,
goto auth_failure_user;
}
group_id = GroupPool::USERS_ID;
group_ids.insert( GroupPool::USERS_ID );
//--------------------------------------------------------------------------
// Add the user to the secondary groups
//--------------------------------------------------------------------------
user = get(user_id,true);
if ( user == 0 )
{
error_str = "User object could not be retrieved";
goto auth_failure_user;
}
for(it = ++group_ids.begin(); it != group_ids.end(); it++)
{
group = gpool->get(*it, true);
if( group == 0 ) //Secondary group no longer exists
{
continue;
}
group->add_user(user_id);
gpool->update(group);
group->unlock();
user->add_group(*it);
}
update(user);
user->unlock();
uname = mad_name;
gname = GroupPool::USERS_NAME;
umask = User::get_default_umask();