Skip to content

Commit

Permalink
Exposing the wamp & http API for grants: (#35)
Browse files Browse the repository at this point in the history
- bondy.grant.create -> POST /realms/:realm_uri/grants
- bondy.grant.revoke -> PUT /realms/:realm_uri/grants
- bondy.realm.grants -> GET /realms/:realm_uri/grants
- bondy.group.grants -> GET /realms/:realm_uri/groups/:id/grants
- bondy.user.grants -> GET /realms/:realm_uri/users/:id/grants
  • Loading branch information
alejandro-miguez authored Jul 23, 2024
1 parent 4664e62 commit e60db85
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 5 deletions.
14 changes: 13 additions & 1 deletion apps/bondy/include/bondy_uris.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@
-define(BONDY_SOURCE_GET, <<"bondy.source.get">>).
-define(BONDY_SOURCE_LIST, <<"bondy.source.list">>).
-define(BONDY_SOURCE_MATCH, <<"bondy.source.match">>).

%% In the RBAC context, the procedures for grants:
%% - GrantPermission(role, resource, permission): Creates a grant to allow the specified role to access the specified resource with the given permission.
%% - RevokePermission(role, resource, permission): Removes a grant that allows the specified role to access the specified resource with the given permission.
%% - ListPermissions(role): Retrieves a list of permissions granted to the specified role or even to the realm (Identity Provider).
-define(BONDY_GRANT_CREATE, <<"bondy.grant.create">>).
-define(BONDY_GRANT_REVOKE, <<"bondy.grant.revoke">>).

-define(BONDY_REALM_GRANTS, <<"bondy.realm.grants">>).
-define(BONDY_GROUP_GRANTS, <<"bondy.group.grants">>).
-define(BONDY_USER_GRANTS, <<"bondy.user.grants">>).

-define(BONDY_USER_ADD, <<"bondy.user.add">>).
-define(BONDY_USER_ADD_ALIAS, <<"bondy.user.add_alias">>).
-define(BONDY_USER_ADD_GROUP, <<"bondy.user.add_group">>).
Expand All @@ -97,7 +109,7 @@
-define(BONDY_USER_GET, <<"bondy.user.get">>).
-define(BONDY_USER_IS_ENABLED, <<"bondy.user.is_enabled">>).
-define(BONDY_USER_LIST, <<"bondy.user.list">>).
-define(BONDY_USER_REMOVE_ALIAS, <<"bondy.user.remove_alias">>).
-define(BONDY_USER_REMOVE_ALIAS, <<"bondy.user.remove_alias">>).
-define(BONDY_USER_REMOVE_GROUP, <<"bondy.user.remove_group">>).
-define(BONDY_USER_REMOVE_GROUPS, <<"bondy.user.remove_groups">>).
-define(BONDY_USER_UPDATE, <<"bondy.user.update">>).
Expand Down
150 changes: 150 additions & 0 deletions apps/bondy/priv/specs/bondy_admin_api.json
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,156 @@
}
}
}
},
"/realms/:realm_uri/grants" : {
"is_collection" : true,
"options": {
"action": {},
"response": {
"on_error": {
"body": ""
},
"on_result": {
"body": ""
}
}
},
"get" : {
"action" : {
"type" : "wamp_call",
"procedure" : "bondy.realm.grants",
"options" : {},
"args" : [
"{{request.bindings.realm_uri}}"
]
},
"response" : {
"on_error" : {
"status_code" : "{{status_codes |> get({{action.error.error_uri}}, 500) |> integer}}",
"body" : "{{variables.wamp_error_body}}"
},
"on_result" : {
"body" :
"{{action.result.args |> head}}"
}
}
},
"post" : {
"action" : {
"type" : "wamp_call",
"procedure" : "bondy.grant.create",
"options" : {},
"args" : [
"{{request.bindings.realm_uri}}",
"{{request.body}}"
],
"kwargs" : {
}
},
"response" : {
"on_error" : {
"status_code": "{{status_codes |> get({{action.error.error_uri}}, 500) |> integer}}",
"body" : "{{variables.wamp_error_body}}"
},
"on_result" : {
"body" :
"{{action.result.args |> head}}"
}
}
},
"put" : {
"action" : {
"type" : "wamp_call",
"procedure" : "bondy.grant.revoke",
"options" : {},
"args" : [
"{{request.bindings.realm_uri}}",
"{{request.body}}"
],
"kwargs" : {
}
},
"response" : {
"on_error" : {
"status_code": "{{status_codes |> get({{action.error.error_uri}}, 500) |> integer}}",
"body" : "{{variables.wamp_error_body}}"
},
"on_result" : {
"body" :
"{{action.result.args |> head}}"
}
}
}
},
"/realms/:realm_uri/groups/:id/grants" : {
"is_collection" : true,
"options": {
"action": {},
"response": {
"on_error": {
"body": ""
},
"on_result": {
"body": ""
}
}
},
"get" : {
"action" : {
"type" : "wamp_call",
"procedure" : "bondy.group.grants",
"options" : {},
"args" : [
"{{request.bindings.realm_uri}}",
"{{request.bindings.id}}"
]
},
"response" : {
"on_error" : {
"status_code" : "{{status_codes |> get({{action.error.error_uri}}, 500) |> integer}}",
"body" : "{{variables.wamp_error_body}}"
},
"on_result" : {
"body" :
"{{action.result.args |> head}}"
}
}
}
},
"/realms/:realm_uri/users/:id/grants" : {
"is_collection" : true,
"options": {
"action": {},
"response": {
"on_error": {
"body": ""
},
"on_result": {
"body": ""
}
}
},
"get" : {
"action" : {
"type" : "wamp_call",
"procedure" : "bondy.user.grants",
"options" : {},
"args" : [
"{{request.bindings.realm_uri}}",
"{{request.bindings.id}}"
]
},
"response" : {
"on_error" : {
"status_code" : "{{status_codes |> get({{action.error.error_uri}}, 500) |> integer}}",
"body" : "{{variables.wamp_error_body}}"
},
"on_result" : {
"body" :
"{{action.result.args |> head}}"
}
}
}
}
}
}
Expand Down
44 changes: 40 additions & 4 deletions apps/bondy/src/bondy_rbac.erl
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
required => true,
allow_undefined => true,
default => undefined,
datatype => {in, [<<"exact">>, <<"prefix">>, <<"wildcard">>]}
datatype => {in, [?EXACT_MATCH, ?PREFIX_MATCH, ?WILDCARD_MATCH]}
}
}).

Expand Down Expand Up @@ -178,6 +178,7 @@

-export([authorize/2]).
-export([authorize/3]).
-export([externalize_grant/1]).
-export([get_anonymous_context/1]).
-export([get_anonymous_context/2]).
-export([get_context/1]).
Expand All @@ -190,12 +191,12 @@
-export([is_reserved_name/1]).
-export([normalise_name/1]).
-export([refresh_context/1]).
-export([remove_all/2]).
-export([request/1]).
-export([revoke/2]).
-export([revoke_group/2]).
-export([revoke_user/2]).
-export([revoke/2]).
-export([user_grants/2]).
-export([remove_all/2]).



Expand Down Expand Up @@ -606,6 +607,41 @@ remove_all(RealmUri, _Opts) ->
Opts
).

-spec externalize_grant(grant()) -> map().

%% -----------------------------------------------------------------------------
%% @doc To list the grants for a realm
%% @end
%% -----------------------------------------------------------------------------
externalize_grant({{Role, {_, _} = Resource}, Permissions}) ->
ResourceMap = externalize_grant({Resource, Permissions}),
ResourceMap#{
<<"roles">> => [Role]
};

%% -----------------------------------------------------------------------------
%% @doc To list the grants for a role (group or user)
%% @end
%% -----------------------------------------------------------------------------
externalize_grant({{Uri, Strategy}, Permissions}) ->
#{
<<"resources">> => #{
<<"uri">> => Uri,
<<"match">> => Strategy
},
<<"permissions">> => Permissions
};
%% TODO: check if it is possible or necessary to remove this clause
%% due to {<<>>, <<"prefix">>} is stored in this case matching the previous clause
externalize_grant({any, Permissions}) ->
#{
<<"resources">> => #{
<<"uri">> => <<"">>,
<<"match">> => ?PREFIX_MATCH
},
<<"permissions">> => Permissions
}.



%% =============================================================================
Expand Down Expand Up @@ -634,7 +670,7 @@ get_context(RealmUri, Username, Grants) ->
fun
({any, Permissions}, {Map, L}) ->
{maps:put(any, Permissions, Map), L};
({{Uri, <<"exact">>}, Permissions}, {Map, L}) ->
({{Uri, ?EXACT_MATCH}, Permissions}, {Map, L}) ->
{maps:put(Uri, Permissions, Map), L};
(Term, {Map, L}) ->
{Map, [Term|L]}
Expand Down
11 changes: 11 additions & 0 deletions apps/bondy/src/bondy_rbac_group_wamp_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,17 @@ handle_call(?BONDY_GROUP_REMOVE_GROUPS, #call{} = M, Ctxt) ->
{reply, E}
end;

%% -----------------------------------------------------------------------------
%% @doc It returns the grants for a given group.
%% @end
%% -----------------------------------------------------------------------------
handle_call(?BONDY_GROUP_GRANTS, #call{} = M, Ctxt) ->
[Uri, GroupName] = bondy_wamp_utils:validate_call_args(M, Ctxt, 2),

Ext = [bondy_rbac:externalize_grant(X) || X <- bondy_rbac:group_grants(Uri, GroupName)],
R = wamp_message:result(M#call.request_id, #{}, [Ext]),
{reply, R};

handle_call(_, #call{} = M, _) ->
E = bondy_wamp_utils:no_such_procedure_error(M),
{reply, E}.
Expand Down
11 changes: 11 additions & 0 deletions apps/bondy/src/bondy_rbac_user_wamp_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,17 @@ handle_call(?BONDY_USER_REMOVE_GROUPS, #call{} = M, Ctxt) ->
{reply, E}
end;

%% -----------------------------------------------------------------------------
%% @doc It returns the grants for a given user.
%% @end
%% -----------------------------------------------------------------------------
handle_call(?BONDY_USER_GRANTS, #call{} = M, Ctxt) ->
[Uri, Username] = bondy_wamp_utils:validate_call_args(M, Ctxt, 2),

Ext = [bondy_rbac:externalize_grant(X) || X <- bondy_rbac:user_grants(Uri, Username)],
R = wamp_message:result(M#call.request_id, #{}, [Ext]),
{reply, R};

handle_call(_, #call{} = M, _) ->
E = bondy_wamp_utils:no_such_procedure_error(M),
{reply, E}.
Expand Down
30 changes: 30 additions & 0 deletions apps/bondy/src/bondy_rbac_wamp_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,36 @@
}
| {reply, wamp_result() | wamp_error()}.

%% -----------------------------------------------------------------------------
%% @doc It creates a grant for a given realm URI.
%% @end
%% -----------------------------------------------------------------------------
handle_call(?BONDY_GRANT_CREATE, #call{} = M, Ctxt) ->
[Uri, Data] = bondy_wamp_utils:validate_call_args(M, Ctxt, 2),
case bondy_rbac:grant(Uri, Data) of
ok ->
R = wamp_message:result(M#call.request_id, #{}),
{reply, R};
{error, Reason} ->
E = bondy_wamp_utils:error(Reason, M),
{reply, E}
end;

%% -----------------------------------------------------------------------------
%% @doc It revokes a grant for a given realm URI.
%% @end
%% -----------------------------------------------------------------------------
handle_call(?BONDY_GRANT_REVOKE, #call{} = M, Ctxt) ->
[Uri, Data] = bondy_wamp_utils:validate_call_args(M, Ctxt, 2),
case bondy_rbac:revoke(Uri, Data) of
ok ->
R = wamp_message:result(M#call.request_id, #{}),
{reply, R};
{error, Reason} ->
E = bondy_wamp_utils:error(Reason, M),
{reply, E}
end;

handle_call(_, #call{} = M, _) ->
E = bondy_wamp_utils:no_such_procedure_error(M),
{reply, E}.
Expand Down
11 changes: 11 additions & 0 deletions apps/bondy/src/bondy_realm_wamp_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ handle_call(?BONDY_REALM_SECURITY_IS_ENABLED, M, Ctxt) ->
R = wamp_message:result(M#call.request_id, #{}, [Boolean]),
{reply, R};

%% -----------------------------------------------------------------------------
%% @doc It returns the grants for a given realm URI.
%% @end
%% -----------------------------------------------------------------------------
handle_call(?BONDY_REALM_GRANTS, #call{} = M, Ctxt) ->
[Uri] = bondy_wamp_utils:validate_admin_call_args(M, Ctxt, 1),

Ext = [bondy_rbac:externalize_grant(X) || X <- bondy_realm:grants(Uri)],
R = wamp_message:result(M#call.request_id, #{}, [Ext]),
{reply, R};

handle_call(_, M, _) ->
E = bondy_wamp_utils:no_such_procedure_error(M),
{reply, E}.
Expand Down
2 changes: 2 additions & 0 deletions apps/bondy/src/bondy_wamp_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ do_handle_call(<<"bondy.oauth2.", _/binary>> = Proc, M, Ctxt) ->
do_handle_call(<<"bondy.telemetry.", _/binary>> = Proc, M, Ctxt) ->
bondy_telemetry_wamp_api:handle_call(Proc, M, Ctxt);

do_handle_call(<<"bondy.grant.", _/binary>> = Proc, M, Ctxt) ->
bondy_rbac_wamp_api:handle_call(Proc, M, Ctxt);

% do_handle_call(<<"bondy.registry.", _/binary>> = Proc, M, Ctxt) ->
% do_do_handle_call(Proc, M, Ctxt);
Expand Down

0 comments on commit e60db85

Please sign in to comment.