depot3 0.0.0a1 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +55 -1
  3. data/bin/d3 +323 -0
  4. data/bin/d3admin +1011 -0
  5. data/bin/d3helper +354 -0
  6. data/bin/puppytime +334 -0
  7. data/data/d3/com.pixar.d3.RepoMan.plist +23 -0
  8. data/data/d3/d3.conf.example +507 -0
  9. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftAppKit.dylib +0 -0
  10. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCore.dylib +0 -0
  11. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCoreData.dylib +0 -0
  12. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCoreGraphics.dylib +0 -0
  13. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCoreImage.dylib +0 -0
  14. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftDarwin.dylib +0 -0
  15. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftDispatch.dylib +0 -0
  16. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftFoundation.dylib +0 -0
  17. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftObjectiveC.dylib +0 -0
  18. data/data/d3/d3RepoMan.app/Contents/Info.plist +56 -0
  19. data/data/d3/d3RepoMan.app/Contents/MacOS/d3RepoMan +0 -0
  20. data/data/d3/d3RepoMan.app/Contents/PkgInfo +1 -0
  21. data/data/d3/d3RepoMan.app/Contents/Resources/Base.lproj/MainMenu.nib +0 -0
  22. data/data/d3/d3RepoMan.app/Contents/Resources/last-foreground-times-template.plist +5 -0
  23. data/data/d3/d3RepoMan.app/Contents/_CodeSignature/CodeResources +214 -0
  24. data/data/d3/puppytime/ImageLicenses.txt +165 -0
  25. data/data/d3/puppytime/notification_image +1 -0
  26. data/data/d3/puppytime/opt_out_image +1 -0
  27. data/data/d3/puppytime/slideshow/2008-07-11_White_German_Shepherd_pup_chilling_at_the_Coker_Arboretum.jpg +0 -0
  28. data/data/d3/puppytime/slideshow/2009-04-21_APBT_pup_on_deck.jpg +0 -0
  29. data/data/d3/puppytime/slideshow/A_puppy_Yorkie.jpg +0 -0
  30. data/data/d3/puppytime/slideshow/Alert_Pug_Puppy.jpg +0 -0
  31. data/data/d3/puppytime/slideshow/Australian_Cattle_Dog_puppies_04.JPG +0 -0
  32. data/data/d3/puppytime/slideshow/Beagle_puppy_Cadet.jpg +0 -0
  33. data/data/d3/puppytime/slideshow/Bernese_Mountain_Dog.jpg +0 -0
  34. data/data/d3/puppytime/slideshow/Bloodhound_Puppy.jpg +0 -0
  35. data/data/d3/puppytime/slideshow/Boston_terrier_with_toy.jpg +0 -0
  36. data/data/d3/puppytime/slideshow/Boxer_puppy_fawn_portrai.jpg +0 -0
  37. data/data/d3/puppytime/slideshow/Caracal_kitten.jpg +0 -0
  38. data/data/d3/puppytime/slideshow/Chihuahua_&_Doberman_Pup.jpg +0 -0
  39. data/data/d3/puppytime/slideshow/Cuccioli_di_Margot_a_35_gg_Basenjis.jpg +0 -0
  40. data/data/d3/puppytime/slideshow/Dalmatian_puppy_03.jpg +0 -0
  41. data/data/d3/puppytime/slideshow/GoldenRetrieverPuppyDaisyParker.JPG +0 -0
  42. data/data/d3/puppytime/slideshow/Green_eyed_beige_Chihuahua.jpg +0 -0
  43. data/data/d3/puppytime/slideshow/Let_Sleeping_Dogs_Lie.jpg +0 -0
  44. data/data/d3/puppytime/slideshow/Meatball_-_French_Bulldog_Puppy.jpg +0 -0
  45. data/data/d3/puppytime/slideshow/Oola_-_9_weeks.jpg +0 -0
  46. data/data/d3/puppytime/slideshow/Pancho0008.JPG +0 -0
  47. data/data/d3/puppytime/slideshow/Pomeranian_orange-sable_Coco.jpg +0 -0
  48. data/data/d3/puppytime/slideshow/Pug_puppy_001.jpg +0 -0
  49. data/data/d3/puppytime/slideshow/Puggle_puppy_6_weeks.JPG +0 -0
  50. data/data/d3/puppytime/slideshow/Puli_kan.jpg +0 -0
  51. data/data/d3/puppytime/slideshow/Puppy_French_Bulldog.jpg +0 -0
  52. data/data/d3/puppytime/slideshow/Rocco_the_Bulldog.jpg +0 -0
  53. data/data/d3/puppytime/slideshow/Rottweiler_Face.jpg +0 -0
  54. data/data/d3/puppytime/slideshow/Saint_Bernard_puppy.jpg +0 -0
  55. data/data/d3/puppytime/slideshow/Scottish_froment.jpg +0 -0
  56. data/data/d3/puppytime/slideshow/Shar_pei_puppy_(age_2_months).jpg +0 -0
  57. data/data/d3/puppytime/slideshow/Shiba-Inu_beim_Spielen_im_Schnee.JPG +0 -0
  58. data/data/d3/puppytime/slideshow/Smooth-coat_Border_Collie_puppy..jpg +0 -0
  59. data/data/d3/puppytime/slideshow/Smooth_Dachshund_puppies.jpg +0 -0
  60. data/data/d3/puppytime/slideshow/Snow_dog.jpg +0 -0
  61. data/data/d3/puppytime/slideshow/Taylor_the_Pembroke_Welsh_Corgi.png +0 -0
  62. data/data/d3/puppytime/slideshow/Weim_Pups_001.jpg +0 -0
  63. data/data/d3/puppytime/slideshow/Westie_pups.jpg +0 -0
  64. data/data/d3/puppytime/slideshow/Yellow_Labrador_puppies_(4165737325).jpg +0 -0
  65. data/lib/d3/admin/add.rb +451 -0
  66. data/lib/d3/admin/auth.rb +470 -0
  67. data/lib/d3/admin/edit.rb +297 -0
  68. data/lib/d3/admin/help.rb +396 -0
  69. data/lib/d3/admin/interactive.rb +972 -0
  70. data/lib/d3/admin/options.rb +454 -0
  71. data/lib/d3/admin/prefs.rb +204 -0
  72. data/lib/d3/admin/report.rb +727 -0
  73. data/lib/d3/admin/state.rb +42 -0
  74. data/lib/d3/admin/validate.rb +413 -0
  75. data/lib/d3/admin.rb +42 -0
  76. data/lib/d3/basename.rb +217 -0
  77. data/lib/d3/client/auth.rb +108 -0
  78. data/lib/d3/client/class_methods.rb +766 -0
  79. data/lib/d3/client/class_variables.rb +47 -0
  80. data/lib/d3/client/cli.rb +187 -0
  81. data/lib/d3/client/environment.rb +134 -0
  82. data/lib/d3/client/help.rb +110 -0
  83. data/lib/d3/client/lists.rb +314 -0
  84. data/lib/d3/client/receipt.rb +1173 -0
  85. data/lib/d3/client.rb +45 -0
  86. data/lib/d3/configuration.rb +319 -0
  87. data/lib/d3/constants.rb +60 -0
  88. data/lib/d3/database.rb +488 -0
  89. data/lib/d3/exceptions.rb +44 -0
  90. data/lib/d3/log.rb +271 -0
  91. data/lib/d3/package/aliases.rb +80 -0
  92. data/lib/d3/package/attributes.rb +97 -0
  93. data/lib/d3/package/class_methods.rb +817 -0
  94. data/lib/d3/package/class_variables.rb +46 -0
  95. data/lib/d3/package/client_actions.rb +293 -0
  96. data/lib/d3/package/constants.rb +58 -0
  97. data/lib/d3/package/constructor.rb +191 -0
  98. data/lib/d3/package/getters.rb +164 -0
  99. data/lib/d3/package/mixins.rb +39 -0
  100. data/lib/d3/package/private_methods.rb +227 -0
  101. data/lib/d3/package/questions.rb +95 -0
  102. data/lib/d3/package/server_actions.rb +683 -0
  103. data/lib/d3/package/setters.rb +326 -0
  104. data/lib/d3/package/validate.rb +448 -0
  105. data/lib/d3/package.rb +51 -0
  106. data/lib/d3/puppytime/pending_puppy.rb +108 -0
  107. data/lib/d3/puppytime/puppy_queue.rb +274 -0
  108. data/lib/d3/puppytime.rb +68 -0
  109. data/lib/d3/state.rb +105 -0
  110. data/lib/d3/utility.rb +325 -0
  111. data/lib/d3/version.rb +1 -1
  112. metadata +162 -9
@@ -0,0 +1,470 @@
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 D3
27
+ module Admin
28
+
29
+ ### This module contains methods for dealing with d3 admin authentication
30
+ ### getting, & storing the passwords needed to connect to the JSS and the
31
+ ### database as a d3 admin.
32
+ ###
33
+ module Auth
34
+ extend self
35
+
36
+ ################# Module Constants #################
37
+
38
+ RW_CREDENTIAL_KINDS = [:jss, :db, :dist]
39
+
40
+ KEYCHAIN_SERVICE_BASE = "d3admin"
41
+ KEYCHAIN_LABEL_BASE = "com.pixar.d3.admin"
42
+
43
+ KEYCHAIN_JSS_SERVICE = KEYCHAIN_SERVICE_BASE + ".jss-api"
44
+ KEYCHAIN_JSS_LABEL = KEYCHAIN_LABEL_BASE + ".jss-api"
45
+
46
+ KEYCHAIN_DB_SERVICE = KEYCHAIN_SERVICE_BASE + ".db"
47
+ KEYCHAIN_DB_LABEL = KEYCHAIN_LABEL_BASE + ".db"
48
+
49
+ KEYCHAIN_DIST_ACCT = "defined_in_jss"
50
+ KEYCHAIN_DIST_SERVICE = KEYCHAIN_SERVICE_BASE + ".distribution"
51
+ KEYCHAIN_DIST_LABEL = KEYCHAIN_LABEL_BASE + ".distribution"
52
+
53
+ ### Connect to the JSS API and MySQL DB
54
+ ### with admin credentials from the keychain
55
+ ###
56
+ ### @return [String] the JSS hostname to which the connection was made
57
+ ###
58
+ def connect (alt_db = false)
59
+ api = rw_credentials :jss
60
+ db = rw_credentials :db
61
+
62
+ JSS::DB_CNX.connect :user => db[:user], :pw => db[:password], :connect_timeout => 10
63
+ JSS::API.connect :user => api[:user], :pw => api[:password], :open_timeout => 10
64
+ D3::Database.check_schema_version
65
+ return JSS::API.cnx.options[:server]
66
+ end
67
+
68
+ # Disconnect admin credentials from the JSS API and MySQL DB
69
+ def disconnect
70
+ JSS::API.disconnect if JSS::API.connected?
71
+ JSS::DB_CNX.disconnect if JSS::DB_CNX.connected?
72
+ end
73
+
74
+ ### Fetch read-write credentials from the login keychain
75
+ ###
76
+ ### If the login keychain is locked, the user will be prompted
77
+ ### to unlock it in the GUI.
78
+ ###
79
+ ### @param kind[Symbol] which kind of credentials? :jss, :db, or :dist
80
+ ###
81
+ ### @param checking_for_existence[Boolean] Are we just checking to see if
82
+ ### this value has been set? If so, and it hasn't, don't prompt for
83
+ ### saving, just return an empty hash.
84
+ ###
85
+ ### @return [Hash{Symbol => String}] A Hash with :user and :password values.
86
+ ### or empty if unset and checking for existence.
87
+ ###
88
+ def rw_credentials(kind, checking_for_existence = false)
89
+ Keychain.user_interaction_allowed = true
90
+ unlock_keychain
91
+ search_conditions = case kind
92
+ when :jss
93
+ {:service => KEYCHAIN_JSS_SERVICE, :label => KEYCHAIN_JSS_LABEL}
94
+ when :db
95
+ {:service => KEYCHAIN_DB_SERVICE, :label => KEYCHAIN_DB_LABEL}
96
+ when :dist
97
+ {:service => KEYCHAIN_DIST_SERVICE, :account => KEYCHAIN_DIST_ACCT, :label => KEYCHAIN_DIST_LABEL}
98
+ else
99
+ raise JSS::InvalidDataError, "argument must be one of :#{RW_CREDENTIAL_KINDS.join ', :'}"
100
+ end #pw_item = case kind
101
+
102
+ pw_item = Keychain.default.generic_passwords.where(search_conditions).first
103
+ return {} if pw_item.nil? and checking_for_existence
104
+
105
+ if pw_item
106
+ return {:user => pw_item.account, :password => pw_item.password}
107
+ else
108
+ # doesn't exist in the keychain, so get from the user and save in the keychain
109
+ ask_for_rw_credentials(kind)
110
+ end # if pw_item
111
+ end
112
+
113
+ ### Prompt for a JSS or MySQL server hostname & port.
114
+ ### Test that its a valid server,
115
+ ### and save it to the User-level JSS config file
116
+ ###
117
+ ### @param type[Symbol] either :jss or :db
118
+ ###
119
+ ### @return [void]
120
+ ###
121
+ def get_server (type)
122
+
123
+ case type
124
+ when :jss
125
+ thing = "API"
126
+ current = JSS::CONFIG.api_server_name
127
+ current_port = JSS::CONFIG.api_server_port
128
+ current_port ||= JSS::APIConnection::SSL_PORT
129
+ when :db
130
+ thing = "MySQL DB"
131
+ current = JSS::CONFIG.db_server_name
132
+ current_port = JSS::CONFIG.db_server_port
133
+ current_port ||= JSS::DBConnection::DFT_PORT
134
+ else
135
+ raise JSS::InvalidDataError, "Argument must be :jss or :db"
136
+ end
137
+
138
+ got_it = false
139
+ until got_it
140
+ puts
141
+ puts "Enter the server hostname for the JSS #{thing}"
142
+ puts "Hit return for #{current}" if current
143
+ print "JSS #{thing} Server: "
144
+ server_entered = $stdin.gets.chomp
145
+ server_entered = current if server_entered.empty?
146
+
147
+ next if server_entered.empty?
148
+
149
+ puts
150
+ puts "Enter the port number for the JSS #{thing} on #{server_entered}"
151
+ puts "Hit return for #{current_port}" if current_port
152
+ print "JSS #{thing} port: "
153
+ port_entered = $stdin.gets.chomp
154
+ port_entered = current_port if port_entered.empty?
155
+
156
+ got_it = test_server_available(type, server_entered, port_entered)
157
+
158
+ if got_it
159
+ case type
160
+ when :jss then
161
+ JSS::CONFIG.api_server_name = server_entered
162
+ JSS::CONFIG.api_server_port = port_entered
163
+ when :db
164
+ JSS::CONFIG.db_server_name = server_entered
165
+ JSS::CONFIG.db_server_port = port_entered
166
+ end # case
167
+ JSS::CONFIG.save :user
168
+ end # if got_it
169
+ end # until
170
+ return server_entered
171
+ end # def get server
172
+
173
+ ### Test that a given hostname is actually a server of the given type
174
+ ### by testing the connection without actually logging in.
175
+ ### Displays the connection error if unable to connect.
176
+ ###
177
+ ### @param type[Symbol] either :jss or :db
178
+ ###
179
+ ### @param server[String] the hostname to try connecting to
180
+ ###
181
+ ### @return [Boolean] does the host run a server of that type?
182
+ ###
183
+ def test_server_available (type, server, port)
184
+ puts "Checking connection to #{server}"
185
+ case type
186
+ when :jss then
187
+ if JSS::API.valid_server? server
188
+ JSS::CONFIG.api_server_name = server
189
+ JSS::CONFIG.save :user
190
+ return true
191
+ else
192
+ failure = "'#{server}' does not host a JSS API server"
193
+ end # if
194
+
195
+ when :db
196
+ if JSS::DB_CNX.valid_server? server, port
197
+ JSS::CONFIG.db_server_name = server
198
+ JSS::CONFIG.save :user
199
+ return true
200
+ else
201
+ failure = "'#{server}' does not host a MySQL server"
202
+ end # if
203
+
204
+ else
205
+ failure = "Unknown Server Type: #{type}"
206
+ end # case
207
+
208
+ puts "Sorry, that server is invalid: #{failure}"
209
+ return false
210
+ end # test_server_available
211
+
212
+ ### Prompt for read-write credentials & store them in the default (login) keychain
213
+ ###
214
+ ### Raises an exception after 3 failures
215
+ ###
216
+ ### @param kind[Symbol] which kind of credentials? :jss, :db, or :dist
217
+ ###
218
+ ### @return [Hash{Symbol => String}] A Hash with :user and :password values.
219
+ ###
220
+ def ask_for_rw_credentials(kind)
221
+
222
+ #$stdin.reopen("/dev/tty")
223
+
224
+ # make sure we have a server, which will be stored in the user-level JSS::Configuration
225
+ get_server (kind) unless kind == :dist
226
+
227
+ # make sure the keychain is unlocked
228
+ unlock_keychain
229
+
230
+ thing_to_access = case kind
231
+ when :jss then "the JSS API on #{JSS::API.hostname}"
232
+ when :db then "the JSS MySQL db at #{JSS::DB_CNX.hostname}"
233
+ when :dist then "read-write access to the JSS Master Distribution Point"
234
+ else raise JSS::InvalidDataError, "argument must be one of :#{RW_CREDENTIAL_KINDS.join ', :'}"
235
+ end # case kind
236
+
237
+ # three tries
238
+ begin
239
+ pw = nil
240
+ tries = 0
241
+ while tries != 3
242
+
243
+ # for dist we only need a password
244
+ if kind == :dist
245
+ user = KEYCHAIN_DIST_ACCT
246
+ user_text = ''
247
+ else
248
+ print "Username for RW access to #{thing_to_access}: "
249
+ user = $stdin.gets.chomp
250
+ user_text = "#{user} @ "
251
+ end
252
+
253
+ print "Password for #{user_text}#{thing_to_access}: "
254
+ system "stty -echo"
255
+ pw = $stdin.gets.chomp
256
+ system "stty echo"
257
+ break if check_credentials(kind, user, pw)
258
+
259
+ puts "\nSorry, that was incorrect"
260
+ tries += 1
261
+ end # while
262
+
263
+ # did we get it in 3 tries?
264
+ raise JSS::InvalidDataError, "Three wrong attempts, please contact a Casper administrator." if 3 == tries
265
+
266
+ save_credentials(kind, user, pw)
267
+ puts "\nThank you, the credentials have been saved in your OS X login keychain"
268
+ ensure
269
+ # make sure terminal is usable at the end of this
270
+ system "stty echo"
271
+ puts ""
272
+ end # begin
273
+
274
+ # we should now have user and pw
275
+ return {:user => user, :password => pw}
276
+ end # def ask_for_rw_credentials(kind)
277
+
278
+ ### Check a user and password for validity
279
+ ###
280
+ ### @param kind[Symbol] which kind of credentials? :jss, :db, or :dist
281
+ ###
282
+ ### @param user[String] the username to check
283
+ ###
284
+ ### @param pw[String] the password to try with the username
285
+ ###
286
+ ### @return [Boolean] were the user and password valid?
287
+ ###
288
+ def check_credentials(kind, user = "", pw = "")
289
+ case kind
290
+ when :jss then check_jss_credentials(user,pw)
291
+ when :db then check_db_credentials(user,pw)
292
+ when :dist then check_dist_credentials(pw)
293
+ else raise JSS::InvalidDataError, "First argument must be one of :#{RW_CREDENTIAL_KINDS.join ', :'}"
294
+ end # case kind
295
+ end
296
+
297
+ ### Check a username and passwd for rw access to the JSS API
298
+ ###
299
+ ### Note: this only checks for connectivity, not permissions once connected.
300
+ ###
301
+ ### @param user[String] the username to check
302
+ ###
303
+ ### @param pw[String] the password to try with the username
304
+ ###
305
+ ### @return [Boolean] were the user and password valid?
306
+ ###
307
+ def check_jss_credentials(user,pw)
308
+ begin
309
+ JSS::API.disconnect if JSS::API.connected?
310
+ JSS::API.connect :user => user, :pw => pw, :server => JSS::CONFIG.api_server_name
311
+ rescue JSS::AuthenticationError
312
+ return false
313
+ end
314
+ JSS::API.disconnect if JSS::API.connected?
315
+ return true
316
+ end
317
+
318
+ ### Check a username and passwd for rw access to the JSS MySQL DB
319
+ ###
320
+ ### Note: this only checks for connectivity, not permissions once connected.
321
+ ###
322
+ ### @param user[String] the username to check
323
+ ###
324
+ ### @param pw[String] the password to try with the username
325
+ ###
326
+ ### @return [Boolean] were the user and password valid?
327
+ ###
328
+ def check_db_credentials(user,pw)
329
+ begin
330
+ JSS::DB_CNX.disconnect if JSS::DB_CNX.connected?
331
+ JSS::DB_CNX.connect :user => user, :pw => pw, :server => JSS::CONFIG.db_server_name
332
+ rescue Mysql::ServerError::AccessDeniedError
333
+ return false
334
+ end
335
+ JSS::DB_CNX.disconnect if JSS::DB_CNX.connected?
336
+ return true
337
+ end
338
+
339
+ ### Check a passwd for rw access to the master distribution point in the JSS
340
+ ###
341
+ ### @param pw[String] the password to try
342
+ ###
343
+ ### @return [Boolean] was the password valid?
344
+ ###
345
+ def check_dist_credentials(pw)
346
+ D3::Admin::Auth.connect
347
+ ok = JSS::DistributionPoint.master_distribution_point.check_pw :rw, pw
348
+ D3::Admin::Auth.disconnect
349
+ ok
350
+ end
351
+
352
+ ### Save a user and password to the login keychain
353
+ ###
354
+ ### Note: assumes the validity of the credentials
355
+ ###
356
+ ### @param kind[Symbol] which kind of credentials? :jss, :db, or :dist
357
+ ###
358
+ ### @param user[String] the username to check
359
+ ###
360
+ ### @param pw[String] the password to try with the username
361
+ ###
362
+ ### @return [Boolean] were the user and password valid?
363
+ ###
364
+ def save_credentials(kind, user = "", pw = "")
365
+ case kind
366
+ when :jss then save_jss_rw_credentials(user,pw)
367
+ when :db then save_db_rw_credentials(user,pw)
368
+ when :dist then save_dist_rw_credentials(pw)
369
+ else raise JSS::InvalidDataError, "First argument must be one of :#{RW_CREDENTIAL_KINDS.join ', :'}"
370
+ end # case kind
371
+ end
372
+
373
+ ### Save the credentials for read-write access to the JSS API in the login keychain
374
+ ###
375
+ ### Note: assumes the validity of the user and passwd. See {#check_jss_pw}
376
+ ###
377
+ ### @param user[String] the username to save
378
+ ###
379
+ ### @param pw[String] the password to save with the username
380
+ ###
381
+ ### @return [void]
382
+ ###
383
+ def save_jss_rw_credentials(user, pw)
384
+ pw_item = Keychain.default.generic_passwords.where(:service => KEYCHAIN_JSS_SERVICE, :label => KEYCHAIN_JSS_LABEL, :account => user).first
385
+ pw_item.delete if pw_item
386
+ Keychain.default.generic_passwords.create :service => KEYCHAIN_JSS_SERVICE, :label => KEYCHAIN_JSS_LABEL, :account => user, :password => pw
387
+ end
388
+
389
+ ### Save the credentials for read-write access to the JSS DB in the login keychain
390
+ ###
391
+ ### Note: assumes the validity of the user and passwd. See {#check_db_pw}
392
+ ###
393
+ ### @param user[String] the username to save
394
+ ###
395
+ ### @param pw[String] the password to save with the username
396
+ ###
397
+ ### @return [void]
398
+ ###
399
+ def save_db_rw_credentials(user, pw)
400
+ pw_item = Keychain.default.generic_passwords.where(:service => KEYCHAIN_DB_SERVICE, :label => KEYCHAIN_DB_LABEL, :account => user).first
401
+ pw_item.delete if pw_item
402
+ Keychain.default.generic_passwords.create :service => KEYCHAIN_DB_SERVICE, :label => KEYCHAIN_DB_LABEL, :account => user, :password => pw
403
+ end
404
+
405
+ ### Save the credentials for read-write access to the JSS master dist. point
406
+ ### in the login keychain
407
+ ###
408
+ ### Note: assumes the validity of the passwd. See {#check_dist_rw_pw}
409
+ ###
410
+ ### @param pw[String] the password to save with the username
411
+ ###
412
+ ### @return [void]
413
+ ###
414
+ def save_dist_rw_credentials(pw)
415
+ pw_item = Keychain.default.generic_passwords.where(:service => KEYCHAIN_DIST_SERVICE, :label => KEYCHAIN_DIST_LABEL, :account => KEYCHAIN_DIST_ACCT).first
416
+ pw_item.delete if pw_item
417
+ Keychain.default.generic_passwords.create :service => KEYCHAIN_DIST_SERVICE, :label => KEYCHAIN_DIST_LABEL, :account => KEYCHAIN_DIST_ACCT, :password => pw
418
+ end
419
+
420
+ ### Prompt the user to unlock the default keychain
421
+ ###
422
+ ### @return [void]
423
+ ###
424
+ def unlock_keychain
425
+ return true unless Keychain.default.locked?
426
+ begin
427
+ unlocked = false
428
+ tries = 0
429
+ until unlocked or tries == 3
430
+ puts "Please enter the password for your default keychain"
431
+ puts "(#{Keychain.default.path})"
432
+ print "Keychain password: "
433
+ system "stty -echo"
434
+ pw = $stdin.gets.chomp
435
+ system "stty echo"
436
+ begin
437
+ Keychain.default.unlock! pw
438
+ unlocked = true
439
+ rescue Keychain::AuthFailedError
440
+ puts
441
+ puts "Sorry that was incorrect"
442
+ tries += 1
443
+ end # begin..rescue
444
+ end # until
445
+ ensure
446
+ system "stty echo"
447
+ end #begin..ensure
448
+
449
+ raise JSS::AuthenticationError, "Three incorrect attempts to unlock keychain" if tries == 3
450
+ return true
451
+ end # unlock keychain
452
+
453
+
454
+ end # module Auth
455
+
456
+ ### @see D3::Admin::Auth.connect
457
+ ###
458
+ def self.connect (alt_db = false)
459
+ Auth.connect alt_db
460
+ end
461
+
462
+ ### @see D3::Admin::Auth.disconnect
463
+ ###
464
+ def self.disconnect
465
+ Auth.disconnect
466
+ end
467
+
468
+ end # module Admin
469
+ end # module D3
470
+