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_option_as_role(c) ⇒ Object
-
.command_option_kind(c) ⇒ Object
-
.command_options_for_list(c) ⇒ Object
-
.command_options_for_search(c) ⇒ Object
-
.context_option(command) ⇒ Object
-
.current_role ⇒ Object
-
.current_user ⇒ Object
-
.destination_role(options) ⇒ Object
-
.display(obj, options = {}) ⇒ Object
-
.display_members(members, member_field, options) ⇒ Numeric, Hash
Displays members, which may be either:.
-
.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
-
.process_command_options_for_search(options) ⇒ 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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
# File 'lib/conjur/command.rb', line 193
def command_impl_for_list(global_options, options, args)
opts = process_command_options_for_search(options)
resources = api.resources(opts)
if resources.is_a?(Numeric)
puts resources
elsif 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_option_as_role(c) ⇒ Object
151
152
153
154
155
156
|
# File 'lib/conjur/command.rb', line 151
def command_option_as_role 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]
end
|
.command_option_kind(c) ⇒ Object
146
147
148
149
|
# File 'lib/conjur/command.rb', line 146
def command_option_kind c
c.desc "Filter by kind"
c.flag [:k, :kind]
end
|
.command_options_for_list(c) ⇒ Object
172
173
174
175
176
177
178
179
180
181
|
# File 'lib/conjur/command.rb', line 172
def command_options_for_list(c)
command_option_as_role c
command_options_for_search c
c.desc "Show only ids"
c.switch [:i, :ids]
c.desc "Show annotations in 'raw' format"
c.switch [:r, :"raw-annotations"]
end
|
.command_options_for_search(c) ⇒ Object
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# File 'lib/conjur/command.rb', line 158
def command_options_for_search c
c.desc "Full-text search on resource id and annotation values"
c.flag [:s, :search]
c.desc "Offset to start from"
c.flag [:o, :offset]
c.desc "Maximum number of records to return"
c.flag [:l, :limit]
c.desc "Show the number of results, rather than printing them"
c.switch [:count]
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
512
513
514
515
516
517
518
519
|
# File 'lib/conjur/command.rb', line 512
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
235
236
237
238
239
240
241
242
|
# File 'lib/conjur/command.rb', line 235
def destination_role options
destination = options[:"destination-role"]
if destination
api.role(destination)
else
api.user('attic')
end
end
|
.display(obj, options = {}) ⇒ Object
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
|
# File 'lib/conjur/command.rb', line 373
def display(obj, options = {})
str = if obj.is_a?(Numeric)
obj.to_s
elsif 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, member_field, options) ⇒ Numeric, Hash
Displays members, which may be either:
- A numeric count
- A list of role ids
- A list of RoleGrant
options may include:
- V Show full RoleGrant info
- system show system (internal) roles
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
|
# File 'lib/conjur/command.rb', line 337
def display_members(members, member_field, options)
return display(members) if members.is_a?(Numeric)
result, roleid_function = if members.blank?
[ [], nil ]
elsif members.first.is_a?(Conjur::RoleGrant)
if options[:V]
items = members.collect do |member|
{
member: member.member.roleid,
grantor: member.grantor.roleid,
admin_option: member.admin_option
}.tap do |obj|
obj[:role] = member.role.roleid if member.role
end
end
[
items, lambda {|member| member[member_field] }
]
else
[ members.map{|m| m.send(member_field) }.map(&:roleid), lambda{|r| r} ]
end
else
[ members.map(&:roleid), lambda{|r| r} ]
end
unless options[:system]
result.reject! do |member|
roleid_function.call(member) =~ /^.+?:@/
end
end
display result
end
|
.elevated? ⇒ Boolean
244
245
246
|
# File 'lib/conjur/command.rb', line 244
def elevated?
api.privilege == 'elevate' && api.global_privilege_permitted?('elevate')
end
|
.give_away_resource(obj, options) ⇒ Object
311
312
313
314
315
316
317
318
319
320
321
322
323
|
# File 'lib/conjur/command.rb', line 311
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
521
522
523
524
525
526
527
|
# File 'lib/conjur/command.rb', line 521
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
402
403
404
|
# File 'lib/conjur/command.rb', line 402
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
529
530
531
|
# File 'lib/conjur/command.rb', line 529
def notify_deprecated
STDERR.puts 'WARNING! This command is deprecated and will be removed. Use policy instead.'
end
|
.process_command_options_for_search(options) ⇒ Object
183
184
185
186
187
188
189
190
191
|
# File 'lib/conjur/command.rb', line 183
def process_command_options_for_search options
opts = options.slice(:search, :count, :limit, :offset, :kind)
opts[:acting_as] = options[:role] if options[:role]
opts[:search] = opts[:search].gsub('-',' ') if opts[:search]
if opts[:kind] && opts[:kind].index(',')
opts[:kind] = opts[:kind].split(',')
end
opts
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
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
|
# File 'lib/conjur/command.rb', line 461
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
406
407
408
409
410
411
412
413
414
415
416
|
# File 'lib/conjur/command.rb', line 406
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
480
481
482
483
484
485
486
487
488
|
# File 'lib/conjur/command.rb', line 480
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
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
|
# File 'lib/conjur/command.rb', line 490
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
418
419
420
421
422
423
424
425
426
427
428
429
430
|
# File 'lib/conjur/command.rb', line 418
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
390
391
392
393
394
395
396
397
398
399
400
|
# File 'lib/conjur/command.rb', line 390
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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
|
# File 'lib/conjur/command.rb', line 295
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
224
225
226
227
228
229
230
231
232
233
|
# File 'lib/conjur/command.rb', line 224
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
268
269
270
271
272
273
274
275
276
|
# File 'lib/conjur/command.rb', line 268
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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
# File 'lib/conjur/command.rb', line 278
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
215
216
217
218
219
220
221
222
|
# File 'lib/conjur/command.rb', line 215
def validate_privileges message, &block
valid = begin
yield
rescue RestClient::Forbidden
false
end
exit_now! message unless valid
end
|
.validate_public_key(key) ⇒ Object
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
|
# File 'lib/conjur/command.rb', line 433
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
# File 'lib/conjur/command.rb', line 248
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
|