conjur-cli 4.26.0 → 4.27.0

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.
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