Add LDAP service and seed task
This commit is contained in:
		
							parent
							
								
									93d56f79d5
								
							
						
					
					
						commit
						c3b9ff8b4a
					
				| @ -50,6 +50,13 @@ back-end: | |||||||
| 
 | 
 | ||||||
|     docker-compose exec ldap dsconf localhost backend create --suffix="dc=kosmos,dc=org" --be-name="dev" |     docker-compose exec ldap dsconf localhost backend create --suffix="dc=kosmos,dc=org" --be-name="dev" | ||||||
| 
 | 
 | ||||||
|  | Now you can seed the back-end with data using this Rails task: | ||||||
|  | 
 | ||||||
|  |     bundle exec rails ldap:seed | ||||||
|  | 
 | ||||||
|  | The seeds task will first delete any existing entries in the directory tree | ||||||
|  | ("dc=kosmos,dc=org"), and then create our example/development entries. | ||||||
|  | 
 | ||||||
| ## Documentation | ## Documentation | ||||||
| 
 | 
 | ||||||
| * [Ruby on Rails](https://guides.rubyonrails.org/) | * [Ruby on Rails](https://guides.rubyonrails.org/) | ||||||
|  | |||||||
							
								
								
									
										111
									
								
								app/services/ldap_service.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								app/services/ldap_service.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | |||||||
|  | class LdapService < ApplicationService | ||||||
|  |   def initialize | ||||||
|  |     @suffix = ENV["LDAP_SUFFIX"] || "dc=kosmos,dc=org" | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def add_entry(dn, attrs, interactive=false) | ||||||
|  |     puts "Adding entry: #{dn}" if interactive | ||||||
|  |     res = ldap_client.add dn: dn, attributes: attrs | ||||||
|  |     puts res.inspect if interactive && !res | ||||||
|  |     res | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def delete_entry(dn, interactive=false) | ||||||
|  |     puts "Deleting entry: #{dn}" if interactive | ||||||
|  |     res = ldap_client.delete dn: dn | ||||||
|  |     puts res.inspect if interactive && !res | ||||||
|  |     res | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def delete_all_entries | ||||||
|  |     if Rails.env.production? | ||||||
|  |       raise "Mass deletion of entries not allowed in production" | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     filter  = Net::LDAP::Filter.eq("objectClass", "*") | ||||||
|  |     entries = ldap_client.search(base: @suffix, filter: filter, attributes: %w{dn}) | ||||||
|  |     entries.sort_by!{ |e| e.dn.length }.reverse! | ||||||
|  | 
 | ||||||
|  |     entries.each do |e| | ||||||
|  |       delete_entry e.dn, true | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def fetch_users(args={}) | ||||||
|  |     if args[:ou] | ||||||
|  |       treebase = "ou=#{args[:ou]},cn=users,#{@suffix}" | ||||||
|  |     else | ||||||
|  |       treebase = ldap_config["base"] | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     attributes = %w{dn cn uid mail admin} | ||||||
|  |     filter     = Net::LDAP::Filter.eq("uid", "*") | ||||||
|  | 
 | ||||||
|  |     entries = ldap_client.search(base: treebase, filter: filter, attributes: attributes) | ||||||
|  |     entries.sort_by! { |e| e.cn[0] } | ||||||
|  | 
 | ||||||
|  |     entries = entries.collect do |e| | ||||||
|  |       { | ||||||
|  |         uid: e.uid.first, | ||||||
|  |         mail: e.try(:mail) ? e.mail.first : nil, | ||||||
|  |         admin: e.try(:admin) ? 'admin' : nil | ||||||
|  |         # password: e.userpassword.first | ||||||
|  |       } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def fetch_organizations | ||||||
|  |     attributes = %w{dn ou description} | ||||||
|  |     filter     = Net::LDAP::Filter.eq("objectClass", "organizationalUnit") | ||||||
|  |     # filter     = Net::LDAP::Filter.eq("objectClass", "*") | ||||||
|  |     treebase   = "cn=users,#{@suffix}" | ||||||
|  | 
 | ||||||
|  |     entries = ldap_client.search(base: treebase, filter: filter, attributes: attributes) | ||||||
|  | 
 | ||||||
|  |     entries.sort_by! { |e| e.ou[0] } | ||||||
|  | 
 | ||||||
|  |     entries = entries.collect do |e| | ||||||
|  |       { | ||||||
|  |         dn: e.dn, | ||||||
|  |         ou: e.ou.first, | ||||||
|  |         description: e.try(:description) ? e.description.first : nil, | ||||||
|  |       } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def add_organization(ou, description, interactive=false) | ||||||
|  |     dn = "ou=#{ou},cn=users,#{@suffix}" | ||||||
|  | 
 | ||||||
|  |     aci = <<-EOS | ||||||
|  | (target="ldap:///cn=*,ou=#{ou},cn=users,#{@suffix}")(targetattr="cn || sn || uid || mail || userPassword || nsRole || objectClass") (version 3.0; acl "service-#{ou.gsub(".", "-")}-read-search"; allow (read,search) userdn="ldap:///uid=service,ou=#{ou},cn=applications,#{@suffix}";) | ||||||
|  |     EOS | ||||||
|  | 
 | ||||||
|  |     attrs = { | ||||||
|  |       objectClass: ["top", "organizationalUnit"], | ||||||
|  |       description: description, | ||||||
|  |       ou: ou, | ||||||
|  |       aci: aci | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     add_entry dn, attrs, interactive | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def ldap_client | ||||||
|  |     ldap_client ||= Net::LDAP.new host: ldap_config['host'], | ||||||
|  |       port: ldap_config['port'], | ||||||
|  |       # TODO has to be :simple_tls if TLS is enabled | ||||||
|  |       # encryption: ldap_config['ssl'], | ||||||
|  |       auth: { | ||||||
|  |         method: :simple, | ||||||
|  |         username: ldap_config['admin_user'], | ||||||
|  |         password: ldap_config['admin_password'] | ||||||
|  |       } | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def ldap_config | ||||||
|  |     ldap_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env] | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  | end | ||||||
							
								
								
									
										24
									
								
								lib/tasks/ldap.rake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lib/tasks/ldap.rake
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | namespace :ldap do | ||||||
|  |   desc "Set up base entries for LDAP directory" | ||||||
|  |   task seed: :environment do |t, args| | ||||||
|  |     ldap = LdapService.new | ||||||
|  | 
 | ||||||
|  |     ldap.delete_all_entries | ||||||
|  | 
 | ||||||
|  |     ldap.add_entry "dc=kosmos,dc=org", { | ||||||
|  |       dc: "kosmos", objectClass: ["top", "domain"] | ||||||
|  |     }, true | ||||||
|  |     ldap.add_entry "cn=users,dc=kosmos,dc=org", { | ||||||
|  |        cn: "users", objectClass: ["top", "organizationalRole"] | ||||||
|  |     }, true | ||||||
|  | 
 | ||||||
|  |     ldap.add_organization "kosmos.org", "Kosmos", true | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   desc "List user domains/organizations" | ||||||
|  |   task list_organizations: :environment do |t, args| | ||||||
|  |     ldap = LdapService.new | ||||||
|  |     orgs = ldap.fetch_organizations | ||||||
|  |     puts orgs.inspect | ||||||
|  |   end | ||||||
|  | end | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user