Current section
Files
Jump to
Current section
Files
lib/cert_cache.ex
defmodule CertCache do
@moduledoc """
A certificate cache.
NOTE: Currently, certificates must be stored on disk in PEM format.
"""
@name __MODULE__
alias CertCache.FileCertProvider
@doc """
"""
def start_link(base_dir) do
initial_state = {base_dir, Map.new}
Agent.start_link(fn -> initial_state end, name: @name)
end
@doc """
Certs are loaded from disk on first get, and from cache then after, unless
false is passed for the cached param.
Raises File.Error if requested cert file is not found.
Certs are returned in DER format. Pass them directly to erlang ssl via the
cert/cacerts/key options instead of passing filenames via the
certfile/cacertfile/keyfile options.
ex: (hackney)
```
mycert = CertCache.get_cert("cert.pem")
:hackney.get(url, ssl_options: [ cacerts: [ mycert ] ])
```
ex: (HTTPoison)
```
mycert = CertCache.get_cert("cert.pem")
HTTPoison.get(url, ssl: [ cacerts: [ mycert ] ])
```
"""
def get_cert(filename, cached \\ true) do
if not cached do
load_cert_from_provider(filename)
else
case find_cert_in_cache(filename) do
nil -> load_cert_from_provider(filename)
cert -> cert
end
end
end
defp find_cert_in_cache(filename) do
Agent.get(@name, fn state -> Map.get(Kernel.elem(state, 1), filename) end)
end
defp load_cert_from_provider(filename) do
base_path = Agent.get(@name, fn state -> Kernel.elem(state, 0) end)
cert = FileCertProvider.load_cert(filename, base_path)
Agent.update(@name, fn state -> {
base_path, Map.put(Kernel.elem(state, 1), filename, cert)
} end)
cert
end
end