Authenticate T5 and T6 telemetry over HTTPS

This commit is contained in:
2026-10-05 22:24:14 -04:00
parent 05a906c3e2
commit 5521f4ea43
5 changed files with 93 additions and 14 deletions
+31
View File
@@ -88,6 +88,37 @@ and telemetry still work. Open `.help` during a record page and check that the
record resumes afterwards without overlapping it. Runtime linking and client record resumes afterwards without overlapping it. Runtime linking and client
readiness require Plutonium. readiness require Plutonium.
## Telemetry authentication (T5 and T6)
Both reporters default to `https://ec.thewrightserver.net/api/telemetry` and send
`Authorization: Bearer <token>` plus `Content-Type: application/json` on every
POST. Existing event fields and queue behavior are unchanged. An explicit
`tws_telemetry_url` override must also use HTTPS; remove any old HTTP override.
Before upgrading the API or loading these reporters:
1. Set the Electric Cherry service's **environment variable**
`EC_TELEMETRY_TOKEN` to a separate shared secret of at least 32 characters.
A missing service token disables ingestion.
2. Both telemetry scripts embed the matching reporter secret in
`level.telemetry_token`. No game-server token dvar or private config is needed.
3. Keep `tws_server_id` set to the exact registered server name, then restart
the map. Both reporters refuse to start with a short embedded token or a
non-HTTPS URL. Rotating the service token requires editing the token in both
scripts, deploying them to every game server, and restarting the maps.
The API also accepts `X-EC-Telemetry-Token`; these reporters use Bearer auth.
Cookies, query parameters, and JSON fields cannot authenticate telemetry.
Missing or incorrect request tokens are rejected before payload parsing or
recording. Reporters that cannot set headers need a trusted relay with an HTTPS
reporter-facing endpoint. The plugins used here accept a headers array.
After deployment, verify all four event types reach Electric Cherry. On a test
server, also verify that a short embedded token and an HTTP URL prevent startup,
that a wrong token is rejected without recording an event, and that deploying
the correct token restores ingestion. Plugin transport completion alone does
not prove API acceptance; inspect the API response or ingestion records.
## Validating T6 ## Validating T6
```powershell ```powershell
+9 -4
View File
@@ -354,7 +354,7 @@ and [spawn entry point](https://github.com/plutoniummod/t5-scripts/blob/main/ZM/
| `tws_lock_round` | `tws_lock` | `20` | Round at which the lobby locks | | `tws_lock_round` | `tws_lock` | `20` | Round at which the lobby locks |
| `tws_server_id` | `tws_bank`, `tws_telemetry` | Required for telemetry | Exact registered Electric Cherry server name; also used as the bank label | | `tws_server_id` | `tws_bank`, `tws_telemetry` | Required for telemetry | Exact registered Electric Cherry server name; also used as the bank label |
| `tws_telemetry_enabled` | `tws_telemetry` | `1` | Set to `0` to disable telemetry at init | | `tws_telemetry_enabled` | `tws_telemetry` | `1` | Set to `0` to disable telemetry at init |
| `tws_telemetry_url` | `tws_telemetry` | `http://192.168.1.199:3000/api/telemetry` | Electric Cherry telemetry endpoint for JSON POSTs | | `tws_telemetry_url` | `tws_telemetry` | `https://ec.thewrightserver.net/api/telemetry` | Electric Cherry telemetry endpoint for JSON POSTs |
| `tws_telemetry_log_level` | `tws_telemetry` | `1` | Read live: `0` warnings/errors/recovery only, `1` lifecycle/request/health logs, `2` also capture/queue logs and response previews | | `tws_telemetry_log_level` | `tws_telemetry` | `1` | Read live: `0` warnings/errors/recovery only, `1` lifecycle/request/health logs, `2` also capture/queue logs and response previews |
## tws_telemetry.gsc ## tws_telemetry.gsc
@@ -362,13 +362,17 @@ and [spawn entry point](https://github.com/plutoniummod/t5-scripts/blob/main/ZM/
Uses `t5-gsc-utils` HTTP/JSON components to POST directly to Electric Cherry's Uses `t5-gsc-utils` HTTP/JSON components to POST directly to Electric Cherry's
`/api/telemetry`. Install alongside `tws_common.gsc` in `storage/t5/scripts/sp/`. `/api/telemetry`. Install alongside `tws_common.gsc` in `storage/t5/scripts/sp/`.
No HUD or database dependency. Reports run whether or not a beta is active. No HUD or database dependency. Reports run whether or not a beta is active.
Follow the shared [authentication setup](../README.md#telemetry-authentication-t5-and-t6)
to configure the service before upgrading. The reporter token is embedded in
`level.telemetry_token`; it must match the service's `EC_TELEMETRY_TOKEN`. Short
embedded tokens and non-HTTPS URLs disable reporting at init.
Example server config (except log level, read at script init; restart the map after changes): Example server config (except log level, read at script init; restart the map after changes):
```cfg ```cfg
set tws_server_id "t5_zombie_prototype_1" set tws_server_id "t5_zombie_prototype_1"
set tws_telemetry_enabled "1" set tws_telemetry_enabled "1"
set tws_telemetry_url "http://192.168.1.199:3000/api/telemetry" set tws_telemetry_url "https://ec.thewrightserver.net/api/telemetry"
set tws_telemetry_log_level "1" set tws_telemetry_log_level "1"
``` ```
@@ -410,8 +414,9 @@ use `jsonSerialize` for escaping.
Events are captured immediately into an in-memory queue. One HTTP worker Events are captured immediately into an in-memory queue. One HTTP worker
POSTs each snapshot once, in gameplay order, with `Content-Type: POSTs each snapshot once, in gameplay order, with `Content-Type:
application/json`, waiting for completion before sending the next. Gameplay application/json` and `Authorization: Bearer <token>`, waiting for completion
and round detection continue while requests are pending. Repeated joins or before sending the next. Gameplay and round detection continue while requests
are pending. Repeated joins or
end notifications do not duplicate start/end reports. At game over, the end notifications do not duplicate start/end reports. At game over, the
reporter captures any round change since the last poll, stops detection, reporter captures any round change since the last poll, stops detection,
and lets the sender drain through `game_end`. and lets the sender drain through `game_end`.
+17 -1
View File
@@ -21,7 +21,22 @@ init()
level.telemetry_url = GetDvar("tws_telemetry_url"); level.telemetry_url = GetDvar("tws_telemetry_url");
if (level.telemetry_url == "") if (level.telemetry_url == "")
level.telemetry_url = "http://192.168.1.199:3000/api/telemetry"; level.telemetry_url = "https://ec.thewrightserver.net/api/telemetry";
if (getSubStr(toLower(level.telemetry_url), 0, 8) != "https://")
{
print("^1[tws_telemetry] Telemetry disabled: tws_telemetry_url must use HTTPS");
return;
}
// Shared reporter secret; update both scripts when rotating it.
// This must match Electric Cherry's EC_TELEMETRY_TOKEN environment variable.
level.telemetry_token = "e03a03f7d22418f0c062b0b2a7317fd91b1194c4400e84b469866de501180dc2";
if (level.telemetry_token.size < 32)
{
print("^1[tws_telemetry] Telemetry disabled: embedded telemetry token must be at least 32 characters");
return;
}
level.telemetry_server = GetDvar("tws_server_id"); level.telemetry_server = GetDvar("tws_server_id");
if (level.telemetry_server == "") if (level.telemetry_server == "")
@@ -273,6 +288,7 @@ telemetry_send(entry)
headers = []; headers = [];
headers["Content-Type"] = "application/json"; headers["Content-Type"] = "application/json";
headers["Authorization"] = "Bearer " + level.telemetry_token;
options = []; options = [];
options["method"] = "POST"; options["method"] = "POST";
+19 -8
View File
@@ -1,7 +1,8 @@
# TWS T6 Zombies scripts # TWS T6 Zombies scripts
Plutonium T6 versions of the T5 server scripts. Defaults live in the scripts, Plutonium T6 versions of the T5 server scripts. Defaults live in the scripts,
just like T5. There is no separate TWS config file or database setup. just like T5. The telemetry token is embedded in the reporter script; no
separate token config or database setup is required.
| File | Role | Dependencies | | File | Role | Dependencies |
| --- | --- | --- | | --- | --- | --- |
@@ -20,7 +21,9 @@ just like T5. There is no separate TWS config file or database setup.
2. For telemetry or leaderboard, install [t6-gsc-utils v3.1.1](https://github.com/alicealys/t6-gsc-utils/releases/tag/v3.1.1) 2. For telemetry or leaderboard, install [t6-gsc-utils v3.1.1](https://github.com/alicealys/t6-gsc-utils/releases/tag/v3.1.1)
in `Plutonium/plugins/` and restart the server process. The other five scripts in `Plutonium/plugins/` and restart the server process. The other five scripts
do not require that plugin. do not require that plugin.
3. Restart the map to load script updates. 3. Ensure the API service's `EC_TELEMETRY_TOKEN` matches the token embedded in
the reporter; see [authentication setup](../README.md#telemetry-authentication-t5-and-t6).
4. Restart the map to load script updates.
If upgrading from the earlier leaderboard filename, **remove If upgrading from the earlier leaderboard filename, **remove
`tws_leaderboard.gsc` from the T6 server script directory** before installing `tws_leaderboard.gsc` from the T6 server script directory** before installing
@@ -86,14 +89,15 @@ their module's initialization so the list stays current.
- Lock uses T5's HUD round/game-over notifications. Default threshold is 20. - Lock uses T5's HUD round/game-over notifications. Default threshold is 20.
As in T5, it clears `g_password` at startup and game over. As in T5, it clears `g_password` at startup and game over.
- Telemetry is enabled by default and posts to - Telemetry is enabled by default and posts to
`http://192.168.1.199:3000/api/telemetry`. Set `tws_server_id` to the exact, `https://ec.thewrightserver.net/api/telemetry`. Set `tws_server_id` to the exact,
case-sensitive Electric Cherry registry name; missing or overlong names case-sensitive Electric Cherry registry name; missing or overlong names
disable reporting with a console diagnostic. disable reporting with a console diagnostic. An embedded token matching the service's
`EC_TELEMETRY_TOKEN` (at least 32 characters) and an HTTPS URL are required as well.
The optional dvars already present in T5 are still supported: `tws_lock_round`, The dvars already present in T5 are still supported: `tws_lock_round`,
`tws_server_id`, `tws_telemetry_url`, and `tws_telemetry_enabled` (`0` disables `tws_server_id`, `tws_telemetry_url`, and `tws_telemetry_enabled` (`0` disables
telemetry). None require a separate config file. If earlier settings are already telemetry). Earlier settings still override defaults; remove any old HTTP URL
set on the server, they still override these defaults. override when upgrading. The reporter token lives in `level.telemetry_token`.
## Round telemetry ## Round telemetry
@@ -102,9 +106,16 @@ Cherry registry name and full endpoint in your existing server configuration:
```cfg ```cfg
set tws_server_id "t6_zombie_town_1" set tws_server_id "t6_zombie_town_1"
set tws_telemetry_url "http://192.168.1.199:3000/api/telemetry" set tws_telemetry_url "https://ec.thewrightserver.net/api/telemetry"
``` ```
The script embeds the reporter token in `level.telemetry_token`; it must match
the API service's `EC_TELEMETRY_TOKEN` environment variable. Follow the shared
[authentication setup](../README.md#telemetry-authentication-t5-and-t6). Every
request includes `Authorization: Bearer <token>` and `Content-Type:
application/json`. Token rotation requires updating and redeploying both reporter
scripts. Token and endpoint changes require a map restart.
It sends four event types over the life of a match, mirroring the T5 script: It sends four event types over the life of a match, mirroring the T5 script:
| Event | When | Round in payload | | Event | When | Round in payload |
+17 -1
View File
@@ -26,7 +26,22 @@ init()
level.telemetry_url = GetDvar("tws_telemetry_url"); level.telemetry_url = GetDvar("tws_telemetry_url");
if (level.telemetry_url == "") if (level.telemetry_url == "")
level.telemetry_url = "http://192.168.1.199:3000/api/telemetry"; level.telemetry_url = "https://ec.thewrightserver.net/api/telemetry";
if (getSubStr(toLower(level.telemetry_url), 0, 8) != "https://")
{
println("^1[tws_t6_telemetry] Telemetry disabled: tws_telemetry_url must use HTTPS");
return;
}
// Shared reporter secret; update both scripts when rotating it.
// This must match Electric Cherry's EC_TELEMETRY_TOKEN environment variable.
level.telemetry_token = "e03a03f7d22418f0c062b0b2a7317fd91b1194c4400e84b469866de501180dc2";
if (level.telemetry_token.size < 32)
{
println("^1[tws_t6_telemetry] Telemetry disabled: embedded telemetry token must be at least 32 characters");
return;
}
level.telemetry_server = GetDvar("tws_server_id"); level.telemetry_server = GetDvar("tws_server_id");
if (level.telemetry_server == "" || level.telemetry_server.size > 255) if (level.telemetry_server == "" || level.telemetry_server.size > 255)
@@ -292,6 +307,7 @@ telemetry_send(entry)
headers = []; headers = [];
headers["Content-Type"] = "application/json"; headers["Content-Type"] = "application/json";
headers["Authorization"] = "Bearer " + level.telemetry_token;
options = []; options = [];
options["method"] = "POST"; options["method"] = "POST";