Initial commit
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
namespace :cartodb do
|
||||
namespace :ldap do
|
||||
desc "Tests an LDAP connection. Returns a summary of all tests ran, with success status and error messages."
|
||||
task :test_ldap_connection, [:from_database] => :environment do |_t, args|
|
||||
args.with_defaults(from_database: false)
|
||||
|
||||
test_user = ENV['TEST_USER']
|
||||
test_password = ENV['TEST_PASSWORD']
|
||||
test_search = ENV['TEST_SEARCH']
|
||||
ldap = if args.from_database
|
||||
Carto::Ldap::Configuration.first
|
||||
else
|
||||
ldap_configuration_from_environment(Carto::Organization.new)
|
||||
end
|
||||
|
||||
# Test configuration
|
||||
config_result = if ldap.valid?
|
||||
{ success: true }
|
||||
else
|
||||
{ success: false, error: ldap.errors.to_h }
|
||||
end
|
||||
|
||||
result = { config: config_result }
|
||||
|
||||
REQUIRED_FIELDS = [:host, :port, :connection_user, :connection_password].freeze
|
||||
if !config_result[:success] && config_result[:error].keys.any? { |k| REQUIRED_FIELDS.include?(k) }
|
||||
result[:connection] = { success: false, error: 'Configuration not valid' }
|
||||
end
|
||||
|
||||
# Test connection
|
||||
result[:connection] = ldap.test_connection unless result[:connection]
|
||||
|
||||
CONNECTION_DEPENDENT_TESTS = [:login, :user_search, :group_search, :search].freeze
|
||||
if result[:connection][:success]
|
||||
result[:connection].delete(:connection)
|
||||
if ldap.domain_bases.present?
|
||||
result[:login] = if test_user.present? && test_password.present?
|
||||
test_ldap_user(ldap, test_user, test_password)
|
||||
else
|
||||
{ success: false, error: 'Test credentials not provided' }
|
||||
end
|
||||
|
||||
result[:user_search] = if ldap.user_object_class.present?
|
||||
user_count = ldap.users.count
|
||||
{ success: user_count > 0, count: user_count }
|
||||
else
|
||||
{ success: false, error: 'User class not provided' }
|
||||
end
|
||||
|
||||
result[:group_search] = if ldap.group_object_class.present?
|
||||
group_count = ldap.groups.count
|
||||
{ success: group_count > 0, count: group_count }
|
||||
else
|
||||
{ success: false, error: 'Group class not provided' }
|
||||
end
|
||||
|
||||
result[:search] = if test_search.present?
|
||||
object_count = ldap.send(:search_in_domain_bases, Net::LDAP::Filter.eq('objectClass', test_search)).count
|
||||
{ success: true, count: object_count }
|
||||
else
|
||||
{ success: false, error: 'Object class not provided' }
|
||||
end
|
||||
else
|
||||
CONNECTION_DEPENDENT_TESTS.each do |test|
|
||||
result[test] = { success: false, error: 'Domain bases not provided' }
|
||||
end
|
||||
end
|
||||
else
|
||||
CONNECTION_DEPENDENT_TESTS.each do |test|
|
||||
result[test] = { success: false, error: 'Connection failed' }
|
||||
end
|
||||
end
|
||||
puts JSON.pretty_generate(result)
|
||||
end
|
||||
|
||||
# INFO: Separate multiple domain names by commas
|
||||
desc "Creates an LDAP Configuration entry"
|
||||
task :create_ldap_configuration, [] => :environment do |_t, _args|
|
||||
|
||||
if ENV['ORGANIZATION_ID'].blank?
|
||||
if ENV['ORGANIZATION_NAME'].blank?
|
||||
raise "Missing ORGANIZATION_ID and ORGANIZATION_NAME. Must provide one of both"
|
||||
else
|
||||
organization = Carto::Organization.where(name: ENV['ORGANIZATION_NAME']).first
|
||||
end
|
||||
else
|
||||
organization = Carto::Organization.find(ENV['ORGANIZATION_ID'])
|
||||
end
|
||||
ldap = ldap_configuration_from_environment(organization)
|
||||
|
||||
unless ldap.valid?
|
||||
missing = ldap.errors.keys.reject { |k| k == :domain_bases_list }
|
||||
raise "Missing: " + missing.join(', ').upcase
|
||||
end
|
||||
|
||||
if ldap.save
|
||||
puts "LDAP configuration created with id: #{ldap.id}"
|
||||
else
|
||||
puts "Error saving LDAP configuration"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Deletes existing LDAP Configuration entries"
|
||||
task :reset_ldap_configuration, [] => :environment do |_t, _args|
|
||||
Carto::Ldap::Configuration.delete_all
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ldap_configuration_from_environment(organization)
|
||||
# Mandatory: connection parameters
|
||||
host = ENV['HOST']
|
||||
port = ENV['PORT']
|
||||
ssl_version = ENV['SSL_VERSION'].blank? ? nil : ENV['SSL_VERSION']
|
||||
encryption = ENV['ENCRYPTION'].blank? ? nil : ENV['ENCRYPTION']
|
||||
connection_user = ENV['CONNECTION_USER']
|
||||
connection_password = ENV['CONNECTION_PASSWORD']
|
||||
|
||||
# Optional: for testing auth/searches
|
||||
user_id_field = ENV['USER_ID_FIELD']
|
||||
domain_bases = ENV['DOMAIN_BASES']
|
||||
additional_search_filter = ENV['ADDITIONAL_SEARCH_FILTER']
|
||||
|
||||
# Optional: for testing searches
|
||||
username_field = ENV['USERNAME_FIELD']
|
||||
email_field = ENV['EMAIL_FIELD']
|
||||
user_object_class = ENV['USER_OBJECT_CLASS']
|
||||
group_object_class = ENV['GROUP_OBJECT_CLASS']
|
||||
|
||||
Carto::Ldap::Configuration.new(
|
||||
organization: organization,
|
||||
host: host,
|
||||
port: port,
|
||||
encryption: encryption,
|
||||
ssl_version: ssl_version,
|
||||
connection_user: connection_user,
|
||||
connection_password: connection_password,
|
||||
user_id_field: user_id_field,
|
||||
username_field: username_field,
|
||||
additional_search_filter: additional_search_filter,
|
||||
email_field: email_field,
|
||||
domain_bases: domain_bases,
|
||||
user_object_class: user_object_class,
|
||||
group_object_class: group_object_class
|
||||
)
|
||||
end
|
||||
|
||||
def test_ldap_user(ldap, test_user, test_password)
|
||||
unless ldap.user_id_field.present? && ldap.username_field.present? && ldap.email_field.present?
|
||||
return { success: false, error: 'User id, username or email attribute names not specified.' }
|
||||
end
|
||||
|
||||
entry = ldap.authenticate(test_user, test_password)
|
||||
return { success: false, error: 'Cannot login with test credentials' } unless entry
|
||||
|
||||
if entry.email && entry.username
|
||||
{ success: true, email: entry.email, username: entry.username }
|
||||
else
|
||||
{ success: false, error: 'Cannot retrieve user attributes. Check the email and username attribute names' }
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user