chron-mcp 0.1.14 → 0.1.17
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/README.md +305 -0
- package/dashboards/logscale/README.md +121 -0
- package/dashboards/sentinel/README.md +123 -0
- package/dashboards/sentinel/ai-tool-usage.kql +7 -0
- package/dashboards/sentinel/daily-active-developers.kql +6 -0
- package/dashboards/sentinel/events-by-type.kql +5 -0
- package/dashboards/sentinel/secrets-alert.kql +7 -0
- package/dashboards/sentinel/secrets-detected.kql +7 -0
- package/dashboards/sentinel/sessions-by-developer.kql +6 -0
- package/dashboards/splunk/README.md +138 -0
- package/dashboards/splunk/ai-tool-usage.spl +3 -0
- package/dashboards/splunk/daily-active-developers.spl +2 -0
- package/dashboards/splunk/events-by-type.spl +2 -0
- package/dashboards/splunk/secrets-alert.spl +3 -0
- package/dashboards/splunk/secrets-detected.spl +4 -0
- package/dashboards/splunk/sessions-by-developer.spl +3 -0
- package/dist/cli/index.js +300 -3
- package/dist/index.js +180 -38
- package/package.json +1 -1
- package/skills/chron/SKILL.md +8 -1
- package/skills/chron.skill.md +7 -0
package/README.md
CHANGED
|
@@ -24,6 +24,8 @@ Chron fixes that. Every exchange is logged with a precise local datetime (includ
|
|
|
24
24
|
|
|
25
25
|
## Install
|
|
26
26
|
|
|
27
|
+
**MCP server** (for Claude Desktop, Claude Code, Cursor, Windsurf):
|
|
28
|
+
|
|
27
29
|
Add to your AI tool's MCP config:
|
|
28
30
|
|
|
29
31
|
```json
|
|
@@ -37,10 +39,46 @@ Add to your AI tool's MCP config:
|
|
|
37
39
|
}
|
|
38
40
|
```
|
|
39
41
|
|
|
42
|
+
**CLI** (for `chron history`, `chron connect`, `chron export`, etc.):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install -g chron-mcp
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
> `npx chron-mcp` starts the MCP server only — it does not put the `chron` CLI command in your PATH. You need a global install for the CLI.
|
|
49
|
+
|
|
40
50
|
First run creates `~/.chron/chron.db` automatically. No database setup, no env vars, no migrations.
|
|
41
51
|
|
|
42
52
|
---
|
|
43
53
|
|
|
54
|
+
## CLI
|
|
55
|
+
|
|
56
|
+
After `npm install -g chron-mcp`, the `chron` command is available globally:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Usage: chron <command> [options]
|
|
60
|
+
|
|
61
|
+
Commands:
|
|
62
|
+
history List sessions or show full log for a session
|
|
63
|
+
report Aggregate audit stats across sessions
|
|
64
|
+
export Export a session as markdown
|
|
65
|
+
secrets List detected secrets across sessions
|
|
66
|
+
settings View current configuration
|
|
67
|
+
connect Connect to a SIEM integration (crowdstrike, sentinel, splunk)
|
|
68
|
+
|
|
69
|
+
Options (history):
|
|
70
|
+
--limit=<n> Max sessions to show (default: 20)
|
|
71
|
+
<id-prefix> Show full log for the session with this ID prefix
|
|
72
|
+
|
|
73
|
+
Options (report):
|
|
74
|
+
--since=<range> Filter by date: 7d, 30d, or YYYY-MM-DD (default: all time)
|
|
75
|
+
|
|
76
|
+
Options (export / secrets):
|
|
77
|
+
<id-prefix> Scope to a single session
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
44
82
|
## What it logs
|
|
45
83
|
|
|
46
84
|
Every exchange is recorded with precise local timestamps — user message when received, assistant response when sent:
|
|
@@ -173,6 +211,261 @@ This turns your local log into a verifiable audit artifact. Any edit to a stored
|
|
|
173
211
|
|
|
174
212
|
---
|
|
175
213
|
|
|
214
|
+
## CrowdStrike LogScale integration
|
|
215
|
+
|
|
216
|
+
Stream AI session telemetry directly from developer machines into your CrowdStrike LogScale repository. No relay service — events go straight to your own LogScale instance.
|
|
217
|
+
|
|
218
|
+
**What gets sent:** session starts, message counts (role only), and masked credential detections. Message content never leaves the machine.
|
|
219
|
+
|
|
220
|
+
### Setup
|
|
221
|
+
|
|
222
|
+
**1. Create a LogScale repository and ingest token**
|
|
223
|
+
|
|
224
|
+
In Falcon console → **Log Management** → **Repositories** → **New repository** (name it `ChronAIEvents`).
|
|
225
|
+
Then **Settings** → **API Tokens** → **Add token** → select **Ingest** permission → copy the token.
|
|
226
|
+
|
|
227
|
+
Your ingest URL follows this pattern:
|
|
228
|
+
```
|
|
229
|
+
https://<your-cluster>.humio.com/api/v1/ingest/humio-structured
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**2. Install the CLI and run the onboarding wizard**
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
npm install -g chron-mcp
|
|
236
|
+
chron connect crowdstrike
|
|
237
|
+
# Paste your ingest URL and token when prompted
|
|
238
|
+
# The wizard sends a test event and confirms before saving
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**3. Add env vars to your MCP client config**
|
|
242
|
+
|
|
243
|
+
The wizard prints the exact block to paste. For Claude Code, add to the `chron` entry in `~/.claude.json`:
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"mcpServers": {
|
|
248
|
+
"chron": {
|
|
249
|
+
"command": "npx",
|
|
250
|
+
"args": ["-y", "chron-mcp"],
|
|
251
|
+
"env": {
|
|
252
|
+
"CHRON_LOGSCALE_URL": "https://<your-cluster>.humio.com/api/v1/ingest/humio-structured",
|
|
253
|
+
"CHRON_LOGSCALE_TOKEN": "<your-ingest-token>"
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Restart your AI tool to pick up the new env vars.
|
|
261
|
+
|
|
262
|
+
**4. Import the pre-built dashboard**
|
|
263
|
+
|
|
264
|
+
In Falcon → **Log Management** → **Dashboards** → **Import**:
|
|
265
|
+
```
|
|
266
|
+
node_modules/chron-mcp/dashboards/logscale/chron-ai-activity.yaml
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Full guide with SOC alert setup: [dashboards/logscale/README.md](dashboards/logscale/README.md)
|
|
270
|
+
|
|
271
|
+
### Env vars
|
|
272
|
+
|
|
273
|
+
| Env var | Description |
|
|
274
|
+
|---|---|
|
|
275
|
+
| `CHRON_LOGSCALE_URL` | LogScale ingest endpoint |
|
|
276
|
+
| `CHRON_LOGSCALE_TOKEN` | LogScale ingest token |
|
|
277
|
+
|
|
278
|
+
Both must be set for events to flow. If unset, the integration is silently disabled.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Splunk integration
|
|
283
|
+
|
|
284
|
+
Stream AI session telemetry into Splunk via HTTP Event Collector (HEC). Works with Splunk Enterprise, Splunk Cloud, and a local Docker instance.
|
|
285
|
+
|
|
286
|
+
**What gets sent:** session starts, message counts (role only), and masked credential detections. Message content never leaves the machine.
|
|
287
|
+
|
|
288
|
+
### Setup
|
|
289
|
+
|
|
290
|
+
**Option A — Local Docker (fastest, no account needed)**
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Start a local Splunk instance (Apple Silicon: --platform linux/amd64 is required)
|
|
294
|
+
docker run -d --name splunk-chron \
|
|
295
|
+
--platform linux/amd64 \
|
|
296
|
+
-p 8000:8000 -p 8088:8088 \
|
|
297
|
+
-e SPLUNK_START_ARGS=--accept-license \
|
|
298
|
+
-e SPLUNK_GENERAL_TERMS=--accept-sgt-current-at-splunk-com \
|
|
299
|
+
-e SPLUNK_PASSWORD=Admin1234! \
|
|
300
|
+
-e SPLUNK_HEC_TOKEN=chron-test-token \
|
|
301
|
+
splunk/splunk:latest
|
|
302
|
+
|
|
303
|
+
# Wait ~2 minutes, then watch until ready:
|
|
304
|
+
docker logs -f splunk-chron 2>&1 | grep -i "Ansible playbook complete"
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Option B — Splunk Enterprise or Cloud**
|
|
308
|
+
|
|
309
|
+
Settings → **Data Inputs** → **HTTP Event Collector** → **New Token** → name it `chron-ingest` → source type `chron:event` → copy the token.
|
|
310
|
+
|
|
311
|
+
**2. Install the CLI and run the onboarding wizard**
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
npm install -g chron-mcp
|
|
315
|
+
chron connect splunk
|
|
316
|
+
# For local Docker: URL = https://localhost:8088, Token = chron-test-token
|
|
317
|
+
# TLS verification is skipped automatically for localhost (self-signed cert)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**3. Add env vars to your MCP client config**
|
|
321
|
+
|
|
322
|
+
The wizard prints the exact block to paste. For Claude Code, add to `~/.claude.json`:
|
|
323
|
+
|
|
324
|
+
```json
|
|
325
|
+
{
|
|
326
|
+
"mcpServers": {
|
|
327
|
+
"chron": {
|
|
328
|
+
"command": "npx",
|
|
329
|
+
"args": ["-y", "chron-mcp"],
|
|
330
|
+
"env": {
|
|
331
|
+
"CHRON_SPLUNK_URL": "https://localhost:8088",
|
|
332
|
+
"CHRON_SPLUNK_TOKEN": "chron-test-token",
|
|
333
|
+
"CHRON_SPLUNK_INSECURE": "1"
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
> Remove `CHRON_SPLUNK_INSECURE` for production Splunk instances with valid TLS certificates.
|
|
341
|
+
|
|
342
|
+
Restart your AI tool to pick up the new env vars.
|
|
343
|
+
|
|
344
|
+
**4. Search in Splunk**
|
|
345
|
+
|
|
346
|
+
Open [http://localhost:8000](http://localhost:8000) → **Search & Reporting** → run:
|
|
347
|
+
```
|
|
348
|
+
sourcetype="chron:event"
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Events appear in real time as you have AI conversations.
|
|
352
|
+
|
|
353
|
+
Full guide with dashboard templates and alert setup: [dashboards/splunk/README.md](dashboards/splunk/README.md)
|
|
354
|
+
|
|
355
|
+
### Env vars
|
|
356
|
+
|
|
357
|
+
| Env var | Description |
|
|
358
|
+
|---|---|
|
|
359
|
+
| `CHRON_SPLUNK_URL` | Splunk HEC base URL, e.g. `https://localhost:8088` or `https://your-host:8088` |
|
|
360
|
+
| `CHRON_SPLUNK_TOKEN` | HEC ingest token |
|
|
361
|
+
| `CHRON_SPLUNK_INSECURE` | Set to `1` to skip TLS verification (local Docker with self-signed cert) |
|
|
362
|
+
|
|
363
|
+
`CHRON_SPLUNK_URL` and `CHRON_SPLUNK_TOKEN` must both be set for events to flow.
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Microsoft Sentinel integration
|
|
368
|
+
|
|
369
|
+
Stream AI session telemetry into your Microsoft Sentinel workspace via the Azure Monitor Logs Ingestion API. Events go directly from developer machines to your own Log Analytics workspace — no relay service.
|
|
370
|
+
|
|
371
|
+
**What gets sent:** session starts, message counts (role only), and masked credential detections. Message content never leaves the machine.
|
|
372
|
+
|
|
373
|
+
### Setup
|
|
374
|
+
|
|
375
|
+
**1. Register an Azure App**
|
|
376
|
+
|
|
377
|
+
Azure Portal → **Azure Active Directory** → **App registrations** → **New registration** → name it `chron-ingest`.
|
|
378
|
+
Note the **Application (client) ID** and **Directory (tenant) ID**.
|
|
379
|
+
Go to **Certificates & secrets** → **New client secret** → copy the value immediately.
|
|
380
|
+
|
|
381
|
+
**2. Create a custom table in Log Analytics**
|
|
382
|
+
|
|
383
|
+
Open your Log Analytics workspace → **Tables** → **Create** → **New custom log (DCR-based)** → name it `ChronEvents_CL`.
|
|
384
|
+
|
|
385
|
+
Add these columns (in addition to the auto-added `TimeGenerated`):
|
|
386
|
+
|
|
387
|
+
| Column | Type |
|
|
388
|
+
|---|---|
|
|
389
|
+
| `EventType` | string |
|
|
390
|
+
| `SessionIdPrefix` | string |
|
|
391
|
+
| `AiTool` | string |
|
|
392
|
+
| `OS` | string |
|
|
393
|
+
| `ChronVersion` | string |
|
|
394
|
+
| `Computer` | string |
|
|
395
|
+
| `Role` | string |
|
|
396
|
+
| `DetectionType` | string |
|
|
397
|
+
| `MaskedValue` | string |
|
|
398
|
+
|
|
399
|
+
The wizard creates a **Data Collection Endpoint (DCE)** and **Data Collection Rule (DCR)** — note both.
|
|
400
|
+
|
|
401
|
+
**3. Grant the App ingest permission**
|
|
402
|
+
|
|
403
|
+
Open the DCR → **Access control (IAM)** → **Add role assignment** → Role: **Monitoring Metrics Publisher** → Member: the `chron-ingest` app.
|
|
404
|
+
|
|
405
|
+
**4. Get the DCR Immutable ID**
|
|
406
|
+
|
|
407
|
+
Open the DCR → **Overview** → **JSON view** → copy the `immutableId` field (starts with `dcr-`).
|
|
408
|
+
|
|
409
|
+
**5. Install the CLI and run the onboarding wizard**
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
npm install -g chron-mcp
|
|
413
|
+
chron connect sentinel
|
|
414
|
+
# Enter tenant ID, client ID, client secret, DCE URL, DCR immutable ID, and stream name
|
|
415
|
+
# The wizard authenticates with Azure AD and sends a test event before saving
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**6. Add env vars to your MCP client config**
|
|
419
|
+
|
|
420
|
+
The wizard prints the exact block to paste. For Claude Code, add to `~/.claude.json`:
|
|
421
|
+
|
|
422
|
+
```json
|
|
423
|
+
{
|
|
424
|
+
"mcpServers": {
|
|
425
|
+
"chron": {
|
|
426
|
+
"command": "npx",
|
|
427
|
+
"args": ["-y", "chron-mcp"],
|
|
428
|
+
"env": {
|
|
429
|
+
"CHRON_SENTINEL_TENANT_ID": "<your-tenant-id>",
|
|
430
|
+
"CHRON_SENTINEL_CLIENT_ID": "<your-client-id>",
|
|
431
|
+
"CHRON_SENTINEL_CLIENT_SECRET": "<your-client-secret>",
|
|
432
|
+
"CHRON_SENTINEL_DCE": "https://<your-dce>.ingest.monitor.azure.com",
|
|
433
|
+
"CHRON_SENTINEL_DCR_ID": "dcr-<your-immutable-id>",
|
|
434
|
+
"CHRON_SENTINEL_STREAM": "Custom-ChronEvents_CL"
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Restart your AI tool to pick up the new env vars.
|
|
442
|
+
|
|
443
|
+
**7. Query in Sentinel**
|
|
444
|
+
|
|
445
|
+
Sentinel → **Logs** → paste any query from `dashboards/sentinel/`:
|
|
446
|
+
```kql
|
|
447
|
+
ChronEvents_CL
|
|
448
|
+
| where TimeGenerated > ago(24h)
|
|
449
|
+
| summarize count() by EventType, AiTool
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Full guide with KQL queries and alert rule setup: [dashboards/sentinel/README.md](dashboards/sentinel/README.md)
|
|
453
|
+
|
|
454
|
+
### Env vars
|
|
455
|
+
|
|
456
|
+
| Env var | Description |
|
|
457
|
+
|---|---|
|
|
458
|
+
| `CHRON_SENTINEL_TENANT_ID` | Azure AD tenant ID |
|
|
459
|
+
| `CHRON_SENTINEL_CLIENT_ID` | App Registration client ID |
|
|
460
|
+
| `CHRON_SENTINEL_CLIENT_SECRET` | App Registration client secret |
|
|
461
|
+
| `CHRON_SENTINEL_DCE` | Data Collection Endpoint URL |
|
|
462
|
+
| `CHRON_SENTINEL_DCR_ID` | DCR Immutable ID (starts with `dcr-`) |
|
|
463
|
+
| `CHRON_SENTINEL_STREAM` | Stream name, e.g. `Custom-ChronEvents_CL` |
|
|
464
|
+
|
|
465
|
+
All six must be set for events to flow. Token refresh is automatic (1-hour Azure AD tokens, refreshed 60s before expiry).
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
176
469
|
## Configuration
|
|
177
470
|
|
|
178
471
|
| Env var | Default | Description |
|
|
@@ -181,6 +474,18 @@ This turns your local log into a verifiable audit artifact. Any edit to a stored
|
|
|
181
474
|
| `CHRON_TRANSPORT` | `stdio` | Set to `http` to enable HTTP+SSE mode |
|
|
182
475
|
| `CHRON_API_KEY` | _(none)_ | Bearer token for HTTP mode |
|
|
183
476
|
| `PORT` | `3001` | Port for HTTP mode |
|
|
477
|
+
| `CHRON_LOGSCALE_URL` | _(none)_ | LogScale ingest endpoint (enables CrowdStrike integration) |
|
|
478
|
+
| `CHRON_LOGSCALE_TOKEN` | _(none)_ | LogScale ingest token |
|
|
479
|
+
| `CHRON_SENTINEL_TENANT_ID` | _(none)_ | Azure AD tenant ID (enables Sentinel integration) |
|
|
480
|
+
| `CHRON_SENTINEL_CLIENT_ID` | _(none)_ | App Registration client ID |
|
|
481
|
+
| `CHRON_SENTINEL_CLIENT_SECRET` | _(none)_ | App Registration client secret |
|
|
482
|
+
| `CHRON_SENTINEL_DCE` | _(none)_ | Data Collection Endpoint URL |
|
|
483
|
+
| `CHRON_SENTINEL_DCR_ID` | _(none)_ | DCR Immutable ID |
|
|
484
|
+
| `CHRON_SENTINEL_STREAM` | _(none)_ | Stream name (e.g. `Custom-ChronEvents_CL`) |
|
|
485
|
+
| `CHRON_SPLUNK_URL` | _(none)_ | Splunk HEC base URL (enables Splunk integration) |
|
|
486
|
+
| `CHRON_SPLUNK_TOKEN` | _(none)_ | Splunk HEC ingest token |
|
|
487
|
+
| `CHRON_RELAY_URL` | _(none)_ | Generic relay endpoint (any SIEM or webhook) |
|
|
488
|
+
| `CHRON_RELAY_TOKEN` | _(none)_ | Bearer token for generic relay |
|
|
184
489
|
|
|
185
490
|
---
|
|
186
491
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Chron → CrowdStrike LogScale
|
|
2
|
+
|
|
3
|
+
Stream AI session telemetry directly from developer machines into your CrowdStrike LogScale repository. No relay service, no data routed through Chron infrastructure — events go from the developer's machine straight to your own LogScale instance.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- CrowdStrike Falcon with **LogScale / Next-Gen SIEM** access
|
|
8
|
+
- Admin access to create a LogScale repository and ingest token
|
|
9
|
+
|
|
10
|
+
## Step 1 — Create a LogScale repository
|
|
11
|
+
|
|
12
|
+
1. Open Falcon console → **Log Management** → **Repositories**
|
|
13
|
+
2. Click **New repository** → name it `ChronAIEvents` (or any name)
|
|
14
|
+
3. Go to **Settings** → **API Tokens** → **Add token**
|
|
15
|
+
4. Select **Ingest** permission, name it `chron-ingest`, copy the token
|
|
16
|
+
|
|
17
|
+
## Step 2 — Get your cluster URL
|
|
18
|
+
|
|
19
|
+
Your LogScale ingest URL follows this pattern:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
https://<your-cluster>.humio.com/api/v1/ingest/humio-structured
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Common cluster URLs:
|
|
26
|
+
- US: `https://cloud.us.humio.com/api/v1/ingest/humio-structured`
|
|
27
|
+
- EU: `https://cloud.humio.com/api/v1/ingest/humio-structured`
|
|
28
|
+
|
|
29
|
+
Your exact URL is visible in Falcon under **Log Management → Repositories → <your repo> → Ingest API**.
|
|
30
|
+
|
|
31
|
+
## Step 3 — Connect from the developer machine
|
|
32
|
+
|
|
33
|
+
Run the onboarding command:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
chron connect crowdstrike
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Paste the ingest URL and token when prompted. The command sends a test event and confirms the connection before saving.
|
|
40
|
+
|
|
41
|
+
## Step 4 — Add env vars to your MCP client
|
|
42
|
+
|
|
43
|
+
The `connect` command prints the exact block to paste. For Claude Code, add to the `chron` entry in `~/.claude.json`:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"chron": {
|
|
49
|
+
"type": "stdio",
|
|
50
|
+
"command": "node",
|
|
51
|
+
"args": ["/path/to/dist/index.js"],
|
|
52
|
+
"env": {
|
|
53
|
+
"CHRON_LOGSCALE_URL": "https://<your-cluster>.humio.com/api/v1/ingest/humio-structured",
|
|
54
|
+
"CHRON_LOGSCALE_TOKEN": "<your-ingest-token>"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For org-wide rollout, push these env vars via MDM (Jamf, Intune, etc.) instead of configuring each machine individually.
|
|
62
|
+
|
|
63
|
+
## Step 5 — Import the dashboard
|
|
64
|
+
|
|
65
|
+
In Falcon console → **Log Management** → **Dashboards** → **Import**:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
node_modules/chron-mcp/dashboards/logscale/chron-ai-activity.yaml
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The dashboard includes five widgets:
|
|
72
|
+
- **Daily Active Developers** — distinct machines with AI sessions per day
|
|
73
|
+
- **AI Tool Usage** — breakdown by tool (Claude, Cursor, Windsurf, etc.)
|
|
74
|
+
- **Secrets Detected by Type** — credential exposures over time
|
|
75
|
+
- **Sessions by Developer** — per-machine session count with AI tool
|
|
76
|
+
- **Credential Exposures** — full table of api_key, jwt, aws_key detections for SOC review
|
|
77
|
+
|
|
78
|
+
## Step 6 — Set up the API key alert (optional)
|
|
79
|
+
|
|
80
|
+
In LogScale, create a **Scheduled Search** using `api-key-alert.lql`:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
event_type = "secret_detected"
|
|
84
|
+
| detection_type in ["api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt"]
|
|
85
|
+
| table([#host, ai_tool, detection_type, masked_value, session_id_prefix, @timestamp])
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Set the alert to trigger when results > 0 and route to your SOC notification channel.
|
|
89
|
+
|
|
90
|
+
## Event schema
|
|
91
|
+
|
|
92
|
+
All events arrive in LogScale with:
|
|
93
|
+
|
|
94
|
+
| Tag | Value |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `#host` | Developer's machine hostname |
|
|
97
|
+
| `#source` | `chron-mcp` |
|
|
98
|
+
|
|
99
|
+
| Attribute | Present on |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `event_type` | All events: `session_started`, `message_logged`, `secret_detected` |
|
|
102
|
+
| `session_id_prefix` | All events |
|
|
103
|
+
| `ai_tool` | All events: `claude`, `cursor`, `windsurf`, etc. |
|
|
104
|
+
| `os` | All events: `darwin`, `linux`, `win32` |
|
|
105
|
+
| `chron_version` | All events |
|
|
106
|
+
| `role` | `message_logged` only: `user` or `assistant` |
|
|
107
|
+
| `detection_type` | `secret_detected` only: `api_key`, `aws_key`, `jwt`, etc. |
|
|
108
|
+
| `masked_value` | `secret_detected` only: e.g. `AKIA****F3K2` |
|
|
109
|
+
|
|
110
|
+
**What is never transmitted:** message content, actual secret values, file paths, or any user-typed text.
|
|
111
|
+
|
|
112
|
+
## Individual LQL queries
|
|
113
|
+
|
|
114
|
+
| File | Use |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `secrets-by-type.lql` | Time-series widget — secret detections by type |
|
|
117
|
+
| `sessions-by-developer.lql` | Table — sessions per host and AI tool |
|
|
118
|
+
| `api-key-alert.lql` | Scheduled alert — credential exposures |
|
|
119
|
+
| `ai-tool-usage.lql` | Pie chart — tool adoption breakdown |
|
|
120
|
+
| `daily-active-developers.lql` | Time-series — distinct active machines per day |
|
|
121
|
+
| `chron-ai-activity.yaml` | Full importable dashboard (all five) |
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Chron → Microsoft Sentinel
|
|
2
|
+
|
|
3
|
+
Stream AI session telemetry directly from developer machines into your Microsoft Sentinel workspace via the Azure Monitor Logs Ingestion API. No relay service — events go from the developer's machine straight to your own Log Analytics workspace.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Microsoft Sentinel enabled on a Log Analytics workspace
|
|
8
|
+
- Azure subscription with permission to create App Registrations and Data Collection Rules
|
|
9
|
+
|
|
10
|
+
## Step 1 — Register an Azure App
|
|
11
|
+
|
|
12
|
+
1. Open **Azure Portal** → **Azure Active Directory** → **App registrations** → **New registration**
|
|
13
|
+
2. Name it `chron-ingest` (or any name), leave defaults, click **Register**
|
|
14
|
+
3. Note the **Application (client) ID** and **Directory (tenant) ID**
|
|
15
|
+
4. Go to **Certificates & secrets** → **New client secret** — copy the value immediately
|
|
16
|
+
|
|
17
|
+
## Step 2 — Create a custom table in Log Analytics
|
|
18
|
+
|
|
19
|
+
1. Open your Log Analytics workspace → **Tables** → **Create** → **New custom log (DCR-based)**
|
|
20
|
+
2. Name the table `ChronEvents_CL`
|
|
21
|
+
3. Define the schema (add these columns):
|
|
22
|
+
|
|
23
|
+
| Column | Type |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `EventType` | string |
|
|
26
|
+
| `SessionIdPrefix` | string |
|
|
27
|
+
| `AiTool` | string |
|
|
28
|
+
| `OS` | string |
|
|
29
|
+
| `ChronVersion` | string |
|
|
30
|
+
| `Computer` | string |
|
|
31
|
+
| `Role` | string |
|
|
32
|
+
| `DetectionType` | string |
|
|
33
|
+
| `MaskedValue` | string |
|
|
34
|
+
|
|
35
|
+
(`TimeGenerated` is added automatically.)
|
|
36
|
+
|
|
37
|
+
4. The wizard creates a **Data Collection Endpoint (DCE)** and **Data Collection Rule (DCR)** — note both URLs/IDs.
|
|
38
|
+
|
|
39
|
+
## Step 3 — Grant the App ingest permission
|
|
40
|
+
|
|
41
|
+
1. Open the DCR you created → **Access control (IAM)** → **Add role assignment**
|
|
42
|
+
2. Role: **Monitoring Metrics Publisher**
|
|
43
|
+
3. Member: the `chron-ingest` app registration
|
|
44
|
+
|
|
45
|
+
## Step 4 — Get the DCR Immutable ID
|
|
46
|
+
|
|
47
|
+
Open the DCR → **Overview** → **JSON view** → copy the `immutableId` field (starts with `dcr-`).
|
|
48
|
+
|
|
49
|
+
## Step 5 — Connect from the developer machine
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
chron connect sentinel
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Enter the tenant ID, client ID, client secret, DCE URL, DCR immutable ID, and stream name when prompted. The command authenticates, sends a test event, and confirms before saving.
|
|
56
|
+
|
|
57
|
+
## Step 6 — Add env vars to your MCP client
|
|
58
|
+
|
|
59
|
+
The `connect` command prints the exact block to paste. For Claude Code, add to the `chron` entry in `~/.claude.json`:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"chron": {
|
|
65
|
+
"type": "stdio",
|
|
66
|
+
"command": "node",
|
|
67
|
+
"args": ["/path/to/dist/index.js"],
|
|
68
|
+
"env": {
|
|
69
|
+
"CHRON_SENTINEL_TENANT_ID": "<your-tenant-id>",
|
|
70
|
+
"CHRON_SENTINEL_CLIENT_ID": "<your-client-id>",
|
|
71
|
+
"CHRON_SENTINEL_CLIENT_SECRET": "<your-client-secret>",
|
|
72
|
+
"CHRON_SENTINEL_DCE": "https://<your-dce>.ingest.monitor.azure.com",
|
|
73
|
+
"CHRON_SENTINEL_DCR_ID": "dcr-<your-immutable-id>",
|
|
74
|
+
"CHRON_SENTINEL_STREAM": "Custom-ChronEvents_CL"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Step 7 — Add KQL queries to Sentinel
|
|
82
|
+
|
|
83
|
+
In Sentinel → **Logs**, run queries from this directory:
|
|
84
|
+
|
|
85
|
+
| File | Use |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `events-by-type.kql` | Time-series — event volume by type |
|
|
88
|
+
| `sessions-by-developer.kql` | Table — sessions per machine and AI tool |
|
|
89
|
+
| `secrets-detected.kql` | Table — credential exposures for SOC review |
|
|
90
|
+
| `ai-tool-usage.kql` | Summary — tool adoption breakdown |
|
|
91
|
+
| `daily-active-developers.kql` | Time-series — distinct active machines per day |
|
|
92
|
+
| `secrets-alert.kql` | Scheduled alert rule — credential exposures |
|
|
93
|
+
|
|
94
|
+
## Step 8 — Set up the credential alert (recommended)
|
|
95
|
+
|
|
96
|
+
1. Sentinel → **Analytics** → **Create** → **Scheduled query rule**
|
|
97
|
+
2. Paste `secrets-alert.kql` as the rule query
|
|
98
|
+
3. Set **Run query every**: 1 hour, **Lookup data from the last**: 1 hour
|
|
99
|
+
4. Alert threshold: **Number of results greater than 0**
|
|
100
|
+
5. Route to your SOC incident queue
|
|
101
|
+
|
|
102
|
+
## Event schema
|
|
103
|
+
|
|
104
|
+
All events arrive in `ChronEvents_CL` with:
|
|
105
|
+
|
|
106
|
+
| Column | Present on |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `TimeGenerated` | All events |
|
|
109
|
+
| `EventType` | All: `session_started`, `message_logged`, `secret_detected` |
|
|
110
|
+
| `SessionIdPrefix` | All events |
|
|
111
|
+
| `AiTool` | All events: `claude`, `cursor`, `windsurf`, etc. |
|
|
112
|
+
| `OS` | All events: `darwin`, `linux`, `win32` |
|
|
113
|
+
| `ChronVersion` | All events |
|
|
114
|
+
| `Computer` | All events: developer's machine hostname |
|
|
115
|
+
| `Role` | `message_logged` only: `user` or `assistant` |
|
|
116
|
+
| `DetectionType` | `secret_detected` only: `api_key`, `aws_key`, `jwt`, etc. |
|
|
117
|
+
| `MaskedValue` | `secret_detected` only: e.g. `AKIA****F3K2` |
|
|
118
|
+
|
|
119
|
+
**What is never transmitted:** message content, actual secret values, file paths, or any user-typed text.
|
|
120
|
+
|
|
121
|
+
## Token refresh
|
|
122
|
+
|
|
123
|
+
Chron automatically refreshes the Azure AD access token before it expires (tokens are valid for 1 hour). No manual intervention required after initial setup.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Scheduled alert rule — trigger when credential exposures > 0
|
|
2
|
+
// Use in: Sentinel → Analytics → Scheduled query rule
|
|
3
|
+
ChronEvents_CL
|
|
4
|
+
| where TimeGenerated > ago(1h)
|
|
5
|
+
| where EventType == "secret_detected"
|
|
6
|
+
| where DetectionType in ("api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt")
|
|
7
|
+
| project TimeGenerated, Computer, AiTool, DetectionType, MaskedValue, SessionIdPrefix
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Credential exposures by type — full table for SOC review
|
|
2
|
+
ChronEvents_CL
|
|
3
|
+
| where TimeGenerated > ago(30d)
|
|
4
|
+
| where EventType == "secret_detected"
|
|
5
|
+
| where DetectionType in ("api_key", "aws_key", "gcp_key", "azure_key", "private_key", "jwt")
|
|
6
|
+
| project TimeGenerated, Computer, AiTool, DetectionType, MaskedValue, SessionIdPrefix
|
|
7
|
+
| sort by TimeGenerated desc
|