adap 0.0.19 → 0.1.3

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
  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