Skip to content

Commit a1a582a

Browse files
authored
TIKA-4764 -- more granular selection of features in tika-server and tika-grpc (#2909)
1 parent c34bc08 commit a1a582a

43 files changed

Lines changed: 620 additions & 136 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGES.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ Release 4.0.0-beta-1 - unreleased
1818
The extra jars are also forwarded onto forked pipes/server worker processes,
1919
so they are available where parsing actually happens (TIKA-4755).
2020

21+
* More granular, default-deny capability flags for tika-server and tika-grpc.
22+
tika-server's enableUnsecureFeatures is split into allowPipes (gates the
23+
/pipes and /async endpoints) and allowPerRequestConfig (gates the /config
24+
endpoints and the multipart config part); the /status endpoint is no longer
25+
gated and is enabled simply by listing it under endpoints. tika-grpc gains
26+
the same allowPerRequestConfig flag plus allowComponentModifications (gates
27+
runtime Save/Delete of fetchers and pipes iterators). All flags default to
28+
false, so an out-of-the-box tika-grpc server no longer accepts per-request
29+
configuration or runtime store mutations (TIKA-4764).
30+
2131
OTHER CHANGES
2232

2333
* Release artifacts are now channel-specific. Maven Central gets slim

docs/modules/ROOT/pages/advanced/integration-testing/run-uat-script.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ Coverage includes:
5151
* `/unpack/all` (embedded extraction; verifies the response is a valid zip)
5252
* `/language/stream`
5353
* `/meta/form`, `/rmeta/form` (multipart variants)
54-
* `enableUnsecureFeatures=false` gating: `/meta/config`, `/rmeta/config`,
55-
`/tika/config` all return 403; and selecting the `/pipes`, `/async`, or `/status`
56-
endpoints without `enableUnsecureFeatures` makes the server refuse to start
54+
* `allowPerRequestConfig=false` gating: `/meta/config`, `/rmeta/config`,
55+
`/tika/config` all return 403; and `allowPipes=false` gating: selecting the
56+
`/pipes` or `/async` endpoints without `allowPipes` makes the server refuse to start
5757
* `X-Tika-OCRskipOcr` header, `Content-Disposition` filename
5858
* 404 / 405 error handling
5959

docs/modules/ROOT/pages/advanced/integration-testing/tika-server.adoc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -212,39 +212,40 @@ curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F "file=@testPDF.pdf" http:/
212212
curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F "file=@testPDF.pdf" http://localhost:9998/unpack/config
213213
----
214214

215-
*Expected:* All return HTTP 403 with message: "Config endpoints are disabled. Set enableUnsecureFeatures=true in server config."
215+
*Expected:* All return HTTP 403 with message: "Config endpoints are disabled. Set allowPerRequestConfig=true in server config."
216216

217-
=== Test 18b: `/pipes`, `/async`, `/status` Require enableUnsecureFeatures
217+
=== Test 18b: `/pipes` and `/async` Require allowPipes
218218

219219
[source,bash]
220220
----
221-
cat > tika-config-pipes-no-unsecure.json << 'EOF'
221+
cat > tika-config-pipes-no-flags.json << 'EOF'
222222
{
223223
"server": {"port": 9998, "endpoints": ["tika", "pipes"]},
224224
"pipes": {"numClients": 2},
225225
"plugin-roots": "/tmp/tika-server-test/plugins"
226226
}
227227
EOF
228228
229-
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c tika-config-pipes-no-unsecure.json
229+
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c tika-config-pipes-no-flags.json
230230
----
231231

232-
*Expected:* The server refuses to start, failing with a `TikaConfigException` stating that the `pipes` endpoint requires `enableUnsecureFeatures` to be `true`. The same applies to `async` and `status`.
232+
*Expected:* The server refuses to start, failing with a `TikaConfigException` stating that the `pipes` endpoint requires `allowPipes` to be `true`. The same applies to `async`. (`/status` is no longer gated — it can be enabled simply by listing `status` under `endpoints`.)
233233

234-
== Part 2: Tests with enableUnsecureFeatures
234+
== Part 2: Tests with allowPipes / allowPerRequestConfig
235235

236236
Stop the default server and create a config file:
237237

238238
[source,bash]
239239
----
240240
pkill -f "tika-server-standard-4.0.0-SNAPSHOT.jar"
241241
242-
cat > tika-config-unsecure.json << 'EOF'
242+
cat > tika-config-capabilities.json << 'EOF'
243243
{
244244
"server": {
245245
"port": 9998,
246246
"host": "localhost",
247-
"enableUnsecureFeatures": true
247+
"allowPipes": true,
248+
"allowPerRequestConfig": true
248249
},
249250
"parsers": [
250251
{"default-parser": {}}
@@ -253,7 +254,7 @@ cat > tika-config-unsecure.json << 'EOF'
253254
}
254255
EOF
255256
256-
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c tika-config-unsecure.json &
257+
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c tika-config-capabilities.json &
257258
sleep 10
258259
curl -s http://localhost:9998/version
259260
----
@@ -382,7 +383,7 @@ rm -rf /tmp/tika-server-test
382383

383384
The following endpoints were tested and verified working:
384385

385-
=== Default Mode (enableUnsecureFeatures=false)
386+
=== Default Mode (allowPipes=false, allowPerRequestConfig=false)
386387

387388
[cols="1,1,1", options="header"]
388389
|===
@@ -412,7 +413,7 @@ The following endpoints were tested and verified working:
412413
|`/unpack/config` |POST |BLOCKED (403) - Expected
413414
|===
414415

415-
=== With enableUnsecureFeatures=true
416+
=== With allowPerRequestConfig=true
416417

417418
[cols="1,1,1", options="header"]
418419
|===

docs/modules/ROOT/pages/advanced/robustness.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ tika-server restarts gracefully.
9797

9898
tika-pipes::
9999
Available through programmatic use, tika-app `-a` option, or tika-server's `/async`
100-
and `/pipes` endpoints (the server endpoints require `enableUnsecureFeatures=true`).
100+
and `/pipes` endpoints (the server endpoints require `allowPipes=true`).
101101

102102
== Security Testing and Prevention
103103

docs/modules/ROOT/pages/configuration/index.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ used wherever a section is missing.
7474
"unpack-config": { /* embedded-byte extraction */ }
7575
/* other SelfConfiguring components by component name */
7676
},
77-
"server": { /* tika-server options: enableUnsecureFeatures, cors, ... */ },
77+
"server": { /* tika-server options: allowPipes, allowPerRequestConfig, cors, ... */ },
7878
"pipes": { /* Pipes process management: numClients, parseMode, ... */ },
7979
"fetchers": { /* named fetcher instances */ },
8080
"emitters": { /* named emitter instances */ },

docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,23 @@ The following `TikaServerConfig` options have been removed:
132132
133133
* **Fetcher-based streaming** - The `InputStreamFactory` pattern for fetching documents via HTTP headers (`fetcherName`, `fetchKey`) has been removed. All documents are now processed via temp files through the pipes infrastructure.
134134
135-
=== `/pipes`, `/async`, and `/status` Require `enableUnsecureFeatures`
135+
=== `/pipes` and `/async` Require `allowPipes`; Per-Request Config Requires `allowPerRequestConfig`
136136
137-
Previously these endpoints were enabled simply by listing them under `server.endpoints`. They now *also* require `enableUnsecureFeatures` to be `true`; selecting any of `pipes`, `async`, or `status` without it causes the server to refuse to start with a clear error. `/pipes` and `/async` drive process-isolated batch parsing through your fetchers and emitters, and `/status` exposes server information, so this makes enabling them an explicit, deliberate opt-in.
137+
Previously these endpoints (and per-request parser configuration) were enabled simply by listing endpoints under `server.endpoints`. The capabilities are now split into two default-`false` flags in the `server` section:
138138
139-
**Migration:** if your config selects `pipes`, `async`, or `status`, add `"enableUnsecureFeatures": true` to the `server` section:
139+
* `allowPipes` gates the `/pipes` and `/async` endpoints, which drive process-isolated batch parsing through your fetchers and emitters. Selecting either without `allowPipes` causes the server to refuse to start with a clear error.
140+
* `allowPerRequestConfig` gates per-request parser configuration: the `/config` family of endpoints and the multipart `config` part. When off, such requests are rejected with 403.
141+
142+
`/status` is no longer gated: it exposes only aggregate counters, so it is enabled simply by listing `status` under `endpoints`.
143+
144+
**Migration:** if your config selects `pipes` or `async`, add `"allowPipes": true`; if you rely on per-request config, add `"allowPerRequestConfig": true`:
140145
141146
[source,json]
142147
----
143148
{
144149
"server": {
145-
"enableUnsecureFeatures": true,
150+
"allowPipes": true,
151+
"allowPerRequestConfig": true,
146152
"endpoints": ["tika", "rmeta", "pipes", "async", "status"]
147153
}
148154
}

docs/modules/ROOT/pages/pipes/index.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ While Tika Pipes has a programmatic Java API, it is best used through:
2929

3030
* xref:using-tika/cli/index.adoc[tika-app] — batch processing from the command line
3131
* xref:using-tika/server/index.adoc[tika-server] — REST API with pipes-based robustness built in
32-
* xref:using-tika/grpc/index.adoc[tika-grpc] — gRPC API with pipes-based robustness built in
32+
* xref:using-tika/grpc/index.adoc[tika-grpc] — gRPC API with pipes-based robustness built in. More exposed by default than tika-server; run only on a trusted network (see xref:using-tika/grpc/index.adoc#_security[Security]).
3333

3434
See xref:advanced/robustness.adoc[Robustness] for details on how Tika Pipes protects
3535
against problematic files.

docs/modules/ROOT/pages/pipes/timeouts.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ This can be combined with other parse-context settings:
6868

6969
== Per-Request Overrides
7070

71-
When using Tika Server with `enableUnsecureFeatures: true`, timeouts can be overridden per-request
71+
When using Tika Server with `allowPerRequestConfig: true`, timeouts can be overridden per-request
7272
by including `TimeoutLimits` in the `ParseContext` of a `FetchEmitTuple`:
7373

7474
[source,java]

docs/modules/ROOT/pages/using-tika/grpc/index.adoc

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,131 @@ register a fetcher (`SaveFetcher`) and then submit `FetchAndParseRequest`
2929
messages, each of which returns a `FetchAndParseReply` with extracted
3030
metadata and content.
3131

32+
== Security
33+
34+
[WARNING]
35+
====
36+
Treat tika-grpc as a privileged, trusted-network-only service — it is *more
37+
exposed by default than tika-server*. By default it has no transport security and
38+
no per-caller authorization, and its core `FetchAndParse` surface is always on:
39+
anyone who can reach the gRPC port can fetch and parse whatever the server's
40+
configured fetchers can reach.
41+
42+
Its most dangerous capabilities — runtime mutation of the fetcher/iterator store
43+
(for example `SaveFetcher`, which can read files and load code on the server
44+
host) and per-request parse configuration — are *off by default*, behind the
45+
flags in <<_capability_flags>>, mirroring tika-server's default-deny capability
46+
flags (`allowPipes`, `allowPerRequestConfig`). Those flags are defense in depth,
47+
not a substitute for network controls and mutual TLS. Run tika-grpc only behind
48+
strict network controls.
49+
====
50+
51+
=== Capability Flags
52+
53+
Like tika-server, tika-grpc locks down its dangerous capabilities by default.
54+
The two flags below live in the `grpc` section of your tika-config and both
55+
default to `false`. Out of the box, the server only fetches and parses using the
56+
fetchers and pipes iterators declared in the config file, using the server's own
57+
parse configuration.
58+
59+
[cols="1,3",options="header"]
60+
|===
61+
|Setting |Description
62+
63+
|`allowPerRequestConfig`
64+
|When `true`, callers may attach per-request configuration to `FetchAndParse`
65+
requests (`parse_context_json` and `additional_fetch_config_json`), overriding
66+
the server's defaults for that request. Because this can reconfigure any pipeline
67+
component (fetcher, parser, timeouts, ...), it is off by default. When `false`, a
68+
request carrying either field is rejected with `PERMISSION_DENIED`.
69+
70+
|`allowComponentModifications`
71+
|When `true`, callers may add, modify, or delete fetchers and pipes iterators at
72+
runtime (`SaveFetcher`, `DeleteFetcher`, `SavePipesIterator`,
73+
`DeletePipesIterator`). Because this changes what the server can reach for all
74+
subsequent requests (for example, adding a fetcher that escapes a configured base
75+
path), it is off by default. When `false`, those RPCs are rejected with
76+
`PERMISSION_DENIED`.
77+
|===
78+
79+
Enable these only for trusted callers over a secured channel:
80+
81+
[source,json]
82+
----
83+
{
84+
"grpc": {
85+
"allowPerRequestConfig": true,
86+
"allowComponentModifications": true
87+
}
88+
}
89+
----
90+
91+
=== Transport Security (TLS)
92+
93+
By default the gRPC server runs *without TLS*: connections are plaintext and
94+
unauthenticated. This includes the `apache/tika-grpc` Docker image, whose
95+
entrypoint does not pass `--secure`. Only run in this mode on a trusted network.
96+
97+
Transport security is configured entirely through command-line flags (there is no
98+
JSON config for gRPC TLS), with three modes:
99+
100+
*Insecure (default).* No `--secure` flag. Plaintext, no authentication.
101+
102+
*Server (1-way) TLS.* Enable `-s`/`--secure` and supply the server certificate
103+
and key. The server authenticates to clients; clients are not authenticated.
104+
105+
[source,bash]
106+
----
107+
java -jar tika-grpc-<version>.jar --secure \
108+
--cert-chain server.pem --private-key server.key
109+
----
110+
111+
Add `--private-key-password` if the private key is encrypted.
112+
113+
*Mutual (2-way) TLS.* Additionally supply the trust collection (the CA used to
114+
verify client certificates) and require client authentication:
115+
116+
[source,bash]
117+
----
118+
java -jar tika-grpc-<version>.jar --secure \
119+
--cert-chain server.pem --private-key server.key \
120+
--trust-cert-collection ca.pem --client-auth-required
121+
----
122+
123+
Mutual TLS is opt-in: `--client-auth-required` is off by default, so it has no
124+
effect unless `--trust-cert-collection` is also given (a missing or non-existent
125+
trust-collection path is silently ignored). The default port is `50052`
126+
(`-p`/`--port`).
127+
128+
When running the Docker image, append these flags to the container command — they
129+
are forwarded to the server — and mount the certificate files into the container.
130+
131+
=== Kubernetes and Service Meshes
132+
133+
Running tika-grpc in Kubernetes does not make it safe on its own. By default, pod
134+
networking is flat: any pod can reach any other pod's port, traffic is
135+
unencrypted, and there is no authentication or authorization between pods.
136+
Kubernetes gives you the tools to lock this down, but none of them are applied
137+
automatically. Two distinct controls are involved, and both matter:
138+
139+
* *Transport security.* A service mesh (for example Istio or Linkerd) with sidecar
140+
mTLS encrypts and authenticates pod-to-pod traffic. If the mesh provides this,
141+
you can run tika-grpc without `--secure` and let the mesh handle transport
142+
security in place of the TLS flags above.
143+
* *Reachability.* A `NetworkPolicy` that admits only your trusted client(s) to the
144+
tika-grpc Service. This is the control that actually mitigates the exposure
145+
described above: because tika-grpc has no per-caller authorization, the set of
146+
pods that can reach the port is effectively the set of pods that can use its
147+
enabled RPC surface.
148+
149+
Mesh mTLS authenticates *who opened the connection*; it does not authorize *what
150+
that caller may do*, so an authenticated-but-untrusted pod can still invoke
151+
whatever RPC surface is enabled — at minimum `FetchAndParse` against your
152+
configured fetchers, and the runtime-mutation RPCs too if you have set
153+
`allowComponentModifications`. Restricting reachability with a `NetworkPolicy` is
154+
therefore required, not optional — running in Kubernetes without one leaves
155+
tika-grpc reachable by every pod in the cluster.
156+
32157
== Per-Request `ParseContext`
33158

34159
`FetchAndParseRequest.parse_context_json` lets the caller override the
@@ -46,6 +171,11 @@ parse-context component names; values are their JSON configs.
46171
See `META-INF/tika/parse-context.idx` (generated at build time from
47172
`@TikaComponent` annotations) for the available component names.
48173

174+
NOTE: Per-request configuration is disabled by default. A request that sets
175+
`parse_context_json` (or `additional_fetch_config_json`) is rejected with
176+
`PERMISSION_DENIED` unless `allowPerRequestConfig` is enabled. See
177+
<<_capability_flags,Capability Flags>>.
178+
49179
== Topics
50180

51181
// Add links to specific topics as they are created

docs/modules/ROOT/pages/using-tika/index.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ and microservice architectures.
3636

3737
xref:using-tika/grpc/index.adoc[gRPC]::
3838
Use Tika via gRPC protocol. Best for high-performance, cross-language communication.
39+
+
40+
NOTE: tika-grpc is more exposed by default than tika-server — by default it has no
41+
transport security or per-caller authorization, and its core fetch-and-parse surface
42+
is always on. (Its most dangerous capabilities — runtime fetcher/iterator changes and
43+
per-request parse configuration — are off by default.) Run it only on a trusted,
44+
access-controlled network. See the
45+
xref:using-tika/grpc/index.adoc#_security[Security] section.
3946

4047
== Which Should I Use?
4148

0 commit comments

Comments
 (0)