Class: Foobara::AWS::Check

Inherits:
Object
  • Object
show all
Defined in:
lib/foobara/aws/check.rb

Overview

Checks a DEPLOYED API against the plan it was deployed from.

result = Foobara::AWS::Check.new(url: "https://api.example.com", plan: plan).run
puts result.report
exit 1 unless result.ok?

Not a substitute for the application's own tests. It asserts the handful of things that are true of every Foobara deployment and that unit tests structurally cannot see, because they live at the edge:

* a public command is reachable WITHOUT credentials
* a command requiring authentication is refused without them
* a refusal is a refusal, not an HTML page with a 200 on it

Each of those has a specific failure behind it. A public command that 401s usually means the authorizer declared an identity source, so API Gateway answered before the authorizer ran — silent, because the function was never invoked and logged nothing. A refusal arriving as 200 text/html usually means a SPA history fallback is rewriting the API's errors, which turns every client error check into a lie.

WHAT IT SENDS. Every request carries {} as its body, so a command that requires inputs answers 422. That is treated as SUCCESS: the point is whether the request reached the command at all, not whether it liked the inputs. It also means gated commands are only ever called WITHOUT credentials, so they are refused before executing and nothing is written.

Public commands ARE executed, with empty inputs. That is safe for the usual case — a command reachable anonymously is nearly always a read — but it is the caller's judgement, and skip: exists for when it is not.

Defined Under Namespace

Classes: Finding, Result

Constant Summary collapse

REFUSALS =

Anything at all, as long as it is not a refusal and not HTML.

[401, 403].freeze

Instance Method Summary collapse

Constructor Details

#initialize(url:, plan:, skip: [], invalid_token: "not.a.token", http: nil) ⇒ Check

http is injectable so this can be tested without a network, and so a caller can supply its own client (a proxy, a custom CA, an SSM-fetched token). It receives (url, body_hash, headers) and returns [status, content_type, body_string].



66
67
68
69
70
71
72
# File 'lib/foobara/aws/check.rb', line 66

def initialize(url:, plan:, skip: [], invalid_token: "not.a.token", http: nil)
  @url = url.to_s.chomp("/")
  @plan = plan
  @skip = Array(skip).map(&:to_s)
  @invalid_token = invalid_token
  @http = http || method(:request)
end

Instance Method Details

#runObject



74
75
76
# File 'lib/foobara/aws/check.rb', line 74

def run
  Result.new(findings: @plan.units.flat_map { |unit| check_unit(unit) })
end