adap 0.0.19 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79f0099367a12ae334622a2de2da08349595a29295bdbab740df1436a5049c3e
4
- data.tar.gz: b1038603bd55124f3d2179736755e72e26d4015da212b7866942ced393335022
3
+ metadata.gz: 5902e0cff391896473b36f3c70291da1f649517ecb9086e0876d795602d961de
4
+ data.tar.gz: f4779fef13ca503c0a1529a6f128e11306202d0e822a4b77038e7738e75624f0
5
5
  SHA512:
6
- metadata.gz: 54ffe5f02ce54bbdc962c176452091e37d6bad1ee56e73b0447b462535d2e09d356843e61f5d5ae6e30408ee6731ac76ad054d80b1ba69e781e748f63a322362
7
- data.tar.gz: 9c519f4d69255a9d9bc58012d0181f35b1ccbf4427956b10bcf8d35cfb5906047e3bed4457bdd7a704fc7c1f2bfa7aec154d71e3d149285f15976cb86a0700bb
6
+ metadata.gz: f70534ab1eb79938881066d121514c9f04f20fd9e9e8fed3852399fcf7d9d746ec678fcb883d878f12b91bc5e77036e62cca836412ea02e15715b37a2cf1b637
7
+ data.tar.gz: 17c77cb0d8748dd3eb0cc07903458bde6cdc66679513f411aedc590b91be2b27df4022853ea67bf77b514d2666e6ff1a6ca910f3548fed0d9958a1af51c962ce
@@ -0,0 +1,16 @@
1
+ version: 2.1
2
+ orbs:
3
+ ruby: circleci/ruby@0.1.2
4
+
5
+ jobs:
6
+ build:
7
+ docker:
8
+ - image: ruby:2.7
9
+ executor: ruby/default
10
+ steps:
11
+ - checkout
12
+ - run: bundle check || bundle install
13
+ - run:
14
+ command: bundle exec rake test
15
+ when: always
16
+
data/README.md CHANGED
@@ -42,9 +42,73 @@ adap = Adap.new({
42
42
  })
43
43
 
44
44
  # This operation will synchronize a user taro-suzuki to LDAP from AD
45
- adap.sync_user("taro-suzuki")
45
+ adap.sync_user("john", "secret")
46
46
  ```
47
47
 
48
+ ## Attributes to be synched by default
49
+ Attributes to be synched by default are like below.
50
+
51
+ | Name of attribute in AD | | Name of attribute in LDAP | Note |
52
+ | ----------------------- | ------- | ------------------------- | ---- |
53
+ | cn | → | cn | |
54
+ | sn | → | sn | |
55
+ | uid | → | uid | |
56
+ | uidNumber | → | uidNumber | |
57
+ | gidNumber | → | gidNumber | |
58
+ | displayName | → | displayName | |
59
+ | loginShell | → | loginShell | |
60
+ | gecos | → | gecos | |
61
+ | givenName | → | givenName | |
62
+ | description | → | description | |
63
+ | mail | → | mail | |
64
+ | employeeNumber | → | employeeNumber | |
65
+ | unixHomeDirectory | → | homeDirectory | Synched by different names of attributes between AD and LDAP |
66
+ | - | → | userPassword | Password of users also will be synched with some limitations |
67
+
68
+ Some attributes will be added as synched parameters if you add some options, for example options of phonetics.
69
+
70
+ ## Other options
71
+ ### Password hash algorithm
72
+ There are some supported password hash algorithms like `:md5(MD5)`, `:sha(SHA1)`, `:ssha(SSHA)`, `:virtual_crypt_sha256(virtualCryptSHA256)`, `:virtual_crypt_sha512(virtualCryptSHA512)`.
73
+ `:ssha(SSHA)` will be chosen if you didn't specify any method.
74
+
75
+ ```ruby
76
+ adap = Adap.new({
77
+ # Abbreviate other necessary attributes...
78
+ :password_hash_algorithm => :sha
79
+ })
80
+ ```
81
+
82
+ But please be careful, even if you choose any method, you will encounter some limitations.
83
+
84
+ * [You have to give plain password if you choose password hash algorithm as :md5, :sha or :ssha](https://github.com/TsutomuNakamura/adap/#you-have-to-give-plain-password-if-you-choose-password-hash-algorithm-as-md5-sha-or-ssha)
85
+ * [AD must allow CryptSHA256 or CryptSHA512 to store password and they have to be same as a storing method in LDAP if you chose password hash algorithm as :virtual_crypt_sha256 or :virtual_crypt_sha512](https://github.com/TsutomuNakamura/adap/#ad-must-allow-cryptsha256-or-cryptsha512-to-store-password-and-they-have-to-be-same-as-a-storing-method-in-ldap)
86
+
87
+ ### Phonetics
88
+ adap can sync phonetics from AD to LDAP if you specify attribute names.
89
+
90
+ ```ruby
91
+ adap = Adap.new({
92
+ # Abbreviate other necessary attributes...
93
+ :map_msds_phonetics => {
94
+ # This will sync the value of :'msds-phoneticdisplayname'(msDS-PhoneticDisplayName) in AD to the value of "displayname;lang-ja;phonetic" in LDAP
95
+ :'msds-phoneticdisplayname' => :'displayname;lang-ja;phonetic'
96
+ }
97
+ })
98
+ ```
99
+
100
+ All supported phonetics in AD are like below.
101
+
102
+ | Symbol | Name of attribute | General name of attribute in LDAP(ex:ja) |
103
+ | --------------------------- | ------------------------ | ---------------------------------------- |
104
+ | :'msds-phoneticcompanyname' | msDS-PhoneticCompanyName | companyName;lang-ja;phonetic |
105
+ | :'msds-phoneticdepartment' | msDS-PhoneticDepartment  | department;lang-ja;phonetic |
106
+ | :'msds-phoneticfirstname' | msDS-PhoneticFirstName   | firstname;lang-ja;phonetic |
107
+ | :'msds-phoneticlastname' | msDS-PhoneticLastName | lastname;lang-ja;phonetic |
108
+ | :'msds-phoneticdisplayname' | msDS-PhoneticDisplayName | displayname;lang-ja;phonetic |
109
+
110
+ Ofcourse, you can change the name of attributes that will be synced in LDAP(General name of attribute in LDAP) depends on your environment.
111
+
48
112
  ## Requirements and limitations
49
113
 
50
114
  This program has some requirements and limitations like below.
@@ -65,12 +129,27 @@ ldap server require strong auth = no
65
129
 
66
130
  This program will fail to get user data from AD if you did not allow this setting.
67
131
 
68
- ### AD must allow CryptSHA256 or CryptSHA512 to store password and they have to be same as a storing method in LDAP
132
+ ### You have to give a plain password of the user that will be synched if you choose password hash algorithm as :md5, :sha or :ssha
133
+ AD never be able to have passwords as :md5(MD5), :sha(SHA1) or :ssha(SSHA) that same as LDAP(OpenLDAP).
134
+ So this program can not sync user password from only parameters in AD to LDAP.
135
+ You have to pass the plain password to sync passwords to LDAP.
136
+
137
+ ```ruby
138
+ adap = Adap.new({
139
+ # Abbreviate other necessary attributes...
140
+ })
141
+
142
+ adap.sync_user("john", "secret") # You have to give a plain password as a second parameter of the sync_user().
143
+ ```
144
+
145
+ ### AD must allow CryptSHA256 or CryptSHA512 to store password and they have to be same as a storing method in LDAP if you choose password hash algorithm as :virtual_crypt_sha256 or :virtual_crypt_sha512
69
146
 
70
147
  AD must allow storing password as CryptSHA256 or CryptSHA512 by setting smb.conf like below.
71
148
 
72
149
  * your AD's smb.conf
73
150
  ```
151
+ [global]
152
+ # ......
74
153
  password hash userPassword schemes = CryptSHA256 CryptSHA512
75
154
  ```
76
155
 
@@ -103,7 +182,18 @@ olcPasswordCryptSaltFormat: $6$%.16s
103
182
  EOF
104
183
  ```
105
184
 
106
- ### This program must be located in AD server
185
+ After you have set them, you can sync a user and password between AD and LDAP like below.
186
+
187
+ ```ruby
188
+ adap = Adap.new({
189
+ # Abbreviate other necessary attributes...
190
+ :password_hash_algorithm => :virtual_crypt_sha512
191
+ })
192
+
193
+ adap.sync_user("john") # You don't have to give a plain password.
194
+ ```
195
+
196
+ ### This program must be located in AD server if you chose a password hash algorithm as :virtual_crypt_sha256 or :virtual_crypt_sha512
107
197
 
108
198
  This program must be located in AD server because samba-tool on AD only support getting hashed password only from `ldapi://` or `tdb://`.
109
199
 
@@ -24,9 +24,20 @@ class Adap
24
24
  }
25
25
 
26
26
  # List of attributes for user in AD
27
- @ad_user_required_attributes = [:cn, :sn, :uid, :uidnumber, :gidnumber, :displayname, :loginshell, :gecos, :givenname, :description, :unixhomedirectory]
27
+ @ad_user_required_attributes = [:cn, :sn, :uid, :uidnumber, :gidnumber, :displayname, :loginshell, :gecos, :givenname, :description, :mail, :employeenumber, :businesscategory, :employeeType, :unixhomedirectory]
28
28
  # List of attributes for user in LDAP
29
- @ldap_user_required_attributes = [:cn, :sn, :uid, :uidnumber, :gidnumber, :displayname, :loginshell, :gecos, :givenname, :description, :homedirectory]
29
+ @ldap_user_required_attributes = [:cn, :sn, :uid, :uidnumber, :gidnumber, :displayname, :loginshell, :gecos, :givenname, :description, :mail, :employeenumber, :businesscategory, :employeeType, :homedirectory]
30
+
31
+ # List of supported hash algorithms keys and string values to operate
32
+ @supported_hash_algorithms_map = {
33
+ :md5 => "{MD5}",
34
+ :sha => "{SHA}",
35
+ :ssha => "{SSHA}",
36
+ :virtual_crypt_sha256 => "virtualCryptSHA256",
37
+ :virtual_crypt_sha512 => "virtualCryptSHA512"
38
+ }
39
+ # List of unsupported hash algorithms in AD but OpenLDAP support
40
+ @unsupported_hash_algorithms_in_ad = [:md5, :sha, :ssha]
30
41
 
31
42
  @ad_host = params[:ad_host]
32
43
  @ad_port = (params[:ad_port] ? params[:ad_port] : 389)
@@ -40,8 +51,17 @@ class Adap
40
51
  @ldap_basedn = params[:ldap_basedn]
41
52
  @ldap_user_basedn = params[:ldap_user_basedn]
42
53
  @ldap_auth = (params.has_key?(:ldap_password) ? { :method => :simple, :username => @ldap_binddn, :password => params[:ldap_password] } : nil )
43
- # This attribute converted in generally ... :'msds-phoneticdisplayname' -> :'displayname;lang-ja;phonetic'
44
- @password_hash_algorithm = (params[:password_hash_algorithm] ? params[:password_hash_algorithm] : 'virtualCryptSHA512')
54
+
55
+ # A password-hash algorithm to sync to the LDAP.
56
+ # Popular LDAP products like Open LDAP usually supports md5({MD5}), sha1({SHA}) and ssha({SSHA}) algorithms.
57
+ # If you want to use virtualCryptSHA256 or virtualCryptSHA512, you have to set additional configurations to OpenLDAP.
58
+ @password_hash_algorithm = (params[:password_hash_algorithm] ? params[:password_hash_algorithm] : :ssha)
59
+ # TODO: Check a hash algorithm is supported or not
60
+ unless @supported_hash_algorithms_map.has_key?(@password_hash_algorithm) then
61
+ raise "This program only supports :md5, :sha, :ssha(default), :virtual_crypt_sha256 and :virtual_crypt_sha512 " \
62
+ + "as :password_hash_algorithm. " \
63
+ + "An algorithm you chose #{@password_hash_algorithm.is_a?(Symbol) ? ":" : ""}#{@password_hash_algorithm} was unsupported."
64
+ end
45
65
 
46
66
  # Phonetics are listed in https://lists.samba.org/archive/samba/2017-March/207308.html
47
67
  @map_ad_msds_phonetics = {}
@@ -112,20 +132,33 @@ class Adap
112
132
  attributes
113
133
  end
114
134
 
115
- def get_password(username)
116
- result = get_raw_password(username, @password_hash_algorithm)
117
- if not result.nil? then
118
- result = result.chomp
135
+ def get_password_hash(username, password)
136
+ case @password_hash_algorithm
137
+ when :md5, :sha, :ssha then
138
+ if password.nil? then
139
+ raise "Password must not be nil when you chose the algorithm of password-hash is :md5 or :sha or :ssha. Pass password of #{username} please."
140
+ end
141
+ result = Net::LDAP::Password.generate(@password_hash_algorithm, password)
142
+ else
143
+ # Expects :virtual_crypt_sha256(virtualCryptSHA256) or :virtual_crypt_sha512(virtualCryptSHA512)
144
+ result = get_raw_password_from_ad(username, @supported_hash_algorithms_map[@password_hash_algorithm])
145
+ end
146
+
147
+ if result.nil? or result.empty? then
148
+ raise "Failed to get hashed password with algorithm :#{@password_hash_algorithm} of user #{username}. " +
149
+ "Its result was nil. If you chose hash-algorithm :virtual_crypt_sha256 or :virtual_crypt_sha512, " +
150
+ "did you enabled AD to store passwords as virtualCryptSHA256 and/or virtualCryptSHA512 in your smb.conf? " +
151
+ "This program requires the configuration to get password from AD as virtualCryptSHA256 or virtualCryptSHA512."
119
152
  end
120
153
 
121
- return result
154
+ result.chomp
122
155
  end
123
156
 
124
- def get_raw_password(username, algo)
157
+ def get_raw_password_from_ad(username, algo)
125
158
  `samba-tool user getpassword #{username} --attribute #{algo} 2> /dev/null | grep -E '^virtualCrypt' -A 1 | tr -d ' \n' | cut -d ':' -f 2`
126
159
  end
127
160
 
128
- def sync_user(uid)
161
+ def sync_user(uid, password=nil)
129
162
  ad_entry = nil
130
163
  ldap_entry = nil
131
164
  ad_dn = get_ad_dn(uid)
@@ -137,6 +170,7 @@ class Adap
137
170
  end
138
171
  ret_code = @ad_client.get_operation_result.code
139
172
 
173
+ # Return 32 means that the object does not exist
140
174
  return {
141
175
  :code => ret_code,
142
176
  :operations => nil,
@@ -156,11 +190,16 @@ class Adap
156
190
 
157
191
  ret = nil
158
192
  if !ad_entry.nil? and ldap_entry.nil? then
159
- ret = add_user(ldap_dn, ad_entry, get_password(uid))
193
+ ret = add_user(ldap_dn, ad_entry, get_password_hash(uid, password))
160
194
  elsif ad_entry.nil? and !ldap_entry.nil? then
161
195
  ret = delete_user(ldap_dn)
162
196
  elsif !ad_entry.nil? and !ldap_entry.nil? then
163
- ret = modify_user(ldap_dn, ad_entry, ldap_entry, get_password(uid))
197
+ ret = modify_user(
198
+ ldap_dn,
199
+ ad_entry,
200
+ ldap_entry,
201
+ ( password.nil? and (@unsupported_hash_algorithms_in_ad.include?(@password_hash_algorithm)) ) ? nil : get_password_hash(uid, password)
202
+ )
164
203
  else
165
204
  # ad_entry.nil? and ldap_entry.nil? then
166
205
  return {:code => 0, :operations => nil, :message => "There are not any data of #{uid} to sync."}
@@ -183,7 +222,7 @@ class Adap
183
222
 
184
223
  def add_user(ldap_user_dn, ad_entry, password)
185
224
  if password == nil || password.empty?
186
- raise "Password of #{ldap_user_dn} from AD in add_user is empty or nil. Did you enabled AD password option virtualCryptSHA512 and/or virtualCryptSHA256?"
225
+ raise "add_user() requires password. Set a hashed password of the user #{ad_entry[:cn]} please."
187
226
  end
188
227
 
189
228
  attributes = create_ldap_attributes(ad_entry)
@@ -211,7 +250,7 @@ class Adap
211
250
  return {
212
251
  :code => ret_code,
213
252
  :operations => [:add_user],
214
- :message => "Failed to modify a user #{ldap_user_dn} in add_user() - " + @ldap_client.get_operation_result.error_message
253
+ :message => "Failed to modify a user #{ldap_user_dn} to add userPassword in add_user() - " + @ldap_client.get_operation_result.error_message
215
254
  } if ret_code != 0
216
255
 
217
256
  return {:code => ret_code, :operations => [:add_user], :message => nil}
@@ -1,3 +1,3 @@
1
1
  module ModAdap
2
- VERSION = "0.0.19"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.19
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tsutomu Nakamura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-26 00:00:00.000000000 Z
11
+ date: 2020-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -59,6 +59,7 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - ".circleci/config.yml"
62
63
  - ".gitignore"
63
64
  - ".travis.yml"
64
65
  - Gemfile
@@ -94,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
95
  - !ruby/object:Gem::Version
95
96
  version: '0'
96
97
  requirements: []
97
- rubygems_version: 3.1.3
98
+ rubygems_version: 3.1.4
98
99
  signing_key:
99
100
  specification_version: 4
100
101
  summary: LDAP migration tool from AD to NT schema