16.2.1.3. Audit log¶
16.2.1.3.1. Base class¶
This is the BaseClass for audit trails
The audit is supposed to work like this. First we need to create an audit object. E.g. this can be done in the before_request:
g.audit_object = getAudit(file_config)
During the request, the g.audit_object can be used to add audit information:
g.audit_object.log({"client": "123.2.3.4", "action": "validate/check"})
Thus, at many different places in the code, audit information can be added to the audit object. Finally, the audit_object needs to be stored to the audit storage. So we call:
g.audit_object.finalize_log()
which creates a signature of the audit data and writes the data to the audit storage.
- class privacyidea.lib.auditmodules.base.Audit(config=None, startdate=None)[source]¶
Create a new audit object.
- Parameters:
config (dict) – The web config is passed to the audit module, so that the special module implementation can get its configuration.
startdate (datetime.datetime) – The datetime of the beginning of the request
- Returns:
Audit object
- add_policy(policy_names: set | list | str)[source]¶
This method adds triggered policy names to the list of triggered policies.
- Parameters:
policy_names – A set, list or single policy name(s)
- Returns:
- add_to_log(param, add_with_comma=False)[source]¶
Add to existing log entry.
- Parameters:
param
add_with_comma – If set to true, new values will be appended comma separated
- Returns:
- audit_entry_to_dict(audit_entry)[source]¶
If the search_query returns an iterator with elements that are not a dictionary, the audit module needs to provide this function, to convert the audit entry to a dictionary.
- property available_audit_columns¶
- csv_generator(param: dict | None = None, admin_params: dict | None = None, user=None, timelimit: timedelta | None = None)[source]¶
A generator that can be used to stream the audit log
- Parameters:
param
- Returns:
- finalize_log()[source]¶
This method is called to finalize the audit_data. I.e. sign the data and write it to the database. It should hash the data and do a hash chain and sign the data
- get_count(search_dict, timedelta=None, success=None)[source]¶
Returns the number of found log entries. E.g. used for checking the timelimit.
- Parameters:
param – List of filter parameters
- Returns:
number of found entries
- get_total(param: dict, admin_params: dict | None = None, AND: bool = True, display_error: bool = True, timelimit: timedelta | None = None) int[source]¶
This method returns the total number of audit entries in the audit store
- property has_data¶
- initialize_log(param)[source]¶
This method initialized the log state. The fact, that the log state was initialized, also needs to be logged. Therefor the same parameters are passed as in the log method.
- is_readable = False¶
- log(param)[source]¶
This method is used to log the data. During a request this method can be called several times to fill the internal audit_data dictionary.
Add new log details in param to the internal log data self.audit_data.
- Parameters:
param (dict) – Log data that is to be added
- Returns:
None
- log_token_num(count)[source]¶
Log the number of the tokens. Can be passed like log_token_num(get_tokens(count=True))
- Parameters:
count (int) – Number of tokens
- Returns:
- read_keys(pub, priv)[source]¶
Set the private and public key for the audit class. This is achieved by passing the values:
priv = config.get("privacyideaAudit.key.private") pub = config.get("privacyideaAudit.key.public")
- Parameters:
pub (string with filename) – Public key, used for verifying the signature
priv (string with filename) – Private key, used to sign the audit entry
- Returns:
None
- search(search_dict: dict, admin_params: dict | None = None, page_size: int = 15, page: int = 1, sortorder: str = 'asc', timelimit: timedelta | None = None)[source]¶
This function is used to search audit events.
- Parameters:
search_dict – Filter parameters that are concatenated with a logical AND
admin_params –
Optional admin parameters containing the admin name, admin realm and a list of realms the admin is allowed to see, such as
{"admin": "admin_name", "admin_realm": "realm_of_the_admin", "allowed_audit_realms": ["realm1", "realm2"]}
page_size – Number of entries per page
page – The page number
sortorder – “asc” - ascending or “desc” - descending
timelimit – Only audit entries newer than this timedelta will be searched
16.2.1.3.2. SQL Audit module¶
The SQL Audit Module is used to write audit entries to an SQL database. The SQL Audit Module is configured like this:
PI_AUDIT_MODULE = "privacyidea.lib.auditmodules.sqlaudit"
PI_AUDIT_KEY_PRIVATE = "tests/testdata/private.pem"
PI_AUDIT_KEY_PUBLIC = "tests/testdata/public.pem"
PI_AUDIT_SERVERNAME = "your choice"
Optional:
PI_AUDIT_SQL_URI = "sqlite://"
PI_AUDIT_SQL_TRUNCATE = True | False
PI_AUDIT_SQL_COLUMN_LENGTH = {"user": 60, "info": 10 ...}
If the PI_AUDIT_SQL_URI is omitted the Audit data is written to the token database.
- class privacyidea.lib.auditmodules.sqlaudit.Audit(config=None, startdate=None)[source]¶
This is the SQLAudit module, which writes the audit entries to an SQL database table.
It requires the following configuration parameters in The Config File:
PI_AUDIT_KEY_PUBLICPI_AUDIT_KEY_PRIVATE
If you want to host the SQL Audit database in another DB than the token DB, you can use:
PI_AUDIT_SQL_URIandPI_AUDIT_SQL_OPTIONS
With
PI_AUDIT_SQL_OPTIONS = {}You can pass options to the DB engine creation. IfPI_AUDIT_SQL_OPTIONSis not set,SQLALCHEMY_ENGINE_OPTIONSwill be used.This module also takes the following optional parameters:
PI_AUDIT_POOL_SIZEPI_AUDIT_POOL_RECYCLEPI_AUDIT_SQL_TRUNCATEPI_AUDIT_NO_SIGNPI_CHECK_OLD_SIGNATURES
You can use
PI_AUDIT_NO_SIGN = Trueto avoid signing of the audit log.If
PI_CHECK_OLD_SIGNATURES = Trueold style signatures (text-book RSA) will be checked as well, otherwise they will be marked asFAIL.Create a new audit object.
- Parameters:
config (dict) – The web config is passed to the audit module, so that the special module implementation can get its configuration.
startdate (datetime.datetime) – The datetime of the beginning of the request
- Returns:
Audit object
- audit_entry_to_dict(audit_entry)[source]¶
If the search_query returns an iterator with elements that are not a dictionary, the audit module needs to provide this function, to convert the audit entry to a dictionary.
- clear()[source]¶
Deletes all entries in the database table. This is only used for test cases! :return:
- csv_generator(param: dict | None = None, admin_params: dict | None = None, user=None, timelimit: timedelta | None = None)[source]¶
Returns the audit log as csv file.
- Parameters:
timelimit – Limit the number of dumped entries by time
param – The request parameters
admin_params –
Optional admin parameters containing the admin name, admin realm and a list of realms the admin is allowed to see, such as
{"admin": "admin_name", "admin_realm": "realm_of_the_admin", "allowed_audit_realms": ["realm1", "realm2"]}
user – The user, who issued the request
- Returns:
None. It yields results as a generator
- finalize_log()[source]¶
This method is used to log the data. It should hash the data and do a hash chain and sign the data
- get_count(search_dict, timedelta=None, success=None)[source]¶
Returns the number of found log entries. E.g. used for checking the timelimit.
- Parameters:
param – List of filter parameters
- Returns:
number of found entries
- get_total(param: dict, admin_params: dict | None = None, AND: bool = True, display_error: bool = True, timelimit: timedelta | None = None) int[source]¶
This method returns the total number of audit entries in the audit store
- is_readable = True¶
- search(search_dict: dict, admin_params: dict | None = None, page_size: int = 15, page: int = 1, sortorder: str = 'asc', timelimit: timedelta | None = None)[source]¶
This function returns the audit log as a Pagination object.
- Parameters:
search_dict – Filter parameters that are concatenated with a logical AND
admin_params –
Optional admin parameters containing the admin name, admin realm and a list of realms the admin is allowed to see, such as
{"admin": "admin_name", "admin_realm": "realm_of_the_admin", "allowed_audit_realms": ["realm1", "realm2"]}
page_size – Number of entries per page
page – The page number
sortorder – “asc” - ascending or “desc” - descending
timelimit – Only audit entries newer than this timedelta will be searched
- search_query(search_dict: dict, admin_params: dict | None = None, page_size: int = 15, page: int = 1, sortorder: str = 'asc', sortname: str = 'number', timelimit: timedelta | None = None)[source]¶
This function returns the audit log as an iterator on the result
- Parameters:
search_dict – Filter parameters that are concatenated with a logical AND
admin_params –
Optional admin parameters containing the admin name, admin realm and a list of realms the admin is allowed to see, such as
{"admin": "admin_name", "admin_realm": "realm_of_the_admin", "allowed_audit_realms": ["realm1", "realm2"]}
page_size – Number of entries per page
page – The page number
sortorder – “asc” - ascending or “desc” - descending
sortname – The column name to sort after. E.g. “number”, “date”, “user”, …
timelimit (timedelta) – Only audit entries newer than this timedelta will be searched
- class privacyidea.lib.auditmodules.sqlaudit.to_isodate(*clauses, **kwargs)[source]¶
Construct a
FunctionElement.- Parameters:
*clauses – list of column expressions that form the arguments of the SQL function call.
**kwargs – additional kwargs are typically consumed by subclasses.
See also
funcFunction- inherit_cache = True¶
Indicate if this
HasCacheKeyinstance should make use of the cache key generation scheme used by its immediate superclass.The attribute defaults to
None, which indicates that a construct has not yet taken into account whether or not its appropriate for it to participate in caching; this is functionally equivalent to setting the value toFalse, except that a warning is also emitted.This flag can be set to
Trueon a particular class, if the SQL that corresponds to the object does not change based on attributes which are local to this class, and not its superclass.See also
compilerext_caching - General guideslines for setting the
HasCacheKey.inherit_cacheattribute for third-party or user defined SQL constructs.
- name = 'to_isodate'¶
16.2.1.3.3. Container Audit module¶
The Container Audit Module allows to write audit information to several different audit modules at the same time. E.g. it can write audit information to the SQL Audit Module and to the Logger Audit Module. This way audit information can be saved in the SQL database and at the same time be passed to a file or external services via the Python logging facility.
The Container Audit Module is configured like this:
PI_AUDIT_MODULE = ‘privacyidea.lib.auditmodules.containeraudit’ PI_AUDIT_CONTAINER_WRITE = [‘privacyidea.lib.auditmodules.sqlaudit’,’privacyidea.lib.auditmodules.loggeraudit’] PI_AUDIT_CONTAINER_READ = ‘privacyidea.lib.auditmodules.sqlaudit’
You also have to provide the configuration parameters for the referenced audit modules.
- class privacyidea.lib.auditmodules.containeraudit.Audit(config=None, startdate=None)[source]¶
This is the ContainerAudit module, which writes the audit entries to a list of audit modules.
Create a new audit object.
- Parameters:
config (dict) – The web config is passed to the audit module, so that the special module implementation can get its configuration.
startdate (datetime.datetime) – The datetime of the beginning of the request
- Returns:
Audit object
- add_policy(policy_names: set | list | str)[source]¶
Call the add_policy method for all writeable modules
- add_to_log(param, add_with_comma=False)[source]¶
Call the add_to_log method for all writeable modules
- csv_generator(param: dict | None = None, admin_params: dict | None = None, user=None, timelimit: timedelta | None = None)[source]¶
Call the csv_generator method for the one readable module
- get_count(search_dict, timedelta=None, success=None)[source]¶
Call the count method for the one readable module
- get_total(param: dict, admin_params: dict | None = None, AND: bool = True, display_error: bool = True, timelimit: timedelta | None = None) int[source]¶
Call the total method for the one readable module
- property has_data¶
16.2.1.3.4. Logger Audit module¶
The Logger Audit Module is used to write audit entries to the Python logging module.
The Logger Audit Module is configured like this:
PI_AUDIT_MODULE = “privacyidea.lib.auditmodules.loggeraudit” PI_AUDIT_SERVERNAME = “your choice”
PI_LOGCONFIG = “/etc/privacyidea/logging.cfg”
The LoggerAudit Class uses the same PI logging config as you could use anyways. To explicitly write audit logs, you need to add something like the following to the logging.cfg
Example:
[handlers] keys=file,audit
[loggers] keys=root,privacyidea,audit
…
[logger_audit] handlers=audit qualname=privacyidea.lib.auditmodules.loggeraudit level=INFO
[handler_audit] class=logging.handlers.RotatingFileHandler backupCount=14 maxBytes=10000000 formatter=detail level=INFO args=(‘/var/log/privacyidea/audit.log’,)
- class privacyidea.lib.auditmodules.loggeraudit.Audit(config=None, startdate=None)[source]¶
This is the LoggerAudit module, which writes the audit entries to the Python logging
Note
This audit module does not provide a Read capability.
Create a new audit object.
- Parameters:
config (dict) – The web config is passed to the audit module, so that the special module implementation can get its configuration.
startdate (datetime.datetime) – The datetime of the beginning of the request
- Returns:
Audit object