conjur-cli 2.6.0 → 4.1.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.
@@ -1,3 +1,23 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ #
1
21
  require 'conjur/command'
2
22
 
3
23
  class Conjur::Command::Id < Conjur::Command
@@ -1,19 +1,38 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ #
1
21
  require 'conjur/authn'
2
22
  require 'conjur/resource'
3
23
  require 'conjur/command'
4
24
 
5
25
  class Conjur::Command::Resources < Conjur::Command
6
26
  self.prefix = :resource
7
-
27
+
8
28
  desc "Create a new resource"
9
- arg_name "kind resource-id"
29
+ arg_name "resource-id"
10
30
  command :create do |c|
11
31
  acting_as_option(c)
12
32
 
13
33
  c.action do |global_options,options,args|
14
- kind = require_arg(args, "kind")
15
- id = require_arg(args, "resource-id")
16
- resource = api.resource([ conjur_account, kind, id ].join(':'))
34
+ id = full_resource_id( require_arg(args, "resource-id") )
35
+ resource = api.resource(id)
17
36
 
18
37
  if ownerid = options.delete(:ownerid)
19
38
  options[:acting_as] = ownerid
@@ -25,48 +44,43 @@ class Conjur::Command::Resources < Conjur::Command
25
44
  end
26
45
 
27
46
  desc "Show a resource"
28
- arg_name "kind resource-id"
47
+ arg_name "resource-id"
29
48
  command :show do |c|
30
49
  c.action do |global_options,options,args|
31
- kind = require_arg(args, "kind")
32
- id = require_arg(args, "resource-id")
33
- display api.resource([ conjur_account, kind, id ].join(':')).attributes
50
+ id = full_resource_id( require_arg(args, "resource-id") )
51
+ display api.resource(id).attributes
34
52
  end
35
53
  end
36
54
 
37
55
  desc "Determines whether a resource exists"
38
- arg_name "kind resource-id"
56
+ arg_name "resource-id"
39
57
  command :exists do |c|
40
58
  c.action do |global_options,options,args|
41
- kind = require_arg(args, "kind")
42
- id = require_arg(args, "resource-id")
43
- resource = api.resource([ conjur_account, kind, id ].join(':'))
44
- puts resource.exists?
59
+ id = full_resource_id( require_arg(args, "resource-id") )
60
+ puts api.resource(id).exists?
45
61
  end
46
62
  end
47
63
 
48
- desc "Grant a privilege on a resource"
49
- arg_name "kind resource-id role privilege"
64
+ desc "Give a privilege on a resource"
65
+ arg_name "resource-id role privilege"
50
66
  command :permit do |c|
51
67
  c.action do |global_options,options,args|
52
- kind = require_arg(args, "kind")
53
- id = require_arg(args, "resource-id")
68
+ id = full_resource_id( require_arg(args, "resource-id") )
54
69
  role = require_arg(args, "role")
55
70
  privilege = require_arg(args, "privilege")
56
- api.resource([ conjur_account, kind, id ].join(':')).permit privilege, role
71
+ api.resource(id).permit privilege, role
57
72
  puts "Permission granted"
58
73
  end
59
74
  end
60
75
 
61
- desc "Revoke a privilege on a resource"
62
- arg_name "kind resource-id role privilege"
76
+ desc "Deny a privilege on a resource"
77
+ arg_name "resource-id role privilege"
63
78
  command :deny do |c|
64
79
  c.action do |global_options,options,args|
65
- kind = require_arg(args, "kind")
66
- id = require_arg(args, "resource-id")
80
+ id = full_resource_id( require_arg(args, "resource-id") )
67
81
  role = require_arg(args, "role")
68
82
  privilege = require_arg(args, "privilege")
69
- api.resource([ conjur_account, kind, id ].join(':')).deny privilege, role
83
+ api.resource(id).deny privilege, role
70
84
  puts "Permission revoked"
71
85
  end
72
86
  end
@@ -78,44 +92,41 @@ class Conjur::Command::Resources < Conjur::Command
78
92
  When the role argument is used, either the logged-in user must either own the specified
79
93
  resource or be an admin of the specified role (i.e. be granted the specified role with grant option).
80
94
  """
81
- arg_name "kind resource-id privilege"
95
+ arg_name "resource-id privilege"
82
96
  command :check do |c|
83
97
  c.desc "Role to check. By default, the current logged-in role is used"
84
98
  c.flag [:r,:role]
85
99
 
86
100
  c.action do |global_options,options,args|
87
- kind = args.shift or raise "Missing parameter: resource-kind"
88
- resource_id = args.shift or raise "Missing parameter: resource-id"
101
+ id = full_resource_id( require_arg(args, "resource-id") )
89
102
  privilege = args.shift or raise "Missing parameter: privilege"
90
103
  if role = options[:role]
91
104
  role = api.role(role)
92
- puts role.permitted? kind, resource_id, privilege
105
+ puts role.permitted? id, privilege
93
106
  else
94
- puts api.resource([ conjur_account, kind, resource_id ].join(':')).permitted? privilege
107
+ puts api.resource(id).permitted? privilege
95
108
  end
96
109
  end
97
110
  end
98
111
 
99
112
  desc "Grant ownership on a resource to a new owner"
100
- arg_name "kind resource-id owner"
113
+ arg_name "resource-id owner"
101
114
  command :give do |c|
102
115
  c.action do |global_options,options,args|
103
- kind = require_arg(args, "kind")
104
- id = require_arg(args, "resource-id")
116
+ id = full_resource_id( require_arg(args, "resource-id") )
105
117
  owner = require_arg(args, "owner")
106
- api.resource([ conjur_account, kind, id ].join(':')).give_to owner
118
+ api.resource(id).give_to owner
107
119
  puts "Ownership granted"
108
120
  end
109
121
  end
110
122
 
111
- desc "List roles with a specified permission on a resource"
112
- arg_name "kind resource-id permission"
123
+ desc "List roles with a specified permission on the resource"
124
+ arg_name "resource-id permission"
113
125
  command :permitted_roles do |c|
114
126
  c.action do |global_options,options,args|
115
- kind = require_arg(args, "kind")
116
- id = require_arg(args, "resource-id")
127
+ id = full_resource_id( require_arg(args, "resource-id") )
117
128
  permission = require_arg(args, "permission")
118
- display api.resource([ conjur_account, kind, id ].join(':')).permitted_roles(permission)
129
+ display api.resource(id).permitted_roles(permission)
119
130
  end
120
131
  end
121
- end
132
+ end
@@ -1,3 +1,23 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ #
1
21
  require 'conjur/authn'
2
22
  require 'conjur/command'
3
23
 
@@ -91,4 +111,4 @@ class Conjur::Command::Roles < Conjur::Command
91
111
  puts "Role revoked"
92
112
  end
93
113
  end
94
- end
114
+ end
@@ -1,3 +1,23 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ #
1
21
  require 'conjur/authn'
2
22
  require 'conjur/command'
3
23
 
@@ -23,4 +43,4 @@ class Conjur::Command::Secrets < Conjur::Command
23
43
  puts api.secret(id).value
24
44
  end
25
45
  end
26
- end
46
+ end
@@ -1,13 +1,47 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ require 'conjur/api/authn'
1
22
  require 'conjur/authn'
2
23
  require 'conjur/command'
3
24
 
4
25
  class Conjur::Command::Users < Conjur::Command
5
26
  self.prefix = :user
6
27
 
28
+ def self.prompt_for_password
29
+ # use stderr to allow output redirection, e.g.
30
+ # conjur user:create -p username > user.json
31
+ hl = HighLine.new($stdin, $stderr)
32
+
33
+ password = hl.ask("Enter the password (it will not be echoed): "){ |q| q.echo = false }
34
+ confirmation = hl.ask("Confirm the password: "){ |q| q.echo = false }
35
+
36
+ raise "Password does not match confirmation" unless password == confirmation
37
+
38
+ password
39
+ end
40
+
7
41
  desc "Create a new user"
8
42
  arg_name "login"
9
43
  command :create do |c|
10
- c.desc "Prompt for a password for the user"
44
+ c.desc "Prompt for a password for the user (default: --no-password)"
11
45
  c.switch [:p,:password]
12
46
 
13
47
  acting_as_option(c)
@@ -16,21 +50,25 @@ class Conjur::Command::Users < Conjur::Command
16
50
  login = require_arg(args, 'login')
17
51
 
18
52
  opts = options.slice(:ownerid)
19
- if options[:p]
20
-
21
- # use stderr to allow output redirection, e.g.
22
- # conjur user:create -p username > user.json
23
- hl = HighLine.new($stdin, $stderr)
24
53
 
25
- password = hl.ask("Enter the password (it will not be echoed): "){ |q| q.echo = false }
26
- confirmation = hl.ask("Confirm the password: "){ |q| q.echo = false }
27
-
28
- raise "Password does not match confirmation" unless password == confirmation
29
-
30
- opts[:password] = password
54
+ if options[:p]
55
+ opts[:password] = prompt_for_password
31
56
  end
32
57
 
33
58
  display api.create_user(login, opts)
34
59
  end
35
60
  end
61
+
62
+ desc "Update the password of the logged-in user"
63
+ command :update_password do |c|
64
+ c.desc "Password to use, otherwise you will be prompted"
65
+ c.flag [:p,:password]
66
+
67
+ c.action do |global_options,options,args|
68
+ username, password = Conjur::Authn.read_credentials
69
+ new_password = options[:password] || prompt_for_password
70
+
71
+ Conjur::API.update_password username, password, new_password
72
+ end
73
+ end
36
74
  end
@@ -1,3 +1,23 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ #
1
21
  require 'conjur/authn'
2
22
  require 'conjur/command'
3
23
 
@@ -62,4 +82,4 @@ class Conjur::Command::Variables < Conjur::Command
62
82
  $stdout.write api.variable(id).value(options[:version])
63
83
  end
64
84
  end
65
- end
85
+ end
data/lib/conjur/config.rb CHANGED
@@ -1,3 +1,23 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ #
1
21
  module Conjur
2
22
  class Config
3
23
  @@attributes = {}
@@ -1,3 +1,23 @@
1
+ #
2
+ # Copyright (C) 2013 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
+ #
1
21
  module Conjur
2
- VERSION = "2.6.0"
22
+ VERSION = "4.1.0"
3
23
  end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe Conjur::Command::Assets, logged_in: true do
4
+
5
+ let(:asset) { double(attributes: asset_attributes ) }
6
+ let(:asset_attributes) { {"some"=>"attributes" } }
7
+ before(:each) { api.stub(KIND.to_sym).and_return(asset) }
8
+ def invoke_silently
9
+ expect { invoke }.to write
10
+ end
11
+
12
+ context "asset:create" do
13
+ before(:each) {
14
+ api.stub(:method).with("create_#{KIND}").and_return(double(arity:1))
15
+ api.stub("create_#{KIND}".to_sym).and_return(asset)
16
+ }
17
+ describe_command "asset:create #{KIND}:#{ID}" do
18
+ it "calls api.create_#{KIND}(id:#{ID})" do
19
+ api.should_receive("create_#{KIND}".to_sym).with(id: ID)
20
+ invoke_silently
21
+ end
22
+ it "writes JSONised attributes to stdout" do
23
+ JSON.parse( expect { invoke }.to write ).should == asset_attributes
24
+ end
25
+ end
26
+ describe_command "asset:create #{KIND}" do
27
+ it "calls api.create_#{KIND}({})" do
28
+ api.should_receive("create_#{KIND}".to_sym).with({})
29
+ invoke_silently
30
+ end
31
+ it "writes JSONised attributes to stdout" do
32
+ JSON.parse( expect { invoke }.to write ).should == asset_attributes
33
+ end
34
+ end
35
+ end
36
+
37
+ describe_command "asset:show #{KIND}:#{ID}" do
38
+ it "obtains asset instance as api.#{KIND}(#{ID})" do
39
+ api.should_receive(KIND.to_sym).with(ID)
40
+ invoke_silently
41
+ end
42
+ it "writes JSONised attributes to stdout" do
43
+ JSON.parse( expect { invoke }.to write ).should == asset_attributes
44
+ end
45
+ end
46
+
47
+ describe_command "asset:exists #{KIND}:#{ID}" do
48
+ let(:exists_response) { "exists? response" }
49
+ before(:each) { asset.stub(:exists?).and_return(exists_response) }
50
+ it "obtains asset instance as api.#{KIND}(#{ID})" do
51
+ api.should_receive(KIND.to_sym).with(ID)
52
+ invoke_silently
53
+ end
54
+ it "calls asset.exists?" do
55
+ asset.should_receive(:exists?)
56
+ invoke_silently
57
+ end
58
+ it "writes response to stdout" do
59
+ expect { invoke }.to write exists_response
60
+ end
61
+ end
62
+
63
+ describe_command "asset:list #{KIND}" do
64
+ let(:assets_names) { %W[klaatu barada nikto] }
65
+ let(:assets_list) {
66
+ assets_names.map { |x|
67
+ double(attributes: { "id" => x } )
68
+ }
69
+ }
70
+ before(:each) { api.stub("#{KIND}s".to_sym).and_return(assets_list) }
71
+
72
+ it "calls api.#{KIND}s" do
73
+ api.should_receive("#{KIND}s".to_sym)
74
+ invoke_silently
75
+ end
76
+ it "for each asset from response displays it's attributes" do
77
+ expect { invoke }.to write assets_names.
78
+ map { |x|
79
+ JSON.pretty_generate(id:x)
80
+ }.join("\n")
81
+ end
82
+ end
83
+
84
+ shared_examples 'it obtains role via asset' do
85
+ it "obtains asset instance as api.#{KIND}(#{ID})" do
86
+ api.should_receive(KIND.to_sym).with(ID)
87
+ invoke_silently
88
+ end
89
+ it "account=asset.core_conjur_account" do
90
+ asset.should_receive(:core_conjur_account)
91
+ invoke_silently
92
+ end
93
+ it "kind=asset.resource_kind" do
94
+ asset.should_receive(:resource_kind)
95
+ invoke_silently
96
+ end
97
+ it "id=asset.resource_id" do
98
+ asset.should_receive(:resource_id)
99
+ invoke_silently
100
+ end
101
+
102
+ it "obtains role as #{ACCOUNT}:@:#{KIND}/#{ID}/#{ROLE}" do
103
+ api.should_receive(:role).with("#{ACCOUNT}:@:#{KIND}/#{ID}/#{ROLE}")
104
+ invoke_silently
105
+ end
106
+ end
107
+
108
+ shared_context "asset with role" do
109
+ before(:each) {
110
+ asset.stub(:core_conjur_account).and_return(ACCOUNT)
111
+ asset.stub(:resource_kind).and_return(KIND)
112
+ asset.stub(:resource_id).and_return(ID)
113
+ api.stub(:role).and_return(role_instance)
114
+ }
115
+ let(:role_instance) { double(grant_to: true, revoke_from: true) }
116
+ end
117
+
118
+ describe_command "asset:members:add #{KIND}:#{ID} #{ROLE} #{MEMBER}" do
119
+ include_context "asset with role"
120
+ it_behaves_like "it obtains role via asset"
121
+ it 'calls role.grant_to(member,...)' do
122
+ role_instance.should_receive(:grant_to).with(MEMBER, anything)
123
+ invoke_silently
124
+ end
125
+ it { expect { invoke }.to write "Membership granted" }
126
+ end
127
+
128
+ describe_command "asset:members:remove #{KIND}:#{ID} #{ROLE} #{MEMBER}" do
129
+ include_context "asset with role"
130
+ it_behaves_like "it obtains role via asset"
131
+ it 'calls role.revoke_from(member)' do
132
+ role_instance.should_receive(:revoke_from).with(MEMBER)
133
+ invoke_silently
134
+ end
135
+ it { expect { invoke }.to write "Membership revoked" }
136
+ end
137
+ end