Last active
August 8, 2023 16:29
-
-
Save technion/f299433f42dd3ae5dd96 to your computer and use it in GitHub Desktop.
Runs Acme Client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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:[email protected]') | |
# 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) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note there has been an overhauled API in the acme-client gem. This gist is now obsolete.