Skip to content

Instantly share code, notes, and snippets.

@technion
Last active August 8, 2023 16:29
Show Gist options
  • Save technion/f299433f42dd3ae5dd96 to your computer and use it in GitHub Desktop.
Save technion/f299433f42dd3ae5dd96 to your computer and use it in GitHub Desktop.
Runs Acme Client
#!/usr/bin/env ruby
# We're going to need a private key.
require 'openssl'
# Initialize the client
require 'acme/client'
# We need an ACME server to talk to, see github.com/letsencrypt/boulder
ENDPOINT = 'https://acme-v01.api.letsencrypt.org/'
#ENDPOINT = 'https://acme-staging.api.letsencrypt.org'
ACCOUNT_FILE = 'account_key.pem'
NAMES = { 'lolware.net' => '/var/www/html',
'erlvulnscan.lolware.net' => '/home/technion/erlvulnscan/frontend/build',
'ctadvisor.lolware.net' => '/home/technion/ct_advisor_int/public',
'www.lolware.net' => '/var/www/html'
}
unless File.exist?(ACCOUNT_FILE)
puts "Creating new account file"
private_key = OpenSSL::PKey::RSA.new(2048)
client = Acme::Client.new(private_key: private_key, endpoint: ENDPOINT)
# If the private key is not known to the server, we need to register it for the
first time.
registration = client.register(contact: 'mailto:technion@lolware.net')
# You'll may need to agree to the term (that's up the to the server to require i
t or not but boulder does by default)
registration.agree_terms
NAMES.each do |subject, path|
authorization = client.authorize(domain: subject)
challenge = authorization.http01
# Save the file. We'll create a public directory to serve it from, and we'll cre
ating the challenge directory.
FileUtils.mkdir_p( File.join( path, File.dirname( challenge.filename ) ) )
# Then writing the file
File.write( File.join( path, challenge.filename), challenge.file_content )
# Wait a bit for the server to make the request, or really just blink, it should
be fast.
sleep(5)
puts "Verification status: " + challenge.verify_status # => 'pending'
end
open ACCOUNT_FILE, 'w' do |io|
io.write private_key.to_pem
end
puts "New account written"
end
private_key = OpenSSL::PKey::RSA.new(File.read ACCOUNT_FILE)
client = Acme::Client.new(private_key: private_key, endpoint: ENDPOINT)
# We're going to need a certificate signing request. If not explicitly
# specified, the first name listed becomes the common name.
csr = Acme::Client::CertificateRequest.new(names: NAMES.keys)
# We can now request a certificate, you can pass anything that returns
# a valid DER encoded CSR when calling to_der on it, for example a
# OpenSSL::X509::Request too.
certificate = client.new_certificate(csr) # => #<Acme::Client::Certificate ....>
# Save the certificate and key
File.write("privkey.pem", certificate.request.private_key.to_pem)
File.write("fullchain.pem", certificate.fullchain_to_pem)
@andrewkendall
Copy link

I'm also seeing 'Error creating new cert :: Authorizations for these names not found or expired'.

I received the email saying my domain had been whitelisted, @solisoft, @cromulus did you find a solution?

@unkmas
Copy link

unkmas commented Dec 9, 2015

@andrewkendall You will receive such an error, if your verify_status will be 'invalid'. It can be, for example, if you not started your server, or it is unavailable and LetsEncrypt can't read your verification file

@technion
Copy link
Author

Note there has been an overhauled API in the acme-client gem. This gist is now obsolete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment