HarperFast / HarperFast/harper

operationsApi.network.mtls and mtls_required are unregistered config params — client-cert verification can never be enabled on the ops/replication ports

Open
#2,641 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## Summary

`operationsApi.network.mtls` and `operationsApi.network.mtls_required` are read by the server but are **not registered config parameters**, so they resolve to `undefined` no matter how they are set. The operations and replication listeners therefore can never be configured to request or require client certificates — `requestCert` stays false and `rejectUnauthorized` stays false on those ports.

This is not just the env-var path: the value is unreachable via environment variable, via `harper-config.yaml` / `harperdb-config.yaml`, and via `set_configuration` alike.

## Mechanism

The read site builds the parameter name dynamically from the server prefix:

```js
// v5 main — server/http.ts:595-596
const mtls = env.get(serverPrefix + '_mtls');
const mtlsRequired = env.get(serverPrefix + '_mtls_required');
```

…and the result feeds `requestCert` / `rejectUnauthorized` (`server/http.ts:610-611`) and `server.verifiesClientCerts` (`:816`).

But `env.get` is gated on the registry:

```js
// config/configUtils.ts:282-297
const paramMap = CONFIG_PARAM_MAP[param.toLowerCase()];
if (paramMap === undefined) return undefined;
return flatConfigObj[paramMap.toLowerCase()];
```

`CONFIG_PARAM_MAP` is built solely from the static `CONFIG_PARAMS` registry plus manual aliases (`utility/hdbTerms.ts:661-735`). The `OPERATIONSAPI_NETWORK_*` block (`utility/hdbTerms.ts:576-592`) registers CORS, CORSACCESSLIST, HEADERSTIMEOUT, HTTPS, KEEPALIVETIMEOUT, PORT, DOMAINSOCKET, SECUREPORT, HTTP2, MAXREQUESTBODYSIZE, TIMEOUT — **there is no `OPERATIONSAPI_NETWORK_MTLS` or `_MTLS_REQUIRED` entry**, and none of the aliases map to one. By contrast `HTTP_MTLS` (`:533`) and `MQTT_NETWORK_MTLS` (`:707`) are both registered.

`environmentManager.get()`'s fallback does not rescue it either — `installProps` is populated only from the boot-properties file, never by matching arbitrary environment keys to parameter names.

And environment variables only ever enter config for names already in the map:

```js
// bin/run.js:100 (also bin/restart.js:75)
const parsed_args = assignCMDENVVariables(Object.keys(terms.CONFIG_PARAM_MAP), true);
```

so an unregistered name is never ingested from the environment at all.

Consistent with the above, `validation/configValidator.ts:286-296` (the `operationsApi.network` Joi schema) and `static/defaultConfig.yaml:62-69` both omit `mtls`, while the equivalent `http` and `mqtt.network` blocks declare it. `set_configuration` also refuses to write an unregistered parameter (`config/configUtils.ts:757-765`, "unrecognized config parameter").

There is a second dead end worth noting: `flattenConfig` (`config/configUtils.ts:884-886`) *does* compute a merged `operationsapi_network_mtls` key in `flatConfigObj` (inheriting `http.mtls` when unset), but the `CONFIG_PARAM_MAP` gate above means that computed value can never be read back through `env.get()`. It is dead data.

## Impact

An operator who sets `operationsApi.network.mtls: true` (or the corresponding env var) to require client certificates on the operations/replication ports gets **no error and no effect**. The setting appears accepted; client-certificate verification is simply never enabled. A hand-edited YAML entry is the worst case — it shows up in `get_configuration` output, so it reads as applied config while remaining functionally inert.

This is a hardening control being silently unavailable rather than an authentication bypass — request authentication still applies — but it means "we require mTLS on the operations API" cannot currently be made true by configuration.

## Versions

Present in **v5 `main`** and in **v4** (verified at tag `release_4.5.36`): `getConfigValue` and `environmentManager.get()` are logically identical there, `hdbTerms` likewise registers only `HTTP_MTLS*`/`MQTT_NETWORK_MTLS*`, and the read site is `server/threads/threadServer.js:433`. v4 has no `server/http.ts`, but the root cause — the missing `CONFIG_PARAMS` entry plus the `CONFIG_PARAM_MAP` gate — predates v5 and is unchanged.

## Expected

Either register `OPERATIONSAPI_NETWORK_MTLS` / `_MTLS_REQUIRED` in `CONFIG_PARAMS` (and add them to the Joi schema and default config, matching the `http` block), or reject/warn on the unrecognized key at load so it cannot silently read as applied.

## Related

`harper-pro#734` — same failure class (`env.get` resolves only names registered in `CONFIG_PARAMS`, so config values are silently ignored and the compiled-in default always wins), different subsystem. Worth fixing together, and worth a general sweep for other read sites that build parameter names dynamically.

Contributor guide

Open the contributing guide

Research direction

Start with the OPERATIONSAPI_NETWORK_* entries in utility/hdbTerms.ts, then compare validation/configValidator.ts, static/defaultConfig.yaml, config/configUtils.ts, and the server/http.ts read site. Done means both mTLS settings are recognized and validated, and values supplied through environment variables, YAML, or set_configuration reach requestCert, rejectUnauthorized, and server.verifiesClientCerts.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
api, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.