github-actions[bot] commented on code in PR #66205:
URL: https://github.com/apache/doris/pull/66205#discussion_r3710542241
##########
fe/fe-common/src/main/java/org/apache/doris/common/Config.java:
##########
@@ -337,9 +337,25 @@ public class Config extends ConfigBase {
+ "The connection is abandoned if the clock skew is larger than
this value."})
public static long max_bdbje_clock_delta_ms = 5000; // 5s
- @ConfField(mutable = true, description = {
- "Whether to enable authentication for all HTTP interfaces"},
varType = VariableAnnotation.EXPERIMENTAL)
- public static boolean enable_all_http_auth = false;
+ @ConfField(description = {
+ "Whether to enable authentication for all HTTP interfaces. On by
default. "
+ + "While it is off, some HTTP interfaces (for example
parts of the metadata, statistics "
+ + "and admin surface) serve requests without checking
credentials or privileges. "
+ + "This config is deliberately NOT mutable: turning
authentication off must be a recorded, "
+ + "on-disk decision in fe.conf that survives a restart,
not a runtime command. "
+ + "Upgrade note: a cluster upgrading from a version where
this defaulted to false may have "
+ + "callers that poll those interfaces anonymously
(monitoring, metrics scrapers, ops "
+ + "scripts, health probes); those callers will start
getting 401 until they present "
+ + "credentials. The fix is to give them credentials —
setting this back to false in "
+ + "fe.conf is a temporary migration aid that leaves those
interfaces unauthenticated. "
+ + "Also check fe_custom.conf when upgrading: it is read
after fe.conf and overwrites it, "
+ + "and in releases where this flag was mutable an 'ADMIN
SET FRONTEND CONFIG' with "
+ + "persist=true could have written false into it. Making
the flag non-mutable does not "
+ + "remove or migrate such a value, so a cluster can look
clean in fe.conf and still start "
+ + "with authentication off; delete the entry from
fe_custom.conf to pick up the new default. "
+ + "Security scanning and penetration testing must never be
run with this off."},
+ varType = VariableAnnotation.EXPERIMENTAL)
+ public static boolean enable_all_http_auth = true;
Review Comment:
[P1] Preserve the non-admin /api/query contract before enabling this by
default. StmtExecutionAction already authenticates every request, but this flag
also enables its separate database-ADMIN gate before the submitted SQL is
planned under the caller's identity. The existing cloud regression grants a
user only SELECT_PRIV and expects /api/query to succeed while the instance is
normal, so that test—and restricted web/CDC callers whose SQL privileges are
otherwise sufficient—now fail. Decouple this legacy authorization branch from
the authentication default (and make any replacement catalog-aware), then keep
a non-admin query regression.
##########
threat-model.md:
##########
@@ -424,6 +487,102 @@ provenance.
take effect; counter resets unexpectedly; wraparound. *Severity*:
**security-critical** when the configured behavior is broken
(NOT when default is unconfigured — see §4.9).
+11. **HTTP *authentication* on the FE HTTP surface** *(maintainer,
+ M19)*. *Condition*: default config — `enable_all_http_auth` ships
+ **on** for FE (8030) (§4.5a). Scope:
+ - **FE 8030 — every endpoint that routes through the FE auth
+ path** (the `/api/**` and `/rest/v2/**` REST actions), which
+ must establish a caller identity — valid user credentials, or
+ one of the credential forms listed under *Excluded* below —
+ before returning data or performing an action.
+
+ **Read the property title literally: this is a claim about
+ authentication, not a blanket claim about authorization.** The
+ default flip made the FE HTTP surface demand a credential; it did
+ **not** introduce a centralized privilege check. Authorization on
+ FE HTTP is per-handler, and its coverage is uneven. Handlers that
+ do run a privilege check (for example `checkAdminAuth`, or a
+ per-object `PrivPredicate.SHOW` filter) are covered by property
+ (12) below; the ones that do not are listed as known gaps there.
+ Do not cite this property as evidence that a given FE endpoint
+ enforces the caller's privileges — check the handler.
+
+ **BE 8040 is not in this property.** Its `enable_all_http_auth`
+ default is unchanged (off), so its `NONE`-privilege handlers stay
+ disclaimed under §4.9 and are governed by Zone-2 network
+ isolation, not by this property.
+
+ *Violation symptom*: an in-scope endpoint answers a request that
+ carries no credential of any accepted form, or accepts invalid
+ credentials. *Severity*: **security-critical**. Reports of this
+ shape are `VALID`.
+
+ *Excluded from this property* — this list is meant to be
+ exhaustive; a path that belongs here and is missing is a defect in
+ this document, not a finding:
+ - (a) **FE `/metrics`**, deliberately anonymous, not gated by the
+ flag — see §4.9.
+ - (b) **FE `/api/health`** (`HealthAction`), deliberately
+ anonymous and not gated by the flag either. It returns liveness
+ plus total/online backend counts. A report that `/api/health`
+ answers an unauthenticated request is
+ `BY-DESIGN: property-disclaimed`, not a violation.
+ - (c) Clusters where the operator has set
+ `enable_all_http_auth = false` — a §4.5a knob flipped toward the
+ less-secure side, closed `OUT-OF-MODEL: non-default-build`.
+ Note that the effective value can come from `fe_custom.conf`,
+ which is read after and overwrites `fe.conf`; see §4.5a.
+ - (d) The **cluster-token authenticated** endpoints, where the
+ cluster token *is* the credential — authenticated, just not by
+ user password: FE `/api/get_small_file`; FE `/api/bootstrap`
+ when `cluster_id`+`token` are presented; FE
+ `/api/streaming/commit_offset` and
+ `/api/streaming/report_task_failure`, which accept **only** a
+ `token` header and no user credential at all; the token branch
+ of `/api/{db}/{table}/_stream_load`; and the BE handlers that
+ accept an auth token. A report that one of these serves a
+ request without a user password, while presenting a valid
+ cluster token, is `BY-DESIGN: property-disclaimed`. A report
+ that one of them accepts an *invalid* or absent token is
+ `VALID`.
+
+12. **Per-handler authorization on the FE HTTP surface, where the
+ handler implements it** *(maintainer, M19)*. *Condition*: property
+ (11) holds and the endpoint in question runs a privilege check.
+ *Violation symptom*: a handler that performs a privilege check
+ returns data, or performs an action, that the authenticated caller
+ has no privilege for — for example a metadata listing that leaks
+ objects the caller has no `SHOW` privilege on, or an admin action
+ reachable without `ADMIN_PRIV`. *Severity*:
+ **security-critical**. Reports of this shape are `VALID`.
+
+ **Known gaps — password-only handlers, not yet covered by this
+ property.** These authenticate but perform no SQL-equivalent
+ authorization. They are recorded here so that a report against
+ them is triaged as a *known, accepted gap* rather than silently
+ treated as covered; closing them is tracked in §4.14.
+ - `/api/backends` (`BackendsAction`) — any valid account can
+ enumerate backend host/port/liveness. Intentional: the
+ Flink/Spark connectors call it with an ordinary load account to
+ discover backends before a stream load.
Review Comment:
[P1] Migrate this FE caller before making authentication the default. The ES
open-API regression still invokes both of these endpoints through curl()
without user/pwd, and the corrected generic helper intentionally sends no
Authorization header when user is empty. ESCatalogAction now rejects those
calls under the default-true flag, so the suite's success/mappings/hits
assertions deterministically fail whenever enableEsTest=true. Pass explicit
regression credentials at these FE-only call sites; do not restore implicit
credentials in the generic helper.
##########
fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/BootstrapFinishAction.java:
##########
@@ -60,7 +60,13 @@ public class BootstrapFinishAction extends
RestBaseController {
@RequestMapping(path = "/api/bootstrap", method = RequestMethod.GET)
public ResponseEntity execute(HttpServletRequest request,
HttpServletResponse response) {
- if (Config.enable_all_http_auth) {
+ String clusterIdStr = request.getParameter(CLUSTER_ID);
+ String token = request.getParameter(TOKEN);
+ // A caller that presents the cluster id and token is an FE joining or
probing this cluster;
+ // that pair is its credential and is verified below, so do not also
demand a user password
+ // from it. Callers that present neither are anonymous and must
authenticate.
+ boolean authenticatedByToken = !Strings.isNullOrEmpty(clusterIdStr) &&
!Strings.isNullOrEmpty(token);
Review Comment:
[P2] Validate the cluster credential before using it to bypass Basic
authentication. Here any two non-empty strings set authenticatedByToken, but
parsing and token/cluster comparisons run only inside the later isReady branch.
While the FE is not ready, cluster_id=garbage&token=garbage therefore skips
password/admin authentication and returns the not-ready response without ever
rejecting the invalid credential, contrary to the new threat-model contract.
Validate the pair in every readiness state, then use isReady only to select the
payload; add wrong/malformed-token cases for both states.
##########
fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MetaInfoAction.java:
##########
@@ -88,11 +86,12 @@ public class MetaInfoAction extends RestBaseController {
public Object getAllDatabases(
@PathVariable(value = NS_KEY) String ns,
HttpServletRequest request, HttpServletResponse response) {
- boolean checkAuth = Config.enable_all_http_auth ? true : false;
- ActionAuthorizationInfo authInfo = checkWithCookie(request, response,
checkAuth);
- if (Config.enable_all_http_auth) {
- checkAdminAuth(authInfo.userIdentity);
- }
+ // Authenticate, but do not demand global ADMIN: the per-database SHOW
check below is what
+ // authorizes this response, so a least-privilege account (for example
the user a
+ // Doris-to-Doris external catalog is configured with) can list
exactly the databases it is
+ // allowed to see. Passing false here only skips the ADMIN_OR_NODE
requirement -- a caller
Review Comment:
[P1] Keep the cloud overdue fence when removing the global ADMIN
requirement. checkWithCookie does not use this boolean only for ADMIN_OR_NODE:
in cloud mode it also gates checkInstanceOverdue for Basic requests and the
OVERDUE rejection for cookie sessions. Hard-coding false here (and on the
table/schema routes) therefore lets non-root overdue tenants enumerate metadata
even though an existing enable_all_http_auth=true deployment rejected them.
Split lifecycle validation from the global-privilege switch, and test both
credential paths in the overdue state.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]