ruby-jss 1.1.0b3 → 1.1.0b5
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 +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
|