71 lines
2.2 KiB
Ruby
71 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module ProviderRequestHelper
|
|
private
|
|
|
|
def stub_provider_request(provider, path: '/', method: :get, response_status: 200, response_body: '')
|
|
response_body = encode_body(response_body)
|
|
response_headers = {
|
|
'content-type' => 'application/json',
|
|
}.merge(response_authentication_headers(provider, response_status, response_body))
|
|
|
|
stub_request(method, provider.url(path))
|
|
.to_return do |_request|
|
|
{
|
|
status: response_status,
|
|
body: response_body,
|
|
headers: response_headers,
|
|
}
|
|
end
|
|
end
|
|
|
|
def request_authentication_headers(provider, url: root_url, method: :get, body: '')
|
|
body = encode_body(body)
|
|
headers = {}
|
|
headers['content-digest'] = content_digest(body)
|
|
request = "Net::HTTP::#{method.to_s.classify}".constantize.new(URI(url), headers)
|
|
key = private_key_for(provider)
|
|
Linzer.sign!(request, key:, components: %w(@method @target-uri content-digest))
|
|
signature_headers(request)
|
|
end
|
|
|
|
def response_authentication_headers(provider, status, body)
|
|
response = Net::HTTPResponse::CODE_TO_OBJ[status.to_s].new('1.1', status, Rack::Utils::HTTP_STATUS_CODES[status])
|
|
response.body = body
|
|
response['content-digest'] = content_digest(body)
|
|
key = private_key_for(provider)
|
|
Linzer.sign!(response, key:, components: %w(@status content-digest))
|
|
signature_headers(response)
|
|
end
|
|
|
|
def signature_headers(operation)
|
|
{
|
|
'content-digest' => operation['content-digest'],
|
|
'signature-input' => operation['signature-input'],
|
|
'signature' => operation['signature'],
|
|
}
|
|
end
|
|
|
|
def private_key_for(provider)
|
|
@cached_provider_keys ||= {}
|
|
@cached_provider_keys[provider] ||=
|
|
begin
|
|
key = OpenSSL::PKey.generate_key('ed25519')
|
|
provider.update!(provider_public_key_pem: key.public_to_pem)
|
|
key
|
|
end
|
|
|
|
Linzer.new_ed25519_key(@cached_provider_keys[provider].private_to_pem, provider.id.to_s)
|
|
end
|
|
|
|
def encode_body(body)
|
|
return body if body.nil? || body.is_a?(String)
|
|
|
|
encoder = ActionDispatch::RequestEncoder.encoder(:json)
|
|
encoder.encode_params(body)
|
|
end
|
|
|
|
def content_digest(content)
|
|
"sha-256=:#{OpenSSL::Digest.base64digest('sha256', content)}:"
|
|
end
|
|
end
|