Current section

Files

Jump to
site_encrypt lib site_encrypt certification.ex
Raw

lib/site_encrypt/certification.ex

defmodule SiteEncrypt.Certification do
@moduledoc false
require Logger
alias SiteEncrypt.Registry
alias SiteEncrypt.Certification.Periodic
def child_specs(id) do
[
%{
id: __MODULE__.InitialRenewal,
start: {Task, :start_link, [fn -> start_initial_renewal(id) end]},
restart: :temporary,
binds_to: [:site]
},
Parent.child_spec({Periodic, id}, binds_to: [:site])
]
end
@spec run_renew(SiteEncrypt.config()) :: :ok | :error
def run_renew(config) do
pid =
case start_renew(config) do
{:ok, pid} -> pid
{:error, {:already_started, pid}} -> pid
end
mref = Process.monitor(pid)
receive do
{:DOWN, ^mref, :process, ^pid, reason} ->
if reason == :normal, do: :ok, else: :error
end
end
@spec backup(SiteEncrypt.config()) :: :ok
def backup(config) do
{:ok, tar} = :erl_tar.open(to_charlist(config.backup), [:write, :compressed])
config.db_folder
|> Path.join("*")
|> Path.wildcard()
|> Enum.each(fn path ->
:ok =
:erl_tar.add(
tar,
to_charlist(path),
to_charlist(Path.relative_to(path, config.db_folder)),
[]
)
end)
:ok = :erl_tar.close(tar)
File.chmod!(config.backup, 0o600)
catch
type, error ->
Logger.error(
"Error backing up certificates: #{Exception.format(type, error, __STACKTRACE__)}"
)
end
@spec restore(SiteEncrypt.config()) :: :ok
def restore(config) do
if not is_nil(config.backup) and
File.exists?(config.backup) and
not File.exists?(config.db_folder) do
SiteEncrypt.log(config, "restoring certificates for #{hd(config.domains)}")
File.mkdir_p!(config.db_folder)
:ok =
:erl_tar.extract(
to_charlist(config.backup),
[:compressed, cwd: to_charlist(config.db_folder)]
)
with {:ok, pems} <- SiteEncrypt.client(config).pems(config) do
SiteEncrypt.set_certificate(config.id, pems)
SiteEncrypt.log(config, "certificates for #{hd(config.domains)} restored")
end
end
catch
type, error ->
Logger.error(
"Error restoring certificates: #{Exception.format(type, error, __STACKTRACE__)}"
)
end
defp start_initial_renewal(id) do
config = Registry.config(id)
if config.mode == :auto do
if Periodic.cert_due_for_renewal?(config) or
SiteEncrypt.certificate_subjects_changed?(config) do
start_renew(config)
else
SiteEncrypt.log(config, [
"Certificate for #{hd(config.domains)} is valid until ",
"#{Periodic.cert_valid_until(config)}. ",
"Next renewal is scheduled for #{Periodic.renewal_date(config)}."
])
end
end
end
defp start_renew(config) do
Parent.Client.start_child(
Registry.root(config.id),
{SiteEncrypt.Certification.Job, config}
)
end
end