Browse Source

Added policies, permissions, roles, scopes and resources.

hotfix/merge
Marcos Pereira 7 years ago
parent
commit
9cf3c37676
  1. 34
      keycloak/__init__.py
  2. 9
      keycloak/authorization/__init__.py
  3. 16
      keycloak/authorization/permission.py
  4. 23
      keycloak/authorization/policy.py
  5. 12
      keycloak/authorization/role.py
  6. 20
      keycloak/exceptions.py

34
keycloak/__init__.py

@ -15,7 +15,7 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from keycloak.authorization import Authorization from keycloak.authorization import Authorization
from keycloak.exceptions import KeycloakAuthorizationConfigError
from keycloak.exceptions import KeycloakAuthorizationConfigError, KeycloakInvalidTokenError
from .exceptions import raise_error_from_response, KeycloakGetError, KeycloakSecretNotFound, \ from .exceptions import raise_error_from_response, KeycloakGetError, KeycloakSecretNotFound, \
KeycloakRPTNotFound KeycloakRPTNotFound
from .urls_patterns import ( from .urls_patterns import (
@ -98,6 +98,9 @@ class Keycloak:
return payload return payload
def _build_name_role(self, role):
return self.client_id + "/" + role
def well_know(self): def well_know(self):
""" The most important endpoint to understand is the well-known configuration """ The most important endpoint to understand is the well-known configuration
endpoint. It lists endpoints and other configuration options relevant to endpoint. It lists endpoints and other configuration options relevant to
@ -269,14 +272,39 @@ class Keycloak:
self.authorization.load_config(authorization_json) self.authorization.load_config(authorization_json)
authorization_file.close() authorization_file.close()
def get_permissions(self):
def get_permissions(self, token):
"""
Get permission by user token
:param token: user token
:return: permissions list
"""
if not self.authorization.policies: if not self.authorization.policies:
raise KeycloakAuthorizationConfigError( raise KeycloakAuthorizationConfigError(
"Keycloak settings not found. Load Authorization Keycloak settings." "Keycloak settings not found. Load Authorization Keycloak settings."
) )
return
token_info = self.instropect(token)
if not token_info['active']:
raise KeycloakInvalidTokenError(
"Token expired or invalid."
)
user_resources = token_info['resource_access'].get(self.client_id)
if not user_resources:
return None
permissions = []
for policy_name, policy in self.authorization.policies.items():
for role in user_resources['roles']:
if self._build_name_role(role) in policy.roles:
permissions += policy.permissions
return list(set(permissions))

9
keycloak/authorization/__init__.py

@ -24,6 +24,12 @@ from keycloak.authorization.role import Role
class Authorization: class Authorization:
"""
Keycloak Authorization (policies, roles, scopes and resources).
https://keycloak.gitbooks.io/documentation/authorization_services/index.html
"""
def __init__(self): def __init__(self):
self._policies = {} self._policies = {}
@ -38,8 +44,9 @@ class Authorization:
def load_config(self, data): def load_config(self, data):
""" """
Load policies, roles and permissions (scope/resources).
:param data:
:param data: keycloak authorization data (dict)
:return: :return:
""" """
for pol in data['policies']: for pol in data['policies']:

16
keycloak/authorization/permission.py

@ -17,6 +17,22 @@
class Permission: class Permission:
"""
Consider this simple and very common permission:
A permission associates the object being protected with the policies that must be evaluated to determine whether access is granted.
X CAN DO Y ON RESOURCE Z
where
X represents one or more users, roles, or groups, or a combination of them. You can
also use claims and context here.
Y represents an action to be performed, for example, write, view, and so on.
Z represents a protected resource, for example, "/accounts".
https://keycloak.gitbooks.io/documentation/authorization_services/topics/permission/overview.html
"""
def __init__(self, name, type, logic, decision_strategy): def __init__(self, name, type, logic, decision_strategy):
self._name = name self._name = name

23
keycloak/authorization/policy.py

@ -19,6 +19,17 @@ from keycloak.exceptions import KeycloakAuthorizationConfigError
class Policy: class Policy:
"""
A policy defines the conditions that must be satisfied to grant access to an object.
Unlike permissions, you do not specify the object being protected but rather the conditions
that must be satisfied for access to a given object (for example, resource, scope, or both).
Policies are strongly related to the different access control mechanisms (ACMs) that you can use to
protect your resources. With policies, you can implement strategies for attribute-based access control
(ABAC), role-based access control (RBAC), context-based access control, or any combination of these.
https://keycloak.gitbooks.io/documentation/authorization_services/topics/policy/overview.html
"""
def __init__(self, name, type, logic, decision_strategy): def __init__(self, name, type, logic, decision_strategy):
self._name = name self._name = name
@ -75,10 +86,22 @@ class Policy:
return self._permissions return self._permissions
def add_role(self, role): def add_role(self, role):
"""
Add keycloak role in policy.
:param role: keycloak role.
:return:
"""
if self.type != 'role': if self.type != 'role':
raise KeycloakAuthorizationConfigError( raise KeycloakAuthorizationConfigError(
"Can't add role. Policy type is different of role") "Can't add role. Policy type is different of role")
self._roles.append(role) self._roles.append(role)
def add_permission(self, permission): def add_permission(self, permission):
"""
Add keycloak permission in policy.
:param permission: keycloak permission.
:return:
"""
self._permissions.append(permission) self._permissions.append(permission)

12
keycloak/authorization/role.py

@ -17,6 +17,13 @@
class Role: class Role:
"""
Roles identify a type or category of user. Admin, user,
manager, and employee are all typical roles that may exist in an organization.
https://keycloak.gitbooks.io/documentation/server_admin/topics/roles.html
"""
def __init__(self, name, required=False): def __init__(self, name, required=False):
self.name = name self.name = name
@ -25,3 +32,8 @@ class Role:
@property @property
def get_name(self): def get_name(self):
return self.name return self.name
def __eq__(self, other):
if isinstance(other, str):
return self.name == other
return NotImplemented

20
keycloak/exceptions.py

@ -48,26 +48,10 @@ class KeycloakOperationError(KeycloakError):
pass pass
class KeycloakListError(KeycloakOperationError):
pass
class KeycloakGetError(KeycloakOperationError): class KeycloakGetError(KeycloakOperationError):
pass pass
class KeycloakCreateError(KeycloakOperationError):
pass
class KeycloakUpdateError(KeycloakOperationError):
pass
class KeycloakDeleteError(KeycloakOperationError):
pass
class KeycloakSecretNotFound(KeycloakOperationError): class KeycloakSecretNotFound(KeycloakOperationError):
pass pass
@ -80,6 +64,10 @@ class KeycloakAuthorizationConfigError(KeycloakOperationError):
pass pass
class KeycloakInvalidTokenError(KeycloakOperationError):
pass
def raise_error_from_response(response, error, expected_code=200): def raise_error_from_response(response, error, expected_code=200):
if expected_code == response.status_code: if expected_code == response.status_code:

Loading…
Cancel
Save