cased-ruby 0.4.1 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f91759262adc1b192cc5305bb9f84448b888bcb258c7c297f9494b0bba71b55c
4
- data.tar.gz: ce78dd8209246e35dd4ed0fb76f15870b074352b29cf73f01eba426352176572
3
+ metadata.gz: a98d48b740d571c68ad950fe60ecd5af5126fa9567b80030c50bc9cf3f7428c3
4
+ data.tar.gz: b1fdbda8126943f5421176269d42d60144425790c22d57179abe6cf892e99cb6
5
5
  SHA512:
6
- metadata.gz: f13376f04cc1d8dc3c8d93ffcc0403e073d9819ec71f1344f9cb0801b596ab21e31646c89ba02c3a5577dc1afd65ee6a2f24e779eb1e45c9d59ef49b9754fcf3
7
- data.tar.gz: 8a13f691413981290dfda15d90d6576fdf04723dbc4ede2872d7e9cd476488182bda4a8fdf05eec6f2680490c342fddb1d9aaf0a1f0c32be7739e284c231a01e
6
+ metadata.gz: b519bd5dac037cc8ae8c5e795f44d658f44f44ad879e0456e1368dd18378323e5e9f4c8c8ea2e23a12958c4acc7c4c78a0b18afc95a57b6b78be8fe535bbfb0a
7
+ data.tar.gz: 9ce3b66f202ea6b431ae70d28cc4c22327eb4c5b25ac100a320a733964d91c08b139ecc75fbf4a5932f3603cc796983b9a9de39d68a80c54c80ada772bc7f3c3
@@ -28,19 +28,3 @@ jobs:
28
28
  - name: Run Tests
29
29
  run: |
30
30
  bundle exec rake test
31
-
32
- - name: Generate yard documentation
33
- run: |
34
- bundle exec yard
35
-
36
- - name: Upload test coverage report
37
- uses: actions/upload-artifact@v2
38
- with:
39
- name: coverage
40
- path: coverage/**/*
41
-
42
- - name: Upload generated yard documentation
43
- uses: actions/upload-artifact@v2
44
- with:
45
- name: yard
46
- path: doc/**/*
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cased-ruby (0.4.1)
4
+ cased-ruby (0.4.6)
5
5
  activesupport (~> 6)
6
6
  dotpath (= 0.1.0)
7
7
  faraday (~> 1.0)
@@ -14,7 +14,7 @@ PATH
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- activesupport (6.1.3)
17
+ activesupport (6.1.3.1)
18
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
19
19
  i18n (>= 1.6, < 2)
20
20
  minitest (>= 5.1)
@@ -38,7 +38,7 @@ GEM
38
38
  faraday_middleware (1.0.0)
39
39
  faraday (~> 1.0)
40
40
  hashdiff (1.0.1)
41
- i18n (1.8.9)
41
+ i18n (1.8.10)
42
42
  concurrent-ruby (~> 1.0)
43
43
  jaro_winkler (1.5.4)
44
44
  json (2.5.1)
data/README.md CHANGED
@@ -9,6 +9,7 @@ A Cased client for Ruby applications in your organization to control and monitor
9
9
  - [Usage](#usage)
10
10
  - [Cased CLI](#cased-cli)
11
11
  - [Starting an approval workflow](#starting-an-approval-workflow)
12
+ - [Attaching metadata to all CLI requests](#attaching-metadata-to-all-cli-requests)
12
13
  - [Audit trails](#audit-trails)
13
14
  - [Publishing events to Cased](#publishing-events-to-cased)
14
15
  - [Retrieving events from a Cased audit trail](#retrieving-events-from-a-cased-audit-trail)
@@ -85,6 +86,17 @@ Cased.configure do |config|
85
86
 
86
87
  # CASED_HTTP_READ_TIMEOUT=10
87
88
  config.http_read_timeout = 10
89
+
90
+ # Attach metadata to all CLI requests. This metadata will appear in Cased and
91
+ # any notification source such as email or Slack.
92
+ #
93
+ # You are limited to 20 properties and cannot be a nested dictionary. Metadata
94
+ # specified in the CLI request overrides any configured globally.
95
+ config.cli.metadata = {
96
+ rails_env: ENV['RAILS_ENV'],
97
+ heroku_application: ENV['HEROKU_APP_NAME'],
98
+ git_commit: ENV['GIT_COMMIT'],
99
+ }
88
100
  end
89
101
  ```
90
102
 
@@ -135,7 +147,8 @@ end
135
147
 
136
148
  authentication = Cased::CLI::Authentication.new
137
149
  identity = Cased::CLI::Identity.new
138
- authentication.token = identity.identify
150
+ token, ip_address = identity.identify
151
+ authentication.token = token
139
152
 
140
153
  session = Cased::CLI::Session.new(
141
154
  authentication: authentication,
@@ -180,6 +193,27 @@ You no longer need to handle obtaining the user token or asking for a reason up
180
193
  front, `Cased::CLI::InteractiveSession` will prompt the user for any reason
181
194
  being required as necessary.
182
195
 
196
+ #### Attaching metadata to all CLI requests
197
+
198
+ While you can customize the metadata included for each CLI request, it may prove
199
+ useful to specify metadata globally that will be included with each CLI request.
200
+ Some useful information to include may be the current Rails environment, Heroku
201
+ application, Git commit deployed, and more.
202
+
203
+ Metadata is limited to 20 properties and cannot be a nested dictionary.
204
+
205
+ ```ruby
206
+ Cased.configure do |config|
207
+ config.cli.metadata = {
208
+ rails_env: ENV['RAILS_ENV'],
209
+ heroku_application: ENV['HEROKU_APP_NAME'],
210
+ git_commit: ENV['GIT_COMMIT'],
211
+ }
212
+ end
213
+ ```
214
+
215
+ Note: Metadata specified in the CLI request overrides any configured globally.
216
+
183
217
  ### Audit trails
184
218
 
185
219
  #### Publishing events to Cased
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cased
4
+ module CLI
5
+ class Config
6
+ # @example
7
+ # Cased.configure do |config|
8
+ # config.cli.metadata = {
9
+ # rails_env: ENV['RAILS_ENV'],
10
+ # heroku_application: ENV['HEROKU_APP_NAME'],
11
+ # git_commit: ENV['GIT_COMMIT'],
12
+ # }
13
+ # end
14
+ attr_accessor :metadata
15
+
16
+ def initialize
17
+ @metadata = {}
18
+ end
19
+ end
20
+ end
21
+ end
@@ -23,15 +23,20 @@ module Cased
23
23
  def poll(poll_url)
24
24
  count = 0
25
25
  user_id = nil
26
+ ip_address = nil
26
27
 
27
28
  while user_id.nil?
28
29
  count += 1
29
30
  response = Cased.clients.cli.get(poll_url)
30
- user_id = response.body.dig('user', 'id')
31
- sleep 1 if user_id.nil?
31
+ if response.success?
32
+ user_id = response.body.dig('user', 'id')
33
+ ip_address = response.body.fetch('ip_address')
34
+ else
35
+ sleep 1
36
+ end
32
37
  end
33
38
 
34
- user_id
39
+ [user_id, ip_address]
35
40
  end
36
41
  end
37
42
  end
@@ -30,8 +30,31 @@ module Cased
30
30
  end
31
31
 
32
32
  def create
33
+ signal_handler = Signal.trap('SIGINT') do
34
+ if session.requested?
35
+ Cased::CLI::Log.log 'Exiting and canceling request…'
36
+ session.cancel
37
+ exit 0
38
+ elsif signal_handler.respond_to?(:call)
39
+ # We need to call the original handler if we exit this interactive
40
+ # session successfully
41
+ signal_handler.call
42
+ else
43
+ raise Interrupt
44
+ end
45
+ end
46
+
33
47
  if session.create
34
48
  handle_state(session.state)
49
+ elsif session.reauthenticate?
50
+ Cased::CLI::Log.log "You must re-authenticate with Cased due to recent changes to this application's settings."
51
+
52
+ identity = Cased::CLI::Identity.new
53
+ token, ip_address = identity.identify
54
+ session.authentication.token = token
55
+ session.forwarded_ip_address = ip_address
56
+
57
+ create
35
58
  elsif session.unauthorized?
36
59
  if session.authentication.exists?
37
60
  Cased::CLI::Log.log "Existing credentials at #{session.authentication.credentials_path} are not valid."
@@ -40,7 +63,9 @@ module Cased
40
63
  end
41
64
 
42
65
  identity = Cased::CLI::Identity.new
43
- session.authentication.token = identity.identify
66
+ token, ip_address = identity.identify
67
+ session.authentication.token = token
68
+ session.forwarded_ip_address = ip_address
44
69
 
45
70
  create
46
71
  elsif session.reason_required?
@@ -57,26 +82,40 @@ module Cased
57
82
 
58
83
  def reason_prompt
59
84
  print Cased::CLI::Log.string 'Please enter a reason for access: '
60
- session.reason = gets.chomp
85
+ session.reason = STDIN.gets.chomp
61
86
  end
62
87
 
63
88
  def wait_for_approval
89
+ sleep 1
64
90
  session.refresh && handle_state(session.state)
65
91
  end
66
92
 
93
+ def waiting_for_approval_message
94
+ return if defined?(@waiting_for_approval_message_displayed)
95
+
96
+ motd = session.guard_application.dig('settings', 'message_of_the_day')
97
+ waiting_message = motd.blank? ? 'Approval request sent…' : motd
98
+ Cased::CLI::Log.log "#{waiting_message} (id: #{session.id})"
99
+ @waiting_for_approval_message_displayed = true
100
+ end
101
+
67
102
  def handle_state(state)
68
103
  case state
69
104
  when 'approved'
70
105
  Cased::CLI::Log.log 'CLI session has been approved'
71
106
  session.record
72
107
  when 'requested'
108
+ waiting_for_approval_message
73
109
  wait_for_approval
74
110
  when 'denied'
75
111
  Cased::CLI::Log.log 'CLI session has been denied'
112
+ exit 1
76
113
  when 'timed_out'
77
114
  Cased::CLI::Log.log 'CLI session has timed out'
115
+ exit 1
78
116
  when 'canceled'
79
117
  Cased::CLI::Log.log 'CLI session has been canceled'
118
+ exit 0
80
119
  end
81
120
  end
82
121
  end
data/lib/cased/cli/log.rb CHANGED
@@ -13,6 +13,8 @@ module Cased
13
13
 
14
14
  def self.log(text)
15
15
  puts string(text)
16
+ ensure
17
+ STDOUT.flush
16
18
  end
17
19
 
18
20
  def self.color(text, color, bold = false)
@@ -86,9 +86,17 @@ module Cased
86
86
  # @return [String, nil]
87
87
  attr_accessor :reason
88
88
 
89
+ # Public: The forwarded IP V4 or IP V6 address of the user that initiated
90
+ # the CLI session.
91
+ #
92
+ # @example
93
+ # session.forwarded_ip_address #=> "1.1.1.1"
94
+ # @return [String, nil]
95
+ attr_accessor :forwarded_ip_address
96
+
89
97
  # Public: The client's IP V4 or IP V6 address that initiated the CLI session.
90
98
  # @example
91
- # session.reason #=> "1.1.1.1"
99
+ # session.ip_address #=> "1.1.1.1"
92
100
  # @return [String, nil]
93
101
  attr_reader :ip_address
94
102
 
@@ -120,7 +128,7 @@ module Cased
120
128
  @authentication = authentication || Cased::CLI::Authentication.new
121
129
  @reason = reason
122
130
  @command = command || [$PROGRAM_NAME, *ARGV].join(' ')
123
- @metadata = metadata
131
+ @metadata = Cased.config.cli.metadata.merge(metadata)
124
132
  @requester = {}
125
133
  @responder = {}
126
134
  @guard_application = {}
@@ -144,6 +152,7 @@ module Cased
144
152
  @command = session.fetch('command')
145
153
  @metadata = session.fetch('metadata')
146
154
  @reason = session.fetch('reason')
155
+ @forwarded_ip_address = session.fetch('forwarded_ip_address')
147
156
  @ip_address = session.fetch('ip_address')
148
157
  @requester = session.fetch('requester')
149
158
  @responded_at = session['responded_at']
@@ -175,7 +184,7 @@ module Cased
175
184
  return false unless api_url
176
185
 
177
186
  response = Cased.clients.cli.get(api_url, user_token: authentication.token)
178
- self.session = response.body if response.success?
187
+ self.session = response.body
179
188
  end
180
189
 
181
190
  def error?
@@ -194,6 +203,10 @@ module Cased
194
203
  error == :unauthorized
195
204
  end
196
205
 
206
+ def reauthenticate?
207
+ error == :reauthenticate
208
+ end
209
+
197
210
  def record_output?
198
211
  guard_application.dig('settings', 'record_output') || false
199
212
  end
@@ -222,6 +235,7 @@ module Cased
222
235
 
223
236
  response = Cased.clients.cli.post('cli/sessions',
224
237
  user_token: authentication.token,
238
+ forwarded_ip_address: forwarded_ip_address,
225
239
  reason: reason,
226
240
  metadata: metadata,
227
241
  command: command)
@@ -233,6 +247,8 @@ module Cased
233
247
  @error = :reason_required
234
248
  when 'unauthorized'
235
249
  @error = :unauthorized
250
+ when 'reauthenticate'
251
+ @error = :reauthenticate
236
252
  else
237
253
  @error = true
238
254
  return false
@@ -244,7 +260,7 @@ module Cased
244
260
 
245
261
  def cancel
246
262
  response = Cased.clients.cli.post("#{api_url}/cancel", user_token: authentication.token)
247
- self.session = response.body if response.success?
263
+ self.session = response.body
248
264
 
249
265
  canceled?
250
266
  end
data/lib/cased/config.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'cased/cli/config'
4
+
3
5
  module Cased
4
6
  class Config
5
7
  # The amount of time in seconds to allow the HTTP client to open a
@@ -149,6 +151,16 @@ module Cased
149
151
  # end
150
152
  attr_writer :silence
151
153
 
154
+ # @example
155
+ # Cased.configure do |config|
156
+ # config.cli.metadata = {
157
+ # rails_env: ENV['RAILS_ENV'],
158
+ # heroku_application: ENV['HEROKU_APP_NAME'],
159
+ # git_commit: ENV['GIT_COMMIT'],
160
+ # }
161
+ # end
162
+ attr_reader :cli
163
+
152
164
  def initialize
153
165
  @http_read_timeout = ENV.fetch('CASED_HTTP_READ_TIMEOUT', 10).to_i
154
166
  @http_open_timeout = ENV.fetch('CASED_HTTP_OPEN_TIMEOUT', 5).to_i
@@ -172,6 +184,7 @@ module Cased
172
184
  hash[normalized_key] = api_key if api_key
173
185
  end
174
186
  end
187
+ @cli = Cased::CLI::Config.new
175
188
  end
176
189
 
177
190
  # Policy keys are used to query for events from audit trails.
@@ -20,8 +20,6 @@ module Cased
20
20
 
21
21
  conn.options.timeout = Cased.config.http_read_timeout
22
22
  conn.options.open_timeout = Cased.config.http_open_timeout
23
-
24
- conn.adapter :net_http_persistent
25
23
  end
26
24
  end
27
25
 
data/lib/cased/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cased
4
- VERSION = '0.4.1'
4
+ VERSION = '0.4.6'
5
5
  end
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cased-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garrett Bjerkhoel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-04 00:00:00.000000000 Z
11
+ date: 2021-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -305,6 +305,7 @@ files:
305
305
  - lib/cased/cli/asciinema/file.rb
306
306
  - lib/cased/cli/asciinema/writer.rb
307
307
  - lib/cased/cli/authentication.rb
308
+ - lib/cased/cli/config.rb
308
309
  - lib/cased/cli/identity.rb
309
310
  - lib/cased/cli/interactive_session.rb
310
311
  - lib/cased/cli/log.rb
@@ -343,7 +344,7 @@ files:
343
344
  - lib/cased/sensitive/string.rb
344
345
  - lib/cased/test_helper.rb
345
346
  - lib/cased/version.rb
346
- - vendor/cache/activesupport-6.1.3.gem
347
+ - vendor/cache/activesupport-6.1.3.1.gem
347
348
  - vendor/cache/addressable-2.7.0.gem
348
349
  - vendor/cache/ast-2.4.0.gem
349
350
  - vendor/cache/byebug-11.0.1.gem
@@ -356,7 +357,7 @@ files:
356
357
  - vendor/cache/faraday-net_http-1.0.1.gem
357
358
  - vendor/cache/faraday_middleware-1.0.0.gem
358
359
  - vendor/cache/hashdiff-1.0.1.gem
359
- - vendor/cache/i18n-1.8.9.gem
360
+ - vendor/cache/i18n-1.8.10.gem
360
361
  - vendor/cache/jaro_winkler-1.5.4.gem
361
362
  - vendor/cache/json-2.5.1.gem
362
363
  - vendor/cache/jwt-2.2.2.gem
Binary file
Binary file