github-actions[bot] commented on code in PR #67206:
URL: https://github.com/apache/doris/pull/67206#discussion_r3877692537
##########
fe/fe-core/src/main/java/org/apache/doris/catalog/authorizer/ranger/hive/RangerHivePlugin.java:
##########
@@ -17,17 +17,39 @@
package org.apache.doris.catalog.authorizer.ranger.hive;
+import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
import org.apache.ranger.plugin.service.RangerAuthContextListener;
import org.apache.ranger.plugin.service.RangerBasePlugin;
+import java.util.Map;
+
public class RangerHivePlugin extends RangerBasePlugin {
+ static final String POLICY_REST_URL_PROPERTY =
"ranger.plugin.hive.policy.rest.url";
+
public RangerHivePlugin(String serviceName) {
super(serviceName, null);
}
public RangerHivePlugin(String serviceName, RangerAuthContextListener
rangerAuthContextListener) {
- super(serviceName, null, null);
+ this(serviceName, null, rangerAuthContextListener);
+ }
+
+ public RangerHivePlugin(String serviceName, Map<String, String> properties,
+ RangerAuthContextListener rangerAuthContextListener) {
+ super(createPluginConfig(serviceName, properties));
super.init();
super.registerAuthContextEventListener(rangerAuthContextListener);
}
+
+ static RangerPluginConfig createPluginConfig(String serviceName,
Map<String, String> properties) {
+ if (properties != null &&
properties.containsKey(POLICY_REST_URL_PROPERTY)) {
+ RangerPluginConfig config = new RangerPluginConfig("hive",
serviceName, null, null, null, null);
+ // Keep audit, UGI, and credentials process-scoped. Catalog
properties may only override the policy URL.
+ config.set(POLICY_REST_URL_PROPERTY,
properties.get(POLICY_REST_URL_PROPERTY));
Review Comment:
[P1] Do not send process Ranger credentials to a catalog-selected host
`RangerPluginConfig("hive", ...)` loads the process XML before this
assignment. Ranger 2.8 later reads
`ranger.plugin.hive.policy.rest.client.username/password` from that same
config, and `super.init()` synchronously downloads roles and policies during
CREATE CATALOG's dry run. Because catalog `CREATE` is sufficient, a non-admin
can point this property at an HTTP server they control and receive the FE's
process-scoped Basic Authorization header before the temporary controller is
closed. This is distinct from the existing SHOW/masking thread: the secret
never appears in catalog properties. Keep the URL in the same process-owned
profile as its credentials, or clear all process authentication material for
catalog-selected endpoints and use separately scoped, masked credentials.
Please add a capture-server test proving an unapproved URL receives no
Authorization header.
##########
fe/fe-core/src/main/java/org/apache/doris/catalog/authorizer/ranger/hive/RangerHivePlugin.java:
##########
@@ -17,17 +17,39 @@
package org.apache.doris.catalog.authorizer.ranger.hive;
+import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
import org.apache.ranger.plugin.service.RangerAuthContextListener;
import org.apache.ranger.plugin.service.RangerBasePlugin;
+import java.util.Map;
+
public class RangerHivePlugin extends RangerBasePlugin {
+ static final String POLICY_REST_URL_PROPERTY =
"ranger.plugin.hive.policy.rest.url";
+
public RangerHivePlugin(String serviceName) {
super(serviceName, null);
}
public RangerHivePlugin(String serviceName, RangerAuthContextListener
rangerAuthContextListener) {
- super(serviceName, null, null);
+ this(serviceName, null, rangerAuthContextListener);
+ }
+
+ public RangerHivePlugin(String serviceName, Map<String, String> properties,
+ RangerAuthContextListener rangerAuthContextListener) {
+ super(createPluginConfig(serviceName, properties));
super.init();
super.registerAuthContextEventListener(rangerAuthContextListener);
}
+
+ static RangerPluginConfig createPluginConfig(String serviceName,
Map<String, String> properties) {
+ if (properties != null &&
properties.containsKey(POLICY_REST_URL_PROPERTY)) {
+ RangerPluginConfig config = new RangerPluginConfig("hive",
serviceName, null, null, null, null);
+ // Keep audit, UGI, and credentials process-scoped. Catalog
properties may only override the policy URL.
+ config.set(POLICY_REST_URL_PROPERTY,
properties.get(POLICY_REST_URL_PROPERTY));
Review Comment:
[P1] Keep the Ranger policy authority operator-controlled
A principal with catalog `ALTER` but no `SELECT` can change this property on
an existing working catalog; the property merge preserves its HMS/storage
settings, then controller reset makes this server the authority for
`checkDbPriv`, `checkTblPriv`, and `checkColsPriv`. The principal can point it
at a Ranger-compatible server they control, return a `select` policy for
themselves, and pass external-table authorization without any conjunctive Doris
`SELECT` grant. `CREATE CATALOG` has the same problem for a new reachable
source. The added regression demonstrates the decisive behavior by authorizing
an otherwise ungranted user solely from policies fetched at this URL. This is
not the threat model's disclaimed outbound-request/SSRF case: the untrusted
response becomes the RBAC decision. Keep the Ranger Admin URL
operator-owned/allowlisted, or require an administrator-only privilege to set
or alter it, and add a negative test proving a restricted caller cannot replace
the policy author
ity.
##########
fe/fe-core/src/main/java/org/apache/doris/catalog/authorizer/ranger/hive/RangerHivePlugin.java:
##########
@@ -17,17 +17,39 @@
package org.apache.doris.catalog.authorizer.ranger.hive;
+import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
import org.apache.ranger.plugin.service.RangerAuthContextListener;
import org.apache.ranger.plugin.service.RangerBasePlugin;
+import java.util.Map;
+
public class RangerHivePlugin extends RangerBasePlugin {
+ static final String POLICY_REST_URL_PROPERTY =
"ranger.plugin.hive.policy.rest.url";
+
public RangerHivePlugin(String serviceName) {
super(serviceName, null);
}
public RangerHivePlugin(String serviceName, RangerAuthContextListener
rangerAuthContextListener) {
- super(serviceName, null, null);
+ this(serviceName, null, rangerAuthContextListener);
+ }
+
+ public RangerHivePlugin(String serviceName, Map<String, String> properties,
+ RangerAuthContextListener rangerAuthContextListener) {
+ super(createPluginConfig(serviceName, properties));
super.init();
super.registerAuthContextEventListener(rangerAuthContextListener);
}
+
+ static RangerPluginConfig createPluginConfig(String serviceName,
Map<String, String> properties) {
+ if (properties != null &&
properties.containsKey(POLICY_REST_URL_PROPERTY)) {
+ RangerPluginConfig config = new RangerPluginConfig("hive",
serviceName, null, null, null, null);
Review Comment:
[P1] Isolate Ranger authorization caches by Admin endpoint
This constructor defaults `appId` to `hive`. Ranger 2.8 names its policy,
role, and implicit GDS caches from `appId` plus `serviceName`; none of those
identities includes this catalog-selected URL. With a configured cache
directory, two catalogs that use the same service name on different Ranger
Admins therefore share unsynchronized cache writers. A dry run for endpoint A
can leave A's permissive authorization state behind, and if endpoint B is
temporarily unavailable when its controller initializes, Ranger can load that
service-name-matching state and authorize B with A's policy or role membership.
Controller cleanup does not remove the files. Namespace every authorization
cache by a stable endpoint/catalog identity (and publish atomically), then test
same-service controllers on different endpoints with one endpoint unavailable.
--
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]