ruby-jss 1.1.0b3 → 1.1.0b5
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.
- checksums.yaml +4 -4
- data/CHANGES.md +13 -2
- data/lib/jss/api_connection.rb +6 -2
- data/lib/jss/api_object/computer.rb +2 -1
- data/lib/jss/api_object/distribution_point.rb +234 -256
- data/lib/jss/api_object/network_segment.rb +2 -2
- data/lib/jss/api_object/script.rb +6 -5
- data/lib/jss/ruby_extensions/string.rb +2 -0
- data/lib/jss/ruby_extensions/string/backports.rb +68 -0
- data/lib/jss/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9337d6314a79881c726e5b816872dffb2bccdc0f538a6f7b6407075f5be684a
|
4
|
+
data.tar.gz: dd0d9d6210d1f8abab4bbf4046cc9ec59224e08e138e7b3d6a3122f13c4b2728
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf9e2ca6b9075436d09415eee9cf31c18f3fa88325f5c7c99ab4ca06f996fa0c8e1446b2a88d862dd1628b16b9a3a79676abcc118d07dd26b1fb553826255143
|
7
|
+
data.tar.gz: 15361910ba0e772eecf502bc1d2ce644673b6a55cad00df60c207e495894a48cc67b593d05f8da32789974950984982eea568874762187bd126bb7f8fe47be56
|
data/CHANGES.md
CHANGED
@@ -13,14 +13,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
13
13
|
- ExtensionAttribute definitions when used by extendable classes
|
14
14
|
- Implemented Ruby2.4's `String#casecmp?` in older Rubies
|
15
15
|
- APIObject.fetch can take the search term `:random` and you'll get a randomly selected object. Example: `a_random_computer = JSS::Computer.fetch :random`
|
16
|
-
- Keys of the hash returned by `Computer#hardware` are now available as instance methods on Computer objects. So
|
16
|
+
- Keys of the hash returned by `Computer#hardware` are now available as instance methods on Computer objects. So as well as `a_computer.hardware[:total_ram]` you can also do `a_computer.total_ram`
|
17
|
+
- Policy now recognizes the frequency Symbol `:once_per_user_per_computer`
|
18
|
+
- Attribute reader :management_status added to Computer class
|
19
|
+
- Implemented some useful String methods from newer versions of Ruby into older Rubies: casecmp?, delete_prefix, & delete_suffix
|
17
20
|
|
18
21
|
|
19
22
|
### Fixed
|
20
23
|
- Can't Modify Frozen Hash error when instantiating JSS::Scopbable::Scope. Thanks to @shahn for reporting this one.
|
21
24
|
- MobileDeviceExtensionAttribute now handles empty `as_of` timestamp. Thanks @aurica!
|
22
|
-
- A
|
25
|
+
- A few typos. Thanks to @cybertunnel for finding some.
|
23
26
|
- A bug when parsing the `server_path` parameter to `API::Connection.new`
|
27
|
+
- Bugs in handling blank values in Policy#search_by_path and Policy#printer_ids. Thanks @cybertunnel
|
28
|
+
- Computer.management_data with a specified subset returned one level too high in the data structure
|
29
|
+
- NetworkSegment.my_network_segment: error in number of params passed to other methods
|
30
|
+
- Script#name= now works again, no longer uses a constant from an ancient version. Thanks @shahn
|
31
|
+
- Computer#asset_tag= now accepts nil to erase the value
|
32
|
+
- APIConnection.my_distribution_point & DistributionPoint.my_distribution_point now return the master_distribution_point object if there isn't one assigned to the current network segment.
|
24
33
|
|
25
34
|
### Changed
|
26
35
|
- Monkey Patches are being moved to a better, more traceable technique, see https://www.justinweiss.com/articles/3-ways-to-monkey-patch-without-making-a-mess/
|
@@ -29,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
29
38
|
- `APIObject.valid_id` is now case-insensitive
|
30
39
|
- Removed deprecated VALID_DATA_KEYS constants from APIObject subclasses
|
31
40
|
- Various changes in APIObject and its subclasses to try making `.fetch` and other lookup-methods faster.
|
41
|
+
- All of the NetworkSegment-related methods in APIConnection have been moved back to NetworkSegment. The methods in APIConnection still work, but are marked deprecated and will go away eventually.
|
42
|
+
|
32
43
|
|
33
44
|
## \[1.0.4] - 2019-05-06
|
34
45
|
### Added
|
data/lib/jss/api_connection.rb
CHANGED
@@ -911,8 +911,12 @@ module JSS
|
|
911
911
|
@my_distribution_point = nil if refresh
|
912
912
|
return @my_distribution_point if @my_distribution_point
|
913
913
|
|
914
|
-
|
915
|
-
|
914
|
+
my_net_seg_id = my_network_segments[0]
|
915
|
+
if my_net_seg_id
|
916
|
+
my_net_seg = JSS::NetworkSegment.fetch(id: my_net_seg_id, api: self)
|
917
|
+
@my_distribution_point = JSS::DistributionPoint.fetch(name: my_net_seg.distribution_point)
|
918
|
+
end # if my_net_seg_id
|
919
|
+
|
916
920
|
@my_distribution_point ||= master_distribution_point refresh
|
917
921
|
@my_distribution_point
|
918
922
|
end
|
@@ -1035,7 +1035,8 @@ module JSS
|
|
1035
1035
|
end
|
1036
1036
|
|
1037
1037
|
def asset_tag=(new_val)
|
1038
|
-
|
1038
|
+
new_val = '' if new_val.nil?
|
1039
|
+
return nil if @asset_tag.to_s == new_val
|
1039
1040
|
new_val.strip!
|
1040
1041
|
@asset_tag = new_val
|
1041
1042
|
@need_to_update = true
|
@@ -1,233 +1,222 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
###
|
1
|
+
# Copyright 2019 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
|
+
|
27
25
|
module JSS
|
28
26
|
|
27
|
+
# Module Methods
|
29
28
|
#####################################
|
30
|
-
### Module Methods
|
31
|
-
#####################################
|
32
|
-
|
33
|
-
|
34
|
-
###
|
35
|
-
### A Distribution Point in the JSS
|
36
|
-
###
|
37
|
-
### As well as the normal Class and Instance methods for {APIObject} subclasses, the
|
38
|
-
### DistributionPoint class provides more interaction with other parts of the API.
|
39
|
-
###
|
40
|
-
### Beyond the standard listing methods DistributionPoint.all, .all_ids, etc, every JSS
|
41
|
-
### has a single "master" distribution point. The Class method {DistributionPoint.master_distribution_point} will
|
42
|
-
### return the JSS::DistributionPoint object for that master.
|
43
|
-
###
|
44
|
-
### Also, some network segments have specific DistributionPoints assigned to them. Calling the Class method
|
45
|
-
### {DistributionPoint.my_distribution_point} will return a JSS::DistributionPoint object for your local IP address.
|
46
|
-
###
|
47
|
-
### Once you have an instance of JSS::DistributionPoint, you can mount it (on a Mac) by calling its {#mount} method
|
48
|
-
### and unmount it with {#unmount}. The {JSS::Package} and possibly {JSS::Script} classes use this to upload
|
49
|
-
### items to the master.
|
50
|
-
###
|
51
|
-
### @see JSS::APIObject
|
52
|
-
###
|
53
|
-
class DistributionPoint < JSS::APIObject
|
54
|
-
|
55
|
-
#####################################
|
56
|
-
### Mix-Ins
|
57
|
-
#####################################
|
58
29
|
|
59
|
-
|
60
|
-
|
30
|
+
# A Distribution Point in the JSS
|
31
|
+
#
|
32
|
+
# As well as the normal Class and Instance methods for {APIObject} subclasses, the
|
33
|
+
# DistributionPoint class provides more interaction with other parts of the API.
|
34
|
+
#
|
35
|
+
# Beyond the standard listing methods DistributionPoint.all, .all_ids, etc, every JSS
|
36
|
+
# has a single "master" distribution point. The Class method {DistributionPoint.master_distribution_point} will
|
37
|
+
# return the JSS::DistributionPoint object for that master.
|
38
|
+
#
|
39
|
+
# Also, some network segments have specific DistributionPoints assigned to them. Calling the Class method
|
40
|
+
# {DistributionPoint.my_distribution_point} will return a JSS::DistributionPoint object for your local IP address.
|
41
|
+
#
|
42
|
+
# Once you have an instance of JSS::DistributionPoint, you can mount it (on a Mac) by calling its {#mount} method
|
43
|
+
# and unmount it with {#unmount}. The {JSS::Package} and possibly {JSS::Script} classes use this to upload
|
44
|
+
# items to the master.
|
45
|
+
#
|
46
|
+
# @see JSS::APIObject
|
47
|
+
#
|
48
|
+
class DistributionPoint < JSS::APIObject
|
49
|
+
|
50
|
+
# Class Constants
|
61
51
|
#####################################
|
62
52
|
|
63
|
-
|
64
|
-
RSRC_BASE =
|
53
|
+
# The base for REST resources of this class
|
54
|
+
RSRC_BASE = 'distributionpoints'.freeze
|
65
55
|
|
66
|
-
|
67
|
-
|
56
|
+
# the hash key used for the JSON list output of all objects in the JSS
|
57
|
+
# its also used in various error messages
|
68
58
|
RSRC_LIST_KEY = :distribution_points
|
69
59
|
|
70
|
-
|
71
|
-
|
60
|
+
# The hash key used for the JSON object output.
|
61
|
+
# It's also used in various error messages
|
72
62
|
RSRC_OBJECT_KEY = :distribution_point
|
73
63
|
|
74
|
-
|
75
|
-
MOUNT_OPTIONS = 'nobrowse'
|
64
|
+
# what are the mount options? these are comma-separated, and are passed with -o
|
65
|
+
MOUNT_OPTIONS = 'nobrowse'.freeze
|
76
66
|
|
77
|
-
|
78
|
-
EMPTY_PW_256 =
|
67
|
+
# An empty SHA256 digest
|
68
|
+
EMPTY_PW_256 = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'.freeze
|
79
69
|
|
80
|
-
|
81
|
-
DEFAULT_MOUNTPOINT_DIR = Pathname.new
|
70
|
+
# Set default local mount for distribution point
|
71
|
+
DEFAULT_MOUNTPOINT_DIR = Pathname.new '/tmp'
|
82
72
|
|
83
|
-
DEFAULT_MOUNTPOINT_PREFIX =
|
73
|
+
DEFAULT_MOUNTPOINT_PREFIX = 'CasperDistribution-id'.freeze
|
84
74
|
|
85
75
|
# the object type for this object in
|
86
76
|
# the object history table.
|
87
77
|
# See {APIObject#add_object_history_entry}
|
88
78
|
OBJECT_HISTORY_OBJECT_TYPE = 76
|
89
79
|
|
90
|
-
|
80
|
+
# Class Methods
|
91
81
|
#####################################
|
92
82
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
83
|
+
# Get the DistributionPoint instance for the master
|
84
|
+
# distribution point in the JSS. If there's only one
|
85
|
+
# in the JSS, return it even if not marked as master.
|
86
|
+
#
|
87
|
+
# @param refresh[Boolean] should the distribution point be re-queried?
|
88
|
+
#
|
89
|
+
# @param api[JSS::APIConnection] which API connection should we query?
|
90
|
+
#
|
91
|
+
# @return [JSS::DistributionPoint]
|
92
|
+
#
|
103
93
|
def self.master_distribution_point(refresh = false, api: JSS.api)
|
104
94
|
api.master_distribution_point refresh
|
105
95
|
end
|
106
96
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
97
|
+
# Get the DistributionPoint instance for the machine running
|
98
|
+
# this code, based on its IP address. If none is defined for this IP address,
|
99
|
+
# use the result of master_distribution_point
|
100
|
+
#
|
101
|
+
# @param refresh[Boolean] should the distribution point be re-queried?
|
102
|
+
#
|
103
|
+
# @param api[JSS::APIConnection] which API connection should we query?
|
104
|
+
#
|
105
|
+
# @return [JSS::DistributionPoint]
|
106
|
+
#
|
117
107
|
def self.my_distribution_point(refresh = false, api: JSS.api)
|
118
108
|
api.my_distribution_point refresh
|
119
109
|
end
|
120
110
|
|
121
|
-
|
122
|
-
### Class Attributes
|
111
|
+
# Class Attributes
|
123
112
|
#####################################
|
124
113
|
|
125
|
-
|
114
|
+
# @return [String] the hostname of this DP
|
126
115
|
attr_reader :ip_address
|
127
116
|
|
128
|
-
|
117
|
+
# @return [String] the local path on the server to the distribution point directory
|
129
118
|
attr_reader :local_path
|
130
119
|
|
131
|
-
|
120
|
+
# @return [String] load balanacing enabled?
|
132
121
|
attr_reader :enable_load_balancing
|
133
122
|
|
134
|
-
|
123
|
+
# @return [Integer] the id of the DP to use for failover
|
135
124
|
attr_reader :failover_point
|
136
125
|
|
137
|
-
|
126
|
+
# @return [Boolean] is this the master DP?
|
138
127
|
attr_reader :is_master
|
139
128
|
|
140
|
-
|
129
|
+
# FileService Access
|
141
130
|
|
142
|
-
|
131
|
+
# @return [String] Protocol for fileservice access (e.g. AFP, SMB)
|
143
132
|
attr_reader :connection_type
|
144
133
|
|
145
|
-
|
134
|
+
# @return [Integer] the port for fileservice access
|
146
135
|
attr_reader :share_port
|
147
136
|
|
148
|
-
|
137
|
+
# @return [String] the name of the fileservice sharepoint
|
149
138
|
attr_reader :share_name
|
150
139
|
|
151
|
-
|
140
|
+
# @return [String] the read-write username for fileservice access
|
152
141
|
attr_reader :read_write_username
|
153
142
|
|
154
|
-
|
143
|
+
# @return [String] the read-write password as a SHA256 digest
|
155
144
|
attr_reader :read_write_password_sha256
|
156
145
|
|
157
|
-
|
146
|
+
# @return [String] read-only username for fileservice
|
158
147
|
attr_reader :read_only_username
|
159
148
|
|
160
|
-
|
149
|
+
# @return [String] read-only password as a SHA256 digest
|
161
150
|
attr_reader :read_only_password_sha256
|
162
151
|
|
163
|
-
|
152
|
+
# @return [String] work group or domain for SMB
|
164
153
|
attr_reader :workgroup_or_domain
|
165
154
|
|
166
|
-
|
155
|
+
# http(s) access
|
167
156
|
|
168
|
-
|
157
|
+
# @return [Boolean] are http downloads available from this DP?
|
169
158
|
attr_reader :http_downloads_enabled
|
170
159
|
|
171
|
-
|
160
|
+
# @return [String] the protocol to use for http downloads (http/https)
|
172
161
|
attr_reader :protocol
|
173
162
|
|
174
|
-
|
163
|
+
# @return [Integer] the port for http access
|
175
164
|
attr_reader :port
|
176
165
|
|
177
|
-
|
166
|
+
# @return [String] the "context" for http downloads (what goes after the hostname part of the URL)
|
178
167
|
attr_reader :context
|
179
168
|
|
180
|
-
|
169
|
+
# @return [Boolean] do http downloads work without auth?
|
181
170
|
attr_reader :no_authentication_required
|
182
171
|
|
183
|
-
|
172
|
+
# @return [Boolean] do http downloads use cert. authentication?
|
184
173
|
attr_reader :certificate_required
|
185
174
|
|
186
|
-
|
175
|
+
# @return [Boolean] do http downloads use user/pw auth?
|
187
176
|
attr_reader :username_password_required
|
188
177
|
|
189
|
-
|
178
|
+
# @return [String] the username to use for http downloads if needed for user/pw auth
|
190
179
|
attr_reader :http_username
|
191
180
|
|
192
|
-
|
181
|
+
# @return [String] the password for http downloads, if needed, as a SHA256 digest
|
193
182
|
attr_reader :http_password_sha256
|
194
183
|
|
195
|
-
|
184
|
+
# @return [String] the name of the cert. used for http cert. auth.
|
196
185
|
attr_reader :certificate
|
197
186
|
|
198
|
-
|
187
|
+
# @return [String] the URL for http downloads
|
199
188
|
attr_reader :http_url
|
200
189
|
|
201
|
-
|
190
|
+
# @return [String] the URL to use if this one doesn't work
|
202
191
|
attr_reader :failover_point_url
|
203
192
|
|
204
|
-
|
193
|
+
# ssh (scp, rsync, sftp) access
|
205
194
|
|
206
|
-
|
195
|
+
# @return [String] ssh username
|
207
196
|
attr_reader :ssh_username
|
208
197
|
|
209
|
-
|
198
|
+
# @return [String] the ssh password as a SHA256 digest
|
210
199
|
attr_reader :ssh_password_sha256
|
211
200
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
201
|
+
# As well as the standard :id, :name, and :data, you can
|
202
|
+
# instantiate this class with :id => :master, in which case you'll
|
203
|
+
# get the Master Distribution Point as defined in the JSS.
|
204
|
+
# An error will be raised if one hasn't been defined.
|
205
|
+
#
|
206
|
+
# You can also do this more easily by calling JSS.master_distribution_point
|
207
|
+
#
|
219
208
|
def initialize(args = {})
|
220
|
-
#TODO: this looks redundant with super....
|
209
|
+
# TODO: this looks redundant with super....
|
221
210
|
args[:api] ||= JSS.api
|
222
211
|
@api = args[:api]
|
223
212
|
|
224
213
|
@init_data = nil
|
225
214
|
|
226
|
-
|
215
|
+
# looking for master?
|
227
216
|
if args[:id] == :master
|
228
217
|
|
229
218
|
self.class.all_ids(api: @api).each do |id|
|
230
|
-
@init_data
|
219
|
+
@init_data = @api.get_rsrc("#{RSRC_BASE}/id/#{id}")[RSRC_OBJECT_KEY]
|
231
220
|
if @init_data[:is_master]
|
232
221
|
@id = @init_data[:id]
|
233
222
|
@name = @init_data[:name]
|
@@ -237,9 +226,7 @@ module JSS
|
|
237
226
|
end # each id
|
238
227
|
end # if args is master
|
239
228
|
|
240
|
-
if @init_data.nil?
|
241
|
-
super(args)
|
242
|
-
end
|
229
|
+
super(args) if @init_data.nil?
|
243
230
|
|
244
231
|
@ip_address = @init_data[:ip_address]
|
245
232
|
@local_path = @init_data[:local_path]
|
@@ -261,7 +248,6 @@ module JSS
|
|
261
248
|
@http_username = @init_data[:http_username]
|
262
249
|
@http_password_sha256 = @init_data[:http_password_sha256]
|
263
250
|
|
264
|
-
|
265
251
|
@http_downloads_enabled = @init_data[:http_downloads_enabled]
|
266
252
|
@protocol = @init_data[:protocol]
|
267
253
|
@port = @init_data[:port]
|
@@ -273,44 +259,41 @@ module JSS
|
|
273
259
|
@http_url = @init_data[:http_url]
|
274
260
|
@failover_point_url = @init_data[:failover_point_url]
|
275
261
|
|
276
|
-
|
277
262
|
@port = @init_data[:ssh_password]
|
278
263
|
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
### if we mount for fileservice, where's the mountpoint?
|
264
|
+
# Note, as of Casper 9.3:
|
265
|
+
# :management_password_md5=>"xxxxx"
|
266
|
+
# and
|
267
|
+
# :management_password_sha256=> "xxxxxxxxxx"
|
268
|
+
# Are the read/write password
|
269
|
+
#
|
270
|
+
# An empty passwd is
|
271
|
+
# MD5 = d41d8cd98f00b204e9800998ecf8427e
|
272
|
+
# SHA256 = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
273
|
+
#
|
274
|
+
# Seemms the read-only pw isn't available in the API
|
275
|
+
|
276
|
+
# if we mount for fileservice, where's the mountpoint?
|
293
277
|
@mountpoint = Pathname.new "/#{DEFAULT_MOUNTPOINT_DIR}/#{DEFAULT_MOUNTPOINT_PREFIX}#{@id}"
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
### nil is returned if there is no password set in the JSS.
|
306
|
-
###
|
278
|
+
end # init
|
279
|
+
|
280
|
+
# Check the validity of a password.
|
281
|
+
#
|
282
|
+
# @param user[Symbol] one of :ro, :rw, :ssh, :http
|
283
|
+
#
|
284
|
+
# @param pw[String] the password to check for the given user
|
285
|
+
#
|
286
|
+
# @return [Boolean,Nil] was the password correct?
|
287
|
+
# nil is returned if there is no password set in the JSS.
|
288
|
+
#
|
307
289
|
def check_pw(user, pw)
|
308
|
-
raise JSS::InvalidDataError,
|
290
|
+
raise JSS::InvalidDataError, 'The first parameter must be one of :ro, :rw, :ssh, :http' unless %i[ro rw ssh http].include? user
|
291
|
+
|
309
292
|
sha256 = case user
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
293
|
+
when :rw then @read_write_password_sha256
|
294
|
+
when :ro then @read_only_password_sha256
|
295
|
+
when :http then @http_password_sha256
|
296
|
+
when :ssh then @ssh_password_sha256
|
314
297
|
end # case
|
315
298
|
|
316
299
|
return nil if sha256 == EMPTY_PW_256
|
@@ -318,28 +301,28 @@ module JSS
|
|
318
301
|
sha256 == Digest::SHA2.new(256).update(pw).to_s
|
319
302
|
end
|
320
303
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
def reachable_for_download?
|
304
|
+
# Check to see if this dist point is reachable for downloads (read-only)
|
305
|
+
# via either http, if available, or filesharing.
|
306
|
+
#
|
307
|
+
# @param pw[String] the read-only password to use for checking the connection
|
308
|
+
# If http downloads are enabled, and no http password is required
|
309
|
+
# this can be omitted.
|
310
|
+
#
|
311
|
+
# @param check_http[Boolean] should we try the http download first, if enabled?
|
312
|
+
# If you're intentionally using the ro password for filesharing, and want to check
|
313
|
+
# only filesharing, then set this to false.
|
314
|
+
#
|
315
|
+
# @return [FalseClass, Symbol] false if not reachable, otherwise :http or :mountable
|
316
|
+
#
|
317
|
+
def reachable_for_download?(pw = '', check_http = true)
|
335
318
|
pw ||= ''
|
336
|
-
http_checked =
|
319
|
+
http_checked = ''
|
337
320
|
if check_http && http_downloads_enabled
|
338
321
|
if @username_password_required
|
339
322
|
# we don't check the pw here, because if the connection fails, we'll
|
340
323
|
# drop down below to try the password for mounting.
|
341
324
|
# we'll escape all the chars that aren't unreserved
|
342
|
-
#reserved_chars = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}]")
|
325
|
+
# reserved_chars = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}]")
|
343
326
|
user_pass = "#{CGI.escape @http_username}:#{CGI.escape ro_pw}@"
|
344
327
|
url = @http_url.sub "://#{@ip_address}", "://#{user_pass}#{@ip_address}"
|
345
328
|
else
|
@@ -350,13 +333,13 @@ module JSS
|
|
350
333
|
open(url).read
|
351
334
|
return :http
|
352
335
|
rescue
|
353
|
-
http_checked =
|
336
|
+
http_checked = 'http and '
|
354
337
|
end
|
355
338
|
end # if check_http && http_downloads_enabled
|
356
339
|
|
357
340
|
return :mountable if mounted?
|
358
341
|
|
359
|
-
return false unless check_pw :ro
|
342
|
+
return false unless check_pw :ro, pw
|
360
343
|
|
361
344
|
begin
|
362
345
|
mount pw, :ro
|
@@ -368,16 +351,17 @@ module JSS
|
|
368
351
|
end
|
369
352
|
end
|
370
353
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
def reachable_for_upload?
|
354
|
+
# Check to see if this dist point is reachable for uploads (read-write)
|
355
|
+
# via filesharing.
|
356
|
+
#
|
357
|
+
# @param pw[String] the read-write password to use for checking the connection
|
358
|
+
#
|
359
|
+
# @return [FalseClass, Symbol] false if not reachable, otherwise :mountable
|
360
|
+
#
|
361
|
+
def reachable_for_upload?(pw)
|
379
362
|
return :mountable if mounted?
|
380
|
-
return false unless check_pw :rw
|
363
|
+
return false unless check_pw :rw, pw
|
364
|
+
|
381
365
|
begin
|
382
366
|
mount pw, :rw
|
383
367
|
return :mountable
|
@@ -388,36 +372,34 @@ module JSS
|
|
388
372
|
end
|
389
373
|
end
|
390
374
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
###
|
406
|
-
### @return [Pathname] the mountpoint.
|
407
|
-
###
|
375
|
+
#
|
376
|
+
# Mount this distribution point locally.
|
377
|
+
#
|
378
|
+
# @param pw[String,Symbol] the read-only or read-write password for this DistributionPoint
|
379
|
+
# If :prompt, the user is promted on the commandline to enter the password for the :user.
|
380
|
+
# If :stdin#, the password is read from a line of std in represented by the digits at #,
|
381
|
+
# so :stdin3 reads the passwd from the third line of standard input. defaults to line 2,
|
382
|
+
# if no digit is supplied. see {JSS.stdin}
|
383
|
+
#
|
384
|
+
# @param access[Symbol] how to mount the DistributionPoint, and which password to expect.
|
385
|
+
# :ro (or anything else) = read-only, :rw = read-write
|
386
|
+
#
|
387
|
+
# @return [Pathname] the mountpoint.
|
388
|
+
#
|
408
389
|
def mount(pw = nil, access = :ro)
|
409
390
|
return @mountpoint if mounted?
|
391
|
+
|
410
392
|
access = :ro unless access == :rw
|
411
393
|
|
412
394
|
password = if pw == :prompt
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
395
|
+
JSS.prompt_for_password "Enter the password for the #{access} user '#{access == :ro ? @read_only_username : @read_write_username}':"
|
396
|
+
elsif pw.is_a?(Symbol) && pw.to_s.start_with?('stdin')
|
397
|
+
pw.to_s =~ /^stdin(\d+)$/
|
398
|
+
line = Regexp.last_match(1)
|
399
|
+
line ||= 2
|
400
|
+
JSS.stdin line
|
401
|
+
else
|
402
|
+
pw
|
421
403
|
end
|
422
404
|
|
423
405
|
pwok = check_pw(access, password)
|
@@ -432,74 +414,69 @@ module JSS
|
|
432
414
|
|
433
415
|
@mount_url = "#{@connection_type.downcase}://#{username}:#{safe_pw}@#{@ip_address}/#{@share_name}"
|
434
416
|
@mnt_cmd = case @connection_type.downcase
|
435
|
-
|
436
|
-
|
437
|
-
|
417
|
+
when 'smb' then '/sbin/mount_smbfs'
|
418
|
+
when 'afp' then '/sbin/mount_afp'
|
419
|
+
else raise "Can't mount distribution point #{@name}: no known connection type."
|
438
420
|
end
|
439
421
|
|
440
422
|
@mountpoint.mkpath
|
441
423
|
|
442
424
|
mount_out = `#{@mnt_cmd} -o '#{MOUNT_OPTIONS}' '#{@mount_url}' '#{@mountpoint}' 2>&1`
|
443
|
-
if
|
444
|
-
|
425
|
+
if ($CHILD_STATUS.exitstatus == 0) && @mountpoint.mountpoint?
|
426
|
+
# if system @mnt_cmd.to_s, *['-o', MOUNT_OPTIONS, @mount_url, @mountpoint.to_s]
|
445
427
|
@mounted = access
|
446
428
|
else
|
447
429
|
@mountpoint.rmdir if @mountpoint.directory?
|
448
430
|
@mounted = nil
|
449
431
|
raise JSS::FileServiceError, "Can't mount #{@ip_address}: #{mount_out}"
|
450
432
|
end
|
451
|
-
|
433
|
+
@mountpoint
|
452
434
|
end # mount
|
453
435
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
###
|
436
|
+
# Unmount the distribution point.
|
437
|
+
#
|
438
|
+
# Does nothing if it wasn't mounted with #mount.
|
439
|
+
#
|
440
|
+
# @return [void]
|
441
|
+
#
|
461
442
|
def unmount
|
462
443
|
return nil unless mounted?
|
444
|
+
|
463
445
|
if system "/sbin/umount '#{@mountpoint}'"
|
464
446
|
sleep 1 # the umount takes time.
|
465
|
-
@mountpoint.rmdir if @mountpoint.directory?
|
447
|
+
@mountpoint.rmdir if @mountpoint.directory? && !@mountpoint.mountpoint?
|
466
448
|
@mounted = false
|
467
449
|
else
|
468
|
-
raise
|
450
|
+
raise JSS::FileServiceError, "There was a problem unmounting #{@mountpoint}"
|
469
451
|
end
|
470
452
|
nil
|
471
453
|
end # unmount
|
472
454
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
### @return [Boolean]
|
478
|
-
###
|
455
|
+
# Is this thing mounted right now?
|
456
|
+
#
|
457
|
+
# @return [Boolean]
|
458
|
+
#
|
479
459
|
def mounted?
|
480
|
-
@mountpoint.directory?
|
460
|
+
@mountpoint.directory? && @mountpoint.mountpoint?
|
481
461
|
end
|
482
462
|
|
483
|
-
|
484
463
|
#### aliases
|
485
464
|
alias hostname ip_address
|
486
465
|
alias umount unmount
|
487
466
|
|
488
|
-
|
489
|
-
### Private Instance Methods
|
467
|
+
# Private Instance Methods
|
490
468
|
######################################
|
491
469
|
private
|
492
470
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
###
|
471
|
+
# Unused - until I get around to making DP's updatable
|
472
|
+
#
|
473
|
+
# the XML representation of the current state of this object,
|
474
|
+
# for POSTing or PUTting back to the JSS via the API
|
475
|
+
# Will be supported for Dist Points some day, I'm sure.
|
476
|
+
#
|
500
477
|
def rest_xml
|
501
478
|
doc = REXML::Document.new
|
502
|
-
dp = doc.add_element
|
479
|
+
dp = doc.add_element 'distribution_point'
|
503
480
|
dp.add_element(:name.to_s).text = @name
|
504
481
|
dp.add_element(:ip_address.to_s).text = @ip_address
|
505
482
|
dp.add_element(:local_path.to_s).text = @local_path
|
@@ -531,8 +508,9 @@ module JSS
|
|
531
508
|
dp.add_element(:ssh_username.to_s).text = @ssh_username
|
532
509
|
dp.add_element(:ssh_password.to_s).text = @ssh_password if @ssh_password
|
533
510
|
|
534
|
-
|
535
|
-
end #rest_xml
|
511
|
+
doc.to_s
|
512
|
+
end # rest_xml
|
536
513
|
|
537
514
|
end # class
|
515
|
+
|
538
516
|
end # module
|
@@ -198,7 +198,7 @@ module JSS
|
|
198
198
|
def self.network_segments_for_ip(ip, refresh = false, api: JSS.api)
|
199
199
|
ok_ip = IPAddr.new(ip)
|
200
200
|
matches = []
|
201
|
-
network_ranges.each { |id, subnet| matches << id if subnet.include?(ok_ip) }
|
201
|
+
network_ranges(refresh, api: api).each { |id, subnet| matches << id if subnet.include?(ok_ip) }
|
202
202
|
matches
|
203
203
|
end
|
204
204
|
|
@@ -226,7 +226,7 @@ module JSS
|
|
226
226
|
my_network_segments api: api
|
227
227
|
end
|
228
228
|
|
229
|
-
# All NetworkSegments in
|
229
|
+
# All NetworkSegments in the given API as IPAddr object Ranges representing the
|
230
230
|
# Segment, e.g. with starting = 10.24.9.1 and ending = 10.24.15.254
|
231
231
|
# the range looks like:
|
232
232
|
# <IPAddr: IPv4:10.24.9.1/255.255.255.255>..#<IPAddr: IPv4:10.24.15.254/255.255.255.255>
|
@@ -173,12 +173,13 @@ module JSS
|
|
173
173
|
### @return [void]
|
174
174
|
###
|
175
175
|
def name=(new_val)
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
raise JSS::
|
176
|
+
new_val = new_val.to_s
|
177
|
+
return if new_val == @name
|
178
|
+
|
179
|
+
raise JSS::MissingDataError, "Name can't be empty" if new_val.empty?
|
180
|
+
raise JSS::AlreadyExistsError, "A script already exists with the name '#{new_val}'" if JSS::Script.all_names.include? new_val
|
180
181
|
|
181
|
-
### if the filename
|
182
|
+
### if the filename matches the name, change that too.
|
182
183
|
@filename = new_val if @filename == @name
|
183
184
|
@name = new_val
|
184
185
|
|
@@ -24,6 +24,8 @@
|
|
24
24
|
|
25
25
|
require 'jss/ruby_extensions/string/conversions.rb'
|
26
26
|
require 'jss/ruby_extensions/string/predicates.rb'
|
27
|
+
require 'jss/ruby_extensions/string/backports.rb'
|
27
28
|
|
28
29
|
String.include JSSRubyExtensions::String::Predicates
|
29
30
|
String.include JSSRubyExtensions::String::Conversions
|
31
|
+
String.include JSSRubyExtensions::String::BackPorts
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Copyright 2019 Pixar
|
2
|
+
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
|
+
# with the following modification; you may not use this file except in
|
6
|
+
# compliance with the Apache License and the following modification to it:
|
7
|
+
# Section 6. Trademarks. is deleted and replaced with:
|
8
|
+
#
|
9
|
+
# 6. Trademarks. This License does not grant permission to use the trade
|
10
|
+
# names, trademarks, service marks, or product names of the Licensor
|
11
|
+
# and its affiliates, except as required to comply with Section 4(c) of
|
12
|
+
# the License and to reproduce the content of the NOTICE file.
|
13
|
+
#
|
14
|
+
# You may obtain a copy of the Apache License at
|
15
|
+
#
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
#
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
19
|
+
# distributed under the Apache License with the above modification is
|
20
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
|
+
# KIND, either express or implied. See the Apache License for the specific
|
22
|
+
# language governing permissions and limitations under the Apache License.
|
23
|
+
|
24
|
+
module JSSRubyExtensions
|
25
|
+
|
26
|
+
module String
|
27
|
+
|
28
|
+
module BackPorts
|
29
|
+
|
30
|
+
BLANK = ''.freeze
|
31
|
+
|
32
|
+
# Ruby 2.5 + has these handy delete_* methods
|
33
|
+
unless BLANK.respond_to? :delete_prefix
|
34
|
+
|
35
|
+
def delete_prefix(pfx)
|
36
|
+
sub /\A#{pfx}/, BLANK
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete_prefix!(pfx)
|
40
|
+
sub! /\A#{pfx}/, BLANK
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete_suffix(sfx)
|
44
|
+
sub /#{sfx}\z/, BLANK
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete_suffix!(sfx)
|
48
|
+
sub! /#{sfx}\z/, BLANK
|
49
|
+
end
|
50
|
+
|
51
|
+
end # unless
|
52
|
+
|
53
|
+
# String#casecmp? - its in Ruby 2.4+
|
54
|
+
unless BLANK.respond_to? :casecmp?
|
55
|
+
|
56
|
+
def casecmp?(other)
|
57
|
+
return nil unless other.is_a? String
|
58
|
+
|
59
|
+
casecmp(other).zero?
|
60
|
+
end
|
61
|
+
|
62
|
+
end # unless
|
63
|
+
|
64
|
+
end # module
|
65
|
+
|
66
|
+
end # module
|
67
|
+
|
68
|
+
end # module
|
data/lib/jss/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-jss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.0b5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Lasell
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-09-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: plist
|
@@ -245,6 +245,7 @@ files:
|
|
245
245
|
- lib/jss/ruby_extensions/object.rb
|
246
246
|
- lib/jss/ruby_extensions/pathname.rb
|
247
247
|
- lib/jss/ruby_extensions/string.rb
|
248
|
+
- lib/jss/ruby_extensions/string/backports.rb
|
248
249
|
- lib/jss/ruby_extensions/string/conversions.rb
|
249
250
|
- lib/jss/ruby_extensions/string/predicates.rb
|
250
251
|
- lib/jss/ruby_extensions/time.rb
|