egov_utils 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0acb8a903d4ec6302d92915fff9a99e203ea7e76
4
- data.tar.gz: 8320e02ca0f684d1542ee7d1ea9d0b08882782ed
3
+ metadata.gz: 339e97078108e7d4fbad0dfb86b2dc8a2a4d0d22
4
+ data.tar.gz: 4d2b4bcba50f2c9ce67dd093bc7ca11f0578c535
5
5
  SHA512:
6
- metadata.gz: f02b14675f1cb7215cca5143e3c813b853423e9906a374ff6580d0dea06a5f81f6f78ffa24ce3272fde4a1ef83c125a3d952d81bddacda461116c934989aa633
7
- data.tar.gz: a8b9243c8928d3207325d55250ff1556c12ede9aa75e3160963d673728a2ea6bd91cfd9d1f6ed11a27d4472c42852739342fe9e85688f6c84074565c647e2424
6
+ metadata.gz: 7bf7ae24fa68490735043ea48270c571f747089fe58337a7e9cfcfa8a5ea4303bec9baf4bc95dd999ba97d435dbfaa392de40c4d213191345f97c9657b11238f
7
+ data.tar.gz: 34c12fba18edb08e23fb66f383d8d535991da85cd794c2e493015e7cfa4dfb53024a34145afc6ab5c643911a9c49513a58dfbcea9a88ccec5cc6f660af3d16c4
data/README.md CHANGED
@@ -1,8 +1,98 @@
1
+ [![pipeline status](https://git.servis.justice.cz/libraries/egov_utils-rails/badges/master/pipeline.svg)](https://git.servis.justice.cz/libraries/egov_utils-rails/commits/master)
1
2
  # EgovUtils
2
- Short description and motivation.
3
+ This gem is set of utilities commonly used in Czech egoverment for rails application.
4
+
5
+ Main features:
6
+ * User roles/permissions
7
+ * Ldap integration
8
+ * Addresses/people storing and validation trough Egsb - ( uses egsb_gate gem )
9
+ * Usefull additions for bootstrap ( will be separeted in feature )
10
+ * Data visualization and retrievement api ( uses azahara_schema gem )
11
+
12
+ To be done:
13
+ * NIA integration
14
+ * ISDS SSO integration
3
15
 
4
16
  ## Usage
5
- How to use my plugin.
17
+ Framework uses configuration in file config/config.yml
18
+
19
+ ### LDAP
20
+ LDAP parameters has to be configured in framework config file under the key `ldap`.
21
+ You can configure more than one ldap source. Framework will try all of them. But groups and users are resolved just by the one ldap controller where user resides.
22
+ Following example is for Active Directory ldap using userPrincipalName as username (prefered - in case of multidomain ldap controller it should be mandatory)
23
+ ```yaml
24
+ ldap:
25
+ main:
26
+ label: 'Lab'
27
+ # host: dc01.servis.resort.cz
28
+ domain: servis.resort.cz
29
+ resolve_host: true
30
+ port: 389
31
+ uid: 'userPrincipalName'
32
+ method: 'tls'
33
+ kerberos: true
34
+ bind_dn: 'CN=Uzivatel LDAP aplikace ABC,OU=Servisni,DC=servis,DC=resort,DC=cz'
35
+ password: 'heslo uzivatele LDAP aplikace'
36
+ active_directory: true #enables specific Active Directory functions
37
+ base: 'OU=Appname,DC=servis,DC=resort,DC=cz'
38
+ onthefly_register: members
39
+ attributes:
40
+ username: ['userPrincipalName']
41
+ email: ['mail', 'email']
42
+ name: 'cn'
43
+ first_name: 'givenName'
44
+ last_name: 'sn'
45
+ ```
46
+ #### Authentication to reading ldap and security
47
+ Authentication options are made trough `bind_dn` and `password` options.
48
+ `bind_dn` id DN of user with read permissions for all ldap tree ( or the subtree wich relates to this application ) and `password` is a password for this user.
49
+
50
+ #### Defining host
51
+ Host can be defined in option `host`, but in bigger ldap installation you would prefer to use selection of the host on DNS for load balancing purposes.
52
+
53
+ It can be done by defining option `domain` and `resolve_host: true`.
54
+ Framework will let DNS resolve the servis record `_ldap._tcp.<domain>` and select the first record.
55
+ It relies on resolution of this record to be sorted from less busy controller to most busy.
56
+ It is prefered method for bigger ldaps with load balancing demands.
57
+
58
+ Option `port` has to be defined if you are using `host` option.
59
+ For `resolve_host` option, you can leave out the host option and framework will use the port returned by DNS server.
60
+ But you can wish to define it anyway, if you have global catalog running on another port.
61
+
62
+ Option `method` is for defining a security protocol, wich shoul be used for comunication with the ldap controller.
63
+ * plain
64
+ * ssl
65
+ * tls
66
+ You should always use encrypted connection, so please consider plain method to be just for testing purposes to connect to the test ldap controller.
67
+
68
+ #### Base and attributes
69
+ First you have to specify, where to look for records of users and groups related to the application.
70
+ `base` could be just domain like `DC=servis,DC=resort,DC=cz`, but you should consider to narrowing the scope for performance purposes, so if your users and groups are in specific Organization Unit, you should define DN of the OU as a base.
71
+
72
+ Attributes defines mapping for attributes in LDAP to attributes in the application database.
73
+ If you are using activedirectory, you probably will want to keep the attributes same as in the example.
74
+ But if you want to change them, you can do it. They are pretty self expanatory.
75
+
76
+ #### Onthefly registration
77
+ This parameter defines if administartor has to create the accounts (add users from AD) manually, or it can be created (added) with first login.
78
+
79
+ Parameter `onthefly_register` set to `true` basically saying, that any user in the scope defined by `base` is allowed to login to the application.
80
+ It can be usefull for easy applications, where you create organization unit for them and special account for every user of the application.
81
+ Or on the other hand if the application is for whole resort and you specify the roles and permissions in the application.
82
+
83
+
84
+ More interesting is an option `members`.
85
+ With this option, framework will look in all groups added as groups in application and if the user is member of at least one of them, application will create the account.
86
+ Other users can be added manually by administrator. Membership in groups is looked for recursively.
87
+
88
+ #### Groups
89
+ You can add LDAP groups to the application groups and define roles and permissions to the groups.
90
+ Group membership is solved on the fly for the user, so it does´t depens on the order of making user a memmber of group and adding the group to the application.
91
+ Group membership is looked for recursively, so you can add one big group, define permissions for that group, add other groups as members and end users to this groups.
92
+ This ordering can be useful for more sub organizations, where every organization is managing its users permissions and then it is connected to the global AD catalog, where the application is queriing.
93
+
94
+ #### Kerberos
95
+ To be documented.
6
96
 
7
97
  ## Installation
8
98
  Add this lines to your application's Gemfile:
@@ -87,7 +87,9 @@ module EgovUtils
87
87
  end
88
88
 
89
89
  def all_role_names
90
- @all_role_names ||= groups.collect{|g| g.roles}.reduce([], :concat) + roles
90
+ @all_role_names ||= Rails.cache.fetch("#{cache_key}/all_role_names", expires_in: 1.hours) do
91
+ groups.collect{|g| g.roles}.reduce([], :concat) + roles
92
+ end
91
93
  end
92
94
 
93
95
  def all_roles
@@ -98,9 +100,13 @@ module EgovUtils
98
100
  ldap_groups || []
99
101
  end
100
102
 
103
+ def ldap_dn
104
+ @ldap_dn = auth_source.send(:get_user_dn, login)[:dn]
105
+ end
106
+
101
107
  def ldap_groups
102
108
  if provider.present?
103
- EgovUtils::Group.where(provider: provider).to_a.select{|g| g.ldap_member?(self) }
109
+ EgovUtils::Group.where(provider: provider).to_a.select{|g| auth_source.member?(ldap_dn, g.ldap_uid) }
104
110
  end
105
111
  end
106
112
 
@@ -46,12 +46,31 @@ module EgovUtils
46
46
  @options ||= self.class.config[provider].dup
47
47
  end
48
48
 
49
+ # Resolves host name - it is used only if option <tt>:resolve_host</tt> is set to true and expect <tt>:domain</tt> to be defined as well.
50
+ # ldap controller host is resolved by asking for the <tt>_ldap._tcp.<domain></tt> DNS record and takes first - solve the load balancing of ldap queries.
51
+ def host_dns
52
+ require 'resolv'
53
+ @host_dns = Resolv::DNS.open do |dns|
54
+ dns.getresouce('_ldap._tcp.'+options['domain'], Resolv::DNS::Resource::IN::SRV)
55
+ end
56
+ end
57
+
58
+ # Get host of ldap controller from options.
59
+ #
60
+ # * <tt>:host</tt> - this just give one host and EgovUtils just asks that host
61
+ # * <tt>:domain</tt> with <tt>:resolve_host</tt> set to true. Domain should be domain for your ldap users.
62
+ # in this configuration ldap controller host is resolved by asking for the <tt>_ldap._tcp.<domain></tt> DNS record and takes first - solve the load balancing of ldap queries.
49
63
  def host
50
- options['host']
64
+ if options['host']
65
+ options['host']
66
+ elsif options['resolve_host'] && options['domain']
67
+ host_dns.target.to_s
68
+ end
51
69
  end
52
70
 
71
+ # Returns ldap controller port. If <tt>:resolve_host</tt> is set to true and option for port is not defined, it uses port from DNS response.
53
72
  def port
54
- options['port']
73
+ options['resolve_host'] ? (options['port'] || host_dns.port.to_i) : options['port']
55
74
  end
56
75
 
57
76
  def encryption
@@ -146,6 +165,25 @@ module EgovUtils
146
165
  raise AuthSourceException.new(e.message)
147
166
  end
148
167
 
168
+ def member?(user_dn, group_sid)
169
+ ldap_con = initialize_ldap_con(options['bind_dn'], options['password'])
170
+ group_dn = nil
171
+ Rails.logger.debug("Membership in group for #{user_dn}")
172
+ ldap_con.search(base: options['base'],
173
+ filter: base_group_filter & Net::LDAP::Filter.eq('objectSID', group_sid),
174
+ attributes: ['dn']) do |entry|
175
+ group_dn = get_attr(entry, 'dn')
176
+ end
177
+ if group_dn
178
+ ldap_con.search(base: user_dn,
179
+ filter: base_user_filter & Net::LDAP::Filter.ex('memberOf:1.2.840.113556.1.4.1941', group_dn),
180
+ attributes: ['dn']) do |entry|
181
+ return true
182
+ end
183
+ end
184
+ return false
185
+ end
186
+
149
187
  def group_members(group_sid)
150
188
  ldap_con = initialize_ldap_con(options['bind_dn'], options['password'])
151
189
  group_dn = nil
@@ -55,8 +55,10 @@ module EgovUtils
55
55
  logger.info(" Trying kerberos: #{username}") if logger
56
56
  attrs = EgovUtils::AuthSource.find_kerberos_user(username)
57
57
  if attrs
58
- logger.info(" Found kerberos user: #{attrs[:login]}") if logger
59
- User.active.find_by(login: attrs[:login])
58
+ user = User.active.find_by(login: attrs[:login])
59
+ logger.info(" Found kerberos user: #{attrs[:login]} and it is in database") if logger && user
60
+ logged_user = user
61
+ user
60
62
  end
61
63
  end
62
64
 
@@ -1,3 +1,3 @@
1
1
  module EgovUtils
2
- VERSION = '0.1.9'
2
+ VERSION = '0.1.10'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: egov_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ondřej Ezr
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-19 00:00:00.000000000 Z
11
+ date: 2017-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails