conjur-cli 4.26.0 → 4.27.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/acceptance-features/audit/audit_event_send.feature +104 -0
  4. data/acceptance-features/audit/send.feature +70 -0
  5. data/acceptance-features/authentication/authenticate.feature +10 -0
  6. data/acceptance-features/authentication/login.feature +14 -0
  7. data/acceptance-features/authentication/logout.feature +16 -0
  8. data/acceptance-features/authentication/whoami.feature +5 -0
  9. data/acceptance-features/authorization/resource/annotate.feature +35 -0
  10. data/acceptance-features/authorization/resource/check.feature +22 -0
  11. data/acceptance-features/authorization/resource/create.feature +19 -0
  12. data/acceptance-features/authorization/resource/deny.feature +12 -0
  13. data/acceptance-features/authorization/resource/exists.feature +16 -0
  14. data/acceptance-features/authorization/resource/give.feature +22 -0
  15. data/acceptance-features/authorization/resource/permit.feature +20 -0
  16. data/acceptance-features/authorization/resource/permitted_roles.feature +16 -0
  17. data/acceptance-features/authorization/resource/show.feature +26 -0
  18. data/acceptance-features/authorization/role/create.feature +13 -0
  19. data/acceptance-features/authorization/role/exists.feature +19 -0
  20. data/acceptance-features/authorization/role/grant_to.feature +21 -0
  21. data/acceptance-features/authorization/role/graph.feature +58 -0
  22. data/acceptance-features/authorization/role/members.feature +23 -0
  23. data/acceptance-features/authorization/role/memberships.feature +27 -0
  24. data/acceptance-features/conjurenv/check.feature +28 -0
  25. data/acceptance-features/conjurenv/run.feature +10 -0
  26. data/acceptance-features/conjurenv/template.feature +11 -0
  27. data/acceptance-features/directory/group/create.feature +20 -0
  28. data/acceptance-features/directory/group/retire.feature +54 -0
  29. data/acceptance-features/directory/host/create.feature +23 -0
  30. data/acceptance-features/directory/host/retire.feature +6 -0
  31. data/acceptance-features/directory/layer/create.feature +10 -0
  32. data/acceptance-features/directory/layer/hosts-add.feature +9 -0
  33. data/acceptance-features/directory/layer/hosts-remove.feature +10 -0
  34. data/acceptance-features/directory/user/create.feature +23 -0
  35. data/acceptance-features/directory/user/retire.feature +6 -0
  36. data/acceptance-features/directory/user/update_password.feature +16 -0
  37. data/acceptance-features/directory/variable/create.feature +14 -0
  38. data/acceptance-features/directory/variable/retire.feature +17 -0
  39. data/acceptance-features/directory/variable/value.feature +13 -0
  40. data/acceptance-features/directory/variable/values-add.feature +12 -0
  41. data/acceptance-features/global-privilege/elevate.feature +20 -0
  42. data/acceptance-features/global-privilege/reveal.privilege +20 -0
  43. data/acceptance-features/pubkeys/add.feature +20 -0
  44. data/acceptance-features/pubkeys/delete.feature +9 -0
  45. data/acceptance-features/pubkeys/names.feature +23 -0
  46. data/acceptance-features/pubkeys/show.feature +25 -0
  47. data/acceptance-features/step_definitions/cli.rb +21 -0
  48. data/acceptance-features/step_definitions/graph_steps.rb +22 -0
  49. data/acceptance-features/step_definitions/user_steps.rb +54 -0
  50. data/acceptance-features/support/env.rb +5 -0
  51. data/acceptance-features/support/hooks.rb +179 -0
  52. data/acceptance-features/support/world.rb +153 -0
  53. data/conjur.gemspec +4 -1
  54. data/features/step_definitions/graph_steps.rb +2 -2
  55. data/features/support/hooks.rb +1 -5
  56. data/lib/conjur/cli.rb +1 -1
  57. data/lib/conjur/command/bootstrap.rb +3 -2
  58. data/lib/conjur/command/elevate.rb +76 -0
  59. data/lib/conjur/command/rspec/mock_services.rb +3 -3
  60. data/lib/conjur/command.rb +15 -0
  61. data/lib/conjur/version.rb +1 -1
  62. data/spec/command/elevate_spec.rb +28 -0
  63. metadata +85 -4
@@ -0,0 +1,179 @@
1
+
2
+ require 'conjur/api'
3
+ require 'conjur/cli'
4
+ require 'conjur/authn'
5
+
6
+ netrc = Conjur::Authn.netrc
7
+ username, password = Conjur::Authn.get_credentials
8
+ raise "Not logged in to Conjur" unless username && password
9
+ puts "Logging in as #{username}"
10
+
11
+ # Future Aruba
12
+ #Aruba.configure do |config|
13
+ # config.exit_timeout = 15
14
+ #end
15
+
16
+ Before('@conjurapi-log') do
17
+ set_env 'CONJURAPI_LOG', 'stderr'
18
+ end
19
+
20
+ Before do
21
+ Conjur::Authn.save_credentials username: username, password: password
22
+
23
+ @admin_api = conjur_api = Conjur::Authn.connect
24
+
25
+ @namespace = conjur_api.create_variable("text/plain", "id").id
26
+ user = conjur_api.create_user "admin@#{@namespace}", ownerid: "#{Conjur.configuration.account}:user:#{username}"
27
+
28
+ netrc[Conjur::Authn.host] = [ "admin@#{@namespace}", user.api_key ]
29
+ netrc.save
30
+
31
+ conjur_api = Conjur::Authn.connect
32
+ @security_admin = conjur_api.create_group [ @namespace, "security_admin" ].join('/')
33
+ @security_admin.add_member user, admin_option: true
34
+
35
+ JsonSpec.memorize "MY_ROLEID", %Q("#{user.roleid}")
36
+
37
+ @admin_api.group("pubkeys-1.0/key-managers").add_member @security_admin
38
+ @admin_api.resource('!:!:conjur').permit 'elevate', user, grant_option: true
39
+ @admin_api.resource('!:!:conjur').permit 'reveal', user, grant_option: true
40
+
41
+ conjur_api.create_user "attic@#{@namespace}"
42
+
43
+ @aruba_timeout_seconds = 30
44
+ end
45
+
46
+ After do
47
+ if @admin_api
48
+ @admin_api.group("pubkeys-1.0/key-managers").remove_member @security_admin
49
+ end
50
+ tempfiles.each { |tempfile| File.unlink(tempfile) unless tempfile.nil? }
51
+ end
52
+
53
+ at_exit do
54
+ Conjur::Authn.save_credentials username: username, password: password
55
+ end
56
+
57
+ require 'ostruct'
58
+
59
+ class MockAPI
60
+ attr_reader :things
61
+
62
+ def initialize
63
+ @things = {}
64
+ end
65
+
66
+ def thing(kind, id)
67
+ (@things[kind.to_sym] || []).find{|r| r.id == id}
68
+ end
69
+
70
+ def thing_like(kind, id_pattern)
71
+ (@things[kind.to_sym] || []).find{|r| id_pattern.match(r.id)}
72
+ end
73
+
74
+ def create_host(options = {})
75
+ id = options.delete(:id)
76
+ if id
77
+ host = thing(:host, id)
78
+ else
79
+ id = SecureRandom.uuid
80
+ end
81
+ host ||= create_thing(:host, id, options, role: true, api_key: true)
82
+ end
83
+
84
+ def create_user(id, options = {})
85
+ thing(:user, id) || create_thing(:user, id, options, role: true, api_key: true)
86
+ end
87
+
88
+ def create_variable(mime_type, kind)
89
+ create_thing(:user, SecureRandom.uuid, mime_type: mime_type, kind: kind)
90
+ end
91
+
92
+ def create_resource(id, options = {})
93
+ resource(id).tap do |resource|
94
+ resource.send(:"exists?=", true)
95
+ populate_options resource, options
96
+ end
97
+ end
98
+
99
+ def create_role(id, options = {})
100
+ role(id).tap do |role|
101
+ role.send(:"exists?=", true)
102
+ populate_options role, options
103
+ end
104
+ end
105
+
106
+ [ :user, :host ].each do |kind|
107
+ define_method kind do |id|
108
+ thing(kind, id)
109
+ end
110
+ end
111
+
112
+ def role(id)
113
+ raise "Role id must be a string" unless id.is_a?(String)
114
+ thing(:role, id) || create_thing(:role, id, { exists?: false }, role: true)
115
+ end
116
+
117
+ def resource(id)
118
+ raise "Resource id must be a string" unless id.is_a?(String)
119
+ thing(:resource, id) || create_thing(:resource, id, exists?: false)
120
+ end
121
+
122
+ protected
123
+
124
+ def create_thing(kind, id, options, kind_options = {})
125
+ thing = OpenStruct.new(kind: kind, id: id, exists?: true)
126
+
127
+ class << thing
128
+ def permit(privilege, role, options = {})
129
+ (self.permissions ||= []) << OpenStruct.new(privilege: privilege, role: role.id, grant_option: !!options[:grant_option])
130
+ end
131
+ end
132
+
133
+ if kind_options[:api_key]
134
+ thing.api_key = SecureRandom.uuid
135
+ end
136
+ if kind_options[:role]
137
+ thing.roleid = id
138
+ class << thing
139
+ def can(privilege, resource, options = {})
140
+ resource.permit privilege, self, options
141
+ end
142
+ end
143
+ end
144
+
145
+ populate_options(thing, options)
146
+
147
+ store_thing kind, thing
148
+
149
+ thing
150
+ end
151
+
152
+ def populate_options(thing, options)
153
+ options.each do |k,v|
154
+ thing.send("#{k}=", v)
155
+ end
156
+ end
157
+
158
+ def store_thing(kind, thing)
159
+ (things[kind] ||= []) << thing
160
+ end
161
+ end
162
+
163
+ Before("@dsl") do
164
+ puts "Using MockAPI"
165
+ puts "Using account 'cucumber'"
166
+
167
+ require 'conjur/api'
168
+ require 'conjur/config'
169
+ require 'conjur/dsl/runner'
170
+
171
+ Conjur.stub(:env).and_return "ci"
172
+ Conjur.stub(:stack).and_return "ci"
173
+ Conjur.stub(:account).and_return "cucumber"
174
+
175
+ Conjur::Core::API.stub(:conjur_account).and_return 'cucumber'
176
+ @mock_api ||= MockAPI.new
177
+ Conjur::DSL::Runner.any_instance.stub(:api).and_return @mock_api
178
+ end
179
+
@@ -0,0 +1,153 @@
1
+ require 'aruba/api'
2
+ require 'conjur/api'
3
+
4
+ module ConjurCLIWorld
5
+ include Aruba::Api
6
+
7
+ def last_json
8
+ stdout_from(@last_cmd)
9
+ end
10
+
11
+ def find_or_create_password(username)
12
+ @passwords ||= {}
13
+ unless password = @passwords[username]
14
+ password = @passwords[username] = SecureRandom.hex(12)
15
+ end
16
+ password
17
+ end
18
+
19
+ def namespace
20
+ @namespace or raise "@namespace is not initialized"
21
+ end
22
+
23
+ # Aruba's method
24
+ def run(cmd, *args)
25
+ # it's a thunk now so it should be returned. puts can be added back as block if we want to
26
+ super process_cmd(cmd), *args
27
+
28
+ #puts stderr_from(cmd)
29
+ #puts stdout_from(cmd)
30
+ end
31
+
32
+ def stderr_from(cmd)
33
+ super process_cmd(cmd)
34
+ end
35
+ def stdout_from(cmd)
36
+ super process_cmd(cmd)
37
+ end
38
+ def output_from(cmd)
39
+ super process_cmd(cmd)
40
+ end
41
+
42
+ # Substitute the namespace for marker $ns
43
+ def unescape(string)
44
+ string = super
45
+ string.gsub("$ns", namespace)
46
+ end
47
+
48
+ def get_process(wanted)
49
+ super wanted.gsub("$ns", namespace)
50
+ end
51
+
52
+ def tempfiles
53
+ @tempfiles||=[]
54
+ end
55
+
56
+ protected
57
+
58
+ def process_cmd(cmd)
59
+ cmd = cmd.dup
60
+ cmd.gsub!("$ns", namespace)
61
+ cmd.gsub!("$pubkeys_url", Conjur.configuration.pubkeys_url)
62
+
63
+ @last_cmd = cmd
64
+ JsonSpec.memory.each do |k,v|
65
+ cmd.gsub!("%{#{k}}", v)
66
+ end
67
+ cmd
68
+ end
69
+ end
70
+
71
+ module ConjurWorld
72
+ def last_json
73
+ last_stdout
74
+ end
75
+
76
+ def last_stdout
77
+ raise "No commands have been run" unless last_cmd
78
+ stdout_from last_cmd
79
+ end
80
+
81
+ attr_accessor :last_cmd
82
+
83
+ def account
84
+ Conjur::Core::API.conjur_account
85
+ end
86
+
87
+ def role_kind
88
+ @role_kind ||= "cli-cukes"
89
+ end
90
+
91
+ def role_id_map
92
+ @role_id_map ||= {}
93
+ end
94
+
95
+ def extract_filtered_graph json
96
+ graph = JSON.parse(json.to_s)
97
+ case graph
98
+ when Hash then filter_hash_graph(graph)
99
+ when Array then filter_array_graph(graph)
100
+ else raise "WTF: graph was #{graph.class}?"
101
+ end
102
+ end
103
+
104
+ def filter_hash_graph graph
105
+ allowed = role_id_map.values
106
+ edges = graph['graph']
107
+ filtered = edges.select do |edge|
108
+ allowed.member?(edge['parent']) and allowed.member?(edge['child'])
109
+ end
110
+ {'graph' => filtered}
111
+ end
112
+
113
+ def filter_array_graph graph
114
+ allowed = role_id_map.values
115
+ graph.select do |edge|
116
+ edge.all?{|v| allowed.member?(v)}
117
+ end
118
+ end
119
+
120
+ def graph edges
121
+ # generate roles
122
+ edges.flatten.uniq.each do |role_id|
123
+ role_id_map[role_id] = expanded = expand_role_id(role_id)
124
+ run_command "conjur role create '#{expanded}'"
125
+ end
126
+
127
+ # generate memberships
128
+ edges.each do |parent, child|
129
+ run_command "conjur role grant_to #{expand_role_id(parent)} #{expand_role_id(child)}"
130
+ end
131
+ end
132
+
133
+ def run_command cmd
134
+ step "I successfully run " + '`' + cmd + '`'
135
+ end
136
+
137
+ def expand_role_id role_id
138
+ "#{account}:#{role_kind}:#{prepend_namespace role_id}"
139
+ end
140
+
141
+ def prepend_namespace id
142
+ "#{namespace}-#{id}"
143
+ end
144
+
145
+ def expand_roles string
146
+ role_id_map.each do |role, expanded|
147
+ string.gsub! role, expanded
148
+ end
149
+ string
150
+ end
151
+ end
152
+
153
+ World(ConjurWorld, ConjurCLIWorld)
data/conjur.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
 
18
18
 
19
19
  gem.add_dependency 'activesupport'
20
- gem.add_dependency 'conjur-api', '~> 4.16'
20
+ gem.add_dependency 'conjur-api', '~> 4.19'
21
21
  gem.add_dependency 'gli', '>=2.8.0'
22
22
  gem.add_dependency 'highline'
23
23
  gem.add_dependency 'netrc', '~> 0.10.2'
@@ -35,4 +35,7 @@ Gem::Specification.new do |gem|
35
35
  gem.add_development_dependency 'rake', '~> 10.0'
36
36
  gem.add_development_dependency 'io-grab', '~> 0.0.1'
37
37
  gem.add_development_dependency 'json_spec'
38
+ # For cukes
39
+ gem.add_development_dependency 'conjur-asset-audit-send'
40
+ gem.add_development_dependency 'conjur-asset-host-factory'
38
41
  end
@@ -14,8 +14,8 @@ When(/^I( successfully)? run with role expansion "(.*)"$/) do |successfully, cmd
14
14
  end
15
15
  self.last_cmd = cmd
16
16
  if successfully
17
- step "I successfully run \"#{cmd}\""
17
+ step "I successfully run `#{cmd}`"
18
18
  else
19
- step "I run \"#{cmd}\""
19
+ step "I run `#{cmd}`"
20
20
  end
21
21
  end
@@ -122,11 +122,7 @@ Before("@dsl") do
122
122
  end
123
123
 
124
124
  Before('@real-api') do
125
- require 'conjur/config'
126
- cfg = File.absolute_path("#{File.dirname __FILE__}/../../.conjurrc")
127
- puts "cfg_path = #{cfg}"
128
- puts "contents = #{File.read(cfg)}"
129
- Conjur::Config.load([cfg])
125
+ Conjur::Config.load
130
126
  Conjur::Config.apply
131
127
  @aruba_timeout_seconds = 15
132
128
  end
data/lib/conjur/cli.rb CHANGED
@@ -63,7 +63,7 @@ module Conjur
63
63
  # do too much effort, and GLIs support for aliasing doesn't work out so well with
64
64
  # subcommands.
65
65
  def run args
66
- args = args.shift.split(':') + args unless args.empty?
66
+ args = args.shift.split(':') + args unless args.empty?
67
67
  super args
68
68
  end
69
69
 
@@ -49,6 +49,8 @@ class Conjur::Command::Bootstrap < Conjur::Command
49
49
  # The admin user will always satisfy these conditions, unless they are revoked for some reason.
50
50
  # Other users created by the bootstrap command will (typically) also have these powers.
51
51
  def self.security_admin_manager? api
52
+ return true if elevated?
53
+
52
54
  username = api.username
53
55
  user = if username.index('/')
54
56
  nil
@@ -116,7 +118,6 @@ class Conjur::Command::Bootstrap < Conjur::Command
116
118
  puts "User created"
117
119
  puts "Making '#{username}' a member and admin of group 'security_admin'"
118
120
  security_admin.add_member user, admin_option: true
119
- security_admin.resource.permit "read", user
120
121
  puts "Adminship granted"
121
122
  end
122
123
 
@@ -139,4 +140,4 @@ class Conjur::Command::Bootstrap < Conjur::Command
139
140
  end
140
141
  end
141
142
  end
142
- end
143
+ end
@@ -0,0 +1,76 @@
1
+ #
2
+ # Copyright (C) 2015 Conjur Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+
22
+ # Implement privileged modes such as 'elevate' and 'reveal'
23
+ class Conjur::Command::Elevate < Conjur::DSLCommand
24
+
25
+ def self.subcommand args
26
+ code = Conjur::CLI.run args
27
+ raise GLI::CustomExit.new("Subcommand failed", code) unless code == 0
28
+ end
29
+
30
+ desc "Run a sub-command with elevated privileges"
31
+ long_desc <<-DESC
32
+ If you are allowed to do this by the Conjur server, all server-side permission checks will be bypassed and any
33
+ action will be allowed.
34
+
35
+ To be able to run this command, you must have the 'elevate' privilege on the resource '!:!:conjur'.
36
+
37
+ EXAMPLE
38
+
39
+ Force retirement of a user:
40
+
41
+ $ conjur elevate user retire alice
42
+ DESC
43
+ command :elevate do |c|
44
+ c.action do |global_options,options,args|
45
+ exit_now! "Subcommand is required" if args.empty?
46
+
47
+ Conjur::Command.api = api.with_privilege "elevate"
48
+ subcommand args
49
+ end
50
+ end
51
+
52
+ desc "Run a sub-command in 'reveal' mode"
53
+ long_desc <<-DESC
54
+ If you are allowed to do this by the Conjur server, you can inspect all data in the Conjur
55
+ authorization service. For example, you can list and search for all resources, regardless of
56
+ your ownership and privileges. You can also show details on any resource, and you can perform
57
+ permission checks on any resource.
58
+
59
+ To be able to run this command, you must have the 'reveal' privilege on the resource '!:!:conjur'.
60
+
61
+ EXAMPLE
62
+
63
+ List all groups:
64
+
65
+ $ conjur reveal group list -i
66
+
67
+ DESC
68
+ command :reveal do |c|
69
+ c.action do |global_options,options,args|
70
+ exit_now! "Subcommand is required" if args.empty?
71
+
72
+ Conjur::Command.api = api.with_privilege "reveal"
73
+ subcommand args
74
+ end
75
+ end
76
+ end
@@ -16,6 +16,9 @@ shared_context "with mock authn" do
16
16
  let(:netrcfile) { Tempfile.new 'authtest' }
17
17
  let(:netrc) { Netrc.read(netrcfile.path) }
18
18
  let(:account) { 'the-account' }
19
+ let(:username) { 'dknuth' }
20
+ let(:api_key) { 'sekrit' }
21
+ let(:api) { Conjur::API.new_from_key(username, api_key) }
19
22
  before do
20
23
  allow(Conjur::Core::API).to receive(:conjur_account) { account }
21
24
  allow(Conjur::Authn).to receive_messages(netrc: netrc, host: authn_host)
@@ -25,9 +28,6 @@ end
25
28
 
26
29
  shared_context "when logged in", logged_in: true do
27
30
  include_context "with mock authn"
28
- let(:username) { 'dknuth' }
29
- let(:api_key) { 'sekrit' }
30
- let(:api) { Conjur::API.new_from_key(username, api_key) }
31
31
  before do
32
32
  allow(api).to receive(:credentials) { {} }
33
33
  netrc[authn_host] = [username, api_key]
@@ -28,6 +28,7 @@ module Conjur
28
28
 
29
29
  class << self
30
30
  attr_accessor :prefix
31
+
31
32
  def method_missing *a, &b
32
33
  Conjur::CLI.send *a, &b
33
34
  end
@@ -41,6 +42,14 @@ module Conjur
41
42
  args.shift or raise "Missing parameter: #{name}"
42
43
  end
43
44
 
45
+ def assert_empty(args)
46
+ exit_now! "Received extra command arguments" unless args.empty?
47
+ end
48
+
49
+ def api= api
50
+ @@api = api
51
+ end
52
+
44
53
  def api
45
54
  @@api ||= Conjur::Authn.connect
46
55
  end
@@ -183,7 +192,13 @@ an alternative destination role.)
183
192
  end
184
193
  end
185
194
 
195
+ def elevated?
196
+ api.privilege == 'elevate' && api.global_privilege_permitted?('elevate')
197
+ end
198
+
186
199
  def validate_retire_privileges record, options
200
+ return true if elevated?
201
+
187
202
  if record.respond_to?(:role)
188
203
  memberships = current_user.role.memberships.map(&:roleid)
189
204
  validate_privileges "You can't administer this record" do
@@ -19,6 +19,6 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
- VERSION = "4.26.0"
22
+ VERSION = "4.27.0"
23
23
  ::Version=VERSION
24
24
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Conjur::Command::Elevate do
4
+ describe_command "elevate user show alice" do
5
+ include_context "with mock authn"
6
+
7
+ let(:token) { {login: 'dknuth'} }
8
+ before{
9
+ expect(Conjur::Authn).to receive(:connect).and_return(api)
10
+ }
11
+ it "invokes the sub-command with X-Conjur-Privilege header" do
12
+ allow_any_instance_of(Conjur::API).to receive(:token).and_return(token)
13
+ expect(Conjur::Command).to receive(:api=) do |api|
14
+ expect(api.api_key).to eq("sekrit")
15
+ expect(api.privilege).to eq("elevate")
16
+ end.and_call_original
17
+
18
+ expect(RestClient::Request).to receive(:execute).with({
19
+ method: :get,
20
+ url: "https://core.example.com/users/alice",
21
+ username: "dknuth",
22
+ headers: {:authorization=>"Token token=\"eyJsb2dpbiI6ImRrbnV0aCJ9\"", x_conjur_privilege: "elevate"}
23
+ }.merge(cert_store_options)).and_return(double(:response, body: "[]"))
24
+
25
+ invoke
26
+ end
27
+ end
28
+ end