Commit 9d87d56a authored by telyn's avatar telyn
Browse files

rewrite hooks into a nicer class, add documentation, etc.

parent d88ad722
......@@ -38,6 +38,9 @@
# a Symbiosis system. It can request certificates from LetsEncrypt or generate
# self-signed ones (see PROVIDERS).
#
# In addition, if any domain's certificate set was altered, hooks are run (see
# HOOKS).
#
# PROVIDERS
#
# Currently two providers are supported, namely LetsEncrypt and SelfSigned. A
......@@ -49,6 +52,20 @@
# then no certificates will be generated, but it is possible to manage updating
# certificates with this program.
#
# HOOKS
#
# Hooks are executed from the /etc/symbiosis/ssl-hooks.d directory, given the
# following conditions:
#
# * The file is executable
# * The file's name is made up only of alphanumerics, underscore (_) and hyphen
# (-)
#
# At present, only one event causes the hooks to be executed. If any domain's
# certificate set is altered by symbiosis-ssl, at the end of the process all
# the hooks are called with 'live-update' passed as their only command-line
# argument and the list of domains that were altered
#
# AUTHOR
# Patrick J. Cherry <patrick@bytemark.co.uk>
#
......@@ -237,7 +254,7 @@ domains.sort_by(&:name).each do |domain|
end
end
success = Symbiosis::SSL.call_hooks domains_altered, 'live-update'
success = Symbiosis::SSL::Hooks.run! domains_altered, 'live-update'
exit_code = 2 unless success
exit exit_code
......@@ -5,31 +5,5 @@ module Symbiosis
# SSL knows about which SSL providers exist and provides SSL helper functions
class SSL
PROVIDERS ||= []
def self.call_hooks(domains_with_updates, event)
hooks_path = Symbiosis.path_in_etc('/symbiosis/ssl-hooks.d/*')
success = true
Dir.glob(hooks_path).each do |script|
next unless File.executable?(script)
next unless File.basename(script) =~ /^[a-zA-Z0-9_-]+$/
success &&= run_hook_script(event, script, domains_with_updates)
end
success
end
def self.run_hook_script(event, script, domains_with_updates)
opts = { stdin_data: domains_with_updates.join("\n") }
output, status = Open3.capture2e([script, event], opts)
return true if status.success?
puts "============================================\n"
puts "Error executing SSL script for #{event} hook\n"
puts "#{script} exited with status #{status.exitstatus}\n"
puts output + "\n\n"
false
end
end
end
# Symbiosis module
module Symbiosis
# SSL submodule
module SSL
# Runs the SSL hooks for symbiosis-ssl when
# domains' certificate sets are altered
class Hooks
HOOKS_GLOB = '/symbiosis/ssl-hooks.d/*'.freeze
def self.run!(event, domains)
Hooks.new.run_hooks(event, domains)
end
def initialize(hooks_glob = Symbiosis.path_in_etc(HOOKS_GLOB))
@hooks_glob = hooks_glob
end
def run!(event, domains)
@event = event
@domains = domains
Dir.glob(@hooks_dir)
.filter(valid_hook?)
.all?(runs_successfully?)
end
def valid_hook?(hook)
File.executable?(hook) &&
File.basename(hook) =~ /^[a-zA-Z0-9_-]+$/
end
private
def runs_successfully?(hook)
opts = { stdin_data: @domains.join("\n") }
output, status = Open3.capture2e([hook, event], opts)
return true if status.success?
puts hook_status(output, status)
false
end
def hook_status(output, status)
"============================================\n" \
"Error executing SSL script for #{@event} hook\n" \
"#{script} exited with status #{status.exitstatus}\n" \
"#{output}\n\n"
end
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment