Class: Conjur::Command
Direct Known Subclasses
Assets, Audit, Authn, Bootstrap, Env, Field, Groups, HostFactories, Hosts, Id, Init, LDAPSync, Layers, Plugin, Pubkeys, Resources, Roles, Secrets, Server, ShellInit, Users, Variables, DSLCommand
Defined Under Namespace
Classes: Assets, Audit, Authn, Bootstrap, Elevate, Env, Field, Groups, HostFactories, Hosts, Id, Init, LDAPSync, Layers, Plugin, Pubkeys, Resources, Roles, RubyDSL, Script, Secrets, Server, ShellInit, Users, Variables
Constant Summary
collapse
- @@api =
nil
Class Attribute Summary collapse
Class Method Summary
collapse
-
.acting_as_option(command) ⇒ Object
-
.annotate_option(command) ⇒ Object
-
.api ⇒ Object
-
.api=(api) ⇒ Object
-
.assert_empty(args) ⇒ Object
-
.collection_option(command) ⇒ Object
-
.command(name, *a, &block) ⇒ Object
-
.command_impl_for_list(global_options, options, args) ⇒ Object
-
.command_options_for_list(c) ⇒ Object
-
.context_option(command) ⇒ Object
-
.current_role ⇒ Object
-
.current_user ⇒ Object
-
.destination_role(options) ⇒ Object
-
.display(obj, options = {}) ⇒ Object
-
.display_members(members, options) ⇒ Object
-
.elevated? ⇒ Boolean
-
.give_away_resource(obj, options) ⇒ Object
-
.has_admin?(role, other_role) ⇒ Boolean
-
.hide_docs(command) ⇒ Object
Prevent a deprecated command from being displayed in the help output.
-
.highline ⇒ Object
-
.integer?(v) ⇒ Boolean
-
.interactive_option(command) ⇒ Object
-
.method_missing(*a, &b) ⇒ Object
-
.min_version(command, version) ⇒ Object
-
.notify_deprecated ⇒ Object
-
.prompt_for_annotations ⇒ Object
-
.prompt_for_group(options = {}) ⇒ Object
-
.prompt_for_id(kind, label = 'id') ⇒ Object
-
.prompt_for_idnumber(label) ⇒ Object
-
.prompt_for_password ⇒ Object
-
.prompt_for_public_key ⇒ Object
-
.prompt_to_confirm(kind, properties) ⇒ Object
-
.read_till_eof(prompt = nil) ⇒ Object
-
.require_arg(args, name) ⇒ Object
-
.retire_internal_role(roleObj) ⇒ Object
-
.retire_options(command) ⇒ Object
-
.retire_resource(obj) ⇒ Object
-
.retire_role(obj) ⇒ Object
-
.validate_privileges(message, &block) ⇒ Object
-
.validate_public_key(key) ⇒ Object
-
.validate_retire_privileges(record, options) ⇒ Object
conjur_account, full_resource_id, get_kind_and_id_from_args
Class Attribute Details
.prefix ⇒ Object
Returns the value of attribute prefix.
31
32
33
|
# File 'lib/conjur/command.rb', line 31
def prefix
@prefix
end
|
Class Method Details
.acting_as_option(command) ⇒ Object
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/conjur/command.rb', line 73
def acting_as_option command
return if command.flags.member?(:"as-group") command.desc 'Perform all actions as the specified Group'
command.arg_name 'GROUP'
command.flag [:'as-group']
command.desc 'Perform all actions as the specified Role'
command.arg_name 'ROLE'
command.flag [:'as-role']
end
|
.annotate_option(command) ⇒ Object
102
103
104
105
106
|
# File 'lib/conjur/command.rb', line 102
def annotate_option command
command.arg_name 'annotate'
command.desc 'Add variable annotations interactively'
command.switch [:a, :annotate]
end
|
.api ⇒ Object
54
55
56
|
# File 'lib/conjur/command.rb', line 54
def api
@@api ||= Conjur::Authn.connect
end
|
.api=(api) ⇒ Object
50
51
52
|
# File 'lib/conjur/command.rb', line 50
def api= api
@@api = api
end
|
.assert_empty(args) ⇒ Object
46
47
48
|
# File 'lib/conjur/command.rb', line 46
def assert_empty(args)
exit_now! "Received extra command arguments" unless args.empty?
end
|
.collection_option(command) ⇒ Object
84
85
86
87
88
|
# File 'lib/conjur/command.rb', line 84
def collection_option command
command.desc 'An optional prefix for created roles and resources'
command.arg_name 'collection'
command.flag [:collection]
end
|
.command(name, *a, &block) ⇒ Object
37
38
39
40
|
# File 'lib/conjur/command.rb', line 37
def command name, *a, &block
name = "#{prefix}:#{name}" if prefix
Conjur::CLI.command(name, *a, &block)
end
|
.command_impl_for_list(global_options, options, args) ⇒ Object
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
# File 'lib/conjur/command.rb', line 168
def command_impl_for_list(global_options, options, args)
opts = options.slice(:search, :limit, :options, :kind)
opts[:acting_as] = options[:role] if options[:role]
opts[:search]=opts[:search].gsub('-',' ') if opts[:search]
resources = api.resources(opts)
if options[:ids]
puts JSON.pretty_generate(resources.map(&:resourceid))
else
resources = resources.map &:attributes
unless options[:'raw-annotations']
resources = resources.map do |r|
r['annotations'] = (r['annotations'] || []).inject({}) do |hash, annot|
hash[annot['name']] = annot['value']
hash
end
r
end
end
puts JSON.pretty_generate resources
end
end
|
.command_options_for_list(c) ⇒ Object
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
# File 'lib/conjur/command.rb', line 146
def command_options_for_list(c)
return if c.flags.member?(:role) c.desc "Role to act as. By default, the current logged-in role is used."
c.arg_name 'ROLE'
c.flag [:role]
c.desc "Full-text search on resource id and annotation values"
c.flag [:s, :search]
c.desc "Maximum number of records to return"
c.flag [:l, :limit]
c.desc "Offset to start from"
c.flag [:o, :offset]
c.desc "Show only ids"
c.switch [:i, :ids]
c.desc "Show annotations in 'raw' format"
c.switch [:r, :"raw-annotations"]
end
|
.context_option(command) ⇒ Object
90
91
92
93
94
|
# File 'lib/conjur/command.rb', line 90
def context_option command
command.desc "Load context from this config file, and save it when finished. The file permissions will be 0600 by default."
command.arg_name "FILE"
command.flag [:c, :context]
end
|
.current_role ⇒ Object
452
453
454
455
456
457
458
459
|
# File 'lib/conjur/command.rb', line 452
def current_role
kind, id = api.username.split('/', 2)
if id.nil?
id = kind
kind = 'user'
end
api.role([ kind, id ].join(":"))
end
|
.current_user ⇒ Object
58
59
60
61
62
63
64
65
66
|
# File 'lib/conjur/command.rb', line 58
def current_user
username = api.username
kind, id = username.split('/')
unless kind && id
id = kind
kind = 'user'
end
api.send(kind, username)
end
|
.destination_role(options) ⇒ Object
210
211
212
213
214
215
216
217
|
# File 'lib/conjur/command.rb', line 210
def destination_role options
destination = options[:"destination-role"]
if destination
api.role(destination)
else
api.user('attic')
end
end
|
.display(obj, options = {}) ⇒ Object
315
316
317
318
319
320
321
322
323
324
325
326
327
328
|
# File 'lib/conjur/command.rb', line 315
def display(obj, options = {})
str = if obj.respond_to?(:attributes)
JSON.pretty_generate obj.attributes
elsif obj.respond_to?(:id)
obj.id
else
begin
JSON.pretty_generate(obj)
rescue JSON::GeneratorError
obj.to_json
end
end
puts str
end
|
.display_members(members, options) ⇒ Object
300
301
302
303
304
305
306
307
308
309
310
311
312
313
|
# File 'lib/conjur/command.rb', line 300
def display_members(members, options)
result = if options[:V]
members.collect {|member|
{
member: member.member.roleid,
grantor: member.grantor.roleid,
admin_option: member.admin_option
}
}
else
members.map(&:member).map(&:roleid)
end
display result
end
|
.elevated? ⇒ Boolean
219
220
221
|
# File 'lib/conjur/command.rb', line 219
def elevated?
api.privilege == 'elevate' && api.global_privilege_permitted?('elevate')
end
|
.give_away_resource(obj, options) ⇒ Object
286
287
288
289
290
291
292
293
294
295
296
297
298
|
# File 'lib/conjur/command.rb', line 286
def give_away_resource obj, options
destination = options[:"destination-role"]
destination_role = if destination
api.role(destination)
else
api.user('attic')
end
exit_now! "Role #{destination_role.roleid} doesn't exist" unless destination_role.exists?
puts "Giving ownership to '#{destination_role.roleid}'"
obj.resource.give_to destination_role
end
|
.has_admin?(role, other_role) ⇒ Boolean
461
462
463
464
465
466
467
|
# File 'lib/conjur/command.rb', line 461
def has_admin?(role, other_role)
return true if role.roleid == other_role.roleid
memberships = role.memberships.map(&:roleid)
other_role.members.any? { |m| memberships.member?(m.member.roleid) && m.admin_option }
rescue RestClient::Forbidden
false
end
|
.hide_docs(command) ⇒ Object
Prevent a deprecated command from being displayed in the help output
69
70
71
|
# File 'lib/conjur/command.rb', line 69
def hide_docs(command)
def command.nodoc; true end
end
|
.highline ⇒ Object
128
129
130
131
|
# File 'lib/conjur/command.rb', line 128
def highline
require 'highline'
@highline ||= HighLine.new($stdin,$stderr)
end
|
.integer?(v) ⇒ Boolean
342
343
344
|
# File 'lib/conjur/command.rb', line 342
def integer? v
Integer(v, 10) rescue false
end
|
.interactive_option(command) ⇒ Object
96
97
98
99
100
|
# File 'lib/conjur/command.rb', line 96
def interactive_option command
command.arg_name 'interactive'
command.desc 'Create variable interactively'
command.switch [:i, :'interactive']
end
|
.method_missing(*a, &b) ⇒ Object
33
34
35
|
# File 'lib/conjur/command.rb', line 33
def method_missing *a, &b
Conjur::CLI.send *a, &b
end
|
.min_version(command, version) ⇒ Object
108
109
110
111
112
113
114
115
116
117
|
# File 'lib/conjur/command.rb', line 108
def min_version command, version
version = Semantic::Version.new version
if version.pre == nil
version.pre = "0"
end
command.instance_variable_set(:@conjur_min_version, version)
end
|
.notify_deprecated ⇒ Object
469
470
471
|
# File 'lib/conjur/command.rb', line 469
def notify_deprecated
STDERR.puts 'WARNING! This command is deprecated and will be removed. Use policy instead.'
end
|
.prompt_for_annotations ⇒ Object
119
120
121
122
123
124
125
126
|
# File 'lib/conjur/command.rb', line 119
def prompt_for_annotations
highline.say('Add annotations (a name and value for each one):')
{}.tap do |annotations|
until (name = highline.ask(' annotation name (press enter to quit annotations): ')).empty?
annotations[name] = read_till_eof(' annotation value (^D on its own line to finish):')
end
end
end
|
.prompt_for_group(options = {}) ⇒ Object
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
|
# File 'lib/conjur/command.rb', line 401
def prompt_for_group options = {}
options[:hint] ||= "press enter to own the record yourself"
group_ids = api.groups.map(&:id)
highline.ask("Enter the group which will own the record (#{options[:hint]}): ", [ "" ] + group_ids) do |q|
require 'readline'
Readline.completion_append_character = ""
Readline.completer_word_break_characters = ""
q.readline = true
q.validate = lambda{|id|
@group = nil
id.empty? || (@group = api.group(id)).exists?
}
q.responses[:not_valid] = "Group '<%= @answer %>' doesn't exist, or you don't have permission to use it"
end
@group ? @group.roleid : nil
end
|
.prompt_for_id(kind, label = 'id') ⇒ Object
346
347
348
349
350
351
352
353
354
355
356
|
# File 'lib/conjur/command.rb', line 346
def prompt_for_id kind, label = 'id'
highline.ask("Enter the #{label}: ") do |q|
q.readline = true
q.validate = lambda{|id|
!id.blank? && !api.send(kind, id).exists?
}
q.responses[:not_valid] = "<% if @answer.blank? %>"\
"#{label} cannot be blank<% else %>"\
"A #{kind} called '<%= @answer %>' already exists<% end %>"
end
end
|
.prompt_for_idnumber(label) ⇒ Object
420
421
422
423
424
425
426
427
428
|
# File 'lib/conjur/command.rb', line 420
def prompt_for_idnumber label
result = highline.ask("Enter a #{label}: ") do |q|
q.validate = lambda{|id|
id.blank? || integer?(id)
}
q.responses[:not_valid] = "The #{label} must be an integer"
end
result.blank? ? nil : result.to_i
end
|
.prompt_for_password ⇒ Object
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
|
# File 'lib/conjur/command.rb', line 430
def prompt_for_password
require 'highline'
hl = HighLine.new($stdin, $stderr)
password = hl.ask("Enter the password (it will not be echoed): "){ |q| q.echo = false }
if password.blank?
if hl.agree "No password (y/n)?"
return nil
else
return prompt_for_password
end
end
confirmation = hl.ask("Confirm the password: "){ |q| q.echo = false }
raise "Password does not match confirmation" unless password == confirmation
password
end
|
.prompt_for_public_key ⇒ Object
358
359
360
361
362
363
364
365
366
367
368
369
370
|
# File 'lib/conjur/command.rb', line 358
def prompt_for_public_key
public_key = highline.ask("Enter the public key (press enter to skip): ") do |q|
q.validate = lambda{|key|
if key.blank?
true
else
validate_public_key key
end
}
q.responses[:not_valid] = "Public key format is invalid; please try again"
end
public_key.blank? ? nil : public_key.strip
end
|
.prompt_to_confirm(kind, properties) ⇒ Object
330
331
332
333
334
335
336
337
338
339
340
|
# File 'lib/conjur/command.rb', line 330
def prompt_to_confirm kind, properties
puts
puts "A new #{kind} will be created with the following properties:"
puts
properties.select{|k,v| !v.blank?}.each do |k,v|
printf "%-10s: %s\n", k, v
end
puts
exit(0) unless %w(yes y).member?(highline.ask("Proceed? (yes/no): ").strip.downcase)
end
|
.read_till_eof(prompt = nil) ⇒ Object
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/conjur/command.rb', line 133
def read_till_eof(prompt = nil)
highline.say(prompt) if prompt
[].tap do |lines|
loop do
begin
lines << highline.ask('')
rescue EOFError
break
end
end
end.join("\n")
end
|
.require_arg(args, name) ⇒ Object
42
43
44
|
# File 'lib/conjur/command.rb', line 42
def require_arg(args, name)
args.shift or raise "Missing parameter: #{name}"
end
|
.retire_internal_role(roleObj) ⇒ Object
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
|
# File 'lib/conjur/command.rb', line 270
def retire_internal_role roleObj
members = roleObj.members
self_member = members.select{|m| m.member.roleid == current_user.role.roleid}
self_member.each do |m|
members.delete m
end
members.concat self_member if self_member
members.each do |r|
member = api.role(r.member)
puts "Revoking from role #{member.roleid}"
roleObj.revoke_from member
end
end
|
.retire_options(command) ⇒ Object
199
200
201
202
203
204
205
206
207
208
|
# File 'lib/conjur/command.rb', line 199
def retire_options command
command.arg_name 'role'
command.desc "Specify a role to give the retired record to (default: the 'attic' user)"
command.long_desc %Q(When retired, all a record's roles and permissions are revoked.
As a final step, the record is 'given' (e.g. 'conjur resource give') to a destination role.
The default role to receive the record is the user 'attic'. This option can be used to specify
an alternative destination role.)
command.flag [:d, :"destination-role"]
end
|
.retire_resource(obj) ⇒ Object
243
244
245
246
247
248
249
250
251
|
# File 'lib/conjur/command.rb', line 243
def retire_resource obj
obj.resource.attributes['permissions'].each do |p|
role = api.role(p['role'])
privilege = p['privilege']
next if obj.respond_to?(:roleid) && role.roleid == obj.roleid && privilege == 'read'
puts "Denying #{privilege} privilege to #{role.roleid}"
obj.resource.deny(privilege, role)
end
end
|
.retire_role(obj) ⇒ Object
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
# File 'lib/conjur/command.rb', line 253
def retire_role obj
members = obj.role.members
self_member = members.select{|m| m.member.roleid == current_user.role.roleid}
self_member.each do |m|
members.delete m
end
members.concat self_member if self_member
members.each do |r|
member = api.role(r.member)
puts "Revoking from role #{member.roleid}"
obj.role.revoke_from member
end
end
|
.validate_privileges(message, &block) ⇒ Object
190
191
192
193
194
195
196
197
|
# File 'lib/conjur/command.rb', line 190
def validate_privileges message, &block
valid = begin
yield
rescue RestClient::Forbidden
false
end
exit_now! message unless valid
end
|
.validate_public_key(key) ⇒ Object
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
|
# File 'lib/conjur/command.rb', line 373
def validate_public_key key
if system('which ssh-keygen 2>&1 > /dev/null')
Conjur.log.debug "Using ssh-keygen to verify the public key\n" if Conjur.log
require 'tempfile'
tempfile = Tempfile.new 'public_key'
tempfile.write(key)
tempfile.close
`ssh-keygen -l -f #{tempfile.path}`
$? == 0
else
Conjur.log.debug "ssh-keygen is not available; falling back to simple string testing\n" if Conjur.log
begin
components = key.strip.split ' '
Base64.strict_decode64 components[1]
components.length == 3
rescue NoMethodError, ArgumentError
false
end
end
end
|
.validate_retire_privileges(record, options) ⇒ Object
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
|
# File 'lib/conjur/command.rb', line 223
def validate_retire_privileges record, options
return true if elevated?
if record.respond_to?(:role)
memberships = current_user.role.memberships.map(&:roleid)
validate_privileges "You can't administer this record" do
record.role.members.find{|m| memberships.member?(m.member.roleid) && m.admin_option}
end
end
validate_privileges "You don't own the record" do
current_user.role.member_of?(record.resource.ownerid)
end
role = destination_role(options)
exit_now! "Destination role '#{role.roleid}' doesn't exist" unless role.exists?
end
|