ruby-jss 0.6.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.
Potentially problematic release.
This version of ruby-jss might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.yardopts +7 -0
- data/CHANGES.md +112 -0
- data/LICENSE.txt +174 -0
- data/README.md +426 -0
- data/THANKS.md +6 -0
- data/bin/cgrouper +485 -0
- data/bin/subnet-update +400 -0
- data/lib/jss-api.rb +2 -0
- data/lib/jss.rb +190 -0
- data/lib/jss/api_connection.rb +410 -0
- data/lib/jss/api_object.rb +616 -0
- data/lib/jss/api_object/advanced_search.rb +389 -0
- data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
- data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
- data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
- data/lib/jss/api_object/building.rb +92 -0
- data/lib/jss/api_object/category.rb +147 -0
- data/lib/jss/api_object/computer.rb +852 -0
- data/lib/jss/api_object/creatable.rb +98 -0
- data/lib/jss/api_object/criteriable.rb +189 -0
- data/lib/jss/api_object/criteriable/criteria.rb +231 -0
- data/lib/jss/api_object/criteriable/criterion.rb +228 -0
- data/lib/jss/api_object/department.rb +93 -0
- data/lib/jss/api_object/distribution_point.rb +560 -0
- data/lib/jss/api_object/extendable.rb +221 -0
- data/lib/jss/api_object/extension_attribute.rb +466 -0
- data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
- data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
- data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
- data/lib/jss/api_object/group.rb +380 -0
- data/lib/jss/api_object/group/computer_group.rb +124 -0
- data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
- data/lib/jss/api_object/group/user_group.rb +139 -0
- data/lib/jss/api_object/ldap_server.rb +535 -0
- data/lib/jss/api_object/locatable.rb +286 -0
- data/lib/jss/api_object/matchable.rb +97 -0
- data/lib/jss/api_object/mobile_device.rb +556 -0
- data/lib/jss/api_object/netboot_server.rb +148 -0
- data/lib/jss/api_object/network_segment.rb +414 -0
- data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
- data/lib/jss/api_object/package.rb +839 -0
- data/lib/jss/api_object/peripheral.rb +335 -0
- data/lib/jss/api_object/peripheral_type.rb +295 -0
- data/lib/jss/api_object/policy.rb +898 -0
- data/lib/jss/api_object/purchasable.rb +316 -0
- data/lib/jss/api_object/removable_macaddr.rb +98 -0
- data/lib/jss/api_object/scopable.rb +136 -0
- data/lib/jss/api_object/scopable/scope.rb +621 -0
- data/lib/jss/api_object/script.rb +631 -0
- data/lib/jss/api_object/self_servable.rb +356 -0
- data/lib/jss/api_object/site.rb +93 -0
- data/lib/jss/api_object/software_update_server.rb +109 -0
- data/lib/jss/api_object/updatable.rb +117 -0
- data/lib/jss/api_object/uploadable.rb +138 -0
- data/lib/jss/api_object/user.rb +272 -0
- data/lib/jss/client.rb +504 -0
- data/lib/jss/compatibility.rb +66 -0
- data/lib/jss/composer.rb +185 -0
- data/lib/jss/configuration.rb +306 -0
- data/lib/jss/db_connection.rb +298 -0
- data/lib/jss/exceptions.rb +95 -0
- data/lib/jss/ruby_extensions.rb +35 -0
- data/lib/jss/ruby_extensions/filetest.rb +43 -0
- data/lib/jss/ruby_extensions/hash.rb +79 -0
- data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
- data/lib/jss/ruby_extensions/pathname.rb +77 -0
- data/lib/jss/ruby_extensions/string.rb +59 -0
- data/lib/jss/ruby_extensions/time.rb +63 -0
- data/lib/jss/server.rb +108 -0
- data/lib/jss/utility.rb +478 -0
- data/lib/jss/version.rb +31 -0
- 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
|