![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
@sap/audit-logging
Advanced tools
Provides audit logging functionalities for Node.js applications.
Audit logging is about writing entries in a specific format to a log storage. Subject to audit logging are events of significant importance. For example, security events which may impact the confidentiality, the integrity or the availability of a system. Another example of such an event would be access to sensitive personal data (both reading and altering) like bank accounts, political opinion, health status etc.
While the consumer of ordinary logs is a system administrator who would like to keep track of the state of a system, audit logs are read by an auditor. There are legal requirements (in some countries stricter than in others) regarding audit logging.
In general the events that are supposed to be audit logged can be gouped in 3 main categories:
An audit log entry may contain the following parts:
Verb - contains the action that was performed, e.g. create, read, update, delete and the UTC time the message has been created at.
Object - contains the information about the object the action has been performed on. The objectID is a mandatory field. It is a unique indetifier of the object (e.g., primary key for an entry in a database). objectName is the display name of the object. The library treats this field as optional. The object part may also contain the attributes of the object on which the action has been performed. If none are provided, then it should be considered that the action has been performed over the whole object. For example, if the action is read and the object is user with id 123, and if the attribute birthday is provided, then it is considered that only this attribute of the user has been read. If no attributes are provided, then it is assumed that all the user data has been read.
Custom - contains name-value pairs which add additional context to the audit log message. For example, the user who performed the action, the category of the message, access channel from which the operation has been triggered etc. Application developers can add their own custom attributes as well.
The library provides an API for writing data access event entries of type create, read, update, delete. This general mechanism can be used for entries for any kind of data and can be further classified (e.g. as system configuration) via a category which can be specified as a custom attribute.
The library also provides an API for general security messages.
var auditLog = require('@sap/audit-logging');
The auditLog
object contains the following functions:
Function | Purpose |
---|---|
create | Used to create an entry for a create operation. |
read | Used to create an entry for a read operation. |
update | Used to create an entry for an update operation. |
delete | Used to create an entry for a delete operation. |
securityMessage | Used to create a general security audit log message. |
Such messages are logged when a specific action (create, read, update or delete) is performed on some data.
Let's suppose we need to create an entry for a read operation over user data. We can achieve that with the following code:
auditLog.read('123', 'John Doe')
.attribute('First name', 'John')
.attribute('Last name', 'Doe')
.attribute('Birth date')
.by('John Doe')
The attribute
method sets object attributes. If it is considered that the birth date is too sensitive to be present in the audit logs, the value of the attribute can be left unspecified.
If no attributes are specified, it is assumed that all user data has been read.
It is important to specify which is the driver of the action. The library will enforce it for all the functions of the auditLog
object named after an action.
Setting it can be achieved with the by
method. In this case John Doe has read his own user info. The entry that will be produced would look like the following:
verb={"action":"read","timestamp":"2016-03-24T14:07:05+00:00"},object={"objectID":"123","objectName":"John Doe","objectAttributes":{"First name":"John","Last name":"Doe","Birth date":"n/a"}},custom={"driver of action":"John Doe"}
n/a is used in case object attribute value is not specified.
In that example we set the custom attribute 'driver of action'. This is one of the predefined custom attributes for which there is a dedicated method. It is also possible to set your own custom attribute, like that:
auditLog.read('123', 'John Doe')
.attribute('First name', 'John')
.attribute('Last name', 'Doe')
.attribute('Birth date')
.by('John Doe')
.customAttribute('my custom attribute', 'my value')
Now the message would look like:
verb={"action":"read","timestamp":"2016-03-24T14:12:13+00:00"},object={"objectID":"123","objectName":"John Doe","objectAttributes":{"First name":"John","Last name":"Doe","Birth date":"n/a"}},custom={"driver of action":"John Doe","my custom attribute":"my value"}
In this case the category
method can be used (this is also one of the predefined custom attributes) to add more context information to the message:
auditLog.read('001122', 'application configuration')
.category('configuration')
.attribute('session timeout', 25)
.by('Application Admin')
The resulting message would look like:
verb={"action":"read","timestamp":"2016-03-24T18:11:13+00:00"},object={"objectID":"001122","objectName":"application configuration","objectAttributes":{"session timeout":"25"}},custom={"category":"configuration","driver of action":"Application Admin"}
When creating an entry for an update action it is possible to specify the old and the new value of an object attribute:
auditLog.update('001122', 'application configuration')
.category('configuration')
.attribute('session timeout', 25, 40)
.by('Application Admin')
The entry would look like this:
verb={"action":"update","timestamp":"2016-03-24T16:19:27+00:00"},object={"objectID":"001122","objectName":"application configuration","objectAttributes":{"session timeout":{"oldValue":"25","newValue":"40"}}},custom={"category":"configuration","driver of action":"Application Admin"}
Note: the library throws an error if specifying an old value and a new value of an attribute for an action different from update.
It is also important to create entries for unsuccessful attempts to perform an action. Here is an example how to do so:
auditLog.delete('123', 'John Doe')
.by('An unauthorized user')
.successful(false)
This example shows how to build an audit log message for the case in which the user An unauthorized user has tried to delete all the data for a user with id 123 (John Doe),
but the operation has not been successful. Unsuccessful operations are marked as attempts in the entries and in this example the action would be 'delete-attempt' instead of just 'delete'.
By default operations are marked as successful. To change that use the successful
method. The example entry would look like this:
verb={"action":"delete-attempt","timestamp":"2016-03-24T16:38:31+00:00"},object={"objectID":"123","objectName":"John Doe"},custom={"driver of action":"An unauthorized user"}
Those can be created like this:
auditLog.securityMessage('%d unsuccessful login attempts', 3).by('John Doe')
.customAttribute('user status', 'blocked')
The entry would look like:
verb={"action":null,"timestamp":"2016-03-24T17:13:10+00:00"},custom={"message":"3 unsuccessful login attempts","driver of action":"John Doe","user status":"blocked"}
Note that in this case the action is 'null' and there is no 'object' part in the message.
In the securityMessage
function you may use the same string interpolation mechanism as with util.format.
The custom part of an audit log message contains name-value pairs which can be used to attach additional context of the message. There are several methods (avaialble for both data access messages and general security messages) which can be used to set some commonly used custom properties:
Method | Custom property name | Purpose |
---|---|---|
by | driver of action | States which is the agent that triggered the operation. |
accessChannel | access channel | States how the data (or the system itself) is being accessed (e.g. RFC, Web services, UI). |
externalIP | external IP | States the IP of the machine that contacts the system. |
category | category | Adds a category to the message. |
Use the log
method to actually log a message. It takes one argument, a callback function. Be aware that the state of the audit logs should be consistent
with the state of the system. Make sure you handle errors from the audit log writer properly. Best practice is to wait for the logging to finish before executing other code.
auditLog.create('001122', 'some configuration')
.category('configuration')
.by('Application Admin')
.log(function (err) {
// Place all of the remaining logic here
});
The same function (log
) is used for general security messages as well.
There are several possibilities for storage. The following two environment variables (set by the XS Advanced OnPremise Runtime) are taken into account:
XS_AUDIT_TO_SYSLOG has the highest priority. If it is set to 'true', then the library will sent the audit log entries to Syslog (or Event Log on Windows).
To achieve that the sap_syslog
module (part of SAP Node.js) should be present in the currently used Node.js runtime, otherwise an error is thrown.
If XS_AUDIT_LOG_FILE is provided and XS_AUDIT_TO_SYSLOG is set to 'false' (or is missing), then the entries will be stored in the XS_AUDIT_LOG_FILE.
If those environment variables are not set (e.g. in Cloud Foundry scenarios or local development), then the entries will be sent to the console. The console will be used as well if XS_AUDIT_TO_SYSLOG is set to 'false' and there is no XS_AUDIT_LOG_FILE provided.
In case Syslog is used as a storage (or Event Log on Windows): If your application is running on the XS Advanced OnPremise Runtime (or Cloud Foundry) the component name used is taken from the environment (the application_name property in the VCAP_APPLICATION environment variable). If running the application locally, then the entries will be logged with 'sap-nodejs-audit-logging' as a component name.
FAQs
Provides audit logging functionalities for Node.js applications
The npm package @sap/audit-logging receives a total of 34,506 weekly downloads. As such, @sap/audit-logging popularity was classified as popular.
We found that @sap/audit-logging demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.