conjur-cli 4.4.0 → 4.5.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.
@@ -18,11 +18,11 @@ class MockAPI
18
18
  else
19
19
  id = SecureRandom.uuid
20
20
  end
21
- host ||= create_thing(:host, id, options, role: true)
21
+ host ||= create_thing(:host, id, options, role: true, api_key: true)
22
22
  end
23
23
 
24
24
  def create_user(id, options = {})
25
- thing(:user, id) || create_thing(:user, id, options, role: true)
25
+ thing(:user, id) || create_thing(:user, id, options, role: true, api_key: true)
26
26
  end
27
27
 
28
28
  def create_variable(mime_type, kind)
@@ -70,6 +70,9 @@ class MockAPI
70
70
  end
71
71
  end
72
72
 
73
+ if kind_options[:api_key]
74
+ thing.api_key = SecureRandom.uuid
75
+ end
73
76
  if kind_options[:role]
74
77
  thing.roleid = id
75
78
  class << thing
@@ -0,0 +1,52 @@
1
+ module Conjur
2
+ module Audit
3
+ class Follower
4
+ # Initialize a follower that will fetch more records by
5
+ # calling :block: with options to merge into the options passed
6
+ # to the audit method (eg, limit, offset)
7
+ def initialize &block
8
+ @fetch = block
9
+ end
10
+
11
+ # Follow audit events, yielding non-empty
12
+ # arrays of new events to :block: as they
13
+ # are fetched.
14
+ def follow &block
15
+ @last_event_id = nil
16
+
17
+ loop do
18
+ new_events = fetch_new_events
19
+ block.call new_events unless new_events.empty?
20
+ sleep 1 if new_events.empty?
21
+ end
22
+ end
23
+
24
+ protected
25
+
26
+ # Fetch all events after @last_event_id, updating it
27
+ # to point to the last event returned by this method.
28
+ # May return an empty array if no new events are available.
29
+ def fetch_new_events
30
+ # If @last_event_id is nil just fetch and return the
31
+ # most recent events, updating @last_event_id
32
+ if @last_event_id.nil?
33
+ events = @fetch.call(offset: 0)
34
+ @last_event_id = events.last['event_id'] unless events.empty?
35
+ return events
36
+ end
37
+
38
+ # We have a @last_event_id, fetch batches of events until we
39
+ # find it.
40
+ events = []
41
+ while (index = events.find_index{|e| e['event_id'] == @last_event_id}).nil?
42
+ events = @fetch.call(offset: events.length - 1, limit: 10).reverse.concat events
43
+ end
44
+
45
+ # Update @last_event_id and return the sliced events, reversing it one
46
+ # last time (because the block given to follow expects events to be reversed)
47
+ @last_event_id = events.last['event_id'] unless events.empty?
48
+ events[index + 1..-1].reverse
49
+ end
50
+ end
51
+ end
52
+ end
@@ -43,7 +43,11 @@ module Conjur::Authn
43
43
  end
44
44
 
45
45
  def netrc
46
- @netrc ||= Netrc.read
46
+ args = []
47
+ if path = Conjur::Config[:netrc_path]
48
+ args.unshift(path)
49
+ end
50
+ @netrc ||= Netrc.read(*args)
47
51
  end
48
52
 
49
53
  def get_credentials(options = {})
@@ -1,5 +1,6 @@
1
1
  require 'conjur/command'
2
2
  require 'active_support/ordered_hash'
3
+ require 'conjur/audit/follower'
3
4
 
4
5
  class Conjur::Command
5
6
  class Audit < self
@@ -7,6 +8,40 @@ class Conjur::Command
7
8
 
8
9
  class << self
9
10
  private
11
+ SHORT_FORMATS = {
12
+ 'resource:check' => lambda{|e| "checked that they can #{e[:privilege]} #{e[:resource]} (#{e[:allowed]})" },
13
+ 'resource:create' => lambda{|e| "created resource #{e[:resource_id]} owned by #{e[:owner]}" },
14
+ 'resource:update' => lambda{|e| "gave #{e[:resource]} to #{e[:owner]}" },
15
+ 'resource:destroy' => lambda{|e| "destroyed resource #{e[:resource]}" },
16
+ 'resource:permit' => lambda{|e| "permitted #{e[:grantee]} to #{e[:privilege]} #{e[:resource]} (grant option: #{!!e[:grant_option]})" },
17
+ 'resource:deny' => lambda{|e| "denied #{e[:privilege]} from #{e[:grantee]} on #{e[:resource]}" },
18
+ 'resource:permitted_roles' => lambda{|e| "listed roles permitted to #{e[:permission]} on #{e[:resource]}" },
19
+ 'role:check' => lambda{|e| "checked that #{e[:role] == e[:conjur_user] ? 'they' : e[:role]} can #{e[:privilege]} #{e[:resource]} (#{e[:allowed]})" },
20
+ 'role:grant' => lambda{|e| "granted role #{e[:role]} to #{e[:member]} #{e[:admin_option] ? ' with ' : ' without '}admin" },
21
+ 'role:revoke' => lambda{|e| "revoked role #{e[:role]} from #{e[:member]}" },
22
+ 'role:create' => lambda{|e| "created role #{e[:role_id]}" }
23
+ }
24
+
25
+
26
+ def short_event_format e
27
+ e.symbolize_keys!
28
+ # hack: sometimes resource is a hash. We don't want that!
29
+ if e[:resource] && e[:resource].kind_of?(Hash)
30
+ e[:resource] = e[:resource]['id']
31
+ end
32
+ s = "[#{Time.at(e[:timestamp])}] "
33
+ s << " #{e[:conjur_user]}"
34
+ s << " (as #{e[:conjur_role]})" if e[:conjur_role] != e[:conjur_user]
35
+ formatter = SHORT_FORMATS["#{e[:asset]}:#{e[:action]}"]
36
+ if formatter
37
+ s << " " << formatter.call(e)
38
+ else
39
+ s << " unknown event: #{e[:asset]}:#{e[:action]}!"
40
+ end
41
+ s << " (failed with #{e[:error]})" if e[:error]
42
+ s
43
+ end
44
+
10
45
  def extract_int_option(source, name, dest=nil)
11
46
  if val = source[name]
12
47
  raise "Expected an integer for #{name}, but got #{val}" unless /\d+/ =~ val
@@ -15,15 +50,24 @@ class Conjur::Command
15
50
  end
16
51
 
17
52
  def extract_audit_options options
18
- {}.tap do |opts|
19
- [:limit, :offset].each do |name|
20
- extract_int_option(options, name, opts)
21
- end
53
+ # Do a little song and dance to simplify testing
54
+ extracted = options.slice :follow, :short
55
+ [:limit, :offset].each do |name|
56
+ extract_int_option(options, name, extracted)
22
57
  end
58
+ if extracted[:follow] && extracted[:offset]
59
+ exit_now! "--offset option not allowed for --follow", 1
60
+ end
61
+ extracted
23
62
  end
24
63
 
25
- def show_audit_events events
26
- puts JSON.pretty_generate(events)
64
+ def show_audit_events events, options
65
+ events.reverse!
66
+ if options[:short]
67
+ events.each{|e| puts short_event_format(e)}
68
+ else
69
+ puts JSON.pretty_generate(events)
70
+ end
27
71
  end
28
72
 
29
73
  def audit_feed_command kind, &block
@@ -34,9 +78,23 @@ class Conjur::Command
34
78
  c.desc "Offset of the first event to return"
35
79
  c.flag [:o, :offset]
36
80
 
81
+ c.desc "Short output format"
82
+ c.switch [:s, :short]
83
+
84
+ c.desc "Follow events as they are generated"
85
+ c.switch [:f, :follow]
86
+
37
87
  c.action do |global_options, options, args|
38
- opts = extract_audit_options options
39
- show_audit_events instance_exec(args, opts, &block)
88
+ options = extract_audit_options options
89
+ if options[:follow]
90
+ Conjur::Audit::Follower.new do |merge_options|
91
+ instance_exec(args, options.merge(merge_options), &block)
92
+ end.follow do |events|
93
+ show_audit_events events, options
94
+ end
95
+ else
96
+ show_audit_events instance_exec(args, options, &block), options
97
+ end
40
98
  end
41
99
  end
42
100
  end
@@ -93,8 +93,10 @@ module Conjur
93
93
 
94
94
  def create_variable id = nil, options = {}, &block
95
95
  options[:id] = id if id
96
- mime_type = options.delete(:mime_type)
97
- kind = options.delete(:kind)
96
+ mime_type = options.delete(:mime_type) || 'text/plain'
97
+ kind = options.delete(:kind) || 'secret'
98
+ var = api.create_variable(mime_type, kind, options)
99
+ do_object var, &block
98
100
  end
99
101
 
100
102
  def owns
@@ -19,5 +19,5 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
- VERSION = "4.4.0"
22
+ VERSION = "4.5.0"
23
23
  end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Conjur::Audit::Follower do
4
+
5
+ end
@@ -0,0 +1,28 @@
1
+ require 'conjur/authn'
2
+ require 'conjur/config'
3
+
4
+ describe Conjur::Authn do
5
+ describe "netrc" do
6
+ before {
7
+ Conjur::Authn.instance_variable_set("@netrc", nil)
8
+ Conjur::Config.should_receive(:[]).with(:netrc_path).and_return path
9
+ }
10
+ after {
11
+ Conjur::Authn.instance_variable_set("@netrc", nil)
12
+ }
13
+ context "with specified netrc_path" do
14
+ let(:path) { double("path") }
15
+ it "consults Conjur::Config for netrc_path" do
16
+ Netrc.should_receive(:read).with(path).and_return netrc = double("netrc")
17
+ Conjur::Authn.netrc.should == netrc
18
+ end
19
+ end
20
+ context "without specified netrc_path" do
21
+ let(:path) { nil }
22
+ it "uses default netrc path" do
23
+ Netrc.should_receive(:read).with().and_return netrc = double("netrc")
24
+ Conjur::Authn.netrc.should == netrc
25
+ end
26
+ end
27
+ end
28
+ end
@@ -5,7 +5,7 @@ describe Conjur::Command::Audit, logged_in: true do
5
5
 
6
6
  def expect_api_call method, *args
7
7
  api.should_receive(method.to_sym).with(*args).and_return events
8
- described_class.should_receive(:show_audit_events).with(events)
8
+ described_class.should_receive(:show_audit_events).with(events, an_instance_of(Hash))
9
9
  end
10
10
 
11
11
  def invoke_expecting_api_call method, *args
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conjur-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0
4
+ version: 4.5.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Rafał Rzepecki
@@ -9,151 +10,172 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2013-12-24 00:00:00.000000000 Z
13
+ date: 2014-01-14 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: conjur-api
16
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
17
19
  requirements:
18
- - - '>='
20
+ - - ! '>='
19
21
  - !ruby/object:Gem::Version
20
22
  version: '4.0'
21
23
  type: :runtime
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
24
27
  requirements:
25
- - - '>='
28
+ - - ! '>='
26
29
  - !ruby/object:Gem::Version
27
30
  version: '4.0'
28
31
  - !ruby/object:Gem::Dependency
29
32
  name: gli
30
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
31
35
  requirements:
32
- - - '>='
36
+ - - ! '>='
33
37
  - !ruby/object:Gem::Version
34
38
  version: '0'
35
39
  type: :runtime
36
40
  prerelease: false
37
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
38
43
  requirements:
39
- - - '>='
44
+ - - ! '>='
40
45
  - !ruby/object:Gem::Version
41
46
  version: '0'
42
47
  - !ruby/object:Gem::Dependency
43
48
  name: highline
44
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
45
51
  requirements:
46
- - - '>='
52
+ - - ! '>='
47
53
  - !ruby/object:Gem::Version
48
54
  version: '0'
49
55
  type: :runtime
50
56
  prerelease: false
51
57
  version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
52
59
  requirements:
53
- - - '>='
60
+ - - ! '>='
54
61
  - !ruby/object:Gem::Version
55
62
  version: '0'
56
63
  - !ruby/object:Gem::Dependency
57
64
  name: netrc
58
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
59
67
  requirements:
60
- - - '>='
68
+ - - ! '>='
61
69
  - !ruby/object:Gem::Version
62
70
  version: '0'
63
71
  type: :runtime
64
72
  prerelease: false
65
73
  version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
66
75
  requirements:
67
- - - '>='
76
+ - - ! '>='
68
77
  - !ruby/object:Gem::Version
69
78
  version: '0'
70
79
  - !ruby/object:Gem::Dependency
71
80
  name: methadone
72
81
  requirement: !ruby/object:Gem::Requirement
82
+ none: false
73
83
  requirements:
74
- - - '>='
84
+ - - ! '>='
75
85
  - !ruby/object:Gem::Version
76
86
  version: '0'
77
87
  type: :runtime
78
88
  prerelease: false
79
89
  version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
80
91
  requirements:
81
- - - '>='
92
+ - - ! '>='
82
93
  - !ruby/object:Gem::Version
83
94
  version: '0'
84
95
  - !ruby/object:Gem::Dependency
85
96
  name: deep_merge
86
97
  requirement: !ruby/object:Gem::Requirement
98
+ none: false
87
99
  requirements:
88
- - - '>='
100
+ - - ! '>='
89
101
  - !ruby/object:Gem::Version
90
102
  version: '0'
91
103
  type: :runtime
92
104
  prerelease: false
93
105
  version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
94
107
  requirements:
95
- - - '>='
108
+ - - ! '>='
96
109
  - !ruby/object:Gem::Version
97
110
  version: '0'
98
111
  - !ruby/object:Gem::Dependency
99
112
  name: cas_rest_client
100
113
  requirement: !ruby/object:Gem::Requirement
114
+ none: false
101
115
  requirements:
102
- - - '>='
116
+ - - ! '>='
103
117
  - !ruby/object:Gem::Version
104
118
  version: '0'
105
119
  type: :runtime
106
120
  prerelease: false
107
121
  version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
108
123
  requirements:
109
- - - '>='
124
+ - - ! '>='
110
125
  - !ruby/object:Gem::Version
111
126
  version: '0'
112
127
  - !ruby/object:Gem::Dependency
113
128
  name: rspec
114
129
  requirement: !ruby/object:Gem::Requirement
130
+ none: false
115
131
  requirements:
116
- - - '>='
132
+ - - ! '>='
117
133
  - !ruby/object:Gem::Version
118
134
  version: '0'
119
135
  type: :development
120
136
  prerelease: false
121
137
  version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
122
139
  requirements:
123
- - - '>='
140
+ - - ! '>='
124
141
  - !ruby/object:Gem::Version
125
142
  version: '0'
126
143
  - !ruby/object:Gem::Dependency
127
144
  name: simplecov
128
145
  requirement: !ruby/object:Gem::Requirement
146
+ none: false
129
147
  requirements:
130
- - - '>='
148
+ - - ! '>='
131
149
  - !ruby/object:Gem::Version
132
150
  version: '0'
133
151
  type: :development
134
152
  prerelease: false
135
153
  version_requirements: !ruby/object:Gem::Requirement
154
+ none: false
136
155
  requirements:
137
- - - '>='
156
+ - - ! '>='
138
157
  - !ruby/object:Gem::Version
139
158
  version: '0'
140
159
  - !ruby/object:Gem::Dependency
141
160
  name: aruba
142
161
  requirement: !ruby/object:Gem::Requirement
162
+ none: false
143
163
  requirements:
144
- - - '>='
164
+ - - ! '>='
145
165
  - !ruby/object:Gem::Version
146
166
  version: '0'
147
167
  type: :development
148
168
  prerelease: false
149
169
  version_requirements: !ruby/object:Gem::Requirement
170
+ none: false
150
171
  requirements:
151
- - - '>='
172
+ - - ! '>='
152
173
  - !ruby/object:Gem::Version
153
174
  version: '0'
154
175
  - !ruby/object:Gem::Dependency
155
176
  name: ci_reporter
156
177
  requirement: !ruby/object:Gem::Requirement
178
+ none: false
157
179
  requirements:
158
180
  - - ~>
159
181
  - !ruby/object:Gem::Version
@@ -161,6 +183,7 @@ dependencies:
161
183
  type: :development
162
184
  prerelease: false
163
185
  version_requirements: !ruby/object:Gem::Requirement
186
+ none: false
164
187
  requirements:
165
188
  - - ~>
166
189
  - !ruby/object:Gem::Version
@@ -168,6 +191,7 @@ dependencies:
168
191
  - !ruby/object:Gem::Dependency
169
192
  name: rake
170
193
  requirement: !ruby/object:Gem::Requirement
194
+ none: false
171
195
  requirements:
172
196
  - - ~>
173
197
  - !ruby/object:Gem::Version
@@ -175,6 +199,7 @@ dependencies:
175
199
  type: :development
176
200
  prerelease: false
177
201
  version_requirements: !ruby/object:Gem::Requirement
202
+ none: false
178
203
  requirements:
179
204
  - - ~>
180
205
  - !ruby/object:Gem::Version
@@ -212,6 +237,7 @@ files:
212
237
  - features/support/env.rb
213
238
  - features/support/hooks.rb
214
239
  - lib/conjur.rb
240
+ - lib/conjur/audit/follower.rb
215
241
  - lib/conjur/authn.rb
216
242
  - lib/conjur/cli.rb
217
243
  - lib/conjur/command.rb
@@ -236,6 +262,8 @@ files:
236
262
  - lib/conjur/dsl/runner.rb
237
263
  - lib/conjur/identifier_manipulation.rb
238
264
  - lib/conjur/version.rb
265
+ - spec/audit/follower_spec.rb
266
+ - spec/authn_spec.rb
239
267
  - spec/command/assets_spec.rb
240
268
  - spec/command/audit_spec.rb
241
269
  - spec/command/authn_spec.rb
@@ -251,26 +279,33 @@ files:
251
279
  homepage: https://github.com/inscitiv/cli-ruby
252
280
  licenses:
253
281
  - MIT
254
- metadata: {}
255
282
  post_install_message:
256
283
  rdoc_options: []
257
284
  require_paths:
258
285
  - lib
259
286
  required_ruby_version: !ruby/object:Gem::Requirement
287
+ none: false
260
288
  requirements:
261
- - - '>='
289
+ - - ! '>='
262
290
  - !ruby/object:Gem::Version
263
291
  version: '0'
292
+ segments:
293
+ - 0
294
+ hash: 1871278325472077316
264
295
  required_rubygems_version: !ruby/object:Gem::Requirement
296
+ none: false
265
297
  requirements:
266
- - - '>='
298
+ - - ! '>='
267
299
  - !ruby/object:Gem::Version
268
300
  version: '0'
301
+ segments:
302
+ - 0
303
+ hash: 1871278325472077316
269
304
  requirements: []
270
305
  rubyforge_project:
271
- rubygems_version: 2.0.3
306
+ rubygems_version: 1.8.25
272
307
  signing_key:
273
- specification_version: 4
308
+ specification_version: 3
274
309
  summary: Conjur command line interface
275
310
  test_files:
276
311
  - features/dsl_context.feature
@@ -284,6 +319,8 @@ test_files:
284
319
  - features/step_definitions/dsl_steps.rb
285
320
  - features/support/env.rb
286
321
  - features/support/hooks.rb
322
+ - spec/audit/follower_spec.rb
323
+ - spec/authn_spec.rb
287
324
  - spec/command/assets_spec.rb
288
325
  - spec/command/audit_spec.rb
289
326
  - spec/command/authn_spec.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 873f90a23b9e22be41441f80c9086f5c005137fe
4
- data.tar.gz: 7c6d8a46e66a871415dc3085bc28ef6551c30289
5
- SHA512:
6
- metadata.gz: efe1fdb784cd353cbf45d0b60ab4744bc5bdd83c9ee333257e4ca0515b4e486426edd03645a125b349443729c241a18e42966adb773fd11b9ab533a9eab56a01
7
- data.tar.gz: 5bec66f78fdccf45d679b2f58a8f4c7cec8e2a65d2bafe116b8e266832b9590fc6c50200278b806b22847664a41a53a03bdd601107bb9fc6a47f74630ac87664