mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Solve acme challenges using built in http server
This commit is contained in:
parent
5199ede4a2
commit
77a96b0ec6
@ -160,6 +160,7 @@ listen:
|
||||
request_handlers:
|
||||
"/websocket": ejabberd_http_ws
|
||||
"/api": mod_http_api
|
||||
"/.well-known": acme_challenge
|
||||
## "/pub/archive": mod_http_fileserver
|
||||
web_admin: true
|
||||
http_bind: true
|
||||
@ -668,7 +669,8 @@ language: "en"
|
||||
acme:
|
||||
contact: "mailto:cert-admin-ejabberd@example.com"
|
||||
http_dir: "/home/konstantinos/Desktop/Programming/test-server-for-acme/"
|
||||
cert_dir: "/usr/local/var/lib/ejabberd/"
|
||||
|
||||
cert_dir: "/usr/local/var/lib/ejabberd/"
|
||||
|
||||
###. =======
|
||||
###' MODULES
|
||||
|
@ -1,7 +1,9 @@
|
||||
-module(acme_challenge).
|
||||
|
||||
-export ([ key_authorization/2,
|
||||
solve_challenge/3
|
||||
-export ([key_authorization/2,
|
||||
solve_challenge/3,
|
||||
|
||||
process/2
|
||||
]).
|
||||
%% Challenge Types
|
||||
%% ================
|
||||
@ -13,9 +15,19 @@
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
-include("xmpp.hrl").
|
||||
|
||||
-include("ejabberd_http.hrl").
|
||||
-include("ejabberd_acme.hrl").
|
||||
|
||||
%% TODO: Maybe validate request here??
|
||||
process(LocalPath, Request) ->
|
||||
Result = ets_get_key_authorization(LocalPath),
|
||||
?INFO_MSG("Trying to serve: ~p at: ~p", [Request, LocalPath]),
|
||||
?INFO_MSG("Http Response: ~p", [Result]),
|
||||
{200,
|
||||
[{<<"Content-Type">>, <<"text/plain">>}],
|
||||
Result}.
|
||||
|
||||
|
||||
-spec key_authorization(bitstring(), jose_jwk:key()) -> bitstring().
|
||||
key_authorization(Token, Key) ->
|
||||
Thumbprint = jose_jwk:thumbprint(Key),
|
||||
@ -68,17 +80,49 @@ solve_challenge(ChallengeType, Challenges, Options) ->
|
||||
{ok, url(), bitstring()} | {error, _}.
|
||||
solve_challenge1(Chal = #challenge{type = <<"http-01">>, token=Tkn}, {Key, HttpDir}) ->
|
||||
KeyAuthz = key_authorization(Tkn, Key),
|
||||
%% save_key_authorization(Chal, Tkn, KeyAuthz, HttpDir);
|
||||
ets_put_key_authorization(Tkn, KeyAuthz),
|
||||
{ok, Chal#challenge.uri, KeyAuthz};
|
||||
solve_challenge1(Challenge, _Key) ->
|
||||
?INFO_MSG("Challenge: ~p~n", [Challenge]).
|
||||
|
||||
|
||||
save_key_authorization(Chal, Tkn, KeyAuthz, HttpDir) ->
|
||||
FileLocation = HttpDir ++ "/.well-known/acme-challenge/" ++ bitstring_to_list(Tkn),
|
||||
case file:write_file(FileLocation, KeyAuthz) of
|
||||
ok ->
|
||||
{ok, Chal#challenge.uri, KeyAuthz};
|
||||
{error, _} = Err ->
|
||||
?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Err]),
|
||||
{error, Reason} = Err ->
|
||||
?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Reason]),
|
||||
Err
|
||||
end;
|
||||
%% TODO: Fill stub
|
||||
solve_challenge1(Challenge, _Key) ->
|
||||
?INFO_MSG("Challenge: ~p~n", [Challenge]).
|
||||
end.
|
||||
|
||||
-spec ets_put_key_authorization(bitstring(), bitstring()) -> ok.
|
||||
ets_put_key_authorization(Tkn, KeyAuthz) ->
|
||||
Tab = ets_get_acme_table(),
|
||||
Key = [<<"acme-challenge">>, Tkn],
|
||||
ets:insert(Tab, {Key, KeyAuthz}),
|
||||
ok.
|
||||
|
||||
-spec ets_get_key_authorization([bitstring()]) -> bitstring().
|
||||
ets_get_key_authorization(Key) ->
|
||||
Tab = ets_get_acme_table(),
|
||||
case ets:take(Tab, Key) of
|
||||
[{Key, KeyAuthz}] ->
|
||||
KeyAuthz;
|
||||
_ ->
|
||||
?ERROR_MSG("Unable to serve key authorization in: ~p", [Key]),
|
||||
<<"">>
|
||||
end.
|
||||
|
||||
-spec ets_get_acme_table() -> atom().
|
||||
ets_get_acme_table() ->
|
||||
case ets:info(acme) of
|
||||
undefined ->
|
||||
ets:new(acme, [named_table, public]);
|
||||
_ ->
|
||||
acme
|
||||
end.
|
||||
|
||||
%% Useful functions
|
||||
|
||||
|
@ -513,13 +513,12 @@ get_config_hosts() ->
|
||||
end.
|
||||
|
||||
get_config_cert_dir() ->
|
||||
{ok, Acme} = get_config_acme(),
|
||||
case lists:keyfind(cert_dir, 1, Acme) of
|
||||
{cert_dir, CertDir} ->
|
||||
{ok, CertDir};
|
||||
false ->
|
||||
?ERROR_MSG("No certificate directory has been specified", []),
|
||||
{error, configuration_cert_dir}
|
||||
case ejabberd_config:get_option(cert_dir, undefined) of
|
||||
undefined ->
|
||||
?ERROR_MSG("No cert_dir configuration has been specified", []),
|
||||
throw({error, configuration});
|
||||
CertDir ->
|
||||
{ok, CertDir}
|
||||
end.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -32,6 +32,12 @@
|
||||
-define(MAX_POLL_REQUESTS, 20).
|
||||
-define(POLL_WAIT_TIME, 500). % 500 ms.
|
||||
|
||||
%%%
|
||||
%%% This module contains functions that implement all necessary http
|
||||
%%% requests to the ACME Certificate Authority. Its purpose is to
|
||||
%%% facilitate the acme client implementation by separating the
|
||||
%%% handling/validating/parsing of all the needed http requests.
|
||||
%%%
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%
|
||||
|
Loading…
Reference in New Issue
Block a user