Skip to content

Commit

Permalink
Refactor http operation out of Directory (#233)
Browse files Browse the repository at this point in the history
- More consistent with other resources
- Fix quirks with using an http client that doesn't have an acme-client
- Fix crash when using Google ACME endpoint (because it return nonce on directory which the client doesn't know how to handle)
  • Loading branch information
unixcharles authored Jan 16, 2024
1 parent 28760c9 commit aefbd95
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 42 deletions.
30 changes: 23 additions & 7 deletions lib/acme/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def initialize(jwk: nil, kid: nil, private_key: nil, directory: DEFAULT_DIRECTOR

@kid, @connection_options = kid, connection_options
@bad_nonce_retry = bad_nonce_retry
@directory = Acme::Client::Resources::Directory.new(URI(directory), @connection_options)
@directory_url = URI(directory)
@nonces ||= []
end

Expand Down Expand Up @@ -229,28 +229,44 @@ def get_nonce
true
end

def directory
@directory ||= load_directory
end

def meta
@directory.meta
directory.meta
end

def terms_of_service
@directory.terms_of_service
directory.terms_of_service
end

def website
@directory.website
directory.website
end

def caa_identities
@directory.caa_identities
directory.caa_identities
end

def external_account_required
@directory.external_account_required
directory.external_account_required
end

private

def load_directory
Acme::Client::Resources::Directory.new(self, directory: fetch_directory)
end

def fetch_directory
response = get(@directory_url)
response.body
rescue JSON::ParserError => exception
raise Acme::Client::Error::InvalidDirectory,
"Invalid directory url\n#{@directory_url} did not return a valid directory\n#{exception.inspect}"
end

def prepare_order_identifiers(identifiers)
if identifiers.is_a?(Hash)
[identifiers]
Expand Down Expand Up @@ -351,6 +367,6 @@ def fetch_chain(response, limit = 10)
end

def endpoint_for(key)
@directory.endpoint_for(key)
directory.endpoint_for(key)
end
end
32 changes: 9 additions & 23 deletions lib/acme/client/resources/directory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ class Acme::Client::Resources::Directory
external_account_required: 'externalAccountRequired'
}

def initialize(url, connection_options)
@url, @connection_options = url, connection_options
def initialize(client, **arguments)
@client = client
assign_attributes(**arguments)
end

def endpoint_for(key)
directory.fetch(key) do |missing_key|
@directory.fetch(key) do |missing_key|
raise Acme::Client::Error::UnsupportedOperation,
"Directory at #{@url} does not include `#{missing_key}`"
end
Expand All @@ -45,31 +46,16 @@ def external_account_required
end

def meta
directory[:meta]
@directory[:meta]
end

private

def directory
@directory ||= load_directory
end

def load_directory
body = fetch_directory
result = {}
result[:meta] = body.delete('meta')
def assign_attributes(directory:)
@directory = {}
@directory[:meta] = directory.delete('meta')
DIRECTORY_RESOURCES.each do |key, entry|
result[key] = URI(body[entry]) if body[entry]
@directory[key] = URI(directory[entry]) if directory[entry]
end
result
rescue JSON::ParserError => exception
raise Acme::Client::Error::InvalidDirectory,
"Invalid directory url\n#{@directory} did not return a valid directory\n#{exception.inspect}"
end

def fetch_directory
http_client = Acme::Client::HTTPClient.new_acme_connection(url: @directory, options: @connection_options, client: nil, mode: nil)
response = http_client.get(@url)
response.body
end
end
96 changes: 91 additions & 5 deletions spec/cassettes/directory_endpoint_for.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

96 changes: 91 additions & 5 deletions spec/cassettes/directory_meta.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions spec/directory_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
require 'spec_helper'

describe Acme::Client::Resources::Directory do
let(:directory) { Acme::Client::Resources::Directory.new(DIRECTORY_URL, {}) }
let(:private_key) { generate_private_key }
let(:client) do
client = Acme::Client.new(private_key: private_key, directory: DIRECTORY_URL)
client.new_account(contact: 'mailto:[email protected]', terms_of_service_agreed: true)
client
end

let(:directory) { client.directory }

context 'endpoint_for', vcr: { cassette_name: 'directory_endpoint_for' } do
it { expect(directory.endpoint_for(:new_nonce)).to be_a_kind_of(URI) }
Expand All @@ -22,6 +29,6 @@
context 'meta', vcr: { cassette_name: 'directory_meta' } do
it { expect(directory.meta).to be_a(Hash) }
it { expect(directory.terms_of_service).to be_a(String) }
it { expect(directory.external_account_required).to be_nil }
it { expect(directory.external_account_required).to be false }
end
end

0 comments on commit aefbd95

Please sign in to comment.