@oneuptime/common 12.0.12 → 12.0.13
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/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +32 -5
- package/Models/DatabaseModels/NetworkDevice.ts +64 -0
- package/Models/DatabaseModels/StatusPage.ts +59 -0
- package/Models/DatabaseModels/StatusPageOidc.ts +2 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -2
- package/Server/API/AIChatAPI.ts +55 -56
- package/Server/API/CommonAPI.ts +89 -0
- package/Server/API/MicrosoftTeamsAPI.ts +20 -9
- package/Server/API/SlackAPI.ts +13 -10
- package/Server/API/StatusPageAPI.ts +2197 -2128
- package/Server/API/TelemetryAPI.ts +72 -3
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.ts +30 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/UserAuthorization.ts +11 -2
- package/Server/Services/ApiKeyPermissionService.ts +116 -2
- package/Server/Services/DatabaseService.ts +17 -6
- package/Server/Services/LogAggregationService.ts +34 -0
- package/Server/Services/LogService.ts +21 -0
- package/Server/Services/NetworkSiteService.ts +12 -0
- package/Server/Services/SpanService.ts +21 -0
- package/Server/Services/TraceAggregationService.ts +15 -0
- package/Server/Services/WorkspaceNotificationRuleService.ts +172 -220
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
- package/Server/Types/Database/Permissions/AccessControlPermission.ts +47 -16
- package/Server/Utils/APIKey/AccessPermission.ts +16 -40
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +144 -0
- package/Server/Utils/LogRedaction.ts +576 -0
- package/Server/Utils/Logger.ts +123 -46
- package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +94 -23
- package/Server/Utils/Monitor/MonitorResource.ts +29 -9
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +28 -7
- package/Server/Utils/SessionReplay/SessionReplayGateCacheStore.ts +56 -10
- package/Server/Utils/StartServer.ts +30 -9
- package/Server/Utils/StatusPageSearchEngineIndexing.ts +33 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +441 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +488 -46
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +300 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +130 -0
- package/Tests/Models/DatabaseModels/DatabaseBaseModelToJSONObjectCache.test.ts +180 -0
- package/Tests/Models/StatusPageEnableSearchEngineIndexing.test.ts +157 -0
- package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +23 -1
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +785 -0
- package/Tests/Server/API/BaseAPIApiKeyAuth.test.ts +21 -8
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +290 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +7 -1
- package/Tests/Server/API/StatusPageOverviewCache.test.ts +474 -0
- package/Tests/Server/API/StatusPageSeoSearchEngineIndexing.test.ts +189 -0
- package/Tests/Server/Infrastructure/InMemoryTTLCache.test.ts +158 -0
- package/Tests/Server/Infrastructure/Postgres/DeviceRoleAndDeclaredLinkParentMigration.test.ts +9 -60
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +24 -15
- package/Tests/Server/Middleware/UserAuthorization.test.ts +79 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +332 -0
- package/Tests/Server/Services/ApiKeyPermissionService.test.ts +347 -0
- package/Tests/Server/Services/DatabaseServiceUpdateDebugLogging.test.ts +282 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +56 -2
- package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +267 -0
- package/Tests/Server/Services/WorkspaceNotificationRuleTestRuleChannels.test.ts +702 -0
- package/Tests/Server/Types/Database/Permissions/AccessControlPermission.test.ts +165 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +48 -36
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +213 -0
- package/Tests/Server/Utils/LogRedaction.test.ts +415 -0
- package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +245 -0
- package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +374 -4
- package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +455 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceReachabilityRoundTrip.test.ts +369 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +86 -8
- package/Tests/Server/Utils/PrivacyFilterUtil.test.ts +64 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayGateCacheStore.test.ts +207 -0
- package/Tests/Server/Utils/StartServerBodyVerify.test.ts +335 -0
- package/Tests/Server/Utils/StatusPageSearchEngineIndexing.test.ts +60 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +435 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +607 -62
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstalledTeamIdSpace.test.ts +778 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +44 -10
- package/Tests/Types/API/HostnameFromAuthority.test.ts +164 -0
- package/Tests/Types/Database/AccessControl/ColumnAccessControlCache.test.ts +344 -0
- package/Tests/Types/Database/DatabasePropertyFindOperator.test.ts +518 -0
- package/Tests/Types/Database/TableColumnMetadataCache.test.ts +286 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +100 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +360 -0
- package/Tests/Types/StatusPage/SearchEngineIndexing.test.ts +86 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +254 -0
- package/Tests/UI/Components/CardSelect.test.tsx +1021 -0
- package/Tests/UI/Components/MasterPage.test.tsx +36 -1
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +66 -1
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +115 -6
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +610 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +114 -45
- package/Types/API/Hostname.ts +79 -0
- package/Types/Database/AccessControl/ColumnAccessControl.ts +33 -11
- package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +33 -11
- package/Types/Database/DatabaseProperty.ts +38 -0
- package/Types/Database/TableColumn.ts +34 -7
- package/Types/Events/Recurring.ts +16 -1
- package/Types/Monitor/MonitorStep.ts +13 -1
- package/Types/Monitor/MonitorType.ts +345 -40
- package/Types/Monitor/SSLMonitor/SslMonitorResponse.ts +43 -0
- package/Types/StatusPage/SearchEngineIndexing.ts +61 -0
- package/Types/Telemetry/ResourceEntityFacet.ts +211 -0
- package/UI/Components/CardSelect/CardSelect.tsx +714 -105
- package/UI/Components/EmptyState/EmptyState.tsx +8 -1
- package/UI/Components/Footer/Footer.tsx +32 -6
- package/UI/Components/Forms/Fields/FormField.tsx +3 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Loader/PageLoader.tsx +29 -8
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +26 -4
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +17 -1
- package/UI/Components/MasterPage/MasterPage.tsx +24 -11
- package/Utils/Monitor/MonitorMetricType.ts +16 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +60 -8
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +262 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +41 -24
- package/Utils/Telemetry/CrossSignalScope.ts +75 -4
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +20 -4
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +66 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +60 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js +2 -0
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +48 -35
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +59 -0
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +20 -6
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/SlackAPI.js +13 -10
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +745 -673
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +34 -3
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +6 -2
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js +90 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +15 -6
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +2 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/LogService.js +16 -0
- package/build/dist/Server/Services/LogService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +12 -0
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/SpanService.js +16 -0
- package/build/dist/Server/Services/SpanService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +2 -0
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +137 -164
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js +21 -13
- package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js.map +1 -1
- package/build/dist/Server/Utils/APIKey/AccessPermission.js +9 -32
- package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +87 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +449 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -0
- package/build/dist/Server/Utils/Logger.js +98 -45
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +65 -13
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +20 -3
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +27 -7
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js +29 -10
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +10 -7
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js +24 -0
- package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +311 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +366 -37
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/API/Hostname.js +63 -0
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +20 -6
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +20 -6
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
- package/build/dist/Types/Database/DatabaseProperty.js +38 -0
- package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
- package/build/dist/Types/Database/TableColumn.js +24 -6
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Events/Recurring.js +13 -1
- package/build/dist/Types/Events/Recurring.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +9 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +330 -31
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/StatusPage/SearchEngineIndexing.js +55 -0
- package/build/dist/Types/StatusPage/SearchEngineIndexing.js.map +1 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js +156 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -0
- package/build/dist/UI/Components/CardSelect/CardSelect.js +360 -40
- package/build/dist/UI/Components/CardSelect/CardSelect.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
- package/build/dist/UI/Components/Footer/Footer.js +7 -4
- package/build/dist/UI/Components/Footer/Footer.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Loader/PageLoader.js +15 -5
- package/build/dist/UI/Components/Loader/PageLoader.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +16 -3
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js +13 -1
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js +10 -2
- package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +13 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +34 -7
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +177 -0
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +23 -27
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +44 -4
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Centralized, deny-by-default redaction for everything that reaches a log
|
|
3
|
+
* sink.
|
|
4
|
+
*
|
|
5
|
+
* Every log record this process emits is written to three places: process
|
|
6
|
+
* stdout/stderr, the in-memory recent-log ring buffer that the master-admin
|
|
7
|
+
* support bundle surfaces, and the configured OpenTelemetry log exporter. A
|
|
8
|
+
* credential that reaches a log statement therefore lands in three retention
|
|
9
|
+
* systems at once, and DEBUG is a normal troubleshooting level operators turn
|
|
10
|
+
* on in production.
|
|
11
|
+
*
|
|
12
|
+
* So call sites are not trusted to be careful. Logger runs every message body
|
|
13
|
+
* and every attribute through here first, at every level, and the rules below
|
|
14
|
+
* are the single place that decides what a secret looks like. Removing a
|
|
15
|
+
* careless `logger.debug(requestBody)` is still the right fix at the call
|
|
16
|
+
* site -- this is the net underneath it.
|
|
17
|
+
*
|
|
18
|
+
* Two matching strategies, both applied:
|
|
19
|
+
*
|
|
20
|
+
* 1. Structural. Objects are walked recursively and a value is replaced
|
|
21
|
+
* whenever its KEY names a credential (`client_secret`, `access_token`,
|
|
22
|
+
* `password`, `Authorization`, ...). This is the reliable one: it does
|
|
23
|
+
* not care what the value looks like.
|
|
24
|
+
*
|
|
25
|
+
* 2. Textual. Strings are swept for credentials that were already flattened
|
|
26
|
+
* into text -- `JSON.stringify(req.body)` in a template literal, an OAuth
|
|
27
|
+
* callback URL with `?code=`, an `Authorization: Bearer` header dump -- and
|
|
28
|
+
* for values that are self-identifying regardless of key (JWTs, Slack
|
|
29
|
+
* `xoxb-` tokens, PEM private key blocks).
|
|
30
|
+
*
|
|
31
|
+
* Over-redaction is the intended failure mode. Losing a token count from a
|
|
32
|
+
* debug line costs a little context; leaking a bot token costs the workspace.
|
|
33
|
+
*/
|
|
34
|
+
export const REDACTED = "[REDACTED]";
|
|
35
|
+
// Deep enough for any real log payload, shallow enough to bound the walk.
|
|
36
|
+
const MAX_DEPTH = 12;
|
|
37
|
+
/*
|
|
38
|
+
* A key is sensitive when its normalized form (lowercased, separators
|
|
39
|
+
* stripped, so `client_secret`, `clientSecret` and `CLIENT-SECRET` all collapse
|
|
40
|
+
* to `clientsecret`) CONTAINS one of these fragments. Substring matching is
|
|
41
|
+
* deliberate: it catches `slackBotAccessToken`, `x-api-key`,
|
|
42
|
+
* `refresh_token_expires_in` and every other spelling nobody thought to list.
|
|
43
|
+
*/
|
|
44
|
+
const SENSITIVE_KEY_FRAGMENTS = [
|
|
45
|
+
"password",
|
|
46
|
+
"passwd",
|
|
47
|
+
"passphrase",
|
|
48
|
+
"secret",
|
|
49
|
+
"token",
|
|
50
|
+
"credential",
|
|
51
|
+
"authorization",
|
|
52
|
+
"cookie",
|
|
53
|
+
"apikey",
|
|
54
|
+
"privatekey",
|
|
55
|
+
"accesskey",
|
|
56
|
+
"secretkey",
|
|
57
|
+
"signingkey",
|
|
58
|
+
"encryptionkey",
|
|
59
|
+
"assertion",
|
|
60
|
+
"attestation",
|
|
61
|
+
"signature",
|
|
62
|
+
"salt",
|
|
63
|
+
"otp",
|
|
64
|
+
"jwt",
|
|
65
|
+
"bearer",
|
|
66
|
+
"sessionid",
|
|
67
|
+
"authcode",
|
|
68
|
+
"authorizationcode",
|
|
69
|
+
"verificationcode",
|
|
70
|
+
"backupcode",
|
|
71
|
+
"recoverycode",
|
|
72
|
+
"onetimecode",
|
|
73
|
+
"logincode",
|
|
74
|
+
"resetcode",
|
|
75
|
+
];
|
|
76
|
+
/*
|
|
77
|
+
* Keys that contain a sensitive fragment but never carry the secret itself.
|
|
78
|
+
* These are worth keeping: LLM token accounting and expiry timestamps are
|
|
79
|
+
* exactly the sort of thing someone turns DEBUG on to look at.
|
|
80
|
+
*/
|
|
81
|
+
const NON_SENSITIVE_KEYS = new Set([
|
|
82
|
+
"tokencount",
|
|
83
|
+
"tokencounts",
|
|
84
|
+
"tokensused",
|
|
85
|
+
"totaltokens",
|
|
86
|
+
"inputtokens",
|
|
87
|
+
"outputtokens",
|
|
88
|
+
"prompttokens",
|
|
89
|
+
"completiontokens",
|
|
90
|
+
"cachedtokens",
|
|
91
|
+
"reasoningtokens",
|
|
92
|
+
"maxtokens",
|
|
93
|
+
"tokenlimit",
|
|
94
|
+
"tokenusage",
|
|
95
|
+
"tokentype",
|
|
96
|
+
"hastoken",
|
|
97
|
+
"hasaccesstoken",
|
|
98
|
+
"hasrefreshtoken",
|
|
99
|
+
"tokenexpiresat",
|
|
100
|
+
"tokenexpiry",
|
|
101
|
+
"accesstokenexpiresat",
|
|
102
|
+
"refreshtokenexpiresat",
|
|
103
|
+
"expirestokenat",
|
|
104
|
+
"isauthorized",
|
|
105
|
+
"authorizationurl",
|
|
106
|
+
"authorizationendpoint",
|
|
107
|
+
]);
|
|
108
|
+
/*
|
|
109
|
+
* Keys whose sensitivity depends on the value. `code` is both the OAuth
|
|
110
|
+
* authorization code / TOTP code we must never log AND the `ECONNREFUSED` on
|
|
111
|
+
* every network error, so it is decided by looksLikeSecretCode below.
|
|
112
|
+
*/
|
|
113
|
+
const VALUE_DEPENDENT_KEYS = new Set(["code", "codes"]);
|
|
114
|
+
/*
|
|
115
|
+
* Keys that are always secret but carry no fragment above -- WebAuthn
|
|
116
|
+
* assertion material, mostly.
|
|
117
|
+
*/
|
|
118
|
+
const SENSITIVE_EXACT_KEYS = new Set([
|
|
119
|
+
"pin",
|
|
120
|
+
"totp",
|
|
121
|
+
"mfa",
|
|
122
|
+
"rawid",
|
|
123
|
+
"clientdatajson",
|
|
124
|
+
"authenticatordata",
|
|
125
|
+
"userhandle",
|
|
126
|
+
"challenge",
|
|
127
|
+
"twofactorsecret",
|
|
128
|
+
]);
|
|
129
|
+
export const normalizeLogKey = (key) => {
|
|
130
|
+
return key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
131
|
+
};
|
|
132
|
+
/*
|
|
133
|
+
* Error codes (`ECONNREFUSED`, `ERR_BAD_REQUEST`), exception codes
|
|
134
|
+
* (`BadDataException`) and short status-ish strings are identifiers, never
|
|
135
|
+
* credentials. Anything else under a `code` key -- digits (a TOTP), or a long
|
|
136
|
+
* opaque string with separators (an OAuth authorization code) -- is treated as
|
|
137
|
+
* a secret.
|
|
138
|
+
*/
|
|
139
|
+
const IDENTIFIER_CODE_REGEX = /^[A-Za-z][A-Za-z0-9]*$/;
|
|
140
|
+
const looksLikeSecretCode = (value) => {
|
|
141
|
+
if (typeof value === "number") {
|
|
142
|
+
// HTTP status / exit codes are small; a 6-digit TOTP is not.
|
|
143
|
+
return Math.abs(value) >= 1000;
|
|
144
|
+
}
|
|
145
|
+
if (typeof value !== "string") {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
if (value.length === 0) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return !(IDENTIFIER_CODE_REGEX.test(value) && value.length < 32);
|
|
152
|
+
};
|
|
153
|
+
export const isSensitiveLogKey = (key, value) => {
|
|
154
|
+
const normalized = normalizeLogKey(key);
|
|
155
|
+
if (!normalized) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
if (NON_SENSITIVE_KEYS.has(normalized)) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
if (SENSITIVE_EXACT_KEYS.has(normalized)) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (VALUE_DEPENDENT_KEYS.has(normalized)) {
|
|
165
|
+
return looksLikeSecretCode(value);
|
|
166
|
+
}
|
|
167
|
+
return SENSITIVE_KEY_FRAGMENTS.some((fragment) => {
|
|
168
|
+
return normalized.includes(fragment);
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
/*
|
|
172
|
+
* ---------------------------------------------------------------------------
|
|
173
|
+
* String rules
|
|
174
|
+
* ---------------------------------------------------------------------------
|
|
175
|
+
*/
|
|
176
|
+
/*
|
|
177
|
+
* Credential words as they appear INSIDE text. Kept separate from the key
|
|
178
|
+
* fragment list because a couple of the structural fragments (`salt`, `otp`)
|
|
179
|
+
* are too short to match safely against free-form prose.
|
|
180
|
+
*/
|
|
181
|
+
const TEXT_SECRET_WORDS = "password|passwd|passphrase|secret|token|credential|credentials|authorization|cookie|api[_-]?key|private[_-]?key|access[_-]?key|assertion|attestation|signature|raw[_-]?id|client[_-]?data[_-]?json|authenticator[_-]?data|user[_-]?handle|two[_-]?factor[_-]?secret";
|
|
182
|
+
// Bounded, so a long non-matching run cannot blow up on backtracking.
|
|
183
|
+
const KEY_PREFIX = "[A-Za-z0-9_.-]{0,40}";
|
|
184
|
+
const KEY_SUFFIX = "[A-Za-z0-9_.-]{0,40}";
|
|
185
|
+
const STRING_REDACTION_RULES = [
|
|
186
|
+
{
|
|
187
|
+
/*
|
|
188
|
+
* Runs first: a bare `Bearer <token>` with no key in front of it would
|
|
189
|
+
* otherwise survive every rule below.
|
|
190
|
+
*
|
|
191
|
+
* The lookahead requires the value to carry a digit or a separator, so the
|
|
192
|
+
* scheme words keep working as English -- "Basic authentication failed" and
|
|
193
|
+
* "Token exchange completed" are log lines, not credentials.
|
|
194
|
+
*/
|
|
195
|
+
name: "authorization-scheme",
|
|
196
|
+
regex: /\b(Bearer|Basic|Token)\s+(?=[A-Za-z0-9._~+/=-]*[0-9._~+/=-])[A-Za-z0-9._~+/=-]{8,}/gi,
|
|
197
|
+
replacement: `$1 ${REDACTED}`,
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
/*
|
|
201
|
+
* JSON string members: {"client_secret":"abc"} -- the shape produced by
|
|
202
|
+
* JSON.stringify(req.body) inside a log message. The value pattern allows
|
|
203
|
+
* escaped quotes so an escaped-quote-bearing password cannot end the match
|
|
204
|
+
* early and leave its tail in the clear.
|
|
205
|
+
*/
|
|
206
|
+
name: "json-string-member",
|
|
207
|
+
regex: new RegExp(`"(${KEY_PREFIX}(?:${TEXT_SECRET_WORDS})${KEY_SUFFIX})"(\\s*:\\s*)"(?:[^"\\\\]|\\\\.)*"`, "gi"),
|
|
208
|
+
replacement: `"$1"$2"${REDACTED}"`,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
// JSON numeric members: {"password":123456}
|
|
212
|
+
name: "json-number-member",
|
|
213
|
+
regex: new RegExp(`"(${KEY_PREFIX}(?:${TEXT_SECRET_WORDS})${KEY_SUFFIX})"(\\s*:\\s*)-?\\d+(?:\\.\\d+)?`, "gi"),
|
|
214
|
+
replacement: `"$1"$2"${REDACTED}"`,
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
/*
|
|
218
|
+
* Unquoted key/value text: form bodies (`client_secret=abc&...`), query
|
|
219
|
+
* strings, header dumps (`Authorization: Bearer abc`) and prose
|
|
220
|
+
* (`password: hunter2`).
|
|
221
|
+
*
|
|
222
|
+
* The value alternation tries `Bearer <token>` first, so a header dump is
|
|
223
|
+
* consumed whole -- stopping at the scheme word would leave the token
|
|
224
|
+
* itself sitting in the clear right after the placeholder.
|
|
225
|
+
*/
|
|
226
|
+
name: "key-value-text",
|
|
227
|
+
regex: new RegExp(`\\b(${KEY_PREFIX}(?:${TEXT_SECRET_WORDS})${KEY_SUFFIX})(\\s*[=:]\\s*)(?:"[^"]*"|'[^']*'|(?:Bearer|Basic|Token)\\s+[^\\s,;&)\\]}"']+|[^\\s,;&)\\]}"']+)`, "gi"),
|
|
228
|
+
replacement: `$1$2${REDACTED}`,
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
/*
|
|
232
|
+
* OAuth authorization codes and OTPs as query/form parameters. Restricted
|
|
233
|
+
* to the `code=` form so ordinary prose ("error code: ECONNREFUSED") keeps
|
|
234
|
+
* its meaning -- structural redaction covers the JSON case.
|
|
235
|
+
*/
|
|
236
|
+
name: "code-parameter",
|
|
237
|
+
regex: /\b(code|pin|otp|totp)(=)[^\s&#"'<>]+/gi,
|
|
238
|
+
replacement: `$1$2${REDACTED}`,
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
// {"code":"..."} in flattened JSON.
|
|
242
|
+
name: "json-code-member",
|
|
243
|
+
regex: /"(code|pin|otp|totp)"(\s*:\s*)"(?:[^"\\]|\\.)*"/gi,
|
|
244
|
+
replacement: `"$1"$2"${REDACTED}"`,
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "jwt",
|
|
248
|
+
regex: /\beyJ[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}/g,
|
|
249
|
+
replacement: REDACTED,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "slack-token",
|
|
253
|
+
regex: /\bxox[abeprs]-[A-Za-z0-9-]{8,}/gi,
|
|
254
|
+
replacement: REDACTED,
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: "slack-app-token",
|
|
258
|
+
regex: /\bxapp-[A-Za-z0-9-]{8,}/gi,
|
|
259
|
+
replacement: REDACTED,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
name: "github-token",
|
|
263
|
+
regex: /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}\b|\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
|
|
264
|
+
replacement: REDACTED,
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
name: "aws-access-key-id",
|
|
268
|
+
regex: /\b(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA)[0-9A-Z]{16}\b/g,
|
|
269
|
+
replacement: REDACTED,
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: "google-api-key",
|
|
273
|
+
regex: /\bAIza[0-9A-Za-z_-]{35}\b/g,
|
|
274
|
+
replacement: REDACTED,
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: "private-key-block",
|
|
278
|
+
regex: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9]+ )*PRIVATE KEY-----/g,
|
|
279
|
+
replacement: REDACTED,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
// Credentials embedded in a URL: postgres://user:password@host/db
|
|
283
|
+
name: "url-basic-auth",
|
|
284
|
+
regex: /\b([a-z][a-z0-9+.-]*:\/\/)([^\s/:@]+):[^\s/@]+@/gi,
|
|
285
|
+
replacement: `$1$2:${REDACTED}@`,
|
|
286
|
+
},
|
|
287
|
+
];
|
|
288
|
+
/*
|
|
289
|
+
* Cheap pre-filter. Almost every log line contains none of these, and skipping
|
|
290
|
+
* fifteen regexes for those keeps redaction off the cost of ordinary logging.
|
|
291
|
+
* It must stay a superset of every rule above -- a word missing here is a
|
|
292
|
+
* credential that never gets redacted.
|
|
293
|
+
*/
|
|
294
|
+
const SENSITIVE_TEXT_HINT_REGEX = new RegExp([
|
|
295
|
+
TEXT_SECRET_WORDS,
|
|
296
|
+
"code=",
|
|
297
|
+
"pin=",
|
|
298
|
+
"otp=",
|
|
299
|
+
"totp=",
|
|
300
|
+
'"code"',
|
|
301
|
+
'"pin"',
|
|
302
|
+
'"otp"',
|
|
303
|
+
'"totp"',
|
|
304
|
+
"bearer\\s",
|
|
305
|
+
"basic\\s",
|
|
306
|
+
"eyJ",
|
|
307
|
+
"xox",
|
|
308
|
+
"xapp-",
|
|
309
|
+
"gh[opusr]_",
|
|
310
|
+
"github_pat_",
|
|
311
|
+
"AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA",
|
|
312
|
+
"AIza",
|
|
313
|
+
"-----BEGIN",
|
|
314
|
+
"://",
|
|
315
|
+
].join("|"), "i");
|
|
316
|
+
export const redactLogString = (value) => {
|
|
317
|
+
if (!value) {
|
|
318
|
+
return value;
|
|
319
|
+
}
|
|
320
|
+
if (!SENSITIVE_TEXT_HINT_REGEX.test(value)) {
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
323
|
+
let redacted = value;
|
|
324
|
+
for (const rule of STRING_REDACTION_RULES) {
|
|
325
|
+
/*
|
|
326
|
+
* The rules carry the /g flag and are module-level, so lastIndex has to be
|
|
327
|
+
* reset -- String.replace does that itself, but .test() on the hint regex
|
|
328
|
+
* above and any future .test() here would not.
|
|
329
|
+
*/
|
|
330
|
+
rule.regex.lastIndex = 0;
|
|
331
|
+
redacted = redacted.replace(rule.regex, rule.replacement);
|
|
332
|
+
}
|
|
333
|
+
return redacted;
|
|
334
|
+
};
|
|
335
|
+
const redactValue = (value, depth, seen) => {
|
|
336
|
+
if (value === null || value === undefined) {
|
|
337
|
+
return value;
|
|
338
|
+
}
|
|
339
|
+
if (typeof value === "string") {
|
|
340
|
+
return redactLogString(value);
|
|
341
|
+
}
|
|
342
|
+
if (typeof value === "number" ||
|
|
343
|
+
typeof value === "boolean" ||
|
|
344
|
+
typeof value === "bigint") {
|
|
345
|
+
return value;
|
|
346
|
+
}
|
|
347
|
+
if (typeof value === "function") {
|
|
348
|
+
return "[Function]";
|
|
349
|
+
}
|
|
350
|
+
if (typeof value === "symbol") {
|
|
351
|
+
return value.toString();
|
|
352
|
+
}
|
|
353
|
+
if (value instanceof Date) {
|
|
354
|
+
return value;
|
|
355
|
+
}
|
|
356
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
|
|
357
|
+
// Buffers hold key material as often as they hold anything readable.
|
|
358
|
+
return `[Buffer ${value.length} bytes]`;
|
|
359
|
+
}
|
|
360
|
+
if (depth >= MAX_DEPTH) {
|
|
361
|
+
return "[Truncated]";
|
|
362
|
+
}
|
|
363
|
+
if (seen.has(value)) {
|
|
364
|
+
return "[Circular]";
|
|
365
|
+
}
|
|
366
|
+
seen.add(value);
|
|
367
|
+
try {
|
|
368
|
+
if (value instanceof Error) {
|
|
369
|
+
const redactedError = {
|
|
370
|
+
name: value.name,
|
|
371
|
+
message: redactLogString(value.message),
|
|
372
|
+
};
|
|
373
|
+
if (value.stack) {
|
|
374
|
+
redactedError["stack"] = redactLogString(value.stack);
|
|
375
|
+
}
|
|
376
|
+
for (const key of Object.keys(value)) {
|
|
377
|
+
redactedError[key] = isSensitiveLogKey(key, value[key])
|
|
378
|
+
? REDACTED
|
|
379
|
+
: redactValue(value[key], depth + 1, seen);
|
|
380
|
+
}
|
|
381
|
+
return redactedError;
|
|
382
|
+
}
|
|
383
|
+
if (Array.isArray(value)) {
|
|
384
|
+
return value.map((item) => {
|
|
385
|
+
return redactValue(item, depth + 1, seen);
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
if (value instanceof Map) {
|
|
389
|
+
const fromMap = {};
|
|
390
|
+
for (const [mapKey, mapValue] of value.entries()) {
|
|
391
|
+
const keyAsString = String(mapKey);
|
|
392
|
+
fromMap[keyAsString] = isSensitiveLogKey(keyAsString, mapValue)
|
|
393
|
+
? REDACTED
|
|
394
|
+
: redactValue(mapValue, depth + 1, seen);
|
|
395
|
+
}
|
|
396
|
+
return fromMap;
|
|
397
|
+
}
|
|
398
|
+
if (value instanceof Set) {
|
|
399
|
+
return Array.from(value).map((item) => {
|
|
400
|
+
return redactValue(item, depth + 1, seen);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
/*
|
|
404
|
+
* Models, ObjectIDs and the other Common types serialize through toJSON.
|
|
405
|
+
* Honouring it keeps redacted output shaped exactly like what
|
|
406
|
+
* JSON.stringify would have produced without this pass.
|
|
407
|
+
*/
|
|
408
|
+
const maybeToJSON = value["toJSON"];
|
|
409
|
+
if (typeof maybeToJSON === "function") {
|
|
410
|
+
try {
|
|
411
|
+
const json = maybeToJSON.call(value);
|
|
412
|
+
if (json !== value) {
|
|
413
|
+
return redactValue(json, depth, seen);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
catch (_a) {
|
|
417
|
+
// Fall through to the plain-object walk below.
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const redactedObject = {};
|
|
421
|
+
for (const key of Object.keys(value)) {
|
|
422
|
+
const propertyValue = value[key];
|
|
423
|
+
redactedObject[key] = isSensitiveLogKey(key, propertyValue)
|
|
424
|
+
? REDACTED
|
|
425
|
+
: redactValue(propertyValue, depth + 1, seen);
|
|
426
|
+
}
|
|
427
|
+
return redactedObject;
|
|
428
|
+
}
|
|
429
|
+
finally {
|
|
430
|
+
/*
|
|
431
|
+
* Only the path currently being walked is "seen", so a value referenced
|
|
432
|
+
* twice in a tree is redacted twice instead of being reported as circular.
|
|
433
|
+
*/
|
|
434
|
+
seen.delete(value);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
export const redactLogValue = (value) => {
|
|
438
|
+
try {
|
|
439
|
+
return redactValue(value, 0, new Set());
|
|
440
|
+
}
|
|
441
|
+
catch (_a) {
|
|
442
|
+
/*
|
|
443
|
+
* A getter that throws, an exotic proxy... nothing here is worth crashing
|
|
444
|
+
* a log call for, but the body cannot be passed through unredacted either.
|
|
445
|
+
*/
|
|
446
|
+
return REDACTED;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
//# sourceMappingURL=LogRedaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogRedaction.js","sourceRoot":"","sources":["../../../../Server/Utils/LogRedaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import TelemetryContext from "./Telemetry/TelemetryContext";
|
|
|
4
4
|
import { SeverityNumber } from "@opentelemetry/api-logs";
|
|
5
5
|
import Exception from "../../Types/Exception/Exception";
|
|
6
6
|
import ConfigLogLevel from "../Types/ConfigLogLevel";
|
|
7
|
+
import { REDACTED, isSensitiveLogKey, redactLogString, redactLogValue, } from "./LogRedaction";
|
|
7
8
|
export function getLogAttributesFromRequest(req) {
|
|
8
9
|
var _a;
|
|
9
10
|
if (!req) {
|
|
@@ -27,9 +28,10 @@ export function getLogAttributesFromRequest(req) {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
class logger {
|
|
31
|
+
// `body` has already been through redactBody -- see the level methods.
|
|
30
32
|
static record(level, body) {
|
|
31
33
|
try {
|
|
32
|
-
const message = this.
|
|
34
|
+
const message = this.serializeRedactedBody(body);
|
|
33
35
|
this.recentLogs.push({
|
|
34
36
|
time: new Date().toISOString(),
|
|
35
37
|
level: level,
|
|
@@ -64,14 +66,66 @@ class logger {
|
|
|
64
66
|
}
|
|
65
67
|
return LogLevel;
|
|
66
68
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
/*
|
|
70
|
+
* Turns a body into a redacted copy, once, before it is handed to any sink.
|
|
71
|
+
* Every level method calls this and then passes the RESULT to console, to
|
|
72
|
+
* the recent-log buffer and to telemetry, so a log record is redacted a
|
|
73
|
+
* single time no matter how many places it ends up in.
|
|
74
|
+
*
|
|
75
|
+
* Objects come back as plain redacted copies, so console keeps printing them
|
|
76
|
+
* as objects rather than as a JSON string.
|
|
77
|
+
*
|
|
78
|
+
* Errors are special-cased: when nothing in the message or the stack needed
|
|
79
|
+
* redacting -- the overwhelmingly common case -- the original Error is
|
|
80
|
+
* returned untouched, so console still renders a real stack trace.
|
|
81
|
+
*/
|
|
82
|
+
static redactBody(body) {
|
|
83
|
+
try {
|
|
84
|
+
if (typeof body === "string") {
|
|
85
|
+
return redactLogString(body);
|
|
86
|
+
}
|
|
87
|
+
if (body instanceof Exception || body instanceof Error) {
|
|
88
|
+
const originalStack = body.stack || "";
|
|
89
|
+
const message = redactLogString(body.message);
|
|
90
|
+
const stack = redactLogString(originalStack);
|
|
91
|
+
if (message === body.message && stack === originalStack) {
|
|
92
|
+
return body;
|
|
93
|
+
}
|
|
94
|
+
return stack || `${body.name}: ${message}`;
|
|
95
|
+
}
|
|
96
|
+
return redactLogValue(body);
|
|
97
|
+
}
|
|
98
|
+
catch (_a) {
|
|
99
|
+
// Never pass on a body we could not prove was redacted.
|
|
100
|
+
return REDACTED;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Serialization only. The body must already have been through redactBody.
|
|
104
|
+
static serializeRedactedBody(body) {
|
|
105
|
+
try {
|
|
106
|
+
if (typeof body === "string") {
|
|
107
|
+
return body;
|
|
108
|
+
}
|
|
109
|
+
else if (body instanceof Exception || body instanceof Error) {
|
|
110
|
+
return body.message;
|
|
111
|
+
}
|
|
112
|
+
/*
|
|
113
|
+
* redactBody swept every string inside this copy already, so stringifying
|
|
114
|
+
* it needs no second textual pass.
|
|
115
|
+
*/
|
|
116
|
+
const serialized = JSON.stringify(body);
|
|
117
|
+
return serialized === undefined ? "" : serialized;
|
|
70
118
|
}
|
|
71
|
-
|
|
72
|
-
return
|
|
119
|
+
catch (_a) {
|
|
120
|
+
return REDACTED;
|
|
73
121
|
}
|
|
74
|
-
|
|
122
|
+
}
|
|
123
|
+
/*
|
|
124
|
+
* Redacts and serializes in one step, for callers outside the level methods
|
|
125
|
+
* that hold a raw body.
|
|
126
|
+
*/
|
|
127
|
+
static serializeLogBody(body) {
|
|
128
|
+
return this.serializeRedactedBody(this.redactBody(body));
|
|
75
129
|
}
|
|
76
130
|
static sanitizeAttributes(attributes) {
|
|
77
131
|
if (!attributes) {
|
|
@@ -81,7 +135,17 @@ class logger {
|
|
|
81
135
|
const sanitized = {};
|
|
82
136
|
for (const key in attributes) {
|
|
83
137
|
const value = attributes[key];
|
|
84
|
-
if (value
|
|
138
|
+
if (value === undefined || value === null) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Attributes are a log sink too, and they travel to telemetry verbatim.
|
|
142
|
+
if (isSensitiveLogKey(key, value)) {
|
|
143
|
+
sanitized[key] = REDACTED;
|
|
144
|
+
}
|
|
145
|
+
else if (typeof value === "string") {
|
|
146
|
+
sanitized[key] = redactLogString(value);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
85
149
|
sanitized[key] = value;
|
|
86
150
|
}
|
|
87
151
|
}
|
|
@@ -94,14 +158,11 @@ class logger {
|
|
|
94
158
|
static info(message, attributes) {
|
|
95
159
|
const logLevel = this.getLogLevel();
|
|
96
160
|
if (logLevel === ConfigLogLevel.DEBUG || logLevel === ConfigLogLevel.INFO) {
|
|
161
|
+
const body = this.redactBody(message);
|
|
97
162
|
// eslint-disable-next-line no-console
|
|
98
|
-
console.info(
|
|
99
|
-
this.record("INFO",
|
|
100
|
-
this.
|
|
101
|
-
body: message,
|
|
102
|
-
severityNumber: SeverityNumber.INFO,
|
|
103
|
-
attributes,
|
|
104
|
-
});
|
|
163
|
+
console.info(body);
|
|
164
|
+
this.record("INFO", body);
|
|
165
|
+
this.emitRedacted(body, SeverityNumber.INFO, attributes);
|
|
105
166
|
}
|
|
106
167
|
}
|
|
107
168
|
static error(message, attributes) {
|
|
@@ -110,14 +171,11 @@ class logger {
|
|
|
110
171
|
logLevel === ConfigLogLevel.INFO ||
|
|
111
172
|
logLevel === ConfigLogLevel.WARN ||
|
|
112
173
|
logLevel === ConfigLogLevel.ERROR) {
|
|
174
|
+
const body = this.redactBody(message);
|
|
113
175
|
// eslint-disable-next-line no-console
|
|
114
|
-
console.error(
|
|
115
|
-
this.record("ERROR",
|
|
116
|
-
this.
|
|
117
|
-
body: message,
|
|
118
|
-
severityNumber: SeverityNumber.ERROR,
|
|
119
|
-
attributes,
|
|
120
|
-
});
|
|
176
|
+
console.error(body);
|
|
177
|
+
this.record("ERROR", body);
|
|
178
|
+
this.emitRedacted(body, SeverityNumber.ERROR, attributes);
|
|
121
179
|
}
|
|
122
180
|
}
|
|
123
181
|
static warn(message, attributes) {
|
|
@@ -125,30 +183,28 @@ class logger {
|
|
|
125
183
|
if (logLevel === ConfigLogLevel.DEBUG ||
|
|
126
184
|
logLevel === ConfigLogLevel.INFO ||
|
|
127
185
|
logLevel === ConfigLogLevel.WARN) {
|
|
186
|
+
const body = this.redactBody(message);
|
|
128
187
|
// eslint-disable-next-line no-console
|
|
129
|
-
console.warn(
|
|
130
|
-
this.record("WARN",
|
|
131
|
-
this.
|
|
132
|
-
body: message,
|
|
133
|
-
severityNumber: SeverityNumber.WARN,
|
|
134
|
-
attributes,
|
|
135
|
-
});
|
|
188
|
+
console.warn(body);
|
|
189
|
+
this.record("WARN", body);
|
|
190
|
+
this.emitRedacted(body, SeverityNumber.WARN, attributes);
|
|
136
191
|
}
|
|
137
192
|
}
|
|
138
193
|
static debug(message, attributes) {
|
|
139
194
|
const logLevel = this.getLogLevel();
|
|
140
195
|
if (logLevel === ConfigLogLevel.DEBUG) {
|
|
196
|
+
const body = this.redactBody(message);
|
|
141
197
|
// eslint-disable-next-line no-console
|
|
142
|
-
console.debug(
|
|
143
|
-
this.record("DEBUG",
|
|
144
|
-
this.
|
|
145
|
-
body: message,
|
|
146
|
-
severityNumber: SeverityNumber.DEBUG,
|
|
147
|
-
attributes,
|
|
148
|
-
});
|
|
198
|
+
console.debug(body);
|
|
199
|
+
this.record("DEBUG", body);
|
|
200
|
+
this.emitRedacted(body, SeverityNumber.DEBUG, attributes);
|
|
149
201
|
}
|
|
150
202
|
}
|
|
151
203
|
static emit(data) {
|
|
204
|
+
this.emitRedacted(this.redactBody(data.body), data.severityNumber, data.attributes);
|
|
205
|
+
}
|
|
206
|
+
// `body` must already have been through redactBody.
|
|
207
|
+
static emitRedacted(body, severityNumber, attributes) {
|
|
152
208
|
try {
|
|
153
209
|
const logger = OneUptimeTelemetry.getLogger();
|
|
154
210
|
if (logger === null) {
|
|
@@ -159,9 +215,9 @@ class logger {
|
|
|
159
215
|
* monitorId, requestId, ...) into every log record. Attributes passed
|
|
160
216
|
* explicitly to the log call take precedence over the ambient context.
|
|
161
217
|
*/
|
|
162
|
-
const mergedAttributes = Object.assign(Object.assign({}, TelemetryContext.getAttributes()), (
|
|
218
|
+
const mergedAttributes = Object.assign(Object.assign({}, TelemetryContext.getAttributes()), (attributes || {}));
|
|
163
219
|
const sanitizedAttributes = this.sanitizeAttributes(mergedAttributes);
|
|
164
|
-
logger.emit(Object.assign({ body: this.
|
|
220
|
+
logger.emit(Object.assign({ body: this.serializeRedactedBody(body), severityNumber: severityNumber }, (sanitizedAttributes ? { attributes: sanitizedAttributes } : {})));
|
|
165
221
|
}
|
|
166
222
|
catch (_a) {
|
|
167
223
|
// Never let logging errors propagate
|
|
@@ -170,14 +226,11 @@ class logger {
|
|
|
170
226
|
static trace(message, attributes) {
|
|
171
227
|
const logLevel = this.getLogLevel();
|
|
172
228
|
if (logLevel === ConfigLogLevel.DEBUG) {
|
|
229
|
+
const body = this.redactBody(message);
|
|
173
230
|
// eslint-disable-next-line no-console
|
|
174
|
-
console.trace(
|
|
175
|
-
this.record("TRACE",
|
|
176
|
-
this.
|
|
177
|
-
body: message,
|
|
178
|
-
severityNumber: SeverityNumber.DEBUG,
|
|
179
|
-
attributes,
|
|
180
|
-
});
|
|
231
|
+
console.trace(body);
|
|
232
|
+
this.record("TRACE", body);
|
|
233
|
+
this.emitRedacted(body, SeverityNumber.DEBUG, attributes);
|
|
181
234
|
}
|
|
182
235
|
}
|
|
183
236
|
}
|