Skip to content

Instantly share code, notes, and snippets.

@u1735067
Last active September 17, 2015 18:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save u1735067/9a1e584b6fc1fc1bca23 to your computer and use it in GitHub Desktop.
Save u1735067/9a1e584b6fc1fc1bca23 to your computer and use it in GitHub Desktop.
LDAP import & enforce script
# https://www.redmine.org/issues/1838
# https://www.redmine.org/boards/2/topics/34545
require File.expand_path('../../config/environment', __FILE__)
class AuthSourceLdap
def get_logins_filter(filter)
list = Set.new()
ldap_con = initialize_ldap_con(self.account, self.account_password)
search_filter = filter
ldap_con.search(
:base => self.base_dn,
:filter => search_filter,
:attributes => ['dn', self.attr_login]
) do | entry |
logger.debug("Found entry with DN: #{entry.dn}") if logger
login = AuthSourceLdap.get_attr(entry, self.attr_login).downcase
list << login
end
return list
end
def get_entry(login)
ldap_con = initialize_ldap_con(self.account, self.account_password)
search_filter = Net::LDAP::Filter.eq(self.attr_login, login)
return ldap_con.search(
:base => self.base_dn,
:filter => search_filter,
:attributes => ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail, self.attr_login]
)[0]
end
# admin status : enforced si exists
# auth_source_id = enforced si exists et != -1
def import_logins(logins, admin = false, auth_source_id = nil)
found = created = enforced = 0
skipped = []
ldap_con = initialize_ldap_con(self.account, self.account_password)
logins.each do | login |
# Already exists
if u = User.find_by(login: login)
# Update email if changed
#if u.mail != attrs[0][:mail]
# u.mail = attrs[0][:mail]
# if u.save
# logger.debug("Email for user #{login} was updated") if logger
# end
#end
enforce = false
if auth_source_id != -1 && u.auth_source_id != auth_source_id
logger.debug("User #{login} already there but bad auth_source_id, enforcing.") if logger
u.auth_source_id = auth_source_id
enforce = true
end
if u.admin != admin
logger.debug("User #{login} already there but bad admin status, enforcing.") if logger
u.admin = admin
enforce = true
end
if enforce
u.save
enforced += 1
else
logger.debug("User #{login} already there, skipping...") if logger
skipped.push(login+'(exists)')
end
next
end
# Otherwise find him !
filter = Net::LDAP::Filter.eq(self.attr_login, login)
res = ldap_con.search(
:base => self.base_dn,
:filter => filter,
:attributes => ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail, self.attr_login]
)
# Found, check, register
if !res.empty? && res[0] != nil
entry = res[0]
logger.debug("Importing entry with DN: #{entry.dn}") if logger
found += 1
skip = false
attrs = [:firstname => (AuthSourceLdap.get_attr(entry, self.attr_firstname) != nil ? \
AuthSourceLdap.get_attr(entry, self.attr_firstname) : "Unknown"),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => (!auth_source_id.nil?) ? auth_source_id : self.id]
#sanity checking (all the above attributes are required)
login = AuthSourceLdap.get_attr(entry, self.attr_login).downcase
catch :SKIP do
skip = false
attrs.each { |e|
e.each { |k, v|
if v == nil
# give the admin a clue why importing failed...
logger.debug("User #{login} misses value for attribute '#{k}'.") if logger
skipped.push(login+"(missing attribute '#{k}')")
skip = true
throw :SKIP
end
}
}
end
next if skip
#create user
begin
logger.debug("Trying to create user with attrs: %s" % attrs.to_s) if logger
u = User.create(*attrs)
u.login = login
u.language = Setting.default_language
u.admin = admin
if u.save
created += 1
else
skipped.push(login+'(add failed)')
end
end
end # found & register
end # logins
logger.info("Found #{found} users out of #{logins.length}, imported #{created}, enforced #{enforced}.") if logger
logger.info("Skipped users (#{skipped.length}): #{skipped.join(" ")}") if logger
return {:found => found, :imported => created, :skipped => skipped}
end
# Corrigé, non touché
def import
ldap_con = initialize_ldap_con(self.account, self.account_password)
search_filter = Net::LDAP::Filter.eq("objectClass", "user")
found = created = 0
skipped = []
ldap_con.search(
:base => self.base_dn,
:filter => search_filter,
:attributes => ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail, self.attr_login]
) do | entry |
logger.debug("Found entry with DN: #{entry.dn}") if logger
found += 1
skip = false
attrs = [:firstname => (AuthSourceLdap.get_attr(entry, self.attr_firstname) != nil ? \
AuthSourceLdap.get_attr(entry, self.attr_firstname) : "Unknown"),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => self.id ]
#sanity checking (all the above attributes are required)
login = AuthSourceLdap.get_attr(entry, self.attr_login).downcase
catch :SKIP do
skip = false
attrs.each { |e|
e.each { |k, v|
if v == nil
# give the admin a clue why importing failed...
logger.debug("User #{login} misses value for attribute '#{k}'.") if logger
skipped.push(login+"(missing attribute '#{k}')")
skip = true
throw :SKIP
end
}
}
end
next if skip
if u = User.find_by(login: login)
# Update email if changed
if u.mail != attrs[0][:mail]
u.mail = attrs[0][:mail]
if u.save
logger.debug("Email for user #{login} was updated") if logger
end
end
logger.debug("User #{login} already there, skipping...") if logger
skipped.push(login+'(exists)')
next
end
#create user
begin
logger.debug("Trying to create user with attrs: %s" % attrs.to_s) if logger
u = User.create(*attrs)
u.login = login
u.language = Setting.default_language
if u.save
created += 1
else
skipped.push(login+'(add failed)')
end
end
end
logger.info("Found #{found} users, imported #{created}.") if logger
logger.info("Skipped users: #{skipped.join(" ")}") if logger
return {:found => found, :imported => created, :skipped => skipped}
end
# Créé, non utilisé
def lock_non_existing_logins(logins)
ldap_con = initialize_ldap_con(self.account, self.account_password)
found = 0
logger.debug("Locking users that do not exist in LDAP authentication source: #{self.name}.") if logger
@users = User.all
@users.each { |user|
# ignore anonymous (empty login name and instance of AnonymousUser) and admin users
if user.login.empty? || user.class == AnonymousUser || user.login == "admin"
next
end
# Is not in the passed/admin list
if !logins.include?(user.login)
logger.debug("The user with login name: #{user.login} does not exist as admin any more in the LDAP and will be locked") if logger
found += 1
user.status=User::STATUS_LOCKED
user.save
end
}
logger.info("Locked #{found} users that did not exist as admin in LDAP authentication source: #{self.name}.") if logger
end
# Non touché
def lock_non_existing
ldap_con = initialize_ldap_con(self.account, self.account_password)
found = 0
logger.debug("Locking users that do not exist in LDAP authentication source: #{self.name}.") if logger
@users = User.all
@users.each { |user|
search_filter = Net::LDAP::Filter.eq(self.attr_login, user.login)
entry = ldap_con.search(
:base => self.base_dn,
:filter => search_filter,
:attributes => ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail, self.attr_login]
)
# ignore anonymous (empty login name and instance of AnonymousUser) and admin users
if entry.empty? && !user.login.empty? && user.class != AnonymousUser && user.login != "admin"
logger.debug("The user with login name: #{user.login} does not exist any more in LDAP and will be locked") if logger
found += 1
user.status=User::STATUS_LOCKED
user.save
end
}
logger.info("Locked #{found} users that did not exist in LDAP authentication source: #{self.name}.") if logger
end
# auth_source_id = nil to remove source
def self.unprivilege_non_logins(logins, auth_source_id = -1)
found = 0
logger.debug("Removing admin privilege to users not provided in logins list.") if logger
@users = User.all
@users.each { |user|
# ignore anonymous (empty login name and instance of AnonymousUser) and admin users
if user.login.empty? || user.class == AnonymousUser || user.login == "admin"
next
end
# Has a login & is not in the admin list
if user.admin && !logins.include?(user.login)
logger.debug("The user with login name: #{user.login} is not in the privileged users any more and will be unprivileged") if logger
found += 1
user.admin = false
if auth_source_id != -1
logger.debug("Changing auth_source_id") if logger
user.auth_source_id = auth_source_id
end
user.save
end
}
logger.info("Removed privileges to #{found} users that did not exist in the provided list.") if logger
end
end
ActiveRecord::Base.logger.info("----Starting LDAP Import&Enforce script") if ActiveRecord::Base.logger
#@auth_method = AuthSourceLdap.find(1) # Source contenant les uid / logins
#AuthSourceLdap.where("name like '%User'")
@source_admin = AuthSourceLdap.find_by(name: 'ResEl - Admin')
logins = @source_admin.get_logins_filter(Net::LDAP::Filter.eq("droit", "reseladmin"))
@source_users = AuthSourceLdap.find_by(name: 'ResEl - User')
@source_users.import_logins(logins, true, @source_admin.id)
AuthSourceLdap.unprivilege_non_logins(logins, @source_users.id)
ActiveRecord::Base.logger.info("----Done LDAP Import&Enforce script") if ActiveRecord::Base.logger
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment