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:
|
request_handlers:
|
||||||
"/websocket": ejabberd_http_ws
|
"/websocket": ejabberd_http_ws
|
||||||
"/api": mod_http_api
|
"/api": mod_http_api
|
||||||
|
"/.well-known": acme_challenge
|
||||||
## "/pub/archive": mod_http_fileserver
|
## "/pub/archive": mod_http_fileserver
|
||||||
web_admin: true
|
web_admin: true
|
||||||
http_bind: true
|
http_bind: true
|
||||||
@ -668,7 +669,8 @@ language: "en"
|
|||||||
acme:
|
acme:
|
||||||
contact: "mailto:cert-admin-ejabberd@example.com"
|
contact: "mailto:cert-admin-ejabberd@example.com"
|
||||||
http_dir: "/home/konstantinos/Desktop/Programming/test-server-for-acme/"
|
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
|
###' MODULES
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
-module(acme_challenge).
|
-module(acme_challenge).
|
||||||
|
|
||||||
-export ([ key_authorization/2,
|
-export ([key_authorization/2,
|
||||||
solve_challenge/3
|
solve_challenge/3,
|
||||||
|
|
||||||
|
process/2
|
||||||
]).
|
]).
|
||||||
%% Challenge Types
|
%% Challenge Types
|
||||||
%% ================
|
%% ================
|
||||||
@ -13,9 +15,19 @@
|
|||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
-include("ejabberd_http.hrl").
|
||||||
-include("ejabberd_acme.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().
|
-spec key_authorization(bitstring(), jose_jwk:key()) -> bitstring().
|
||||||
key_authorization(Token, Key) ->
|
key_authorization(Token, Key) ->
|
||||||
Thumbprint = jose_jwk:thumbprint(Key),
|
Thumbprint = jose_jwk:thumbprint(Key),
|
||||||
@ -68,17 +80,49 @@ solve_challenge(ChallengeType, Challenges, Options) ->
|
|||||||
{ok, url(), bitstring()} | {error, _}.
|
{ok, url(), bitstring()} | {error, _}.
|
||||||
solve_challenge1(Chal = #challenge{type = <<"http-01">>, token=Tkn}, {Key, HttpDir}) ->
|
solve_challenge1(Chal = #challenge{type = <<"http-01">>, token=Tkn}, {Key, HttpDir}) ->
|
||||||
KeyAuthz = key_authorization(Tkn, Key),
|
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),
|
FileLocation = HttpDir ++ "/.well-known/acme-challenge/" ++ bitstring_to_list(Tkn),
|
||||||
case file:write_file(FileLocation, KeyAuthz) of
|
case file:write_file(FileLocation, KeyAuthz) of
|
||||||
ok ->
|
ok ->
|
||||||
{ok, Chal#challenge.uri, KeyAuthz};
|
{ok, Chal#challenge.uri, KeyAuthz};
|
||||||
{error, _} = Err ->
|
{error, Reason} = Err ->
|
||||||
?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Err]),
|
?ERROR_MSG("Error writing to file: ~s with reason: ~p~n", [FileLocation, Reason]),
|
||||||
Err
|
Err
|
||||||
end;
|
end.
|
||||||
%% TODO: Fill stub
|
|
||||||
solve_challenge1(Challenge, _Key) ->
|
-spec ets_put_key_authorization(bitstring(), bitstring()) -> ok.
|
||||||
?INFO_MSG("Challenge: ~p~n", [Challenge]).
|
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
|
%% Useful functions
|
||||||
|
|
||||||
|
@ -513,13 +513,12 @@ get_config_hosts() ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
get_config_cert_dir() ->
|
get_config_cert_dir() ->
|
||||||
{ok, Acme} = get_config_acme(),
|
case ejabberd_config:get_option(cert_dir, undefined) of
|
||||||
case lists:keyfind(cert_dir, 1, Acme) of
|
undefined ->
|
||||||
{cert_dir, CertDir} ->
|
?ERROR_MSG("No cert_dir configuration has been specified", []),
|
||||||
{ok, CertDir};
|
throw({error, configuration});
|
||||||
false ->
|
CertDir ->
|
||||||
?ERROR_MSG("No certificate directory has been specified", []),
|
{ok, CertDir}
|
||||||
{error, configuration_cert_dir}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
@ -32,6 +32,12 @@
|
|||||||
-define(MAX_POLL_REQUESTS, 20).
|
-define(MAX_POLL_REQUESTS, 20).
|
||||||
-define(POLL_WAIT_TIME, 500). % 500 ms.
|
-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