Skip to content

Commit 06aff7d

Browse files
authored
Merge pull request #15 from arenadata/ADH-6782
ADH-6782: Add SPNEGO authentication for History Server & SQL Gateway REST APIs
2 parents d60db8f + 2b7b016 commit 06aff7d

72 files changed

Lines changed: 8375 additions & 35 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.

docs/content/docs/deployment/advanced/historyserver.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ bin/historyserver.sh (start|start-foreground|stop)
4343
```
4444

4545
By default, this server binds to `localhost` and listens at port `8082`.
46+
If you bind the HistoryServer to a network-facing address such as `0.0.0.0`, enable authentication or place it behind an authenticated gateway. Without authentication, any user with network access can inspect archived job metadata, execution plans, configuration values, timestamps, and configured log links.
4647

4748
Currently, you can only run it as a standalone process.
4849

@@ -75,6 +76,33 @@ The contained archives are downloaded and cached in the local filesystem. The lo
7576

7677
Check out the configuration page for a [complete list of configuration options]({{< ref "docs/deployment/config" >}}#history-server).
7778

79+
## SPNEGO Authentication
80+
81+
The HistoryServer web UI and REST endpoints can require Kerberos/SPNEGO authentication. This is opt-in; the default `historyserver.web.authentication.type` is `NONE`.
82+
83+
To enable SPNEGO, configure an HTTP service principal and keytab for the HistoryServer process:
84+
85+
```yaml
86+
historyserver.web.authentication.type: KERBEROS
87+
historyserver.web.authentication.kerberos.principal: HTTP/_HOST@EXAMPLE.COM
88+
historyserver.web.authentication.kerberos.keytab: /etc/security/keytabs/flink-historyserver.keytab
89+
historyserver.web.authentication.signature.secret-file: /etc/flink/historyserver-auth-secret
90+
```
91+
92+
The principal must start with `HTTP/`. The `_HOST` placeholder is replaced with the local hostname, and `*` can be used to accept all `HTTP/` principals present in the configured keytab. If `historyserver.web.authentication.kerberos.name-rules` is not configured, the default Hadoop auth-to-local rule is used.
93+
94+
When authentication is enabled, requests without a valid cookie or `Authorization: Negotiate` header return `401` with `WWW-Authenticate: Negotiate`. A valid SPNEGO exchange issues a signed `hadoop.auth` cookie and then proceeds to the existing HistoryServer handlers. Invalid SPNEGO tokens return `403`.
95+
96+
Clients with Kerberos credentials can access the HistoryServer with:
97+
98+
```shell
99+
curl --negotiate -u : http://historyserver.example.com:8082/jobs/overview
100+
```
101+
102+
If multiple HistoryServer instances serve the same endpoint, configure the same `historyserver.web.authentication.signature.secret` or `historyserver.web.authentication.signature.secret-file` on all instances so that authentication cookies are accepted consistently. If neither option is configured, a random process-local signing secret is generated at startup.
103+
104+
SPNEGO authenticates the caller only. It does not add per-user or per-group authorization, and it does not change JobManager or TaskManager REST authentication.
105+
78106
## Log Integration
79107

80108
Flink does not provide built-in methods for archiving logs of completed jobs.

docs/content/docs/deployment/config.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,14 @@ You can configure checkpointing directly in code within your Flink job or applic
161161

162162
**Web UI**
163163

164+
- `web.authentication.type`: Controls authentication for the JobManager Web UI and REST endpoint *(NONE by default)*. Set this to `KERBEROS` to require SPNEGO authentication on all `8081` paths.
164165
- `web.submit.enable`: Enables uploading and starting jobs through the Flink UI *(true by default)*. Please note that even when this is disabled, session clusters still accept jobs through REST requests (HTTP calls). This flag only guards the feature to upload jobs in the UI.
165166
- `web.cancel.enable`: Enables canceling jobs through the Flink UI *(true by default)*. Please note that even when this is disabled, session clusters still cancel jobs through REST requests (HTTP calls). This flag only guards the feature to cancel jobs in the UI.
166167
- `web.upload.dir`: The directory where to store uploaded jobs. Only used when `web.submit.enable` is true.
167168
- `web.exception-history-size`: Sets the size of the exception history that prints the most recent failures that were handled by Flink for a job.
168169

170+
Exposing the JobManager Web UI / REST endpoint to an untrusted network without authentication allows unauthenticated job submission and control operations. Enable `web.authentication.type: KERBEROS` or place the endpoint behind an authenticated proxy before exposing port `8081`.
171+
169172
**Other**
170173

171174
- `io.tmp.dirs`: The directories where Flink puts local data, defaults to the system temp directory (`java.io.tmpdir` property). If a list of directories is configured, Flink will rotate files across the directories.

docs/content/docs/deployment/security/security-kerberos.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ The following services and connectors are supported for Kerberos authentication:
6060
- HDFS
6161
- HBase
6262
- ZooKeeper
63+
- JobManager Web UI / REST endpoint (SPNEGO)
6364

6465
Note that it is possible to enable the use of Kerberos independently for each service or connector.
6566
For example, the user may enable Hadoop security without necessitating the use of Kerberos for ZooKeeper,
@@ -92,6 +93,34 @@ dynamic entries provided by this module.
9293
This module configures certain process-wide ZooKeeper security-related settings, namely the ZooKeeper service name (default: `zookeeper`)
9394
and the JAAS login context name (default: `Client`).
9495

96+
### JobManager Web UI SPNEGO Authentication
97+
98+
The JobManager Web UI and REST endpoint are unauthenticated by default. If port `8081` is reachable from an untrusted network, unauthenticated users can submit jobs and perform control operations. To require Kerberos/SPNEGO authentication on all JobManager WebMonitor paths, enable:
99+
100+
```yaml
101+
web.authentication.type: KERBEROS
102+
web.authentication.kerberos.principal: HTTP/_HOST@EXAMPLE.COM
103+
web.authentication.kerberos.keytab: /etc/security/keytabs/flink-jobmanager-http.keytab
104+
web.authentication.kerberos.name-rules: DEFAULT
105+
web.authentication.token.validity: 10 h
106+
web.authentication.cookie.path: /
107+
web.authentication.signature.secret-file: /etc/flink/jobmanager-web-auth-secret
108+
```
109+
110+
The principal must start with `HTTP/`. The `_HOST` placeholder is replaced from `rest.address`, then `rest.bind-address`, then the local canonical hostname. Use `*` to accept all `HTTP/` principals present in the configured keytab.
111+
112+
When enabled, requests without a valid authentication cookie or `Authorization: Negotiate` header receive `401` with `WWW-Authenticate: Negotiate`; malformed or invalid SPNEGO tokens receive `403`. A successful SPNEGO exchange issues a signed `hadoop.auth` cookie, so subsequent requests do not need to negotiate Kerberos again until the cookie expires.
113+
114+
Clients with Kerberos credentials can access the endpoint with:
115+
116+
```bash
117+
curl --negotiate -u : http://jobmanager.example.com:8081/jobs
118+
```
119+
120+
For multiple JobManager instances behind the same address, configure a shared `web.authentication.signature.secret` or `web.authentication.signature.secret-file`; otherwise each process uses a random local signing secret and cannot verify cookies issued by another process.
121+
122+
SPNEGO authenticates the caller only. It does not add per-user authorization, user or group allowlists, Ranger policy enforcement, Knox integration, session ownership enforcement, or built-in Flink CLI / REST client SPNEGO support.
123+
95124
## Deployment Modes
96125
Here is some information specific to each deployment mode.
97126

docs/content/docs/dev/table/sql-gateway/overview.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ $ ./bin/sql-gateway.sh start -Dsql-gateway.endpoint.rest.address=localhost
5757
The command starts the SQL Gateway with REST Endpoint that listens on the address localhost:8083. You can use the curl command to check
5858
whether the REST Endpoint is available.
5959

60+
{{< hint warning >}}
61+
The SQL Gateway REST endpoint does not authenticate requests by default. If it is bound to a network-facing address, any client with network access can create sessions and execute SQL unless you enable REST SPNEGO authentication or protect the endpoint with external access controls.
62+
{{< /hint >}}
63+
6064
```bash
6165
$ curl http://localhost:8083/v1/info
6266
{"productName":"Apache Flink","version":"{{< version >}}"}

docs/content/docs/dev/table/sql-gateway/rest.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,85 @@ Endpoint Options
8888
<td>Integer</td>
8989
<td>The port that the client connects to. If bind-port has not been specified, then the sql gateway server will bind to this port.</td>
9090
</tr>
91+
<tr>
92+
<td><h5>sql-gateway.endpoint.rest.authentication.type</h5></td>
93+
<td style="word-wrap: break-word;">NONE</td>
94+
<td>Enum</td>
95+
<td>Authentication type for the SQL Gateway REST endpoint. Supported values are NONE and KERBEROS.</td>
96+
</tr>
97+
<tr>
98+
<td><h5>sql-gateway.endpoint.rest.authentication.kerberos.principal</h5></td>
99+
<td style="word-wrap: break-word;">(none)</td>
100+
<td>String</td>
101+
<td>Kerberos principal for accepting SPNEGO requests when REST authentication type is KERBEROS. The value supports HTTP/_HOST@REALM host replacement and * to load all HTTP principals from the keytab.</td>
102+
</tr>
103+
<tr>
104+
<td><h5>sql-gateway.endpoint.rest.authentication.kerberos.keytab</h5></td>
105+
<td style="word-wrap: break-word;">(none)</td>
106+
<td>String</td>
107+
<td>Path to the keytab containing the REST SPNEGO service principal. This option is required when REST authentication type is KERBEROS.</td>
108+
</tr>
109+
<tr>
110+
<td><h5>sql-gateway.endpoint.rest.authentication.kerberos.name-rules</h5></td>
111+
<td style="word-wrap: break-word;">DEFAULT</td>
112+
<td>String</td>
113+
<td>Kerberos auth-to-local rules used to map the authenticated Kerberos principal to a local user name.</td>
114+
</tr>
115+
<tr>
116+
<td><h5>sql-gateway.endpoint.rest.authentication.token.validity</h5></td>
117+
<td style="word-wrap: break-word;">10 h</td>
118+
<td>Duration</td>
119+
<td>Validity of the signed REST authentication cookie issued after a successful SPNEGO exchange.</td>
120+
</tr>
121+
<tr>
122+
<td><h5>sql-gateway.endpoint.rest.authentication.cookie.path</h5></td>
123+
<td style="word-wrap: break-word;">/</td>
124+
<td>String</td>
125+
<td>Path attribute for the REST authentication cookie.</td>
126+
</tr>
127+
<tr>
128+
<td><h5>sql-gateway.endpoint.rest.authentication.signature.secret</h5></td>
129+
<td style="word-wrap: break-word;">(none)</td>
130+
<td>String</td>
131+
<td>Shared secret used to sign REST authentication cookies. If neither this option nor signature.secret-file is configured, a random process-local secret is generated.</td>
132+
</tr>
133+
<tr>
134+
<td><h5>sql-gateway.endpoint.rest.authentication.signature.secret-file</h5></td>
135+
<td style="word-wrap: break-word;">(none)</td>
136+
<td>String</td>
137+
<td>Path to a file containing the shared secret used to sign REST authentication cookies. Configure either signature.secret or signature.secret-file, but not both.</td>
138+
</tr>
91139
</tbody>
92140
</table>
93141

142+
REST SPNEGO Authentication
143+
----------------
144+
145+
By default, the REST endpoint does not authenticate requests. If the endpoint is reachable from an untrusted network, any client that can connect to it can create sessions, execute SQL, submit jobs, and access configured data sources. Bind the endpoint to a trusted interface, place it behind an authenticated gateway, or enable SPNEGO authentication before exposing it beyond a trusted boundary.
146+
147+
SPNEGO authentication is opt-in and applies to every SQL Gateway REST path, including `/v*/info`.
148+
149+
```yaml
150+
sql-gateway.endpoint.rest.authentication.type: KERBEROS
151+
sql-gateway.endpoint.rest.authentication.kerberos.principal: HTTP/_HOST@EXAMPLE.COM
152+
sql-gateway.endpoint.rest.authentication.kerberos.keytab: /etc/security/keytabs/flink-sql-gateway.keytab
153+
sql-gateway.endpoint.rest.authentication.kerberos.name-rules: DEFAULT
154+
sql-gateway.endpoint.rest.authentication.signature.secret-file: /etc/flink/sql-gateway-cookie-secret
155+
```
156+
157+
Clients must use an HTTP client that can negotiate SPNEGO, for example:
158+
159+
```bash
160+
$ kinit user@EXAMPLE.COM
161+
$ curl --negotiate -u : http://sql-gateway-host:8083/v1/info
162+
$ curl --negotiate -u : --request POST http://sql-gateway-host:8083/v1/sessions
163+
```
164+
165+
Unauthenticated requests receive `401` with `WWW-Authenticate: Negotiate`. Malformed or invalid SPNEGO tokens receive `403`.
166+
After a successful SPNEGO exchange, the REST endpoint issues a signed `hadoop.auth` cookie. Multi-instance or load-balanced SQL Gateway deployments must configure the same `sql-gateway.endpoint.rest.authentication.signature.secret` or `sql-gateway.endpoint.rest.authentication.signature.secret-file` on every instance; otherwise cookies issued by one instance will not be accepted by another.
167+
168+
The built-in Flink SQL Client and Flink JDBC Driver do not negotiate SPNEGO with the SQL Gateway REST endpoint in this change. Use an HTTP SPNEGO-capable client or put the SQL Gateway behind a separate authenticated gateway or proxy when those clients are required.
169+
94170
REST API
95171
----------------
96172

docs/layouts/shortcodes/generated/history_server_configuration.html

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,54 @@
5656
<td>String</td>
5757
<td>Address of the HistoryServer's web interface.</td>
5858
</tr>
59+
<tr>
60+
<td><h5>historyserver.web.authentication.cookie.path</h5></td>
61+
<td style="word-wrap: break-word;">"/"</td>
62+
<td>String</td>
63+
<td>Cookie path for HistoryServer SPNEGO authentication cookies.</td>
64+
</tr>
65+
<tr>
66+
<td><h5>historyserver.web.authentication.kerberos.keytab</h5></td>
67+
<td style="word-wrap: break-word;">(none)</td>
68+
<td>String</td>
69+
<td>Absolute path to the keytab file for the HistoryServer SPNEGO principal. Required when HistoryServer web authentication type is KERBEROS.</td>
70+
</tr>
71+
<tr>
72+
<td><h5>historyserver.web.authentication.kerberos.name-rules</h5></td>
73+
<td style="word-wrap: break-word;">(none)</td>
74+
<td>String</td>
75+
<td>Kerberos auth-to-local rules used to map authenticated principals to local user names. If unset, the default rule is used.</td>
76+
</tr>
77+
<tr>
78+
<td><h5>historyserver.web.authentication.kerberos.principal</h5></td>
79+
<td style="word-wrap: break-word;">(none)</td>
80+
<td>String</td>
81+
<td>Kerberos principal for HistoryServer SPNEGO authentication. Required when HistoryServer web authentication type is KERBEROS. The principal must start with HTTP/. The _HOST placeholder is replaced with the local hostname. Use * to accept all HTTP principals in the keytab.</td>
82+
</tr>
83+
<tr>
84+
<td><h5>historyserver.web.authentication.signature.secret</h5></td>
85+
<td style="word-wrap: break-word;">(none)</td>
86+
<td>String</td>
87+
<td>Shared secret for signing HistoryServer SPNEGO authentication cookies. If neither this option nor the secret-file option is set, a random process-local secret is generated. Configure the same secret for all HistoryServer instances that should accept each other's authentication cookies.</td>
88+
</tr>
89+
<tr>
90+
<td><h5>historyserver.web.authentication.signature.secret-file</h5></td>
91+
<td style="word-wrap: break-word;">(none)</td>
92+
<td>String</td>
93+
<td>File containing the shared secret for signing HistoryServer SPNEGO authentication cookies. Configure the same secret file for all HistoryServer instances that should accept each other's authentication cookies.</td>
94+
</tr>
95+
<tr>
96+
<td><h5>historyserver.web.authentication.token.validity</h5></td>
97+
<td style="word-wrap: break-word;">10 h</td>
98+
<td>Duration</td>
99+
<td>Validity period for HistoryServer SPNEGO authentication cookies.</td>
100+
</tr>
101+
<tr>
102+
<td><h5>historyserver.web.authentication.type</h5></td>
103+
<td style="word-wrap: break-word;">NONE</td>
104+
<td><p>Enum</p></td>
105+
<td>Authentication type for the HistoryServer web frontend and REST endpoints.<br /><br />Possible values:<ul><li>"NONE"</li><li>"KERBEROS"</li></ul></td>
106+
</tr>
59107
<tr>
60108
<td><h5>historyserver.web.port</h5></td>
61109
<td style="word-wrap: break-word;">8082</td>

docs/layouts/shortcodes/generated/sql_gateway_rest_configuration.html

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,54 @@
1414
<td>String</td>
1515
<td>The address that should be used by clients to connect to the sql gateway server.</td>
1616
</tr>
17+
<tr>
18+
<td><h5>authentication.cookie.path</h5></td>
19+
<td style="word-wrap: break-word;">"/"</td>
20+
<td>String</td>
21+
<td>Cookie path used for SQL Gateway REST authentication cookies.</td>
22+
</tr>
23+
<tr>
24+
<td><h5>authentication.kerberos.keytab</h5></td>
25+
<td style="word-wrap: break-word;">(none)</td>
26+
<td>String</td>
27+
<td>Kerberos keytab used by the SQL Gateway REST endpoint SPNEGO acceptor.</td>
28+
</tr>
29+
<tr>
30+
<td><h5>authentication.kerberos.name-rules</h5></td>
31+
<td style="word-wrap: break-word;">"DEFAULT"</td>
32+
<td>String</td>
33+
<td>Kerberos auth-to-local rules used to derive the local user name from the authenticated Kerberos principal.</td>
34+
</tr>
35+
<tr>
36+
<td><h5>authentication.kerberos.principal</h5></td>
37+
<td style="word-wrap: break-word;">(none)</td>
38+
<td>String</td>
39+
<td>Kerberos principal used by the SQL Gateway REST endpoint SPNEGO acceptor. The HTTP/_HOST@REALM pattern is supported, and '*' uses all HTTP principals from the keytab.</td>
40+
</tr>
41+
<tr>
42+
<td><h5>authentication.signature.secret</h5></td>
43+
<td style="word-wrap: break-word;">(none)</td>
44+
<td>String</td>
45+
<td>Shared secret used to sign SQL Gateway REST authentication cookies. If neither this option nor authentication.signature.secret-file is configured, a random per-process secret is used.</td>
46+
</tr>
47+
<tr>
48+
<td><h5>authentication.signature.secret-file</h5></td>
49+
<td style="word-wrap: break-word;">(none)</td>
50+
<td>String</td>
51+
<td>File containing the shared secret used to sign SQL Gateway REST authentication cookies. If neither this option nor authentication.signature.secret is configured, a random per-process secret is used.</td>
52+
</tr>
53+
<tr>
54+
<td><h5>authentication.token.validity</h5></td>
55+
<td style="word-wrap: break-word;">10 h</td>
56+
<td>Duration</td>
57+
<td>Validity period of the SQL Gateway REST authentication cookie.</td>
58+
</tr>
59+
<tr>
60+
<td><h5>authentication.type</h5></td>
61+
<td style="word-wrap: break-word;">NONE</td>
62+
<td><p>Enum</p></td>
63+
<td>The authentication type for the SQL Gateway REST endpoint. Supported values are NONE and KERBEROS.<br /><br />Possible values:<ul><li>"NONE"</li><li>"KERBEROS"</li></ul></td>
64+
</tr>
1765
<tr>
1866
<td><h5>bind-address</h5></td>
1967
<td style="word-wrap: break-word;">(none)</td>

0 commit comments

Comments
 (0)