feat: gssapi authentication
This commit is contained in:
parent
4250d01363
commit
1270e6a64d
|
@ -2,6 +2,7 @@ version: '3.9'
|
|||
|
||||
services:
|
||||
erlang:
|
||||
hostname: erlang.emqx.net
|
||||
container_name: erlang
|
||||
image: ${DOCKER_CT_RUNNER_IMAGE:-ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-ubuntu22.04}
|
||||
env_file:
|
||||
|
|
|
@ -394,6 +394,16 @@ handle_in(
|
|||
case ConnState of
|
||||
connecting ->
|
||||
process_connect(NProperties, NChannel);
|
||||
reauthenticating ->
|
||||
{ok, Auth, NChannel1} =
|
||||
handle_out(
|
||||
auth,
|
||||
{?RC_SUCCESS, NProperties},
|
||||
NChannel#channel{conn_state = connected}
|
||||
),
|
||||
{ok, Replies, NChannel2} =
|
||||
process_connect(NProperties, NChannel1),
|
||||
{ok, [?REPLY_OUTGOING(Auth) | Replies], NChannel2};
|
||||
_ ->
|
||||
handle_out(
|
||||
auth,
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
Business Source License 1.1
|
||||
|
||||
Licensor: Hangzhou EMQ Technologies Co., Ltd.
|
||||
Licensed Work: EMQX Enterprise Edition
|
||||
The Licensed Work is (c) 2023
|
||||
Hangzhou EMQ Technologies Co., Ltd.
|
||||
Additional Use Grant: Students and educators are granted right to copy,
|
||||
modify, and create derivative work for research
|
||||
or education.
|
||||
Change Date: 2028-01-26
|
||||
Change License: Apache License, Version 2.0
|
||||
|
||||
For information about alternative licensing arrangements for the Software,
|
||||
please contact Licensor: https://www.emqx.com/en/contact
|
||||
|
||||
Notice
|
||||
|
||||
The Business Source License (this document, or the “License”) is not an Open
|
||||
Source license. However, the Licensed Work will eventually be made available
|
||||
under an Open Source License, as stated in this License.
|
||||
|
||||
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
|
||||
“Business Source License” is a trademark of MariaDB Corporation Ab.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Business Source License 1.1
|
||||
|
||||
Terms
|
||||
|
||||
The Licensor hereby grants you the right to copy, modify, create derivative
|
||||
works, redistribute, and make non-production use of the Licensed Work. The
|
||||
Licensor may make an Additional Use Grant, above, permitting limited
|
||||
production use.
|
||||
|
||||
Effective on the Change Date, or the fourth anniversary of the first publicly
|
||||
available distribution of a specific version of the Licensed Work under this
|
||||
License, whichever comes first, the Licensor hereby grants you rights under
|
||||
the terms of the Change License, and the rights granted in the paragraph
|
||||
above terminate.
|
||||
|
||||
If your use of the Licensed Work does not comply with the requirements
|
||||
currently in effect as described in this License, you must purchase a
|
||||
commercial license from the Licensor, its affiliated entities, or authorized
|
||||
resellers, or you must refrain from using the Licensed Work.
|
||||
|
||||
All copies of the original and modified Licensed Work, and derivative works
|
||||
of the Licensed Work, are subject to this License. This License applies
|
||||
separately for each version of the Licensed Work and the Change Date may vary
|
||||
for each version of the Licensed Work released by Licensor.
|
||||
|
||||
You must conspicuously display this License on each original or modified copy
|
||||
of the Licensed Work. If you receive the Licensed Work in original or
|
||||
modified form from a third party, the terms and conditions set forth in this
|
||||
License apply to your use of that work.
|
||||
|
||||
Any use of the Licensed Work in violation of this License will automatically
|
||||
terminate your rights under this License for the current and all other
|
||||
versions of the Licensed Work.
|
||||
|
||||
This License does not grant you any right in any trademark or logo of
|
||||
Licensor or its affiliates (provided that you may use a trademark or logo of
|
||||
Licensor as expressly required by this License).
|
||||
|
||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
||||
AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
||||
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
||||
TITLE.
|
||||
|
||||
MariaDB hereby grants you permission to use this License’s text to license
|
||||
your works, and to refer to it using the trademark “Business Source License”,
|
||||
as long as you comply with the Covenants of Licensor below.
|
||||
|
||||
Covenants of Licensor
|
||||
|
||||
In consideration of the right to use this License’s text and the “Business
|
||||
Source License” name and trademark, Licensor covenants to MariaDB, and to all
|
||||
other recipients of the licensed work to be provided by Licensor:
|
||||
|
||||
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
||||
or a license that is compatible with GPL Version 2.0 or a later version,
|
||||
where “compatible” means that software provided under the Change License can
|
||||
be included in a program with software provided under GPL Version 2.0 or a
|
||||
later version. Licensor may specify additional Change Licenses without
|
||||
limitation.
|
||||
|
||||
2. To either: (a) specify an additional grant of rights to use that does not
|
||||
impose any additional restriction on the right granted in this License, as
|
||||
the Additional Use Grant; or (b) insert the text “None”.
|
||||
|
||||
3. To specify a Change Date.
|
||||
|
||||
4. Not to modify this License in any other way.
|
|
@ -0,0 +1,16 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-ifndef(EMQX_AUTH_GSSAPI_HRL).
|
||||
-define(EMQX_AUTH_GSSAPI_HRL, true).
|
||||
|
||||
-define(AUTHN_MECHANISM_GSSAPI, gssapi).
|
||||
-define(AUTHN_MECHANISM_GSSAPI_BIN, <<"gssapi">>).
|
||||
|
||||
-define(AUTHN_BACKEND, gssapi).
|
||||
-define(AUTHN_BACKEND_BIN, <<"gssapi">>).
|
||||
|
||||
-define(AUTHN_TYPE_GSSAPI, {?AUTHN_MECHANISM_GSSAPI, ?AUTHN_BACKEND}).
|
||||
|
||||
-endif.
|
|
@ -0,0 +1,7 @@
|
|||
%% -*- mode: erlang -*-
|
||||
|
||||
{deps, [
|
||||
{emqx, {path, "../emqx"}},
|
||||
{emqx_utils, {path, "../emqx_utils"}},
|
||||
{sasl_auth, {git, "https://github.com/kafka4beam/sasl_auth.git", {tag, "v2.1.0"}}}
|
||||
]}.
|
|
@ -0,0 +1,18 @@
|
|||
%% -*- mode: erlang -*-
|
||||
{application, emqx_auth_gssapi, [
|
||||
{description, "EMQX gssapi Authentication"},
|
||||
{vsn, "0.1.0"},
|
||||
{registered, []},
|
||||
{mod, {emqx_auth_gssapi_app, []}},
|
||||
{applications, [
|
||||
kernel,
|
||||
stdlib,
|
||||
emqx_auth,
|
||||
sasl_auth
|
||||
]},
|
||||
{env, []},
|
||||
{modules, []},
|
||||
|
||||
{licenses, ["Apache 2.0"]},
|
||||
{links, []}
|
||||
]}.
|
|
@ -0,0 +1,20 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_auth_gssapi_app).
|
||||
|
||||
-include("emqx_auth_gssapi.hrl").
|
||||
|
||||
-behaviour(application).
|
||||
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
start(_StartType, _StartArgs) ->
|
||||
ok = emqx_authn:register_provider(?AUTHN_TYPE_GSSAPI, emqx_authn_gssapi),
|
||||
{ok, Sup} = emqx_auth_gssapi_sup:start_link(),
|
||||
{ok, Sup}.
|
||||
|
||||
stop(_State) ->
|
||||
ok = emqx_authn:deregister_provider(?AUTHN_TYPE_GSSAPI),
|
||||
ok.
|
|
@ -0,0 +1,25 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_auth_gssapi_sup).
|
||||
|
||||
-behaviour(supervisor).
|
||||
|
||||
-export([start_link/0]).
|
||||
|
||||
-export([init/1]).
|
||||
|
||||
-define(SERVER, ?MODULE).
|
||||
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
|
||||
|
||||
init([]) ->
|
||||
SupFlags = #{
|
||||
strategy => one_for_all,
|
||||
intensity => 0,
|
||||
period => 1
|
||||
},
|
||||
ChildSpecs = [],
|
||||
{ok, {SupFlags, ChildSpecs}}.
|
|
@ -0,0 +1,111 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_authn_gssapi).
|
||||
|
||||
-include("emqx_auth_gssapi.hrl").
|
||||
-include_lib("emqx_auth/include/emqx_authn.hrl").
|
||||
-include_lib("typerefl/include/types.hrl").
|
||||
|
||||
-behaviour(emqx_authn_provider).
|
||||
|
||||
-export([
|
||||
create/2,
|
||||
update/2,
|
||||
destroy/1,
|
||||
authenticate/2
|
||||
]).
|
||||
|
||||
create(
|
||||
AuthenticatorID,
|
||||
#{
|
||||
principal := Principal,
|
||||
keytab_file := KeyTabFile
|
||||
}
|
||||
) ->
|
||||
KeyTabPath = emqx_schema:naive_env_interpolation(KeyTabFile),
|
||||
case sasl_auth:kinit(KeyTabPath, Principal) of
|
||||
ok ->
|
||||
{ok, #{
|
||||
id => AuthenticatorID,
|
||||
principal => Principal,
|
||||
keytab_file => KeyTabFile
|
||||
}};
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
update(Config, #{id := ID}) ->
|
||||
create(ID, Config).
|
||||
|
||||
destroy(_) ->
|
||||
ok.
|
||||
|
||||
authenticate(
|
||||
#{
|
||||
auth_method := <<"GSSAPI">>,
|
||||
auth_data := AuthData,
|
||||
auth_cache := AuthCache
|
||||
},
|
||||
#{principal := Principal}
|
||||
) when AuthData =/= undefined ->
|
||||
case AuthCache of
|
||||
#{sasl_conn := SaslConn} ->
|
||||
auth_continue(SaslConn, AuthData);
|
||||
_ ->
|
||||
case auth_new(Principal) of
|
||||
{ok, SaslConn} -> auth_begin(SaslConn, AuthData);
|
||||
Error -> Error
|
||||
end
|
||||
end;
|
||||
authenticate(_Credential, _State) ->
|
||||
ignore.
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% Internal functions
|
||||
%%------------------------------------------------------------------------------
|
||||
|
||||
auth_new(Principal) ->
|
||||
case sasl_auth:server_new(<<"emqx">>, Principal) of
|
||||
{ok, SaslConn} ->
|
||||
{ok, SaslConn};
|
||||
Error ->
|
||||
?TRACE_AUTHN_PROVIDER("sasl_gssapi_new_failed", #{
|
||||
reason => Error,
|
||||
sasl_function => "server_server_new"
|
||||
}),
|
||||
{error, not_authorized}
|
||||
end.
|
||||
|
||||
auth_begin(SaslConn, ClientToken) ->
|
||||
case sasl_auth:server_start(SaslConn, ClientToken) of
|
||||
{ok, {sasl_continue, ServerToken}} ->
|
||||
{continue, ServerToken, #{sasl_conn => SaslConn}};
|
||||
{ok, {sasl_ok, ServerToken}} ->
|
||||
sasl_auth:server_done(SaslConn),
|
||||
{ok, #{}, ServerToken};
|
||||
Reason ->
|
||||
?TRACE_AUTHN_PROVIDER("sasl_gssapi_start_failed", #{
|
||||
reason => Reason,
|
||||
sasl_function => "server_server_start"
|
||||
}),
|
||||
sasl_auth:server_done(SaslConn),
|
||||
{error, not_authorized}
|
||||
end.
|
||||
|
||||
auth_continue(SaslConn, ClientToken) ->
|
||||
case sasl_auth:server_step(SaslConn, ClientToken) of
|
||||
{ok, {sasl_continue, ServerToken}} ->
|
||||
{continue, ServerToken, #{sasl_conn => SaslConn}};
|
||||
{ok, {sasl_ok, ServerToken}} ->
|
||||
sasl_auth:server_done(SaslConn),
|
||||
{ok, #{}, ServerToken};
|
||||
Reason ->
|
||||
?TRACE_AUTHN_PROVIDER("sasl_gssapi_step_failed", #{
|
||||
reason => Reason,
|
||||
sasl_function => "server_server_step"
|
||||
}),
|
||||
sasl_auth:server_done(SaslConn),
|
||||
{error, not_authorized}
|
||||
end.
|
|
@ -0,0 +1,57 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_authn_gssapi_schema).
|
||||
|
||||
-include("emqx_auth_gssapi.hrl").
|
||||
-include_lib("hocon/include/hoconsc.hrl").
|
||||
|
||||
-behaviour(emqx_authn_schema).
|
||||
|
||||
-export([
|
||||
namespace/0,
|
||||
fields/1,
|
||||
desc/1,
|
||||
refs/0,
|
||||
select_union_member/1
|
||||
]).
|
||||
|
||||
namespace() -> "authn".
|
||||
|
||||
refs() ->
|
||||
[?R_REF(gssapi)].
|
||||
|
||||
select_union_member(#{
|
||||
<<"mechanism">> := ?AUTHN_MECHANISM_GSSAPI_BIN, <<"backend">> := ?AUTHN_BACKEND_BIN
|
||||
}) ->
|
||||
refs();
|
||||
select_union_member(#{<<"mechanism">> := ?AUTHN_MECHANISM_GSSAPI_BIN}) ->
|
||||
throw(#{
|
||||
reason => "unknown_backend",
|
||||
expected => ?AUTHN_BACKEND
|
||||
});
|
||||
select_union_member(_) ->
|
||||
undefined.
|
||||
|
||||
fields(gssapi) ->
|
||||
emqx_authn_schema:common_fields() ++
|
||||
[
|
||||
{mechanism, emqx_authn_schema:mechanism(?AUTHN_MECHANISM_GSSAPI)},
|
||||
{backend, emqx_authn_schema:backend(?AUTHN_BACKEND)},
|
||||
{principal,
|
||||
?HOCON(binary(), #{
|
||||
required => true,
|
||||
desc => ?DESC(emqx_bridge_kafka, auth_kerberos_principal)
|
||||
})},
|
||||
{keytab_file,
|
||||
?HOCON(binary(), #{
|
||||
required => true,
|
||||
desc => ?DESC(emqx_bridge_kafka, auth_kerberos_keytab_file)
|
||||
})}
|
||||
].
|
||||
|
||||
desc(gssapi) ->
|
||||
"Settings for GSSAPI authentication.";
|
||||
desc(_) ->
|
||||
undefined.
|
|
@ -9,7 +9,8 @@
|
|||
{snappyer, "1.2.9"},
|
||||
{emqx_connector, {path, "../../apps/emqx_connector"}},
|
||||
{emqx_resource, {path, "../../apps/emqx_resource"}},
|
||||
{emqx_bridge, {path, "../../apps/emqx_bridge"}}
|
||||
{emqx_bridge, {path, "../../apps/emqx_bridge"}},
|
||||
{sasl_auth, {git, "https://github.com/kafka4beam/sasl_auth.git", {tag, "v2.1.0"}}}
|
||||
]}.
|
||||
|
||||
{shell, [
|
||||
|
|
|
@ -55,7 +55,10 @@ authn_mods(ce) ->
|
|||
];
|
||||
authn_mods(ee) ->
|
||||
authn_mods(ce) ++
|
||||
[emqx_gcp_device_authn_schema].
|
||||
[
|
||||
emqx_gcp_device_authn_schema,
|
||||
emqx_authn_gssapi_schema
|
||||
].
|
||||
|
||||
authz() ->
|
||||
[{emqx_authz_schema, authz_mods()}].
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
emqx_bridge_syskeeper,
|
||||
emqx_bridge_confluent,
|
||||
emqx_ds_shared_sub,
|
||||
emqx_auth_gssapi,
|
||||
emqx_auth_ext,
|
||||
emqx_cluster_link,
|
||||
emqx_ds_builtin_raft
|
||||
|
|
Loading…
Reference in New Issue