@cap-js/audit-logging 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -0
- package/README.md +1 -1
- package/package.json +3 -3
- package/srv/log2restv2.js +8 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
5
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
6
|
+
|
|
7
|
+
## Version 0.3.2 - 2023-10-11
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- If the request has no tenant (e.g., Unauthorized), the audit log shall be sent to the provider account
|
|
12
|
+
|
|
13
|
+
## Version 0.3.1 - 2023-09-25
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Defaulting of `@PersonalData.DataSubjectRole` to entity name
|
|
18
|
+
- Overriding service configuration
|
|
19
|
+
|
|
20
|
+
## Version 0.3.0 - 2023-09-05
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Default value for `cds.requires['audit-log'].handle` changed to `['READ', 'WRITE']`, i.e., accessing sensitive data is now logged by default.
|
|
25
|
+
|
|
26
|
+
## Version 0.2.0 - 2023-09-01
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Export class `AuditLogService` for extending in custom implementations as follows:
|
|
31
|
+
```js
|
|
32
|
+
const { AuditLogService } = require('@cap-js/audit-logging')
|
|
33
|
+
class MyAuditLogService extends AuditLogService {
|
|
34
|
+
async init() {
|
|
35
|
+
[...]
|
|
36
|
+
// call AuditLogService's init
|
|
37
|
+
await super.init()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
module.exports = MyAuditLogService
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Version 0.1.0 - 2023-08-18
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- New API:
|
|
48
|
+
- `await audit.log('<event>', <data>)` for asynchronous logs (cf. `emit`)
|
|
49
|
+
- `await audit.logSync('<event>', <data>)` for synchronous logs (cf. `send`)
|
|
50
|
+
- New REST API-based schema with auto-filled `LogEntry` aspect
|
|
51
|
+
- New events `SensitiveDataRead`, `PersonalDataModified`, `ConfigurationModified`, and `SecurityEvent`
|
|
52
|
+
- Full support for OAuth2 plan of SAP Audit Log Service
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- Whether reading sensitive data and modifying personal data is logged is determined by `cds.requires['audit-log'].handle: [...]`.
|
|
57
|
+
Possible values in the array are `READ` and/ or `WRITE`, with `WRITE` as the sole default entry.
|
|
58
|
+
Hence, accessing sensitive data is not logged by default.
|
|
59
|
+
- Integration with SAP Audit Log Service via REST API instead of client library (`@sap/audit-logging`)
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- Various glitches in log calculation
|
|
64
|
+
|
|
65
|
+
### Removed
|
|
66
|
+
|
|
67
|
+
- Old events `dataAccessLog`, `dataModificationLog`, `configChangeLog`, and `securityLog`
|
|
68
|
+
- `@AuditLog.Operation` annotations are ignored. Having the plugin as dependency signals the intent to audit log.
|
|
69
|
+
- `cds.features.audit_personal_data: true` is no longer necessary. Instead, simply add the plugin as a dependency.
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
## About this project
|
|
5
5
|
|
|
6
|
-
`@cap-js/audit-logging` is a CDS plugin providing integration to the SAP
|
|
6
|
+
`@cap-js/audit-logging` is a CDS plugin providing integration to the SAP Audit Log service as well as out-of-the-box personal data-related audit logging based on annotations.
|
|
7
7
|
|
|
8
8
|
Documentation can be found at [cap.cloud.sap](https://cap.cloud.sap/docs/guides/data-privacy).
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js/audit-logging",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "CDS plugin providing integration to the SAP Audit Log service as well as out-of-the-box personal data-related audit logging based on annotations.",
|
|
5
5
|
"repository": "cap-js/audit-logging",
|
|
6
6
|
"author": "SAP SE (https://www.sap.com)",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"main": "cds-plugin.js",
|
|
10
10
|
"files": [
|
|
11
11
|
"lib",
|
|
12
|
-
"srv"
|
|
12
|
+
"srv",
|
|
13
|
+
"CHANGELOG.md"
|
|
13
14
|
],
|
|
14
15
|
"scripts": {
|
|
15
16
|
"lint": "npx eslint .",
|
|
@@ -21,7 +22,6 @@
|
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@cap-js/sqlite": "^1",
|
|
23
24
|
"axios": "^1",
|
|
24
|
-
"better-sqlite3": "8.5.2",
|
|
25
25
|
"eslint": "^8",
|
|
26
26
|
"express": "^4",
|
|
27
27
|
"jest": "^29"
|
package/srv/log2restv2.js
CHANGED
|
@@ -69,6 +69,7 @@ module.exports = class AuditLog2RESTv2 extends AuditLogService {
|
|
|
69
69
|
setTimeout(() => tokens.delete(tenant), (expires_in - 60) * 1000)
|
|
70
70
|
return access_token
|
|
71
71
|
} catch (err) {
|
|
72
|
+
LOG._trace && LOG.trace('error during token fetch:', err)
|
|
72
73
|
// 401 could also mean x-zid is not valid
|
|
73
74
|
if (String(err.response?.statusCode).match(/^4\d\d$/)) err.unrecoverable = true
|
|
74
75
|
throw err
|
|
@@ -76,25 +77,30 @@ module.exports = class AuditLog2RESTv2 extends AuditLogService {
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
async _send(data, path) {
|
|
79
|
-
let url
|
|
80
80
|
const headers = { 'content-type': 'application/json' }
|
|
81
|
-
// TODO: what are these for?
|
|
82
81
|
if (this._vcap) {
|
|
83
82
|
headers.XS_AUDIT_ORG = this._vcap.organization_name
|
|
84
83
|
headers.XS_AUDIT_SPACE = this._vcap.space_name
|
|
85
84
|
headers.XS_AUDIT_APP = this._vcap.application_name
|
|
86
85
|
}
|
|
86
|
+
let url
|
|
87
87
|
if (this._oauth2) {
|
|
88
88
|
url = this.options.credentials.url + PATHS.OAUTH2[path]
|
|
89
|
+
data.tenant ??= this._providerTenant //> if request has no tenant, stay in provider account
|
|
89
90
|
headers.authorization = 'Bearer ' + (await this._getToken(data.tenant))
|
|
90
91
|
data.tenant = data.tenant === this._providerTenant ? '$PROVIDER' : '$SUBSCRIBER'
|
|
91
92
|
} else {
|
|
92
93
|
url = this.options.credentials.url + PATHS.STANDARD[path]
|
|
93
94
|
headers.authorization = this._auth
|
|
94
95
|
}
|
|
96
|
+
if (LOG._debug) {
|
|
97
|
+
const _headers = Object.assign({}, headers, { authorization: headers.authorization.split(' ')[0] + ' ***' })
|
|
98
|
+
LOG.debug(`sending audit log to ${url} with tenant "${data.tenant}", user "${data.user}", and headers`, _headers)
|
|
99
|
+
}
|
|
95
100
|
try {
|
|
96
101
|
await _post(url, data, headers)
|
|
97
102
|
} catch (err) {
|
|
103
|
+
LOG._trace && LOG.trace('error during log send:', err)
|
|
98
104
|
// 429 (rate limit) is not unrecoverable
|
|
99
105
|
if (String(err.response?.statusCode).match(/^4\d\d$/) && err.response?.statusCode !== 429)
|
|
100
106
|
err.unrecoverable = true
|