conjur-cli 4.18.6 → 4.19.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Rakefile +1 -1
- data/conjur.gemspec +2 -1
- data/features/role_graph.feature +58 -0
- data/features/step_definitions/graph_steps.rb +21 -0
- data/features/support/env.rb +2 -0
- data/features/support/hooks.rb +34 -24
- data/features/support/world.rb +88 -0
- data/lib/conjur/command/roles.rb +85 -1
- data/lib/conjur/version.rb +1 -1
- data/spec/command/roles_spec.rb +59 -0
- metadata +24 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 88cb451c93417c3943171c8948b0b8fca26e9faf
|
|
4
|
+
data.tar.gz: fec1d704173532741c53bfe76b81dd71286fe8d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bdb26d0ec021d83bcdbcf176a6899584b0db21a010c841b3416ab58e3d105a3f89d3ce6591563d6d3869543cb5c58cb3716a0561277e35a72facfb02ecbac86e
|
|
7
|
+
data.tar.gz: a99ecb30867ea4090bc660b6836dc7ff19a95ddc2517fe20aafb7502f25c8dc481d8640dc5f0d59f1033b3414ce7b21b2b2a6f49a211da37dc9e702e8872c318
|
data/CHANGELOG.md
CHANGED
data/Rakefile
CHANGED
|
@@ -11,7 +11,7 @@ Cucumber::Rake::Task.new :features
|
|
|
11
11
|
|
|
12
12
|
task :jenkins => ['ci:setup:rspec', :spec, 'ci:setup:cucumber_report_cleanup'] do
|
|
13
13
|
Cucumber::Rake::Task.new do |t|
|
|
14
|
-
t.cucumber_opts = "--format progress --format CI::Reporter::Cucumber --out features/reports"
|
|
14
|
+
t.cucumber_opts = "--tags ~@real-api --format progress --format CI::Reporter::Cucumber --out features/reports"
|
|
15
15
|
end.runner.run
|
|
16
16
|
File.write('build_number', ENV['BUILD_NUMBER']) if ENV['BUILD_NUMBER']
|
|
17
17
|
end
|
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.
|
|
20
|
+
gem.add_dependency 'conjur-api', '~> 4.12.0'
|
|
21
21
|
gem.add_dependency 'gli', '>=2.8.0'
|
|
22
22
|
gem.add_dependency 'highline'
|
|
23
23
|
gem.add_dependency 'netrc', '~> 0.10.2'
|
|
@@ -33,4 +33,5 @@ Gem::Specification.new do |gem|
|
|
|
33
33
|
gem.add_development_dependency 'ci_reporter_cucumber'
|
|
34
34
|
gem.add_development_dependency 'rake', '~> 10.0'
|
|
35
35
|
gem.add_development_dependency 'io-grab', '~> 0.0.1'
|
|
36
|
+
gem.add_development_dependency 'json_spec'
|
|
36
37
|
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
@real-api
|
|
2
|
+
Feature: Retrieving role graphs
|
|
3
|
+
As a Conjur user
|
|
4
|
+
In order to understand the role hierarchy
|
|
5
|
+
I want to retrieve role graphs and present them in a useful format
|
|
6
|
+
|
|
7
|
+
Background:
|
|
8
|
+
Given a graph with edges
|
|
9
|
+
| Tywin | Jamie |
|
|
10
|
+
| Tywin | Cersei |
|
|
11
|
+
| Cersei | Joffrey |
|
|
12
|
+
| Jamie | Joffrey |
|
|
13
|
+
| Aerys | Tyrion |
|
|
14
|
+
| Joanna | Tyrion |
|
|
15
|
+
|
|
16
|
+
Scenario: Showing the graph as JSON
|
|
17
|
+
When I successfully run with role expansion "conjur role graph --as-role Joffrey Joffrey"
|
|
18
|
+
Then the graph JSON should be:
|
|
19
|
+
"""
|
|
20
|
+
{
|
|
21
|
+
"graph": [
|
|
22
|
+
{ "parent": "Tywin", "child": "Jamie" },
|
|
23
|
+
{ "parent": "Tywin", "child": "Cersei"},
|
|
24
|
+
{ "parent": "Cersei", "child": "Joffrey"},
|
|
25
|
+
{ "parent": "Jamie", "child": "Joffrey" }
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
Scenario: Short JSON output
|
|
31
|
+
When I successfully run with role expansion "conjur role graph --short --as-role Joffrey Joffrey"
|
|
32
|
+
Then the graph JSON should be:
|
|
33
|
+
"""
|
|
34
|
+
[
|
|
35
|
+
[ "Tywin", "Jamie" ],
|
|
36
|
+
[ "Tywin", "Cersei" ],
|
|
37
|
+
[ "Jamie", "Joffrey" ],
|
|
38
|
+
[ "Cersei", "Joffrey"]
|
|
39
|
+
]
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
Scenario: I can restrict the output to show only ancestors or descendants
|
|
43
|
+
When I successfully run with role expansion "conjur role graph --short --no-ancestors --as-role Cersei Cersei"
|
|
44
|
+
Then the graph JSON should be:
|
|
45
|
+
"""
|
|
46
|
+
[
|
|
47
|
+
[ "Cersei", "Joffrey" ]
|
|
48
|
+
]
|
|
49
|
+
"""
|
|
50
|
+
When I successfully run with role expansion "conjur role graph --short --no-descendants --as-role Cersei Cersei Jamie"
|
|
51
|
+
Then the graph JSON should be:
|
|
52
|
+
"""
|
|
53
|
+
[
|
|
54
|
+
[ "Tywin", "Cersei" ],
|
|
55
|
+
[ "Tywin", "Jamie" ]
|
|
56
|
+
]
|
|
57
|
+
"""
|
|
58
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Given /a graph with edges/ do |table|
|
|
2
|
+
graph table.raw
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
Then %r{the graph JSON should be} do |json|
|
|
6
|
+
json = expand_roles json
|
|
7
|
+
last_graph = extract_filtered_graph json
|
|
8
|
+
expect(last_graph.to_json).to be_json_eql(json)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
When(/^I( successfully)? run with role expansion "(.*)"$/) do |successfully, cmd|
|
|
12
|
+
role_id_map.each do |role, expanded_role|
|
|
13
|
+
cmd.gsub! role, expanded_role
|
|
14
|
+
end
|
|
15
|
+
self.last_cmd = cmd
|
|
16
|
+
if successfully
|
|
17
|
+
step "I successfully run \"#{cmd}\""
|
|
18
|
+
else
|
|
19
|
+
step "I run \"#{cmd}\""
|
|
20
|
+
end
|
|
21
|
+
end
|
data/features/support/env.rb
CHANGED
data/features/support/hooks.rb
CHANGED
|
@@ -2,17 +2,17 @@ require 'ostruct'
|
|
|
2
2
|
|
|
3
3
|
class MockAPI
|
|
4
4
|
attr_reader :things
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
def initialize
|
|
7
7
|
@things = {}
|
|
8
8
|
end
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
def thing(kind, id)
|
|
11
|
-
(@things[kind.to_sym] || []).find{|r| r.id == id}
|
|
11
|
+
(@things[kind.to_sym] || []).find{|r| r.id == id}
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def thing_like(kind, id_pattern)
|
|
15
|
-
(@things[kind.to_sym] || []).find{|r| id_pattern.match(r.id)}
|
|
15
|
+
(@things[kind.to_sym] || []).find{|r| id_pattern.match(r.id)}
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def create_host(options = {})
|
|
@@ -24,56 +24,56 @@ class MockAPI
|
|
|
24
24
|
end
|
|
25
25
|
host ||= create_thing(:host, id, options, role: true, api_key: true)
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
def create_user(id, options = {})
|
|
29
29
|
thing(:user, id) || create_thing(:user, id, options, role: true, api_key: true)
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
def create_variable(mime_type, kind)
|
|
33
33
|
create_thing(:user, SecureRandom.uuid, mime_type: mime_type, kind: kind)
|
|
34
34
|
end
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
def create_resource(id, options = {})
|
|
37
37
|
resource(id).tap do |resource|
|
|
38
38
|
resource.send(:"exists?=", true)
|
|
39
39
|
populate_options resource, options
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
def create_role(id, options = {})
|
|
44
44
|
role(id).tap do |role|
|
|
45
45
|
role.send(:"exists?=", true)
|
|
46
46
|
populate_options role, options
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
[ :user, :host ].each do |kind|
|
|
51
51
|
define_method kind do |id|
|
|
52
52
|
thing(kind, id)
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
def role(id)
|
|
57
57
|
raise "Role id must be a string" unless id.is_a?(String)
|
|
58
58
|
thing(:role, id) || create_thing(:role, id, { exists?: false }, role: true)
|
|
59
59
|
end
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
def resource(id)
|
|
62
62
|
raise "Resource id must be a string" unless id.is_a?(String)
|
|
63
63
|
thing(:resource, id) || create_thing(:resource, id, exists?: false)
|
|
64
64
|
end
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
protected
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
def create_thing(kind, id, options, kind_options = {})
|
|
69
69
|
thing = OpenStruct.new(kind: kind, id: id, exists?: true)
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
class << thing
|
|
72
72
|
def permit(privilege, role, options = {})
|
|
73
73
|
(self.permissions ||= []) << OpenStruct.new(privilege: privilege, role: role.id, grant_option: !!options[:grant_option])
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
if kind_options[:api_key]
|
|
78
78
|
thing.api_key = SecureRandom.uuid
|
|
79
79
|
end
|
|
@@ -85,20 +85,20 @@ class MockAPI
|
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
populate_options(thing, options)
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
store_thing kind, thing
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
thing
|
|
94
94
|
end
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
def populate_options(thing, options)
|
|
97
97
|
options.each do |k,v|
|
|
98
98
|
thing.send("#{k}=", v)
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
def store_thing(kind, thing)
|
|
103
103
|
(things[kind] ||= []) << thing
|
|
104
104
|
end
|
|
@@ -107,11 +107,11 @@ end
|
|
|
107
107
|
Before("@dsl") do
|
|
108
108
|
puts "Using MockAPI"
|
|
109
109
|
puts "Using account 'cucumber'"
|
|
110
|
-
|
|
110
|
+
|
|
111
111
|
require 'conjur/api'
|
|
112
112
|
require 'conjur/config'
|
|
113
113
|
require 'conjur/dsl/runner'
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
Conjur.stub(:env).and_return "ci"
|
|
116
116
|
Conjur.stub(:stack).and_return "ci"
|
|
117
117
|
Conjur.stub(:account).and_return "cucumber"
|
|
@@ -119,4 +119,14 @@ Before("@dsl") do
|
|
|
119
119
|
Conjur::Core::API.stub(:conjur_account).and_return 'cucumber'
|
|
120
120
|
@mock_api ||= MockAPI.new
|
|
121
121
|
Conjur::DSL::Runner.any_instance.stub(:api).and_return @mock_api
|
|
122
|
-
end
|
|
122
|
+
end
|
|
123
|
+
|
|
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])
|
|
130
|
+
Conjur::Config.apply
|
|
131
|
+
@aruba_timeout_seconds = 15
|
|
132
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'conjur/api'
|
|
2
|
+
module ConjurWorld
|
|
3
|
+
def last_json
|
|
4
|
+
last_stdout
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def last_stdout
|
|
8
|
+
raise "No commands have been run" unless last_cmd
|
|
9
|
+
stdout_from last_cmd
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_accessor :last_cmd
|
|
13
|
+
|
|
14
|
+
def account
|
|
15
|
+
Conjur::Core::API.conjur_account
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def role_kind
|
|
19
|
+
@role_kind ||= "cli-cukes"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def role_id_map
|
|
23
|
+
@role_id_map ||= {}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def extract_filtered_graph json
|
|
27
|
+
graph = JSON.parse(json) if json.kind_of?(String)
|
|
28
|
+
case graph
|
|
29
|
+
when Hash then filter_hash_graph(graph)
|
|
30
|
+
when Array then filter_array_graph(graph)
|
|
31
|
+
else raise "WTF: graph was #{graph.class}?"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def filter_hash_graph graph
|
|
36
|
+
allowed = role_id_map.values
|
|
37
|
+
edges = graph['graph']
|
|
38
|
+
filtered = edges.select do |edge|
|
|
39
|
+
allowed.member?(edge['parent']) and allowed.member?(edge['child'])
|
|
40
|
+
end
|
|
41
|
+
{'graph' => filtered}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def filter_array_graph graph
|
|
45
|
+
allowed = role_id_map.values
|
|
46
|
+
graph.select do |edge|
|
|
47
|
+
edge.all?{|v| allowed.member?(v)}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def graph edges
|
|
52
|
+
# generate roles
|
|
53
|
+
edges.flatten.uniq.each do |role_id|
|
|
54
|
+
role_id_map[role_id] = expanded = expand_role_id(role_id)
|
|
55
|
+
run_command "conjur role create '#{expanded}'"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# generate memberships
|
|
59
|
+
edges.each do |parent, child|
|
|
60
|
+
run_command "conjur role grant_to #{expand_role_id(parent)} #{expand_role_id(child)}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def run_command cmd
|
|
65
|
+
step "I successfully run " + '`' + cmd + '`'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def expand_role_id role_id
|
|
69
|
+
"#{account}:#{role_kind}:#{prepend_namespace role_id}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def prepend_namespace id
|
|
73
|
+
"#{namespace}-#{id}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def namespace
|
|
77
|
+
@namespace ||= "ns-#{Time.now.to_i}-#{rand(1 << 32)}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def expand_roles string
|
|
81
|
+
role_id_map.each do |role, expanded|
|
|
82
|
+
string.gsub! role, expanded
|
|
83
|
+
end
|
|
84
|
+
string
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
World(ConjurWorld)
|
data/lib/conjur/command/roles.rb
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
#
|
|
21
21
|
|
|
22
22
|
class Conjur::Command::Roles < Conjur::Command
|
|
23
|
+
GRAPH_FORMATS = %w(json dot)
|
|
24
|
+
|
|
23
25
|
|
|
24
26
|
desc "Manage roles"
|
|
25
27
|
command :role do |role|
|
|
@@ -117,6 +119,7 @@ class Conjur::Command::Roles < Conjur::Command
|
|
|
117
119
|
end
|
|
118
120
|
end
|
|
119
121
|
|
|
122
|
+
|
|
120
123
|
role.desc "Revoke a role from another role. You must have admin permission on the revoking role."
|
|
121
124
|
role.arg_name "role member"
|
|
122
125
|
role.command :revoke_from do |c|
|
|
@@ -128,6 +131,87 @@ class Conjur::Command::Roles < Conjur::Command
|
|
|
128
131
|
puts "Role revoked"
|
|
129
132
|
end
|
|
130
133
|
end
|
|
131
|
-
end
|
|
132
134
|
|
|
135
|
+
|
|
136
|
+
role.long_desc <<-EOD
|
|
137
|
+
Retrieves a digraph representing the role members and memberships of one or more roles.
|
|
138
|
+
|
|
139
|
+
The --[no-]ancestors and --[no-descendants] determine whether the graph should include ancestors, descendants, or both. Both
|
|
140
|
+
are included in the graph by default.
|
|
141
|
+
|
|
142
|
+
The --acting-as flag specifies, as usual, a role as which to perform the action. The default is the role of the currently
|
|
143
|
+
authenticated user. Only roles visible to this role will be included in the resulting graph.
|
|
144
|
+
|
|
145
|
+
The output is always written to the standard output, and can be one of the following forms (specified with the --format flag):
|
|
146
|
+
|
|
147
|
+
* png: use the 'dot' command to generate a png image representing the graph.
|
|
148
|
+
|
|
149
|
+
* dot: produce a file in a suitable format for use with the 'dot' program.
|
|
150
|
+
|
|
151
|
+
* json [default]: output a JSON representation of the graph.
|
|
152
|
+
|
|
153
|
+
In order to generate png images, the 'dot' program must be present and on your path. This program is usually installed
|
|
154
|
+
as part of the 'graphviz' package, and is available via apt-get on debian like systems and homebrew on OSX.
|
|
155
|
+
|
|
156
|
+
The JSON format is determined by the presence of the --short flag. If the --short flag is present, the JSON will be an array of
|
|
157
|
+
edges, with each edge represented as an array:
|
|
158
|
+
|
|
159
|
+
[
|
|
160
|
+
[ 'parent1', 'child1' ],
|
|
161
|
+
[ 'parent2', 'child2'],
|
|
162
|
+
...
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
If the --short flag is not present, the JSON output will be more verbose:
|
|
166
|
+
|
|
167
|
+
{
|
|
168
|
+
"graph": [
|
|
169
|
+
{
|
|
170
|
+
"parent": "parent1",
|
|
171
|
+
"child": "child1"
|
|
172
|
+
},
|
|
173
|
+
...
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
EOD
|
|
177
|
+
|
|
178
|
+
role.desc "Describe role memberships as a digraph"
|
|
179
|
+
role.arg_name "role", :multiple
|
|
180
|
+
role.command :graph do |c|
|
|
181
|
+
c.desc "Output formats [#{GRAPH_FORMATS}]"
|
|
182
|
+
c.flag [:f,:format], default_value: 'json', must_match: GRAPH_FORMATS
|
|
183
|
+
|
|
184
|
+
c.desc "Use a more compact JSON format"
|
|
185
|
+
c.switch [:s, :short]
|
|
186
|
+
|
|
187
|
+
c.desc "Whether to show ancestors"
|
|
188
|
+
c.switch [:a, :ancestors], default_value: true
|
|
189
|
+
|
|
190
|
+
c.desc "Whether to show descendants"
|
|
191
|
+
c.switch [:d, :descendants], default_value: true
|
|
192
|
+
|
|
193
|
+
acting_as_option(c)
|
|
194
|
+
|
|
195
|
+
c.action do |_, options, args|
|
|
196
|
+
format = options[:format].downcase.to_sym
|
|
197
|
+
if options[:short] and format != :json
|
|
198
|
+
$stderr.puts "WARNING: the --short option is meaningless when --format is not json"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
params = options.slice(:ancestors, :descendants)
|
|
202
|
+
params[:as_role] = options[:acting_as] if options.member?(:acting_as)
|
|
203
|
+
|
|
204
|
+
graph = api.role_graph(args, params)
|
|
205
|
+
|
|
206
|
+
output = case format
|
|
207
|
+
when :json then graph.to_json(options[:short]) + "\n"
|
|
208
|
+
when :dot then graph.to_dot + "\n"
|
|
209
|
+
else raise "Unsupported format: #{format}" # not strictly necessary, because GLI must_match checks it,
|
|
210
|
+
# but might as well?
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
$stdout.write output
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
133
217
|
end
|
data/lib/conjur/version.rb
CHANGED
data/spec/command/roles_spec.rb
CHANGED
|
@@ -85,4 +85,63 @@ describe Conjur::Command::Roles, logged_in: true do
|
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
|
+
|
|
89
|
+
describe "role graph" do
|
|
90
|
+
let(:roles){ [] }
|
|
91
|
+
let(:options){ { ancestors: true, descendants: true } }
|
|
92
|
+
let(:extra_options){ {} }
|
|
93
|
+
let(:role_graph_args){ [roles, options.merge(extra_options)] }
|
|
94
|
+
let(:graph_edges){ [['a', 'b'], ['b', 'c']] }
|
|
95
|
+
let(:graph){ Conjur::Graph.new graph_edges }
|
|
96
|
+
def output
|
|
97
|
+
JSON::parse(expect{invoke}.to write)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
before do
|
|
101
|
+
allow(api).to receive(:role_graph).with(*role_graph_args).and_return graph
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe_command "role graph foo bar" do
|
|
105
|
+
let(:roles){ %w(foo bar) }
|
|
106
|
+
it "outputs the graph as non-short json" do
|
|
107
|
+
expect(output).to eq(graph.as_json)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe_command 'role graph --short foo' do
|
|
112
|
+
let(:roles){ %w(foo) }
|
|
113
|
+
it 'outputs the graph as short json' do
|
|
114
|
+
expect(output).to eq(graph.as_json(true))
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
describe_command 'role graph --no-ancestors foo' do
|
|
119
|
+
let(:roles){ %w(foo) }
|
|
120
|
+
let(:options){{descendants: true}}
|
|
121
|
+
it "calls role_graph with the expected options and output" do
|
|
122
|
+
expect(output).to eq(graph.as_json(false))
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
describe 'output formats' do
|
|
127
|
+
let(:formatted){ "formatted by #{format_method}" }
|
|
128
|
+
let(:roles){ %w(foo) }
|
|
129
|
+
before do
|
|
130
|
+
|
|
131
|
+
expect_any_instance_of(Conjur::Graph).to receive(format_method).with(any_args).and_return formatted
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.it_formats_the_graph_as method
|
|
135
|
+
let(:format_method){ method }
|
|
136
|
+
it "formats the graph with #{method}" do
|
|
137
|
+
expect((expect{invoke}.to write).chomp).to eq(formatted)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe_command 'role graph -fdot foo' do
|
|
142
|
+
it_formats_the_graph_as :to_dot
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
end
|
|
88
147
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: conjur-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.19.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rafal Rzepecki
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2015-01-
|
|
12
|
+
date: 2015-01-27 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -31,14 +31,14 @@ dependencies:
|
|
|
31
31
|
requirements:
|
|
32
32
|
- - ~>
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: 4.
|
|
34
|
+
version: 4.12.0
|
|
35
35
|
type: :runtime
|
|
36
36
|
prerelease: false
|
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
|
38
38
|
requirements:
|
|
39
39
|
- - ~>
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: 4.
|
|
41
|
+
version: 4.12.0
|
|
42
42
|
- !ruby/object:Gem::Dependency
|
|
43
43
|
name: gli
|
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -221,6 +221,20 @@ dependencies:
|
|
|
221
221
|
- - ~>
|
|
222
222
|
- !ruby/object:Gem::Version
|
|
223
223
|
version: 0.0.1
|
|
224
|
+
- !ruby/object:Gem::Dependency
|
|
225
|
+
name: json_spec
|
|
226
|
+
requirement: !ruby/object:Gem::Requirement
|
|
227
|
+
requirements:
|
|
228
|
+
- - '>='
|
|
229
|
+
- !ruby/object:Gem::Version
|
|
230
|
+
version: '0'
|
|
231
|
+
type: :development
|
|
232
|
+
prerelease: false
|
|
233
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
234
|
+
requirements:
|
|
235
|
+
- - '>='
|
|
236
|
+
- !ruby/object:Gem::Version
|
|
237
|
+
version: '0'
|
|
224
238
|
description:
|
|
225
239
|
email:
|
|
226
240
|
- rafal@conjur.net
|
|
@@ -258,13 +272,16 @@ files:
|
|
|
258
272
|
- features/dsl_role_create.feature
|
|
259
273
|
- features/dsl_user_create.feature
|
|
260
274
|
- features/jsonfield.feature
|
|
275
|
+
- features/role_graph.feature
|
|
261
276
|
- features/step_definitions/conjurize_steps.rb
|
|
262
277
|
- features/step_definitions/dsl_steps.rb
|
|
278
|
+
- features/step_definitions/graph_steps.rb
|
|
263
279
|
- features/support/conjur-test.pem
|
|
264
280
|
- features/support/conjur.conf
|
|
265
281
|
- features/support/env.rb
|
|
266
282
|
- features/support/hooks.rb
|
|
267
283
|
- features/support/host.json
|
|
284
|
+
- features/support/world.rb
|
|
268
285
|
- lib/conjur.rb
|
|
269
286
|
- lib/conjur/audit/follower.rb
|
|
270
287
|
- lib/conjur/authn.rb
|
|
@@ -357,13 +374,16 @@ test_files:
|
|
|
357
374
|
- features/dsl_role_create.feature
|
|
358
375
|
- features/dsl_user_create.feature
|
|
359
376
|
- features/jsonfield.feature
|
|
377
|
+
- features/role_graph.feature
|
|
360
378
|
- features/step_definitions/conjurize_steps.rb
|
|
361
379
|
- features/step_definitions/dsl_steps.rb
|
|
380
|
+
- features/step_definitions/graph_steps.rb
|
|
362
381
|
- features/support/conjur-test.pem
|
|
363
382
|
- features/support/conjur.conf
|
|
364
383
|
- features/support/env.rb
|
|
365
384
|
- features/support/hooks.rb
|
|
366
385
|
- features/support/host.json
|
|
386
|
+
- features/support/world.rb
|
|
367
387
|
- spec/authn_spec.rb
|
|
368
388
|
- spec/command/assets_spec.rb
|
|
369
389
|
- spec/command/audit_spec.rb
|