summaryrefslogtreecommitdiff
path: root/deps/rabbitmq_auth_backend_cache/src/rabbit_auth_backend_cache.erl
diff options
context:
space:
mode:
Diffstat (limited to 'deps/rabbitmq_auth_backend_cache/src/rabbit_auth_backend_cache.erl')
-rw-r--r--deps/rabbitmq_auth_backend_cache/src/rabbit_auth_backend_cache.erl107
1 files changed, 107 insertions, 0 deletions
diff --git a/deps/rabbitmq_auth_backend_cache/src/rabbit_auth_backend_cache.erl b/deps/rabbitmq_auth_backend_cache/src/rabbit_auth_backend_cache.erl
new file mode 100644
index 0000000000..8a556723b5
--- /dev/null
+++ b/deps/rabbitmq_auth_backend_cache/src/rabbit_auth_backend_cache.erl
@@ -0,0 +1,107 @@
+%% This Source Code Form is subject to the terms of the Mozilla Public
+%% License, v. 2.0. If a copy of the MPL was not distributed with this
+%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
+%%
+%% Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
+%%
+
+-module(rabbit_auth_backend_cache).
+-include_lib("rabbit_common/include/rabbit.hrl").
+
+-behaviour(rabbit_authn_backend).
+-behaviour(rabbit_authz_backend).
+
+-export([user_login_authentication/2, user_login_authorization/2,
+ check_vhost_access/3, check_resource_access/4, check_topic_access/4,
+ state_can_expire/0]).
+
+%% API
+
+user_login_authentication(Username, AuthProps) ->
+ with_cache(authn, {user_login_authentication, [Username, AuthProps]},
+ fun({ok, _}) -> success;
+ ({refused, _, _}) -> refusal;
+ ({error, _} = Err) -> Err;
+ (_) -> unknown
+ end).
+
+user_login_authorization(Username, AuthProps) ->
+ with_cache(authz, {user_login_authorization, [Username, AuthProps]},
+ fun({ok, _}) -> success;
+ ({ok, _, _}) -> success;
+ ({refused, _, _}) -> refusal;
+ ({error, _} = Err) -> Err;
+ (_) -> unknown
+ end).
+
+check_vhost_access(#auth_user{} = AuthUser, VHostPath, AuthzData) ->
+ with_cache(authz, {check_vhost_access, [AuthUser, VHostPath, AuthzData]},
+ fun(true) -> success;
+ (false) -> refusal;
+ ({error, _} = Err) -> Err;
+ (_) -> unknown
+ end).
+
+check_resource_access(#auth_user{} = AuthUser,
+ #resource{} = Resource, Permission, AuthzContext) ->
+ with_cache(authz, {check_resource_access, [AuthUser, Resource, Permission, AuthzContext]},
+ fun(true) -> success;
+ (false) -> refusal;
+ ({error, _} = Err) -> Err;
+ (_) -> unknown
+ end).
+
+check_topic_access(#auth_user{} = AuthUser,
+ #resource{} = Resource, Permission, Context) ->
+ with_cache(authz, {check_topic_access, [AuthUser, Resource, Permission, Context]},
+ fun(true) -> success;
+ (false) -> refusal;
+ ({error, _} = Err) -> Err;
+ (_) -> unknown
+ end).
+
+state_can_expire() -> false.
+
+%%
+%% Implementation
+%%
+
+with_cache(BackendType, {F, A}, Fun) ->
+ {ok, AuthCache} = application:get_env(rabbitmq_auth_backend_cache,
+ cache_module),
+ case AuthCache:get({F, A}) of
+ {ok, Result} ->
+ Result;
+ {error, not_found} ->
+ Backend = get_cached_backend(BackendType),
+ {ok, TTL} = application:get_env(rabbitmq_auth_backend_cache,
+ cache_ttl),
+ BackendResult = apply(Backend, F, A),
+ case should_cache(BackendResult, Fun) of
+ true -> ok = AuthCache:put({F, A}, BackendResult, TTL);
+ false -> ok
+ end,
+ BackendResult
+ end.
+
+get_cached_backend(Type) ->
+ {ok, BackendConfig} = application:get_env(rabbitmq_auth_backend_cache,
+ cached_backend),
+ case BackendConfig of
+ Mod when is_atom(Mod) ->
+ Mod;
+ {N, Z} ->
+ case Type of
+ authn -> N;
+ authz -> Z
+ end
+ end.
+
+should_cache(Result, Fun) ->
+ {ok, CacheRefusals} = application:get_env(rabbitmq_auth_backend_cache,
+ cache_refusals),
+ case {Fun(Result), CacheRefusals} of
+ {success, _} -> true;
+ {refusal, true} -> true;
+ _ -> false
+ end.