diff --git a/lemur/api_keys/service.py b/lemur/api_keys/service.py index ea681a62..3cb896aa 100644 --- a/lemur/api_keys/service.py +++ b/lemur/api_keys/service.py @@ -7,6 +7,7 @@ """ from lemur import database from lemur.api_keys.models import ApiKey +from lemur.logs import service as log_service def get(aid): @@ -24,6 +25,7 @@ def delete(access_key): :param access_key: :return: """ + log_service.audit_log("delete_api_key", access_key.name, "Deleting the API key") database.delete(access_key) @@ -34,8 +36,9 @@ def revoke(aid): :return: """ api_key = get(aid) - setattr(api_key, "revoked", False) + setattr(api_key, "revoked", True) + log_service.audit_log("revoke_api_key", api_key.name, "Revoking API key") return database.update(api_key) @@ -55,6 +58,9 @@ def create(**kwargs): :return: """ api_key = ApiKey(**kwargs) + # this logs only metadata about the api key + log_service.audit_log("create_api_key", api_key.name, f"Creating the API key {api_key}") + database.create(api_key) return api_key @@ -69,6 +75,7 @@ def update(api_key, **kwargs): for key, value in kwargs.items(): setattr(api_key, key, value) + log_service.audit_log("update_api_key", api_key.name, f"Update summary - {kwargs}") return database.update(api_key) diff --git a/lemur/auth/views.py b/lemur/auth/views.py index eaed419d..85a8f636 100644 --- a/lemur/auth/views.py +++ b/lemur/auth/views.py @@ -20,6 +20,7 @@ from lemur.common.utils import get_psuedo_random_string from lemur.users import service as user_service from lemur.roles import service as role_service +from lemur.logs import service as log_service from lemur.auth.service import create_token, fetch_token_header, get_rsa_public_key from lemur.auth import ldap @@ -198,7 +199,6 @@ def update_user(user, profile, roles): :param profile: :param roles: """ - # if we get an sso user create them an account if not user: user = user_service.create( @@ -212,10 +212,16 @@ def update_user(user, profile, roles): else: # we add 'lemur' specific roles, so they do not get marked as removed + removed_roles = [] for ur in user.roles: if not ur.third_party: roles.append(ur) + elif ur not in roles: + # This is a role assigned in lemur, but not returned by sso during current login + removed_roles.append(ur.name) + if removed_roles: + log_service.audit_log("unassign_role", user.name, f"Un-assigning roles {removed_roles}") # update any changes to the user user_service.update( user.id, diff --git a/lemur/logs/service.py b/lemur/logs/service.py index f4949911..5e5f30db 100644 --- a/lemur/logs/service.py +++ b/lemur/logs/service.py @@ -7,7 +7,7 @@ :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ -from flask import current_app +from flask import current_app, g from lemur import database from lemur.logs.models import Log @@ -34,6 +34,20 @@ def create(user, type, certificate=None): database.commit() +def audit_log(action, entity, message): + """ + Logs given action + :param action: The action being logged e.g. assign_role, create_role etc + :param entity: The entity undergoing the action e.g. name of the role + :param message: Additional info e.g. Role being assigned to user X + :return: + """ + user = g.current_user.email if hasattr(g, 'current_user') else "LEMUR" + current_app.logger.info( + f"[lemur-audit] action: {action}, user: {user}, entity: {entity}, details: {message}" + ) + + def get_all(): """ Retrieve all logs from the database. diff --git a/lemur/roles/service.py b/lemur/roles/service.py index fa4c9c97..cb733d40 100644 --- a/lemur/roles/service.py +++ b/lemur/roles/service.py @@ -12,6 +12,7 @@ from lemur import database from lemur.roles.models import Role from lemur.users.models import User +from lemur.logs import service as log_service def update(role_id, name, description, users): @@ -29,6 +30,8 @@ def update(role_id, name, description, users): role.description = description role.users = users database.update(role) + + log_service.audit_log("update_role", name, f"Role with id {role_id} updated") return role @@ -44,6 +47,8 @@ def set_third_party(role_id, third_party_status=False): role = get(role_id) role.third_party = third_party_status database.update(role) + + log_service.audit_log("update_role", role.name, f"Updated third_party_status={third_party_status}") return role @@ -71,6 +76,7 @@ def create( if users: role.users = users + log_service.audit_log("create_role", name, "Creating new role") return database.create(role) @@ -101,7 +107,10 @@ def delete(role_id): :param role_id: :return: """ - return database.delete(get(role_id)) + + role = get(role_id) + log_service.audit_log("delete_role", role.name, "Deleting role") + return database.delete(role) def render(args): diff --git a/lemur/users/service.py b/lemur/users/service.py index 8fb91aa3..d708d295 100644 --- a/lemur/users/service.py +++ b/lemur/users/service.py @@ -8,6 +8,7 @@ .. moduleauthor:: Kevin Glisson """ from lemur import database +from lemur.logs import service as log_service from lemur.users.models import User @@ -31,6 +32,7 @@ def create(username, password, email, active, profile_picture, roles): profile_picture=profile_picture, ) user.roles = roles + log_service.audit_log("create_user", username, "Creating new user") return database.create(user) @@ -52,6 +54,8 @@ def update(user_id, username, email, active, profile_picture, roles): user.active = active user.profile_picture = profile_picture update_roles(user, roles) + + log_service.audit_log("update_user", username, f"Updating user with id {user_id}") return database.update(user) @@ -64,19 +68,29 @@ def update_roles(user, roles): :param user: :param roles: """ + removed_roles = [] for ur in user.roles: for r in roles: if r.id == ur.id: break else: user.roles.remove(ur) + removed_roles.append(ur.name) + if removed_roles: + log_service.audit_log("unassign_role", user.username, f"Un-assigning roles {removed_roles}") + + added_roles = [] for r in roles: for ur in user.roles: if r.id == ur.id: break else: user.roles.append(r) + added_roles.append(r.name) + + if added_roles: + log_service.audit_log("assign_role", user.username, f"Assigning roles {added_roles}") def get(user_id):