Repository navigation
branch-4.1: [feature](fe) Gate HMS catalog SSRF endpoints at CREATE / ALTER CATALOG #69588 - #70092
Merged
Merged
Conversation
…OG (apache#69588) ### What problem does this PR solve? Issue Number: None Related PR: apache#69588 Problem Summary: Backport of apache#69588, adapted to the 4.x catalog classes. The master change is built on the fe-connector plugin SPI (ConnectorProvider, ConnectorSecuritySurface, PluginDrivenExternalCatalog), which does not exist on this branch, so it cannot be cherry-picked. When an operator configures the SSRF security SDK (security_checker_class_name), CREATE / ALTER CATALOG did not check an HMS catalog's metastore endpoint against the SSRF policy, so a user with CREATE privilege on a catalog could point the FE's HMS client at an intranet address, and ALTER could repoint an existing one. HMSExternalCatalog now applies the same gate as master on CREATE (checkWhenCreating, before test_connection) and on ALTER, never on replay. It brackets a lightweight TCP connect to every endpoint in hive.metastore.uris, uri and metastore.thrift.uris with the SDK's net-hook, so an intranet target is rejected; a plain connect failure is ignored. Schemed endpoints use java.net.URI host/port semantics, and while a checker is configured an endpoint value containing a ${...} placeholder is rejected, because the client's HiveConf expands it only after the check. With no checker configured the gate is a no-op. The probe must not hold CatalogMgr's write lock, under which 4.x validates ALTER CATALOG (master moved that validation out of the lock in apache#68585). CatalogMgr.alterCatalogProps now snapshots the catalog's properties under the read lock, runs the new ExternalCatalog.validatePropertiesBeforeUpdateUnlocked hook (a no-op by default; HMSExternalCatalog runs the SSRF gate there) without holding the lock, and applies the ALTER under the write lock only if the same catalog still has the snapshot's properties; otherwise it checks again. All other ALTER validation still runs under the lock, unchanged. CREATE already probes before CatalogMgr takes its lock. SecurityChecker gains the no-arg (TCP) start, isEnabled() and checkEndpointForSsrf(). UrlSecurityChecker now binds the SDK's no-arg stop, so the net-hook is no longer leaked onto the pooled FE thread after a bracketed request. checkEndpointForSsrf throws Exception with master's messages because DdlException lives in fe-core on this branch; the HMS gate rethrows it as DdlException. Not ported, because 4.x has no connector plugins: the driver_url gate migration (4.x checks driver_url in each catalog's checkProperties), the rejection of ALTER while a connector provider is unavailable, and the connector API version bump. ### Release note When an SSRF checker is configured, CREATE / ALTER CATALOG checks HMS endpoint destinations (hive.metastore.uris, uri, and metastore.thrift.uris), including URIs containing query, fragment, or userinfo components, and rejects an HMS endpoint value that contains a ${...} placeholder. ### Check List (For Author) - Test: Unit Test - SecurityCheckerTest, HMSExternalCatalogSsrfGateTest, HMSExternalCatalogParquetTimeZoneTest, HttpTableValuedFunctionTest, CatalogMgrTest, CatalogMgrLanceGuardTest and CatalogVarbinaryMigrationTest, with Checkstyle on fe-common and fe-core - Behavior changed: Yes - with an SSRF checker configured, CREATE / ALTER CATALOG probes HMS endpoints and rejects intranet targets and placeholders; the SDK net-hook is now removed after each bracketed request; ALTER CATALOG checks again if the catalog changes while its lock-free checks run - Does this need documentation: No Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
Merged
3 of 16 tasks
Contributor
Author
|
run buildall |
Contributor
FE UT Coverage ReportIncrement line coverage |
yiguolei
pushed a commit
that referenced
this pull request
Nov 4, 2026
… ALTER CATALOG #69588 (#70091) ### What problem does this PR solve? Issue Number: None Related PR: #69588 (Same backport for branch-4.1: #70092) Problem Summary: Backport of #69588 to branch-4.2. The master change cannot be cherry-picked: it is built on the fe-connector plugin SPI (`ConnectorProvider`, `ConnectorSecuritySurface`, `PluginDrivenExternalCatalog`), and none of those exist on 4.2. This PR ports the security fix itself onto the 4.2 catalog classes, with the same rules and the same error messages. **In short** With the SSRF security SDK configured (`security_checker_class_name`), CREATE / ALTER CATALOG on 4.2 never checked an HMS catalog's metastore endpoint, so a user with CREATE_PRIV on a catalog (no ADMIN) could make the FE's HMS client connect to an intranet address. `HMSExternalCatalog` now runs the same CREATE / ALTER gate master got in #69588 (on ALTER, before `CatalogMgr` takes its write lock), and the SDK binding no longer leaks its net-hook onto pooled FE threads. Without a checker configured (the open-source default), the new gate does nothing. **Background** - `security_checker_class_name` names a third-party SDK (Aliyun `com.aliyun.securitysdk.SecurityUtil`), loaded by reflection through `SecurityChecker` / `UrlSecurityChecker` in fe-common. Its net-hook sits at the JDK socket layer: install it on the current thread, connect, and the connect throws `SSRFUnsafeConnectionException` (a `SecurityException`) if the resolved address is intranet. The SDK has no "is this host intranet" string API, so it can only judge a real connect. Today only HTTP callers use it (HTTP TVF, S3, ES, small-file download, stage creation). - An HMS catalog takes its endpoint from `hive.metastore.uris` or its alias `uri`. `HMSBaseProperties` sets that value, plus every other `hive.`-prefixed catalog property, into the `HiveConf` of the FE's HMS client. `HiveMetaStoreClient` reads the endpoint through `MetastoreConf.getVar`, which looks at `metastore.thrift.uris` first, and through Hadoop's `Configuration.get`, which expands `${...}` placeholders (other properties, `${env.X}`, JVM system properties). **1. The problem, and what it cost** - CREATE CATALOG (CREATE_PRIV) and ALTER CATALOG (ALTER privilege on the catalog) accepted any metastore endpoint, so the FE opened a thrift connection to a host inside its own network on behalf of a non-admin user. - `UrlSecurityChecker` bound the SDK's stop method as `stopSSRFNetHookChecking(String)` but invoked it with no argument, so stop never ran and the net-hook stayed on the pooled FE thread after every bracketed HTTP request. - Only the http form of the SDK's start was bound, so nothing could hook a non-http connection such as HMS thrift. **2. How this PR fixes it** - fe-common, `SecurityChecker`: adds the no-arg `startSSRFChecking()` (the SDK's TCP form), `isEnabled()`, and `checkEndpointForSsrf(host, port)`, which brackets a single 5-second TCP connect with the net-hook. A `SecurityException` from the connect is the rejection; a refused / timed-out / unknown-host connect is ignored, so a public endpoint that is down right now can still be used. `UrlSecurityChecker` binds the SDK's no-arg start and no-arg stop; `DummySecurityChecker.isEnabled()` returns false. The singleton becomes lazily initialized with a test setter. - fe-core, `HMSExternalCatalog`: `checkWhenCreating()` (CREATE, before `test_connection`) and the new `validatePropertiesBeforeUpdateUnlocked()` (ALTER) call the new gate on `hive.metastore.uris`, `uri` and `metastore.thrift.uris`. The rules match master: no-op without a checker; a value containing `${` is rejected before anything else (so an ALTER of only the property a stored placeholder refers to is rejected as well); an ALTER probes only when it touches one of these keys; every entry of a comma-separated HA list is probed; schemed values are parsed with `java.net.URI` host/port semantics, so a query, fragment or userinfo part cannot hide the real destination. - fe-core, `CatalogMgr.alterCatalogProps`: on 4.2 ALTER CATALOG is validated under `CatalogMgr`'s write lock, and a probe to an unreachable endpoint can wait up to 5 seconds, so the probe must not run there. ALTER now takes a snapshot of the catalog's properties under the read lock, runs `ExternalCatalog.validatePropertiesBeforeUpdateUnlocked` (new, a no-op by default) on it without holding the lock, and then applies the change under the write lock only if the same catalog still has the snapshot's properties; if another DDL changed or dropped the catalog in between, it starts over from a new snapshot. The rest of the ALTER validation still runs under the lock, unchanged. CREATE already probes before `CatalogMgr` takes its lock. Where the backport differs from master: | Master (#69588) | This PR | Why | | --- | --- | --- | | Endpoint keys declared by the hive connector through `ConnectorSecuritySurface` | Keys are a constant in `HMSExternalCatalog` | 4.2 has no connector SPI; `HMSExternalCatalog` is already the HMS-specific class | | Gate in `PluginDrivenExternalCatalog` | Gate in `HMSExternalCatalog`, through `checkWhenCreating` (CREATE) and the new `validatePropertiesBeforeUpdateUnlocked` (ALTER) | Neither runs on replay: `CatalogFactory` calls `checkWhenCreating` only for a new catalog, and replay goes through `replayAlterCatalogProps`, not `alterCatalogProps` | | `driver_url` gate moved onto the security surface, `driverUrlKeysOf` deleted | Not ported | 4.2 checks `driver_url` in `JdbcExternalCatalog` / `IcebergExternalCatalog` / `PaimonExternalCatalog.checkProperties`; there is no key table to replace | | ALTER rejected while the connector provider is missing | Not ported | 4.2 has no connector providers | | `checkEndpointForSsrf` throws `DdlException` | Throws `Exception` with the same messages; the HMS gate rethrows it as `DdlException` | On 4.2 `DdlException` is in fe-core, which fe-common cannot reference | | Connector plugin API 22.0 -> 23.0 | No version change | No connector plugin API on 4.2 | | All ALTER validation runs before `CatalogMgr` takes its write lock (#68585) | Only the lock-free checks (the probe) run before the write lock, through `validatePropertiesBeforeUpdateUnlocked`, on a snapshot that is checked again under the lock; the rest of ALTER validation stays under the lock | #68585 is not on 4.2 and also changes HDFS HA validation; this keeps the change to the probe | | `metastore.thrift.uris` gated because the hive connector passes every property to `HiveConf` | Gated as well | `HMSBaseProperties` copies only `hive.`-prefixed properties today, so the key does not reach the client yet; gating it keeps the gate correct if that copy widens, and keeps one rule on both branches | **3. Results** With an SSRF checker configured: | Statement | Before | After | | --- | --- | --- | | `CREATE CATALOG ... ("type"="hms", "hive.metastore.uris"="thrift://10.0.0.1:9083")` | Accepted | Rejected: `Endpoint 10.0.0.1:9083 is rejected by the SSRF policy (intranet address not allowed): ...` | | Same, with `test_connection` = false | Accepted | Rejected (the gate does not depend on `test_connection`) | | `ALTER CATALOG c SET PROPERTIES ("hive.metastore.uris"="thrift://10.0.0.1:9083")` | Accepted | Rejected | | `thrift://user@10.0.0.1:9083?x#y`, or an intranet host second in an HA list | Accepted | Rejected | | `"hive.metastore.uris"="thrift://${hive.x}:9083"` with `"hive.x"="127.0.0.1"` | Accepted; the client connects to 127.0.0.1 | Rejected: `... must give its endpoint literally while an SSRF checker is configured ...` | | Public endpoint that is currently unreachable | Accepted | Accepted (a failed connect is not an SSRF signal) | | ALTER of an unrelated property | Accepted | Accepted, no probe | | ALTER that probes an unreachable public endpoint | No probe | Probes for up to 5 seconds without holding `CatalogMgr`'s lock | | Replay of CREATE / ALTER from the edit log | No probe | No probe | Without a checker configured, nothing changes. The only change outside the gate is that the SDK's net-hook is now removed after each bracketed HTTP request, as intended. **4. The classes, and how they call each other** - `SecurityChecker` (fe-common): the SSRF primitive `checkEndpointForSsrf`, plus `isEnabled()` and the TCP start. - `UrlSecurityChecker` / `DummySecurityChecker` (fe-common): SDK binding / no-op. - `HMSExternalCatalog` (fe-core): the endpoint keys, `checkEndpointsAgainstSsrf`, `parseEndpoint`, and the two hooks. - `ExternalCatalog` (fe-core): the new `validatePropertiesBeforeUpdateUnlocked` hook, a no-op by default. - `CatalogMgr` (fe-core): `alterCatalogProps` runs that hook on a snapshot before taking its write lock and checks the snapshot again under it. ``` CREATE CATALOG CatalogFactory.createFromCommand └ HMSExternalCatalog.checkWhenCreating ├ checkEndpointsAgainstSsrf (new) -> SecurityChecker.checkEndpointForSsrf └ super.checkWhenCreating (test_connection) ALTER CATALOG ... SET PROPERTIES CatalogMgr.alterCatalogProps ├ read lock: snapshot the catalog's properties ├ no lock: HMSExternalCatalog.validatePropertiesBeforeUpdateUnlocked (new) │ └ checkEndpointsAgainstSsrf (new) -> SecurityChecker.checkEndpointForSsrf └ write lock: same catalog, same properties? if not, start over └ alterExternalCatalogPropsFenced -> validatePropertiesBeforeUpdate -> checkProperties (unchanged), publish, journal SecurityChecker.checkEndpointForSsrf(host, port) ├ startSSRFChecking() -> SDK startSSRFNetHookChecking() ├ doConnect(host, port, 5s) -> SDK throws SecurityException for an intranet target └ stopSSRFChecking() -> SDK stopSSRFNetHookChecking() Replay: CatalogFactory.createFromLog and replayAlterCatalogProps(isReplay=true) call neither hook. ``` SSRF surface note (per repo policy): the probe is a new FE -> user-named-host outbound TCP connect, made only when the operator installed the SSRF SDK and only at CREATE / ALTER CATALOG (CREATE_PRIV or ADMIN for CREATE, ALTER privilege for ALTER). It exists only so the SDK can reject an intranet target. Known limits, same as master: it is a point-in-time check, so it does not guard a later runtime connection (DNS rebinding) or a client that bypasses the JDK socket layer. ### Release note When an SSRF checker is configured, CREATE / ALTER CATALOG checks HMS endpoint destinations (`hive.metastore.uris`, `uri`, and `metastore.thrift.uris`), including URIs containing query, fragment, or userinfo components, and rejects an HMS endpoint value that contains a `${...}` placeholder. ### Check List (For Author) - Test <!-- At least one of them must be included. --> - [ ] Regression test - [x] Unit Test - [ ] Manual test (add detailed scripts or steps below) - [ ] No need to test or manual test. Explain why: - [ ] This is a refactor/code format and no logic has been changed. - [ ] Previous test can cover this change. - [ ] No code files have been changed. - [ ] Other reason <!-- Add your reason? --> - Unit Test: the new `SecurityCheckerTest` (6 tests) and `HMSExternalCatalogSsrfGateTest` (48), plus the existing `HMSExternalCatalogParquetTimeZoneTest`, `HttpTableValuedFunctionTest`, `CatalogMgrTest`, `CatalogMgrLanceGuardTest`, `ExternalCatalogTest`, `ExternalCatalogRuntimeStateTest`, `CatalogVarbinaryMigrationTest`, `HMSPropertiesTest`, `HiveTableSinkTest`, `JdbcExternalCatalogTest` and `PaimonExternalCatalogDriverUrlSecurityTest`: 134 tests in 13 classes passed with `TZ=Asia/Shanghai mvn test -pl fe-common,fe-core -am`; Checkstyle reports 0 violations in fe-common and fe-core. - `HMSExternalCatalogSsrfGateTest` also drives ALTER through a real `CatalogMgr`. It checks that the probe runs while the thread holds neither the read nor the write lock, that an intranet target leaves the catalog and the journal untouched, and that an ALTER whose catalog is altered or dropped during the probe checks again, or fails with `No catalog found`, instead of applying a stale check. - Mutation check: each of 21 mutants is killed by at least one new test. The mutants drop either hook call, the `isEnabled()` guard of the gate or of `checkEndpointForSsrf`, the touched-key guard, a declared key, the comma split or the URI parsing; run the placeholder rule only on touched keys or ahead of the `isEnabled()` guard; swallow the SDK's rejection or a failed hook install; treat a failed connect as a rejection; skip `stopSSRFChecking()` in `finally`; probe under `CatalogMgr`'s write lock (from `validatePropertiesBeforeUpdate`, or by calling the lock-free hook under the lock); or drop the snapshot comparison or the catalog identity check under the lock. - Checked on this branch that `HMSBaseProperties` hands `hive.metastore.uris` = `thrift://${hive.x}:9083` with `hive.x` = `127.0.0.1` to the HMS client as `thrift://127.0.0.1:9083`, and does not hand it a `metastore.thrift.uris` catalog property. - Behavior changed: - [ ] No. - [x] Yes. With an SSRF checker configured, CREATE / ALTER CATALOG probes HMS metastore endpoints and rejects intranet targets and `${...}` placeholders; the SDK net-hook is now removed after each bracketed request. Without a checker, nothing changes. - Does this need documentation? - [x] No. - [ ] Yes. <!-- Add document PR link here. eg: apache/doris-website#1214 --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label <!-- Add branch pick label that this PR should merge into --> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
yiguolei
approved these changes
Nov 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this PR solve?
Issue Number: None
Related PR: #69588 (Same backport for branch-4.2: #70091)
Problem Summary:
Backport of #69588 to branch-4.1. The master change cannot be cherry-picked: it is built on the fe-connector plugin SPI (
ConnectorProvider,ConnectorSecuritySurface,PluginDrivenExternalCatalog), and none of those exist on 4.1. This PR ports the security fix itself onto the 4.1 catalog classes, with the same rules and the same error messages.In short
With the SSRF security SDK configured (
security_checker_class_name), CREATE / ALTER CATALOG on 4.1 never checked an HMS catalog's metastore endpoint, so a user with CREATE_PRIV on a catalog (no ADMIN) could make the FE's HMS client connect to an intranet address.HMSExternalCatalognow runs the same CREATE / ALTER gate master got in #69588 (on ALTER, beforeCatalogMgrtakes its write lock), and the SDK binding no longer leaks its net-hook onto pooled FE threads. Without a checker configured (the open-source default), the new gate does nothing.Background
security_checker_class_namenames a third-party SDK (Aliyuncom.aliyun.securitysdk.SecurityUtil), loaded by reflection throughSecurityChecker/UrlSecurityCheckerin fe-common. Its net-hook sits at the JDK socket layer: install it on the current thread, connect, and the connect throwsSSRFUnsafeConnectionException(aSecurityException) if the resolved address is intranet. The SDK has no "is this host intranet" string API, so it can only judge a real connect. Today only HTTP callers use it (HTTP TVF, S3, ES, small-file download, stage creation).hive.metastore.urisor its aliasuri.HMSBasePropertiessets that value, plus every otherhive.-prefixed catalog property, into theHiveConfof the FE's HMS client.HiveMetaStoreClientreads the endpoint throughMetastoreConf.getVar, which looks atmetastore.thrift.urisfirst, and through Hadoop'sConfiguration.get, which expands${...}placeholders (other properties,${env.X}, JVM system properties).1. The problem, and what it cost
UrlSecurityCheckerbound the SDK's stop method asstopSSRFNetHookChecking(String)but invoked it with no argument, so stop never ran and the net-hook stayed on the pooled FE thread after every bracketed HTTP request.2. How this PR fixes it
SecurityChecker: adds the no-argstartSSRFChecking()(the SDK's TCP form),isEnabled(), andcheckEndpointForSsrf(host, port), which brackets a single 5-second TCP connect with the net-hook. ASecurityExceptionfrom the connect is the rejection; a refused / timed-out / unknown-host connect is ignored, so a public endpoint that is down right now can still be used.UrlSecurityCheckerbinds the SDK's no-arg start and no-arg stop;DummySecurityChecker.isEnabled()returns false. The singleton becomes lazily initialized with a test setter.HMSExternalCatalog:checkWhenCreating()(CREATE, beforetest_connection) and the newvalidatePropertiesBeforeUpdateUnlocked()(ALTER) call the new gate onhive.metastore.uris,uriandmetastore.thrift.uris. The rules match master: no-op without a checker; a value containing${is rejected before anything else (so an ALTER of only the property a stored placeholder refers to is rejected as well); an ALTER probes only when it touches one of these keys; every entry of a comma-separated HA list is probed; schemed values are parsed withjava.net.URIhost/port semantics, so a query, fragment or userinfo part cannot hide the real destination.CatalogMgr.alterCatalogProps: on 4.1 ALTER CATALOG is validated underCatalogMgr's write lock, and a probe to an unreachable endpoint can wait up to 5 seconds, so the probe must not run there. ALTER now takes a snapshot of the catalog's properties under the read lock, runsExternalCatalog.validatePropertiesBeforeUpdateUnlocked(new, a no-op by default) on it without holding the lock, and then applies the change under the write lock only if the same catalog still has the snapshot's properties; if another DDL changed or dropped the catalog in between, it starts over from a new snapshot. The rest of the ALTER validation still runs under the lock, unchanged. CREATE already probes beforeCatalogMgrtakes its lock.Where the backport differs from master:
ConnectorSecuritySurfaceHMSExternalCatalogHMSExternalCatalogis already the HMS-specific classPluginDrivenExternalCatalogHMSExternalCatalog, throughcheckWhenCreating(CREATE) and the newvalidatePropertiesBeforeUpdateUnlocked(ALTER)CatalogFactorycallscheckWhenCreatingonly for a new catalog, and replay goes throughreplayAlterCatalogProps, notalterCatalogPropsdriver_urlgate moved onto the security surface,driverUrlKeysOfdeleteddriver_urlinJdbcExternalCatalog/IcebergExternalCatalog/PaimonExternalCatalog.checkProperties; there is no key table to replacecheckEndpointForSsrfthrowsDdlExceptionExceptionwith the same messages; the HMS gate rethrows it asDdlExceptionDdlExceptionis in fe-core, which fe-common cannot referenceCatalogMgrtakes its write lock (#68585)validatePropertiesBeforeUpdateUnlocked, on a snapshot that is checked again under the lock; the rest of ALTER validation stays under the lockmetastore.thrift.urisgated because the hive connector passes every property toHiveConfHMSBasePropertiescopies onlyhive.-prefixed properties today, so the key does not reach the client yet; gating it keeps the gate correct if that copy widens, and keeps one rule on both branches3. Results
With an SSRF checker configured:
CREATE CATALOG ... ("type"="hms", "hive.metastore.uris"="thrift://10.0.0.1:9083")Endpoint 10.0.0.1:9083 is rejected by the SSRF policy (intranet address not allowed): ...test_connection= falsetest_connection)ALTER CATALOG c SET PROPERTIES ("hive.metastore.uris"="thrift://10.0.0.1:9083")thrift://user@10.0.0.1:9083?x#y, or an intranet host second in an HA list"hive.metastore.uris"="thrift://${hive.x}:9083"with"hive.x"="127.0.0.1"... must give its endpoint literally while an SSRF checker is configured ...CatalogMgr's lockWithout a checker configured, nothing changes. The only change outside the gate is that the SDK's net-hook is now removed after each bracketed HTTP request, as intended.
4. The classes, and how they call each other
SecurityChecker(fe-common): the SSRF primitivecheckEndpointForSsrf, plusisEnabled()and the TCP start.UrlSecurityChecker/DummySecurityChecker(fe-common): SDK binding / no-op.HMSExternalCatalog(fe-core): the endpoint keys,checkEndpointsAgainstSsrf,parseEndpoint, and the two hooks.ExternalCatalog(fe-core): the newvalidatePropertiesBeforeUpdateUnlockedhook, a no-op by default.CatalogMgr(fe-core):alterCatalogPropsruns that hook on a snapshot before taking its write lock and checks the snapshot again under it.SSRF surface note (per repo policy): the probe is a new FE -> user-named-host outbound TCP connect, made only when the operator installed the SSRF SDK and only at CREATE / ALTER CATALOG (CREATE_PRIV or ADMIN for CREATE, ALTER privilege for ALTER). It exists only so the SDK can reject an intranet target. Known limits, same as master: it is a point-in-time check, so it does not guard a later runtime connection (DNS rebinding) or a client that bypasses the JDK socket layer.
Release note
When an SSRF checker is configured, CREATE / ALTER CATALOG checks HMS endpoint destinations (
hive.metastore.uris,uri, andmetastore.thrift.uris), including URIs containing query, fragment, or userinfo components, and rejects an HMS endpoint value that contains a${...}placeholder.Check List (For Author)
Test
Regression test
Unit Test
Manual test (add detailed scripts or steps below)
No need to test or manual test. Explain why:
Unit Test: the new
SecurityCheckerTest(6 tests) andHMSExternalCatalogSsrfGateTest(48), plus the existingHMSExternalCatalogParquetTimeZoneTest,HttpTableValuedFunctionTest,CatalogMgrTest,CatalogMgrLanceGuardTest,ExternalCatalogTest,ExternalCatalogRuntimeStateTest,CatalogVarbinaryMigrationTest,HMSPropertiesTest,HiveTableSinkTest,JdbcExternalCatalogTestandPaimonExternalCatalogDriverUrlSecurityTest: 134 tests in 13 classes passed withTZ=Asia/Shanghai mvn test -pl fe-common,fe-core -am; Checkstyle reports 0 violations in fe-common and fe-core.HMSExternalCatalogSsrfGateTestalso drives ALTER through a realCatalogMgr. It checks that the probe runs while the thread holds neither the read nor the write lock, that an intranet target leaves the catalog and the journal untouched, and that an ALTER whose catalog is altered or dropped during the probe checks again, or fails withNo catalog found, instead of applying a stale check.Mutation check: each of 21 mutants is killed by at least one new test. The mutants drop either hook call, the
isEnabled()guard of the gate or ofcheckEndpointForSsrf, the touched-key guard, a declared key, the comma split or the URI parsing; run the placeholder rule only on touched keys or ahead of theisEnabled()guard; swallow the SDK's rejection or a failed hook install; treat a failed connect as a rejection; skipstopSSRFChecking()infinally; probe underCatalogMgr's write lock (fromvalidatePropertiesBeforeUpdate, or by calling the lock-free hook under the lock); or drop the snapshot comparison or the catalog identity check under the lock.Checked on this branch that
HMSBasePropertieshandshive.metastore.uris=thrift://${hive.x}:9083withhive.x=127.0.0.1to the HMS client asthrift://127.0.0.1:9083, and does not hand it ametastore.thrift.uriscatalog property.Behavior changed:
${...}placeholders; the SDK net-hook is now removed after each bracketed request. Without a checker, nothing changes.Does this need documentation?
Check List (For Reviewer who merge this PR)