ruby-jss 0.6.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/CHANGES.md +112 -0
  4. data/LICENSE.txt +174 -0
  5. data/README.md +426 -0
  6. data/THANKS.md +6 -0
  7. data/bin/cgrouper +485 -0
  8. data/bin/subnet-update +400 -0
  9. data/lib/jss-api.rb +2 -0
  10. data/lib/jss.rb +190 -0
  11. data/lib/jss/api_connection.rb +410 -0
  12. data/lib/jss/api_object.rb +616 -0
  13. data/lib/jss/api_object/advanced_search.rb +389 -0
  14. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
  15. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
  16. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
  17. data/lib/jss/api_object/building.rb +92 -0
  18. data/lib/jss/api_object/category.rb +147 -0
  19. data/lib/jss/api_object/computer.rb +852 -0
  20. data/lib/jss/api_object/creatable.rb +98 -0
  21. data/lib/jss/api_object/criteriable.rb +189 -0
  22. data/lib/jss/api_object/criteriable/criteria.rb +231 -0
  23. data/lib/jss/api_object/criteriable/criterion.rb +228 -0
  24. data/lib/jss/api_object/department.rb +93 -0
  25. data/lib/jss/api_object/distribution_point.rb +560 -0
  26. data/lib/jss/api_object/extendable.rb +221 -0
  27. data/lib/jss/api_object/extension_attribute.rb +466 -0
  28. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
  29. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
  30. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
  31. data/lib/jss/api_object/group.rb +380 -0
  32. data/lib/jss/api_object/group/computer_group.rb +124 -0
  33. data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
  34. data/lib/jss/api_object/group/user_group.rb +139 -0
  35. data/lib/jss/api_object/ldap_server.rb +535 -0
  36. data/lib/jss/api_object/locatable.rb +286 -0
  37. data/lib/jss/api_object/matchable.rb +97 -0
  38. data/lib/jss/api_object/mobile_device.rb +556 -0
  39. data/lib/jss/api_object/netboot_server.rb +148 -0
  40. data/lib/jss/api_object/network_segment.rb +414 -0
  41. data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
  42. data/lib/jss/api_object/package.rb +839 -0
  43. data/lib/jss/api_object/peripheral.rb +335 -0
  44. data/lib/jss/api_object/peripheral_type.rb +295 -0
  45. data/lib/jss/api_object/policy.rb +898 -0
  46. data/lib/jss/api_object/purchasable.rb +316 -0
  47. data/lib/jss/api_object/removable_macaddr.rb +98 -0
  48. data/lib/jss/api_object/scopable.rb +136 -0
  49. data/lib/jss/api_object/scopable/scope.rb +621 -0
  50. data/lib/jss/api_object/script.rb +631 -0
  51. data/lib/jss/api_object/self_servable.rb +356 -0
  52. data/lib/jss/api_object/site.rb +93 -0
  53. data/lib/jss/api_object/software_update_server.rb +109 -0
  54. data/lib/jss/api_object/updatable.rb +117 -0
  55. data/lib/jss/api_object/uploadable.rb +138 -0
  56. data/lib/jss/api_object/user.rb +272 -0
  57. data/lib/jss/client.rb +504 -0
  58. data/lib/jss/compatibility.rb +66 -0
  59. data/lib/jss/composer.rb +185 -0
  60. data/lib/jss/configuration.rb +306 -0
  61. data/lib/jss/db_connection.rb +298 -0
  62. data/lib/jss/exceptions.rb +95 -0
  63. data/lib/jss/ruby_extensions.rb +35 -0
  64. data/lib/jss/ruby_extensions/filetest.rb +43 -0
  65. data/lib/jss/ruby_extensions/hash.rb +79 -0
  66. data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
  67. data/lib/jss/ruby_extensions/pathname.rb +77 -0
  68. data/lib/jss/ruby_extensions/string.rb +59 -0
  69. data/lib/jss/ruby_extensions/time.rb +63 -0
  70. data/lib/jss/server.rb +108 -0
  71. data/lib/jss/utility.rb +478 -0
  72. data/lib/jss/version.rb +31 -0
  73. metadata +187 -0
@@ -0,0 +1,124 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Constants
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Variables
34
+ #####################################
35
+
36
+ #####################################
37
+ ### Module Methods
38
+ #####################################
39
+
40
+ #####################################
41
+ ### Classes
42
+ #####################################
43
+
44
+ ###
45
+ ### A computer group in the JSS
46
+ ###
47
+ ### See also the parent class JSS::Group
48
+ ###
49
+ ### @see JSS::APIObject
50
+ ###
51
+ ### @see JSS::Group
52
+ ###
53
+ class ComputerGroup < JSS::Group
54
+
55
+ #####################################
56
+ ### Mix-Ins
57
+ #####################################
58
+
59
+ #####################################
60
+ ### Class Methods
61
+ #####################################
62
+
63
+ #####################################
64
+ ### Class Constants
65
+ #####################################
66
+
67
+ ### The base for REST resources of this class
68
+ RSRC_BASE = "computergroups"
69
+
70
+ ### the hash key used for the JSON list output of all objects in the JSS
71
+ RSRC_LIST_KEY = :computer_groups
72
+
73
+ ### The hash key used for the JSON object output.
74
+ ### It's also used in various error messages
75
+ RSRC_OBJECT_KEY = :computer_group
76
+
77
+ ### these keys, as well as :id and :name, are present in valid API JSON data for this class
78
+ VALID_DATA_KEYS = [:is_smart, :computers ]
79
+
80
+ ### this allows the parent Group class to do things right
81
+ MEMBER_CLASS = JSS::Computer
82
+
83
+ #####################################
84
+ ### Class Variables
85
+ #####################################
86
+
87
+ #####################################
88
+ ### Class Methods
89
+ #####################################
90
+
91
+ #####################################
92
+ ### Attributes
93
+ #####################################
94
+
95
+ #####################################
96
+ ### Public Instance Methods
97
+ #####################################
98
+
99
+
100
+ ###
101
+ ### The serial numbers of members in this group
102
+ ###
103
+ ### @return [Array<String>] the member serial numbers
104
+ ###
105
+ def member_serial_numbers
106
+ @members.map{|m| m[:serial_number]}
107
+ end
108
+
109
+ ###
110
+ ### Return an array of the mac_addrs of members in this group
111
+ ###
112
+ ### @return [Array<String>] the member mac addresses
113
+ ###
114
+ def member_mac_addresses
115
+ @members.map{|m| m[:mac_address]} + @members.map{|m| m[:alt_mac_address]}
116
+ end
117
+
118
+ #####################################
119
+ ### Private Instance Methods
120
+ #####################################
121
+
122
+ end # class ComputerGroup
123
+
124
+ end # module
@@ -0,0 +1,139 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Constants
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Variables
34
+ #####################################
35
+
36
+ #####################################
37
+ ### Module Methods
38
+ #####################################
39
+
40
+ #####################################
41
+ ### Classes
42
+ #####################################
43
+
44
+ ###
45
+ ### A Mobile Device group in the JSS
46
+ ###
47
+ ### See also the parent class JSS::Group
48
+ ###
49
+ ### @see JSS::APIObject
50
+ ###
51
+ ### @see JSS::Group
52
+ ###
53
+ class MobileDeviceGroup < JSS::Group
54
+
55
+ #####################################
56
+ ### Mix-Ins
57
+ #####################################
58
+
59
+
60
+ #####################################
61
+ ### Class Constants
62
+ #####################################
63
+
64
+ ### The base for REST resources of this class
65
+ RSRC_BASE = "mobiledevicegroups"
66
+
67
+ ### the hash key used for the JSON list output of all objects in the JSS
68
+ RSRC_LIST_KEY = :mobile_device_groups
69
+
70
+ ### The hash key used for the JSON object output.
71
+ ### It's also used in various error messages
72
+ RSRC_OBJECT_KEY = :mobile_device_group
73
+
74
+ ### these keys, as well as :id and :name, are present in valid API JSON data for this class
75
+ VALID_DATA_KEYS = [:is_smart, :mobile_devices ]
76
+
77
+ ### this allows the parent Group class to do things right
78
+ MEMBER_CLASS = JSS::MobileDevice
79
+
80
+ #####################################
81
+ ### Class Variables
82
+ #####################################
83
+
84
+ #####################################
85
+ ### Class Methods
86
+ #####################################
87
+
88
+ #####################################
89
+ ### Attributes
90
+ #####################################
91
+
92
+ #####################################
93
+ ### Public Instance Methods
94
+ #####################################
95
+
96
+ ###
97
+ ### Return an array of the udids of mobile_devices in this group
98
+ ###
99
+ ### @return [Array<String>] the member udids
100
+ ###
101
+ def member_udids
102
+ @members.map{|m| m[:udid]}
103
+ end
104
+
105
+ ###
106
+ ### Return an array of the serial numbers of mobile_devices in this group
107
+ ###
108
+ ### @return [Array<String>] the member serial numbers
109
+ ###
110
+ def member_serial_numbers
111
+ @members.map{|m| m[:serial_number]}
112
+ end
113
+
114
+ ###
115
+ ### Return an array of the mac_addrs of mobile_devices in this group
116
+ ###
117
+ ### @return [Array<String>] the member mac addresses
118
+ ###
119
+ def member_mac_addresses
120
+ @members.map{|m| m[:mac_address]}
121
+ end
122
+
123
+ ###
124
+ ### Return an array of the wifi mac_addrs of mobile_devices in this group
125
+ ###
126
+ ### @return [Array<String>] the member wifi mac addresses
127
+ ###
128
+ def member_wifi_mac_addresses
129
+ @members.map{|m| m[:wifi_mac_address]}
130
+ end
131
+
132
+ #####################################
133
+ ### Private Instance Methods
134
+ #####################################
135
+
136
+
137
+ end # class ComputerGroup
138
+
139
+ end # module
@@ -0,0 +1,139 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Constants
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Variables
34
+ #####################################
35
+
36
+ #####################################
37
+ ### Module Methods
38
+ #####################################
39
+
40
+ #####################################
41
+ ### Classes
42
+ #####################################
43
+
44
+ ###
45
+ ### A Mobile Device group in the JSS
46
+ ###
47
+ ### See also the parent class JSS::Group
48
+ ###
49
+ ### @see JSS::APIObject
50
+ ###
51
+ ### @see JSS::Group
52
+ ###
53
+ class UserGroup < JSS::Group
54
+
55
+ #####################################
56
+ ### Mix-Ins
57
+ #####################################
58
+
59
+
60
+ #####################################
61
+ ### Class Constants
62
+ #####################################
63
+
64
+ ### The base for REST resources of this class
65
+ RSRC_BASE = "usergroups"
66
+
67
+ ### the hash key used for the JSON list output of all objects in the JSS
68
+ RSRC_LIST_KEY = :user_groups
69
+
70
+ ### The hash key used for the JSON object output.
71
+ ### It's also used in various error messages
72
+ RSRC_OBJECT_KEY = :user_group
73
+
74
+ ### these keys, as well as :id and :name, are present in valid API JSON data for this class
75
+ VALID_DATA_KEYS = [:is_smart, :users ]
76
+
77
+ ### this allows the parent Group class to do things right
78
+ MEMBER_CLASS = JSS::User
79
+
80
+ #####################################
81
+ ### Class Variables
82
+ #####################################
83
+
84
+ #####################################
85
+ ### Class Methods
86
+ #####################################
87
+
88
+ #####################################
89
+ ### Attributes
90
+ #####################################
91
+
92
+ #####################################
93
+ ### Public Instance Methods
94
+ #####################################
95
+
96
+ ###
97
+ ### Return an array of the usernames of users in this group
98
+ ###
99
+ ### @return [Array<String>] the member usernames
100
+ ###
101
+ def member_usernames
102
+ @members.map{|m| m[:username]}
103
+ end
104
+
105
+ ###
106
+ ### Return an array of the full names of users in this group
107
+ ###
108
+ ### @return [Array<String>] the member full names
109
+ ###
110
+ def member_full_names
111
+ @members.map{|m| m[:full_name]}
112
+ end
113
+
114
+ ###
115
+ ### Return an array of the phone numbers of users in this group
116
+ ###
117
+ ### @return [Array<String>] the member phone numbers
118
+ ###
119
+ def member_phone_numbers
120
+ @members.map{|m| m[:phone_number]}
121
+ end
122
+
123
+ ###
124
+ ### Return an array of the email addresses of users in this group
125
+ ###
126
+ ### @return [Array<String>] the member email addresses
127
+ ###
128
+ def member_email_addresses
129
+ @members.map{|m| m[:email_address]}
130
+ end
131
+
132
+ #####################################
133
+ ### Private Instance Methods
134
+ #####################################
135
+
136
+
137
+ end # class UserGroup
138
+
139
+ end # module
@@ -0,0 +1,535 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Variables
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Methods
34
+ #####################################
35
+
36
+
37
+ #####################################
38
+ ### Classes
39
+ #####################################
40
+
41
+ ###
42
+ ### An LDAP server in the JSS.
43
+ ###
44
+ ### This class doesn't curretly provide creation or updaing of LDAP server
45
+ ### definitions in the JSS. Please use the JSS web UI.
46
+ ###
47
+ ### However, it does provide methods for querying users and usergroups from
48
+ ### LDAP servers, and checking group membership.
49
+ ###
50
+ ### When an LDAPServer instance is created, if it
51
+ ### uses anonymous binding for lookups (the Authentication Type is set to 'none') then
52
+ ### the LDAP connection is established immediately. Otherwise, you must use the {#connect}
53
+ ### method, and provide the appropriate password for the lookup account defined.
54
+ ###
55
+ ### Since LDAP server connections are used to verify the validity of LDAP users & groups used in
56
+ ### scopes, if you don't connect to all LDAP servers before modifying any scope's user & group
57
+ ### limitations or exceptions, those new values may not be verifiable. Unverified limitations and
58
+ ### exceptions, when sent to the API, will result in a REST 409 Conflict error if the user or
59
+ ### group doesn't exist. Unfortunately, 409 Conflict errors are very generic and don't indicate the
60
+ ### source of the problem (in this case, a non-existent user or group limitation or exception to the
61
+ ### scope). The {JSS::Scopable} module tries to catch these errors and raise a more useful
62
+ ### exception when they happen.
63
+ ###
64
+ ### The class method {LDAPServer.all_ldaps} returns a Hash of JSS::LDAPServer instances.
65
+ ### one for each server defined in the JSS.
66
+ ###
67
+ ### The class methods {LDAPServer.user_in_ldap?} and {LDAPServer.group_in_ldap?} can be
68
+ ### used to check all defined LDAP servers for a user or group. They are used by
69
+ ### {JSS::Scopable::Scope} when adding user and groups to scope limitations and exceptions.
70
+ ###
71
+ ### Within an LDAPServer instance, the methods {#find_user} and {#find_group} will return
72
+ ### all matches in the server for a given search term.
73
+ ###
74
+ ### @see JSS::APIObject
75
+ ###
76
+ class LDAPServer < JSS::APIObject
77
+
78
+ #####################################
79
+ ### Mix-Ins
80
+ #####################################
81
+
82
+ #####################################
83
+ ### Class Variables
84
+ #####################################
85
+
86
+ @@all_ldaps = nil
87
+
88
+ #####################################
89
+ ### Class Methods
90
+ #####################################
91
+
92
+ ###
93
+ ### @param refresh[Boolean] should the LDAP server data be re-read from the API?
94
+ ###
95
+ ### @return [Hash{String => JSS::LDAPServer}] JSS::LDAPServer instances for all defined servers
96
+ ###
97
+ def self.all_ldaps(refresh = false)
98
+ @@all_ldaps = nil if refresh
99
+ return @@all_ldaps if @@all_ldaps
100
+
101
+ @@all_ldaps = {}
102
+ JSS::LDAPServer.all.each { |svr| @@all_ldaps[svr[:name]] = JSS::LDAPServer.new(:id =>svr[:id])}
103
+
104
+ @@all_ldaps
105
+ end
106
+
107
+ ###
108
+ ### @param user[String] a username to search for in all LDAP servers
109
+ ###
110
+ ### @return [Boolean] does the user exist in any LDAP server?
111
+ ###
112
+ def self.user_in_ldap? (user)
113
+ gotuser = false
114
+ self.all_ldaps.values.each{|ldap| gotuser = true unless ldap.find_user(user, :exact).empty? }
115
+ return gotuser
116
+ end
117
+
118
+ ###
119
+ ### @param group[String] a group to search for in all LDAP servers
120
+ ###
121
+ ### @return [Boolean] does the group exist in any LDAP server?
122
+ ###
123
+ def self.group_in_ldap? (group)
124
+ gotgroup = false
125
+ self.all_ldaps.values.each{|ldap| gotgroup = true unless ldap.find_group(group, :exact).empty? }
126
+ return gotgroup
127
+ end
128
+
129
+
130
+
131
+ #####################################
132
+ ### Class Constants
133
+ #####################################
134
+
135
+ ### The base for REST resources of this class
136
+ RSRC_BASE = "ldapservers"
137
+
138
+ ### the hash key used for the JSON list output of all objects in the JSS
139
+ RSRC_LIST_KEY = :ldap_servers
140
+
141
+ ### The hash key used for the JSON object output.
142
+ ### It's also used in various error messages
143
+ RSRC_OBJECT_KEY = :ldap_server
144
+
145
+ ### these keys, as well as :id and :name, are present in valid API JSON data for this class
146
+ VALID_DATA_KEYS = []
147
+
148
+ ### the default LDAP port
149
+ DEFAULT_PORT = 389
150
+
151
+ ### possible values for search scope
152
+ SEARCH_SCOPES = ["All Subtrees", "First Level Only"]
153
+
154
+ ### possible authentication types
155
+ AUTH_TYPES = {'none' => :anonymous, 'simple' => :simple, 'CRAM-MD5' => :cram_md5, 'DIGEST-MD5' => :digest_md5 }
156
+
157
+ ### possible referral responses
158
+ REFERRAL_RESPONSES = ['', nil, 'follow', 'ignore']
159
+
160
+ ### possible objectclass mapping options
161
+ OBJECT_CLASS_MAPPING_OPTIONS = ["any", "all"]
162
+
163
+ #####################################
164
+ ### Attributes
165
+ #####################################
166
+
167
+ ### These attributes all come from the :connection hash of the
168
+ ### API data
169
+
170
+ ### @return [String] the hostname of the server
171
+ attr_reader :hostanme
172
+
173
+ ### @return [Integer] the port for ldap
174
+ attr_reader :port
175
+
176
+ ### @return [Boolean] should the connection use ssl?
177
+ attr_reader :use_ssl
178
+
179
+ ### @return [String] what authentication method should be used?
180
+ attr_reader :authentication_type
181
+
182
+ ### @return [String] the Distinguished Name of the account used for connections/lookups?
183
+ attr_reader :lookup_dn
184
+
185
+ ### @return [String] the password for the connection/lookup account, as a SHA256 digest.
186
+ attr_reader :lookup_pw_sha256
187
+
188
+ ### @return [Integer] timeout, in seconds, for opening LDAP connections
189
+ attr_reader :open_close_timeout
190
+
191
+ ### @return [Integer] timeout, in seconds, for search queries
192
+ attr_reader :search_timeout
193
+
194
+ ### @return [String] the referral response from the server
195
+ attr_reader :referral_response
196
+
197
+ ### @return [Boolean] should searches use wildcards?
198
+ attr_reader :use_wildcards
199
+
200
+
201
+ ### @return [Hash<Symbol=>String>]
202
+ ###
203
+ ### The LDAP attributes mapped to various user data
204
+ ###
205
+ ### The hash keys are:
206
+ ### - :search_base =>
207
+ ### - :search_scope =>
208
+ ### - :object_classes =>
209
+ ### - :map_object_class_to_any_or_all =>
210
+ ### - :map_username =>
211
+ ### - :map_user_id =>
212
+ ### - :map_department =>
213
+ ### - :map_building =>
214
+ ### - :map_room =>
215
+ ### - :map_realname =>
216
+ ### - :map_phone =>
217
+ ### - :map_email_address =>
218
+ ### - :map_position =>
219
+ ### - :map_user_uuid =>
220
+ ### - :append_to_email_results =>
221
+ ###
222
+ attr_reader :user_mappings
223
+
224
+
225
+ ### @return [Hash<Symbol=>String>]
226
+ ###
227
+ ### The LDAP attributes mapped to various user group data
228
+ ###
229
+ ### The hash keys are:
230
+ ### - :search_base =>
231
+ ### - :search_scope =>
232
+ ### - :object_classes =>
233
+ ### - :map_object_class_to_any_or_all =>
234
+ ### - :map_group_id =>
235
+ ### - :map_group_name =>
236
+ ### - :map_group_uuid =>
237
+ ###
238
+ attr_reader :user_group_mappings
239
+
240
+ ### @return [Hash<Symbol=>String>]
241
+ ###
242
+ ### The LDAP attributes used to identify a user as a member of a group
243
+ ###
244
+ ### The hash keys are:
245
+ ### - :user_group_membership_stored_in =>
246
+ ### - :map_user_membership_use_dn =>
247
+ ### - :map_group_membership_to_user_field =>
248
+ ### - :group_id =>
249
+ ### - :map_object_class_to_any_or_all =>
250
+ ### - :append_to_username =>
251
+ ### - :username =>
252
+ ### - :object_classes =>
253
+ ### - :use_dn =>
254
+ ### - :search_base =>
255
+ ### - :recursive_lookups =>
256
+ ### - :search_scope =>
257
+ ### - :map_user_membership_to_group_field =>
258
+ ###
259
+ attr_reader :user_group_membership_mappings
260
+
261
+ ### @return [Boolean] we we connected to this server at the moment?
262
+ attr_reader :connected
263
+
264
+ #####################################
265
+ ### Constructor
266
+ #####################################
267
+
268
+ ###
269
+ ### See JSS::APIObject#initialize
270
+ ###
271
+ def initialize (args = {})
272
+ require 'net/ldap'
273
+ super
274
+
275
+ @hostname = @init_data[:connection][:hostname]
276
+ @port = @init_data[:connection][:port]
277
+ @use_ssl = @init_data[:connection][:use_ssl]
278
+ @authentication_type = AUTH_TYPES[@init_data[:connection][:authentication_type]]
279
+ @open_close_timeout = @init_data[:connection][:open_close_timeout]
280
+ @search_timeout = @init_data[:connection][:search_timeout]
281
+ @referral_response = @init_data[:connection][:referral_response]
282
+ @use_wildcards = @init_data[:connection][:use_wildcards]
283
+
284
+ @lookup_dn = @init_data[:connection][:account][:distinguished_username]
285
+ @lookup_pw_sha256 = @init_data[:connection][:account][:password_sha256]
286
+
287
+ @user_mappings = @init_data[:mappings_for_users ][:user_mappings]
288
+ @user_group_mappings = @init_data[:mappings_for_users ][:user_group_mappings]
289
+ @user_group_membership_mappings = @init_data[:mappings_for_users ][:user_group_membership_mappings]
290
+
291
+ # the ldap attributes to retrieve with user lookups
292
+ # (all those defined in the user mappings)
293
+ @user_attrs_to_get = {
294
+ :username => @user_mappings[:map_username],
295
+ :user_id => @user_mappings[:map_user_id],
296
+ :department => @user_mappings[:map_department],
297
+ :building => @user_mappings[:map_building],
298
+ :room => @user_mappings[:map_room],
299
+ :realname => @user_mappings[:map_realname],
300
+ :phone => @user_mappings[:map_phone],
301
+ :email_address => @user_mappings[:map_email_address],
302
+ :position => @user_mappings[:map_position],
303
+ :user_uuid => @user_mappings[:map_user_uuid]
304
+ }.delete_if{|k,v| v.nil? }
305
+
306
+ # and for groups....
307
+ @user_group_attrs_to_get = {
308
+ :group_id => @user_group_mappings[:map_group_id],
309
+ :group_name => @user_group_mappings[:map_group_name],
310
+ :group_uuid => @user_group_mappings[:map_group_uuid]
311
+ }.delete_if{|k,v| v.nil? }
312
+
313
+ @connection = nil
314
+ @connected = false
315
+
316
+ # If we are using anonymous binding, connect now
317
+ connect if @authentication_type == :anonymous
318
+ end
319
+
320
+ #####################################
321
+ ### Public Instance Methods
322
+ #####################################
323
+
324
+ ###
325
+ ###
326
+ ### @param user[String] the username to search for
327
+ ###
328
+ ### @param exact[Boolean] if true, force an exact match, otherwise use wildcards if @use_wildcards is true
329
+ ###
330
+ ### @param additional_filter[Net::LDAP::Fliter] an additional filter to be AND'd to the existing filter.
331
+ ###
332
+ ### @return [Array<Hash>] The @user_attrs_to_get for all usernames matching the query
333
+ ###
334
+ def find_user(user, exact = false, additional_filter = nil)
335
+
336
+ raise JSS::InvalidConnectionError, "Not connected to LDAP server '#{@name}'. Please use #connect first." unless @connected
337
+
338
+ if @use_wildcards and not exact
339
+ user_filter = Net::LDAP::Filter.contains(@user_mappings[:map_username], user)
340
+ else
341
+ user_filter = Net::LDAP::Filter.eq(@user_mappings[:map_username], user)
342
+ end
343
+
344
+ # limit the object classes
345
+ ocs = @user_mappings[:object_classes].to_s.chomp.split(/,\s*/)
346
+ anyall = @user_mappings[:map_object_class_to_any_or_all]
347
+ oc_filter = Net::LDAP::Filter.eq("objectclass", ocs.shift)
348
+ ocs.each do |oc|
349
+ if anyall == "any"
350
+ oc_filter = oc_filter | Net::LDAP::Filter.eq("objectclass", oc)
351
+ else
352
+ oc_filter = oc_filter & Net::LDAP::Filter.eq("objectclass", oc)
353
+ end
354
+ end
355
+
356
+ full_filter = oc_filter & user_filter
357
+ full_filter = full_filter & additional_filter if additional_filter
358
+ treebase = @user_mappings[:search_base]
359
+ ldap_attribs = @user_attrs_to_get.values
360
+
361
+ # should we grab membership from the user?
362
+ if @user_group_membership_mappings[:user_group_membership_stored_in] == "user object" and \
363
+ @user_group_membership_mappings[:map_group_membership_to_user_field]
364
+ get_groups = true
365
+ ldap_attribs << @user_group_membership_mappings[:map_group_membership_to_user_field]
366
+ end
367
+
368
+ results = []
369
+
370
+ @connection.search(:base => treebase, :filter => full_filter, :attributes => ldap_attribs ) do |entry|
371
+ userhash = {:dn => entry.dn}
372
+ @user_attrs_to_get.each do |k,attr|
373
+ userhash[k] = entry[attr][0]
374
+ end
375
+ userhash[:groups] = entry[@user_group_membership_mappings[:map_group_membership_to_user_field]] if get_groups
376
+ # to do - if the groups are dns, convert to groupnames
377
+ results << userhash
378
+ end
379
+ results
380
+ end
381
+
382
+ ###
383
+ ###
384
+ ### @param group[String] the group name to search for
385
+ ###
386
+ ### @param exact[Boolean] if true, force an exact match, otherwuse use wildcards if @use_wildcards is true
387
+ ###
388
+ ### @param additional_filter[Net::LDAP::Fliter] an additional filter to be AND'd to the existing filter.
389
+ ###
390
+ ### @return [Array<Hash>] The @user_group_attrs_to_get for all groups matching the query
391
+ ###
392
+ def find_group(group, exact = false, additional_filter = nil)
393
+
394
+ raise JSS::InvalidConnectionError, "Not connected to LDAP server '#{@name}'. Please use #connect first." unless @connected
395
+
396
+ if @use_wildcards and not exact
397
+ group_filter = Net::LDAP::Filter.contains(@user_group_mappings[:map_group_name], group)
398
+ else
399
+ group_filter = Net::LDAP::Filter.eq(@user_group_mappings[:map_group_name], group)
400
+ end
401
+
402
+ # limit the object classes
403
+ ocs = @user_group_mappings[:object_classes].to_s.chomp.split(/,\s*/)
404
+ anyall = @user_group_mappings[:map_object_class_to_any_or_all]
405
+ oc_filter = Net::LDAP::Filter.eq("objectclass", ocs.shift)
406
+ ocs.each do |oc|
407
+ if anyall == "any"
408
+ oc_filter = oc_filter | Net::LDAP::Filter.eq("objectclass", oc)
409
+ else
410
+ oc_filter = oc_filter & Net::LDAP::Filter.eq("objectclass", oc)
411
+ end
412
+ end
413
+
414
+ full_filter = oc_filter & group_filter
415
+ full_filter = full_filter & additional_filter if additional_filter
416
+ treebase = @user_group_mappings[:search_base]
417
+ ldap_attribs = @user_group_attrs_to_get.values
418
+
419
+ # should we grab membership from the group?
420
+ if @user_group_membership_mappings[:user_group_membership_stored_in] == "group object" and \
421
+ @user_group_membership_mappings[:map_user_membership_to_group_field]
422
+ get_members = true
423
+ ldap_attribs << @user_group_membership_mappings[:map_user_membership_to_group_field]
424
+ end
425
+
426
+ results = []
427
+ @connection.search(:base => treebase, :filter => full_filter, :attributes => ldap_attribs ) do |entry|
428
+ hash = {:dn => entry.dn}
429
+ @user_group_attrs_to_get.each do |k,attr|
430
+ hash[k] = entry[attr][0]
431
+ end
432
+ hash[:members] = entry[@user_group_membership_mappings[:map_user_membership_to_group_field]] if get_members
433
+ # to do, if the members are dns, convert to usernames
434
+ results << hash
435
+ end
436
+ results
437
+ end
438
+
439
+
440
+ ###
441
+ ### @param user[String] the username to check for memebership in the group
442
+ ###
443
+ ### @param group[String] the group name to see if the user is a member
444
+ ###
445
+ ### @return [Boolean, nil] is the user a member? Nil if unable to check
446
+ ###
447
+ ### @todo Implement checking groups membership in 'other' ldap area
448
+ ###
449
+ def check_membership(user, group)
450
+
451
+ raise JSS::InvalidConnectionError, "Not connected to LDAP server '#{@name}'. Please use #connect first." unless @connected
452
+
453
+ found_user = find_user(user, :exact)[0]
454
+ found_group = find_group(group, :exact)[0]
455
+
456
+ raise JSS::NoSuchItemError, "No user '#{user}' in LDAP." unless found_user
457
+ raise JSS::NoSuchItemError, "No group '#{group}' in LDAP." unless found_group
458
+
459
+ if @user_group_membership_mappings[:user_group_membership_stored_in] == "group object"
460
+ if @user_group_membership_mappings[:map_user_membership_use_dn]
461
+ return found_group[:members].include? found_user[:dn]
462
+ else
463
+ return found_group[:members].include? user
464
+ end
465
+
466
+
467
+ elsif @user_group_membership_mappings[:user_group_membership_stored_in] == "user object"
468
+ if @user_group_membership_mappings[:use_dn]
469
+ return found_user[:groups].include? found_group[:dn]
470
+ else
471
+ return found_user[:groups].include? group
472
+ end
473
+
474
+
475
+ else
476
+ ### To do!!
477
+ return nil
478
+ # implement a search based on the "other" settings
479
+ # This will be 3 searchs
480
+ # - one for the username mapping in users
481
+ # - one for the gid in groups
482
+ # - one for a record linking them in the "other" search base
483
+ end
484
+ end
485
+
486
+
487
+ ###
488
+ ### The connect to this LDAP server for subsequent use of the {#find_user}, {#find_group}
489
+ ### and {#check_membership} methods
490
+ ###
491
+ ### @param pw[String,Symbol] the LDAP connection password for this server. Can be nil if
492
+ ### authentication type is 'none'.
493
+ ### If :prompt, the user is promted on the commandline to enter the password for the :user.
494
+ ### If :stdin#, the password is read from a line of std in represented by the digit at #,
495
+ ### so :stdin3 reads the passwd from the third line of standard input. defaults to line 2,
496
+ ### if no digit is supplied. see {JSS.stdin}
497
+ ###
498
+ ###
499
+ ### @return [Boolean] did we connect to the LDAP server with the defined credentials
500
+ ###
501
+ def connect(pw = nil)
502
+
503
+ unless @authentication_type == :anonymous
504
+ # how do we get the password?
505
+ password = if pw == :prompt
506
+ JSS.prompt_for_password "Enter the password for the LDAP connection account '#{@lookup_dn}':"
507
+ elsif pw.is_a?(Symbol) and pw.to_s.start_with?('stdin')
508
+ pw.to_s =~ /^stdin(\d+)$/
509
+ line = $1
510
+ line ||= 2
511
+ JSS.stdin line
512
+ else
513
+ pw
514
+ end
515
+
516
+
517
+ raise JSS::InvalidDataError, "Incorrect password for LDAP connection account '#{@lookup_dn}'" unless @lookup_pw_sha256 == Digest::SHA2.new(256).update(password.to_s).to_s
518
+ end # unless
519
+
520
+ @connection = Net::LDAP.new :host => @hostname, :port => @port, :auth => {:method => @authentication_type, :username => @lookup_dn, :password => password }
521
+
522
+ @connected = true
523
+ end # connect
524
+
525
+
526
+
527
+ ###
528
+ ### Aliases
529
+ ###
530
+
531
+ alias connected? connected
532
+
533
+ end # class ldap server
534
+
535
+ end # module