module SSRFsUp
This module contains the AWS lambda client and helper methods to easily make requests to it. All methods take a hostname or URI and a hash or options for the request.
Constants
- VERSION
Attributes
Public Class Methods
# File lib/ssrfs-up.rb, line 128 def configuration @config ||= Configuration.new end
configures the SSRFsUp
module and recreates the AWS Lambda Client from the updated configuration.
# File lib/ssrfs-up.rb, line 123 def configure yield(configuration) @client = Aws::Lambda::Client.new({ region: configuration.region, stub_responses: configuration.test }) end
convenience method for making a DELETE request with do.
# File lib/ssrfs-up.rb, line 91 def delete(host, opts = {}) opts[:method] = "DELETE" invoke(host, opts) end
These methods take a string like “www.google.com” or “google.com” and parse the respective parameters from the string to make the request. If only a hostname is provided, the default options are applied. A hash of options can also be supplied to configure the request. The set of options can be found at github.com/chanzuckerberg/SSRFs-Up/blob/0e18fd30bee3f2b99ff4bc512cb967b83e8d9dcb/openapi.yaml#L97-L119
# File lib/ssrfs-up.rb, line 51 def do(method, host, opts = {}) case method.downcase when "get" get(host, opts) when "put" put(host, opts) when "post" post(host, opts) when "patch" patch(host, opts) when "delete" delete(host, opts) end end
# File lib/ssrfs-up.rb, line 136 def fast_check(host, opts) scheme = opts[:secure] ? "https://" : "http://" path = opts[:path].nil? ? "" : opts[:path] params = opts[:params].nil? ? "" : "?" + URI.encode_www_form(opts[:params]) url = scheme + host + path + params filter_opts = { :max_redirects => opts[:redirect].nil? ? 3 : opts[:redirect] } filter_opts[:params] = opts[:params] unless opts[:params].nil? filter_opts[:body] = opts[:body] unless opts[:body].nil? filter_opts[:headers] = opts[:headers] unless opts[:headers].nil? begin case opts[:method].downcase when "get" resp = SsrfFilter.get(url, filter_opts) when "put" resp = SsrfFilter.put(url, filter_opts) when "post" resp = SsrfFilter.post(url, filter_opts) when "delete" resp = SsrfFilter.delete(url, filter_opts) when "patch" return { status_code: 404, status_text: "Unsupported method", body: "Cannot use patch with fast path." } end { status_code: resp.code.to_i, status_text: resp.message, body: resp.body } rescue SsrfFilter::PrivateIPAddress => exception { status_code: 404, status_text: "Invalid destination", body: exception.to_s } end end
convenience method for making a GET request with do.
# File lib/ssrfs-up.rb, line 67 def get(host, opts = {}) opts[:method] = "GET" invoke(host, opts) end
invokes the lambda with the provided arguments. It handles all lambda related errors so developers should assume the data they receive back is straight from the server they are speaking to.
# File lib/ssrfs-up.rb, line 170 def invoke(host = nil, opts = {}) opts = opts.merge(parseAsUri(host)) if (!opts[:proxy].nil? && !opts[:proxy]) || !configuration.proxy OpenStruct.new(fast_check(opts[:host], opts)) else begin resp = client.invoke({ function_name: configuration.func_name, invocation_type: configuration.invoke_type, log_type: configuration.log_type, payload: payload(opts), }) if resp["status_code"] == 200 OpenStruct.new(JSON.parse(resp&.payload&.string)) else OpenStruct.new({ body: "", status_code: resp[status_code], status_text: "500 Error with proxy" }) end rescue StandardError => e # fall back to local check if the lambda wasn't reachable. OpenStruct.new(fast_check(opts[:host], opts)) end end end
takes an ambiguous string or URI and sets the appropriate options based on if it can be parsed as URI object. If it can't, then the string is assumed to be a hostname only.
# File lib/ssrfs-up.rb, line 99 def parseAsUri(uri = "") uri = uri.to_s opts = { :host => uri.split("/")[0].split("?")[0].split("#")[0] } u = URI(uri) # if the scheme was present, we can parse most of the options from the URI. # otherwise, we can assume the URI was an actual hostname unless u.scheme.nil? opts[:secure] = !(u.scheme == "http") opts[:host] = u.host opts[:path] = u.path unless u.path == "" opts[:params] = CGI.parse(u.query) unless u.query.nil? end opts end
convenience method for making a patch request with do.
# File lib/ssrfs-up.rb, line 85 def patch(host, opts = {}) opts[:method] = "PATCH" invoke(host, opts) end
payload builds an API client Request object with the proper defaults and returns its JSON serialization.
# File lib/ssrfs-up.rb, line 197 def payload(opts = {}) toOpenAPIClient(opts).to_json end
convenience method for making a POST request with do.
# File lib/ssrfs-up.rb, line 79 def post(host, opts = {}) opts[:method] = "POST" invoke(host, opts) end
convenience method for making a PUT request with do.
# File lib/ssrfs-up.rb, line 73 def put(host, opts = {}) opts[:method] = "PUT" invoke(host, opts) end
converts a hash of options to a valid OpenapiClient
Request so that it can be properly consumed by the lambda.
# File lib/ssrfs-up.rb, line 117 def toOpenAPIClient(opts = {}) OpenapiClient::Request.new(opts).to_hash end