You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@polaris.apache.org by "sneethiraj (via GitHub)" <gi...@apache.org> on 2026/03/04 06:20:48 UTC
[PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
sneethiraj opened a new pull request, #3928:
URL: https://github.com/apache/polaris/pull/3928
<!--
π Describe what changes you're proposing, especially breaking or user-facing changes.
π See https://github.com/apache/polaris/blob/main/CONTRIBUTING.md for more.
-->
RFC : https://docs.google.com/document/d/10UIpPMeWVU3VA0goGz_y8OAbXhIDigah/edit?usp=sharing&ouid=103452742845206345322&rtpof=true&sd=true
This RFC proposes integrating Apache Ranger as an external authorization plugin for Apache Polaris by implementing the PolarisAuthorizer SPI. By leveraging Rangerβs mature ecosystem, Polaris can provide enterprises with centralized policy management, fine-grained resource-based access control (RBAC/ABAC), and comprehensive audit logging without replacing its internal authorization model. This integration addresses key enterprise challenges by providing a uniform, centralized security and governance platform for policy management and data access auditing.
## Checklist
- [X] π‘οΈ Don't disclose security issues! (contact security@apache.org)
- [X] π Clearly explained why the changes are needed, or linked related issues: Fixes #
- [X] π§ͺ Added/updated tests with good coverage, or manually tested (and explained how)
- [X] π‘ Added comments for complex logic
- [X] π§Ύ Updated `CHANGELOG.md` (if needed)
- [X] π Updated documentation in `site/content/in-dev/unreleased` (if needed)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4008712014
@flyingImer - thank you for reviewing the PR and suggestions. Issues and suggestions have been addressed now.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2921553905
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
Review Comment:
Same here
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
Review Comment:
Do we need `PolarisPrivilege` as a bridge to route between operation and ranger privileges? Can we map `PolarisAuthorizableOperation` directly to ranger privileges? In that case, the ranger privileges are completely decoupled with `PolarisPrivilege`, which avoid any sync between them. Ranger should only care about the `PolarisAuthorizableOperation`.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizerConfig.PROP_POLARIS_SERVICE_NAME;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+
+ authorizer.init();
+
+ this.authorizer = authorizer;
+ this.serviceName = rangerProp.getProperty(PROP_POLARIS_SERVICE_NAME);
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
Review Comment:
Same here
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
+ boolean isAllowed = RangerAuthzResult.AccessDecision.ALLOW.equals(authzResult.getDecision());
+
+ if (!isAllowed && LOG.isDebugEnabled()) {
+ for (int i = 0; i < accessInfos.size(); i++) {
+ RangerAccessInfo accessInfo = accessInfos.get(i);
+ RangerAuthzResult accessResult = authzResult.getAccesses().get(i);
+
+ if (!RangerAuthzResult.AccessDecision.ALLOW.equals(accessResult.getDecision())) {
+ LOG.debug(
+ "User {} is not authorized for {} on {}",
+ userInfo.getName(),
+ authzOp,
+ accessInfo.getResource());
+ }
+ }
+ }
+
+ return isAllowed;
+ }
+
+ private static Set<PolarisAuthorizableOperation> initAuthorizedOperations() {
+ Set<PolarisAuthorizableOperation> ret = new HashSet<>();
+
+ for (PolarisAuthorizableOperation op : PolarisAuthorizableOperation.values()) {
+ if (isAuthorizable(op)) {
+ ret.add(op);
+ }
+ }
+
+ return ret;
+ }
+
+ private static boolean isAuthorizable(PolarisAuthorizableOperation op) {
+ switch (op) {
+ case CREATE_PRINCIPAL:
+ case DELETE_PRINCIPAL:
+ case UPDATE_PRINCIPAL:
+ case GET_PRINCIPAL:
+ case LIST_PRINCIPALS:
+ case ROTATE_CREDENTIALS:
+ case RESET_CREDENTIALS:
+ return true;
+
+ case CREATE_CATALOG:
+ case DELETE_CATALOG:
+ case UPDATE_CATALOG:
+ case GET_CATALOG:
+ case LIST_CATALOGS:
+ case ATTACH_POLICY_TO_CATALOG:
+ case DETACH_POLICY_FROM_CATALOG:
+ case GET_APPLICABLE_POLICIES_ON_CATALOG:
+ return true;
+
+ case CREATE_NAMESPACE:
+ case DROP_NAMESPACE:
+ case UPDATE_NAMESPACE_PROPERTIES:
+ case LIST_NAMESPACES:
+ case NAMESPACE_EXISTS:
+ case LOAD_NAMESPACE_METADATA:
+ case ATTACH_POLICY_TO_NAMESPACE:
+ case DETACH_POLICY_FROM_NAMESPACE:
+ case GET_APPLICABLE_POLICIES_ON_NAMESPACE:
+ return true;
+
+ case CREATE_TABLE_DIRECT:
+ case CREATE_TABLE_DIRECT_WITH_WRITE_DELEGATION:
+ case CREATE_TABLE_STAGED:
+ case CREATE_TABLE_STAGED_WITH_WRITE_DELEGATION:
+ case REGISTER_TABLE:
+ case DROP_TABLE_WITHOUT_PURGE:
+ case DROP_TABLE_WITH_PURGE:
+ case UPDATE_TABLE:
+ case UPDATE_TABLE_FOR_STAGED_CREATE:
+ case RENAME_TABLE:
+ case LIST_TABLES:
+ case TABLE_EXISTS:
+ case LOAD_TABLE:
+ case LOAD_TABLE_WITH_READ_DELEGATION:
+ case LOAD_TABLE_WITH_WRITE_DELEGATION:
+ case COMMIT_TRANSACTION:
+ case ATTACH_POLICY_TO_TABLE:
+ case DETACH_POLICY_FROM_TABLE:
+ case GET_APPLICABLE_POLICIES_ON_TABLE:
+ case REPORT_READ_METRICS:
+ case REPORT_WRITE_METRICS:
+ case ASSIGN_TABLE_UUID:
+ case UPGRADE_TABLE_FORMAT_VERSION:
+ case ADD_TABLE_SCHEMA:
+ case SET_TABLE_CURRENT_SCHEMA:
+ case ADD_TABLE_PARTITION_SPEC:
+ case ADD_TABLE_SORT_ORDER:
+ case SET_TABLE_DEFAULT_SORT_ORDER:
+ case ADD_TABLE_SNAPSHOT:
+ case SET_TABLE_SNAPSHOT_REF:
+ case REMOVE_TABLE_SNAPSHOTS:
+ case REMOVE_TABLE_SNAPSHOT_REF:
+ case SET_TABLE_LOCATION:
+ case SET_TABLE_PROPERTIES:
+ case REMOVE_TABLE_PROPERTIES:
+ case SET_TABLE_STATISTICS:
+ case REMOVE_TABLE_STATISTICS:
+ case REMOVE_TABLE_PARTITION_SPECS:
+ return true;
+
+ case CREATE_VIEW:
+ case DROP_VIEW:
+ case REPLACE_VIEW:
+ case RENAME_VIEW:
+ case LIST_VIEWS:
+ case VIEW_EXISTS:
+ case LOAD_VIEW:
+ return true;
+
+ case CREATE_POLICY:
+ case DROP_POLICY:
+ case UPDATE_POLICY:
+ case LIST_POLICY:
+ case LOAD_POLICY:
+ return true;
+
+ case SEND_NOTIFICATIONS:
+ return true;
+
+ case CREATE_PRINCIPAL_ROLE:
+ case DELETE_PRINCIPAL_ROLE:
+ case UPDATE_PRINCIPAL_ROLE:
+ case GET_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES:
+ case ASSIGN_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES_ASSIGNED:
+ case LIST_ASSIGNEE_PRINCIPALS_FOR_PRINCIPAL_ROLE:
+ case ADD_PRINCIPAL_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL:
+ case ADD_PRINCIPAL_ROLE_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL_ROLE:
+ case ADD_ROOT_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_ROOT_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_ROOT:
+ return false;
+
+ case CREATE_CATALOG_ROLE:
+ case DELETE_CATALOG_ROLE:
+ case UPDATE_CATALOG_ROLE:
+ case GET_CATALOG_ROLE:
+ case LIST_CATALOG_ROLES:
+ case ASSIGN_CATALOG_ROLE_TO_PRINCIPAL_ROLE:
+ case REVOKE_CATALOG_ROLE_FROM_PRINCIPAL_ROLE:
+ case LIST_CATALOG_ROLES_FOR_PRINCIPAL_ROLE:
+ case LIST_ASSIGNEE_PRINCIPAL_ROLES_FOR_CATALOG_ROLE:
+ case LIST_GRANTS_FOR_CATALOG_ROLE:
+ case ADD_CATALOG_ROLE_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_CATALOG_ROLE_GRANT_FROM_CATALOG_ROLE:
+ case ADD_NAMESPACE_GRANT_TO_CATALOG_ROLE:
+ case ADD_CATALOG_GRANT_TO_CATALOG_ROLE:
+ case ADD_TABLE_GRANT_TO_CATALOG_ROLE:
+ case ADD_VIEW_GRANT_TO_CATALOG_ROLE:
+ case ADD_POLICY_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_NAMESPACE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_CATALOG_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_TABLE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_VIEW_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_POLICY_GRANT_FROM_CATALOG_ROLE:
+ case LIST_GRANTS_ON_CATALOG_ROLE:
+ return false;
+
+ case LIST_GRANTS_ON_CATALOG:
+ case LIST_GRANTS_ON_NAMESPACE:
+ case LIST_GRANTS_ON_TABLE:
+ case LIST_GRANTS_ON_VIEW:
+ return false;
Review Comment:
I'm a bit concerned that every time we add/update/remove an op enum, we need to make changes here as well. What do we do here is basically to exclude all ops related to RBAC. Is it possible we introduced a op type like `rbac` or `native rbac` to indicate these ops are tied to the native RBAC only? cc @sungwy @collado-mike
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
Review Comment:
It looks like there are about 6 debug level log statements here. Would it be possible to consolidate them into a single debug log message instead? That might make the logs easier to read and won't split when other logs happen at the same time.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
+ boolean isAllowed = RangerAuthzResult.AccessDecision.ALLOW.equals(authzResult.getDecision());
+
+ if (!isAllowed && LOG.isDebugEnabled()) {
+ for (int i = 0; i < accessInfos.size(); i++) {
+ RangerAccessInfo accessInfo = accessInfos.get(i);
+ RangerAuthzResult accessResult = authzResult.getAccesses().get(i);
+
+ if (!RangerAuthzResult.AccessDecision.ALLOW.equals(accessResult.getDecision())) {
+ LOG.debug(
+ "User {} is not authorized for {} on {}",
+ userInfo.getName(),
+ authzOp,
+ accessInfo.getResource());
Review Comment:
I think we can group them in a single debug message instead of emitting multiple ones in case of multiple targets and secondaries. The split way is even more confusing as the operation will apply to both target and secondary, not either.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
Review Comment:
Do we need to log an error given we throw right after it? Can we put the error message into the throw statement?
```suggestion
throw new IllegalStateException(errorMsg, excp);
```
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
Looks like we copy the logic from the default authorizer, I think it is the right behavior. Can we move it to a util class so that both default authorizer and ranger authorizer can reuse it?
I'm also curious how OPA remote server handle this? cc @sungwy
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizerConfig.PROP_POLARIS_SERVICE_NAME;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+
+ authorizer.init();
+
+ this.authorizer = authorizer;
+ this.serviceName = rangerProp.getProperty(PROP_POLARIS_SERVICE_NAME);
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerAuthorizer initialized successfully");
+ }
+
+ @PreDestroy
+ public void cleanup() {}
+
+ @Override
+ public RangerPolarisAuthorizer create(RealmConfig realmConfig) {
+ LOG.debug("Creating RangerPolarisAuthorizer");
+
+ if (authorizer == null || StringUtils.isBlank(serviceName)) {
+ throw new IllegalStateException(ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED);
+ }
+
+ try {
+ return new RangerPolarisAuthorizer(authorizer, serviceName, realmConfig);
+ } catch (Throwable t) {
+ LOG.error("Failed to create RangerPolarisAuthorizer", t);
+
+ throw t;
Review Comment:
Same here
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2938389429
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
Review Comment:
> Also FYI my IDE is flagging two CVEs here:
@adutra - both CVEs have moderate severity, and come from commons-configuration2 library. Ranger updated to the latest version, but it is yet to be released. This issue should be adressed with the next version of Ranger. In the meantime, let me know if you prefer to have this library version updated via dependency exclusion and explcitt inclusion of the latest version.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2915405540
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
+ implementation(libs.commons.lang3)
+ implementation(libs.guava)
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+ compileOnly(project(":polaris-immutables"))
+
+ runtimeOnly(libs.graalvm.graal.sdk)
+ runtimeOnly(libs.graalvm.inspect.community)
+ runtimeOnly(libs.graalvm.js.community)
+ runtimeOnly(libs.graalvm.js.scriptengine)
+ runtimeOnly(libs.graalvm.nativeimage)
Review Comment:
Ranger policies support optional use of expressions that can leverage context attributes in making authorization decisions - like `USER.allowedSensitiveLevel <= TAG.sensitiveLevel`, `database: dept_${USER.dept}`. These libraries are used to evaluate these expressions.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2942067274
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
+ private static final String RESOURCE_TYPE_NAME_SEP = ":";
+ private static final String RESOURCE_ELEMENTS_SEP = "/";
+
+ private final PolarisAuthorizer authorizer;
+
+ public TestRangerPolarisAuthorizer() {
+ RangerPolarisAuthorizerFactory factory = new RangerPolarisAuthorizerFactory(createConfig());
+
+ factory.initialize();
+
+ authorizer = factory.create(createRealmConfig());
+
+ assertNotNull(authorizer);
+ }
+
+ @Test
+ public void testAuthzRoot() throws Exception {
+ runTests(authorizer, "/authz_tests/tests_authz_root.json");
Review Comment:
I think capturing test input/output in Json format makes it easier to focus on test details, without any scaffolding distractions while doing the same in Java.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983618374
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
Also, `polarisPrincipal.getName()` may come from an external IdP, so checking it against the Polaris' root name constant is not always justified.
`PolarisAuthorizerImpl` can do that more safely because it resolves authenticated principals against local principal entities.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4262407887
@dimas-b β Thank you for the detailed review and feedback.
@mneethiraj and I have addressed the comments and clarified the remaining points.
Could you please take another look and, if everything looks good, approve the PR so we can proceed with merging into apache/main?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2989060628
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
`RESET_CREDENTIALS` is about managing internal Polaris principal entities.
`PolarisAuthorizerImpl` enforces that only the internal `root` principal can perform this operation.
The internal `root` user will only be exposed to Ranger if the Polaris Admin combines Polaris native Authentication and Ranger Authorization. If the Admin uses an external IdP + Ranger, the Polaris `root` user should never be exposed to Ranger.
Therefore, the Polaris internal `root` principal should not be treated as a special user in the Ranger Authorizer code, IMHO. It is special only in the context on the Polaris native RBAC. To Ranger it should be presented as any other user.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2989060628
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
`RESET_CREDENTIALS` is about managing internal Polaris principal entities.
`PolarisAuthorizerImpl` enforces that only the internal `root` principal can perform this operation.
The internal `root` user will only be exposed to Ranger if the Polaris Admin combines Polaris native Authentication and Ranger Authorization. If the Admin uses an external IdP + Ranger, the Polaris `root` user will should never be exposed to Ranger.
Therefore, the Polaris internal `root` principal should not be treated as a special user in the Ranger Authorizer code, IMHO. It is special only in the context on the Polaris native RBAC. To Ranger it should be presented as any other user.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3050641891
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
Review Comment:
Generally, `intTest` tests should be annotated with `@QuarkusIntegrationTest`.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3074887336
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
Thanks for the info, @sneethiraj !
This still feels a bit risky to me. I'd propose two things:
1) rename the reference to be more explicit about Ranger, e.g. `ranger-graalvm` and add a comment about keeping it in sync with Ranger (e.g. what to check on the Ranger side to figure out what the right version should be).
2) Pin the version to prevent Renovate from updating it (e.g. `25.0.2!!`)
CC: @adutra @snazy
WDYT?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4087063469
Thanks @mneethiraj for working on it. LGTM overall. I'd suggest to file issues for followups and fix the CI failures.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4092134999
Thanks @adnanhemani for your efforts to review and provide valuable comments!
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2957862208
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
Filed issue #4026 to track this refactor.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4093205819
> Unicode license is OK to include, https://www.apache.org/legal/resolved.html#category-a. We need to update the license checker.
Thanks @flyrain. Apart from above failure from `./gradlew :polaris-server:checkLicense`, there are no more CI issues for this PR. This CI failure would be addressed once the licensr checker is updated to allow `Unicode/ICU License`. @dimas-b, @jbonofre - will you be able to help with this please? Thanks!
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4159709586
Addressed the suggestion about adding Integration Tests for Ranger Authz. (commit # be8584ac862fa8cbd347d71b3aa07ba9266860a7)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3025363526
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(RangerTestProfiles.EmbeddedPolicy.class)
+public class RangerAdminServiceIT extends RangerIntegrationTestBase {
+
+ private String baseCatalogName;
+ private String baseCatalogLocation;
+ private String baseRootToken;
+
+ @BeforeEach
+ void setupBaseCatalog() throws Exception {
+ baseRootToken = getRootToken();
+ baseCatalogName = "ranger-base-cat-" + UUID.randomUUID().toString().replace("-", "");
+ baseCatalogLocation = Files.createTempDirectory("ranger-base-cat").toUri().toString();
+ createFileCatalog(
+ baseRootToken, baseCatalogName, baseCatalogLocation, List.of(baseCatalogLocation));
+ }
+
+ @Test
+ void assignCatalogRoleToPrincipalRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ // create catalog role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ // create principal role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ // stranger cannot bind
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
+ principalRole,
+ baseCatalogName)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ void listCatalogsAuthorization() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ // stranger cannot list catalogs
+ given()
+ .header("Authorization", "Bearer " + strangerToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // root lists catalogs successfully
+ given()
+ .header("Authorization", "Bearer " + rootToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(200);
+ }
+
+ @Test
+ void createCatalogAuthorization() throws Exception {
+ String rootToken = getRootToken();
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogName = "ranger-cat-create-" + UUID.randomUUID().toString().replace("-", "");
+ String baseLocation = Files.createTempDirectory("ranger-cat-create").toUri().toString();
+ Map<String, Object> createCatalogRequest =
+ Map.of(
+ "type",
+ "INTERNAL",
+ "name",
+ catalogName,
+ "properties",
+ Map.of("default-base-location", baseLocation),
+ "storageConfigInfo",
+ Map.of("storageType", "FILE", "allowedLocations", List.of(baseLocation)));
+
+ // Stranger cannot create catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // Root creates catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
Review Comment:
Why not use `ManagementApi` like many other tests?
https://github.com/apache/polaris/blob/3e80675f106b8c86be21387d1da07a267c90bdf8/integration-tests/src/main/java/org/apache/polaris/service/it/env/ManagementApi.java#L202
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ } else {
+ props.setProperty(key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
+ if (serviceName().isEmpty()) {
+ throw new IllegalStateException(
Review Comment:
Why declare `serviceName()` as `Optional` when it is required by this check?
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
Review Comment:
nit: `static final` is redundant here
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
So, why do we have do declare and manage the version of `graalvm` in Polaris? Why does it not come from Ranger artifacts' transitive dependencies?
Note: the moment it merges to `main` it will be subject to automated version updates by the Renovate bot.
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties properties = config.toRangerProperties();
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(properties);
Review Comment:
Is there any particular reason for not doing this in the constructor? In that case extra checks in `create()` will not be necessary π€
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties properties = config.toRangerProperties();
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(properties);
+
+ authorizer.init();
+
+ this.authorizer = authorizer;
+ this.serviceName = config.serviceName().orElseThrow();
Review Comment:
`orElseThrow()` looks confusing... `config.validate()` (line 58) makes sure `config.serviceName()` is present.
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(RangerTestProfiles.EmbeddedPolicy.class)
+public class RangerAdminServiceIT extends RangerIntegrationTestBase {
+
+ private String baseCatalogName;
+ private String baseCatalogLocation;
+ private String baseRootToken;
+
+ @BeforeEach
+ void setupBaseCatalog() throws Exception {
+ baseRootToken = getRootToken();
+ baseCatalogName = "ranger-base-cat-" + UUID.randomUUID().toString().replace("-", "");
+ baseCatalogLocation = Files.createTempDirectory("ranger-base-cat").toUri().toString();
+ createFileCatalog(
+ baseRootToken, baseCatalogName, baseCatalogLocation, List.of(baseCatalogLocation));
+ }
+
+ @Test
+ void assignCatalogRoleToPrincipalRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ // create catalog role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ // create principal role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ // stranger cannot bind
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
Review Comment:
What's the point of this test , when we know that `principalRole` was not created (line 81)?
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(RangerTestProfiles.EmbeddedPolicy.class)
+public class RangerAdminServiceIT extends RangerIntegrationTestBase {
+
+ private String baseCatalogName;
+ private String baseCatalogLocation;
+ private String baseRootToken;
+
+ @BeforeEach
+ void setupBaseCatalog() throws Exception {
+ baseRootToken = getRootToken();
+ baseCatalogName = "ranger-base-cat-" + UUID.randomUUID().toString().replace("-", "");
+ baseCatalogLocation = Files.createTempDirectory("ranger-base-cat").toUri().toString();
+ createFileCatalog(
+ baseRootToken, baseCatalogName, baseCatalogLocation, List.of(baseCatalogLocation));
+ }
+
+ @Test
+ void assignCatalogRoleToPrincipalRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ // create catalog role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ // create principal role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ // stranger cannot bind
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
+ principalRole,
+ baseCatalogName)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ void listCatalogsAuthorization() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ // stranger cannot list catalogs
+ given()
+ .header("Authorization", "Bearer " + strangerToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // root lists catalogs successfully
+ given()
+ .header("Authorization", "Bearer " + rootToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(200);
+ }
+
+ @Test
+ void createCatalogAuthorization() throws Exception {
+ String rootToken = getRootToken();
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogName = "ranger-cat-create-" + UUID.randomUUID().toString().replace("-", "");
+ String baseLocation = Files.createTempDirectory("ranger-cat-create").toUri().toString();
+ Map<String, Object> createCatalogRequest =
+ Map.of(
+ "type",
+ "INTERNAL",
+ "name",
+ catalogName,
+ "properties",
+ Map.of("default-base-location", baseLocation),
+ "storageConfigInfo",
+ Map.of("storageType", "FILE", "allowedLocations", List.of(baseLocation)));
+
+ // Stranger cannot create catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // Root creates catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
+ .then()
+ .statusCode(201);
+
+ given()
+ .header("Authorization", "Bearer " + rootToken)
+ .delete("/api/management/v1/catalogs/{cat}", catalogName)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ void grantTablePrivilegesAuthorization() throws Exception {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+ String catalogName = "ranger-grant-cat-" + UUID.randomUUID().toString().replace("-", "");
+ String namespace = "ns_" + UUID.randomUUID().toString().replace("-", "");
+ String tableName = "tbl_" + UUID.randomUUID().toString().replace("-", "");
+ String catalogRole = "role_" + UUID.randomUUID().toString().replace("-", "");
+
+ Path tempDir = Files.createTempDirectory("ranger-grant");
+ String baseLocation = tempDir.toUri().toString();
+ String allowedPrefix = baseLocation + (baseLocation.endsWith("/") ? "" : "/") + namespace;
+ createFileCatalog(
+ rootToken, catalogName, baseLocation, List.of(allowedPrefix, allowedPrefix + "/"));
+
+ createNamespace(rootToken, catalogName, namespace);
+
+ Map<String, Object> registerPayload =
+ buildRegisterTableRequest(tableName, baseLocation, namespace);
+ Map<String, Object> grantRequest =
+ Map.of(
+ "grant",
+ Map.of(
+ "type",
+ "table",
+ "namespace",
+ List.of(namespace),
+ "tableName",
+ tableName,
+ "privilege",
+ "TABLE_READ_DATA"));
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(registerPayload))
+ .post("/api/catalog/v1/{cat}/namespaces/{ns}/register", catalogName, namespace)
+ .then()
+ .statusCode(200);
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", catalogName)
+ .then()
+ .statusCode(403); // TODO: check if this policy could be defined ?
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/catalogs/{cat}/catalog-roles/{role}/grants",
+ catalogName,
+ catalogRole)
+ .then()
+ .statusCode(404);
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/catalogs/{cat}/catalog-roles/{role}/grants",
+ catalogName,
+ catalogRole)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ void listAssigneePrincipalRolesForCatalogRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
+ principalRole,
+ baseCatalogName)
+ .then()
+ .statusCode(404);
Review Comment:
What do we prove here in addition to the 403 response on line 255?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2900042734
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (authzOp == PolarisAuthorizableOperation.ROTATE_CREDENTIALS) {
+ boolean enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+
+ if (enforceCredentialRotationRequiredState
+ && !polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
@flyingImer - This issue has been addressed in the commit - 83a7a932102761ea89d006f8002ec745128cd78e. Please review the latest code in the PR again.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2900032605
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizerFactory {
Review Comment:
@flyingImer - This issue is addressed in commit - 83a7a932102761ea89d006f8002ec745128cd78e. Please take a look at the latest code again.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2892303893
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (authzOp == PolarisAuthorizableOperation.ROTATE_CREDENTIALS) {
Review Comment:
@flyingImer - yes, it makes sense to require the caller to have permission to rotate-credentials. Will update to address this.
Should a principal be implicitly allowed to roate their own credentials?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2892660759
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
Review Comment:
Refactoring of authorizer SPI is in progress, tracked by a separate PR #3779 . The suggestion is to update authorizer implementations once the refactoring is complete.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2893156313
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ Properties prop = new Properties();
+
+ if (resourcePath != null) {
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Adding / to the configFileName [{}]", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
Review Comment:
README updated to call out that the configuration file will be searched in the classpath.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984907903
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
@dimas-b - from the operation name, `RESET_CREDENTIALS` seems to be about managing credentials to authenticate with Polaris and not specific to `PolarisAuthorizerImpl`. If Polaris has no expectation that only root principal can perform `RESET_CREDENTIALS` operation, I will get rid of this block from Ranger authorizer implementation.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984930929
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
Is Hadoop required for audit call paths only?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984919514
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
Do Ranger jars (bundled with Polaris) depend on specific versions of `graalvm` jars?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4214278088
@sneethiraj @mneethiraj @snazy @dimas-b
Regarding our conversation 2 days ago, I'd like to propose the following plan to hopefully move this PR forward and get it to a mergeable state:
### General Philosophy
While there is a consensus that Ranger introduces a significant volume of dependencies - many of which are outdated, contain CVEs, or conflict with existing alternatives - having Ranger support in Polaris OSS remains a superior goal. Consequently, we must remain flexible and should accept the current dependency overhead, provided that a) there is a commitment from the Ranger project to eventually minimize these requirements or transition toward an alternative architecture, such as a sidecar deployment; and b) that we tackle the most problematic cases, detailed below.
### Solr / Jetty / Zookeeper
The most problematic component is `ranger-audit-dest-solr:2.8.0`, which enables Solr audit log support. This particular dependency introduces a variety of transitive dependencies, most notably Jetty 9.4.56, which has reached EOL and contains known CVEs. Since you told us [here](https://github.com/apache/polaris/pull/3928#discussion_r2984937667) that we absolutely need the Solr audit logs, I would suggest removing just Jetty, which seems possible: afaict the actual code paths only use `CloudSolrClient` and `LBHttpSolrClient`, and both rely on Apache HttpClient 4.x.
Solr also brings `org.apache.zookeeper:zookeeper:3.8.4` - but since you told us [here](https://github.com/apache/polaris/pull/3928#discussion_r2984937667) that this is an important enterprise feature for Ranger, I would suggest leaving it.
### Jersey 1.x
Another concerning case is `jersey-bundle 1.19.4`, brought by `ranger-plugins-common:2.8.0`. Jersey 1.x is EOL since 2014. Besides, it's a fat jar bundling Jersey server, client, JSON, and servlet code, and many of these components have CVEs. Good news: I think it's possible to remove that one as well.
### Reload4J
`reload4j` is a drop-in replacement for Log4j 1.x (which had the infamous Log4Shell CVE). I think it can be safely excluded.
### Dropwizard Metrics
Through `org.apache.hadoop:hadoop-auth:3.4.2`, Ranger is also bringing `io.dropwizard.metrics:metrics-core:3.2.4`. I couldn't find any CVE attached to it, but it's very old (2017) and unmaintained. It seems possible to remove it.
### Gethostname4J
@snazy pointed out that this dependency is unmaintained and uses JNA. Unfortunately it cannot be removed, it's required by `org.apache.ranger.plugin.util.RangerRESTUtils`. Considering the limited impact and specific usage, I recommend retaining it for now, though I strongly advise the Ranger community to evaluate alternative options.
### Concrete Proposal
I therefore suggest excluding Jetty, Jersey 1.x, Reload4J and Dropwizard Metrics β and keep all the rest. I was able to compile and run all the tests with the below exclusions in `extensions/auth/ranger/impl/build.gradle.kts`:
```kotlin
implementation(libs.ranger.authz.embedded) {
exclude("org.apache.ranger", "ranger-audit-dest-hdfs")
exclude("com.sun.jersey")
exclude("org.eclipse.jetty")
exclude("org.slf4j", "slf4j-reload4j")
exclude("ch.qos.reload4j", "reload4j")
exclude("io.dropwizard.metrics", "metrics-core")
}
```
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3090614272
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(key, properties().get(key));
+ } else {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
Review Comment:
validate() is invoked as part of the authorizer initialization flow.
Specifically, it is called during the creation of the Ranger authorizer configuration within RangerPolarisAuthorizerFactory. When Ranger is selected as the configured authorizer, the factory constructs the Ranger-specific configuration object and triggers validate() to ensure the required Ranger settings (such as serviceName) are present.
This means validate() is executed only when Ranger is configured as the authorizer, and is not called for other authorizer implementations.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4248248799
@dimas-b : added ranger integration (Beta) details in CHANGELOG.md.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933990149
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizerConfig.PROP_POLARIS_SERVICE_NAME;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
Review Comment:
Addressed in 953eb89.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2932513966
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
+ case SERVICE_MANAGE_ACCESS -> "service-access-manage";
+
+ case PRINCIPAL_CREATE -> "principal-create";
+ case PRINCIPAL_DROP -> "principal-drop";
+ case PRINCIPAL_LIST -> "principal-list";
+ case PRINCIPAL_READ_PROPERTIES -> "principal-properties-read";
+ case PRINCIPAL_WRITE_PROPERTIES -> "principal-properties-write";
+ case PRINCIPAL_FULL_METADATA -> "principal-metadata-full";
+ case PRINCIPAL_ROTATE_CREDENTIALS -> "principal-credentials-rotate";
+ case PRINCIPAL_RESET_CREDENTIALS -> "principal-credentials-reset";
+
+ case CATALOG_CREATE -> "catalog-create";
+ case CATALOG_DROP -> "catalog-drop";
+ case CATALOG_LIST -> "catalog-list";
+ case CATALOG_READ_PROPERTIES -> "catalog-properties-read";
+ case CATALOG_WRITE_PROPERTIES -> "catalog-properties-write";
+ case CATALOG_FULL_METADATA -> "catalog-metadata-full";
+ case CATALOG_MANAGE_METADATA -> "catalog-metadata-manage";
+ case CATALOG_MANAGE_CONTENT -> "catalog-content-manage";
+ case CATALOG_ATTACH_POLICY -> "catalog-policy-attach";
+ case CATALOG_DETACH_POLICY -> "catalog-policy-detach";
+
+ case NAMESPACE_CREATE -> "namespace-create";
+ case NAMESPACE_DROP -> "namespace-drop";
+ case NAMESPACE_LIST -> "namespace-list";
+ case NAMESPACE_READ_PROPERTIES -> "namespace-properties-read";
+ case NAMESPACE_WRITE_PROPERTIES -> "namespace-properties-write";
+ case NAMESPACE_FULL_METADATA -> "namespace-metadata-full";
+ case NAMESPACE_ATTACH_POLICY -> "namespace-policy-attach";
+ case NAMESPACE_DETACH_POLICY -> "namespace-policy-detach";
+
+ case TABLE_CREATE -> "table-create";
+ case TABLE_DROP -> "table-drop";
+ case TABLE_LIST -> "table-list";
+ case TABLE_READ_PROPERTIES -> "table-properties-read";
+ case TABLE_WRITE_PROPERTIES -> "table-properties-write";
+ case TABLE_READ_DATA -> "table-data-read";
+ case TABLE_WRITE_DATA -> "table-data-write";
+ case TABLE_FULL_METADATA -> "table-metadata-full";
+ case TABLE_ATTACH_POLICY -> "table-policy-attach";
+ case TABLE_DETACH_POLICY -> "table-policy-detach";
+ case TABLE_ASSIGN_UUID -> "table-uuid-assign";
+ case TABLE_UPGRADE_FORMAT_VERSION -> "table-format-version-upgrade";
+ case TABLE_ADD_SCHEMA -> "table-schema-add";
+ case TABLE_SET_CURRENT_SCHEMA -> "table-schema-set-current";
+ case TABLE_ADD_PARTITION_SPEC -> "table-partition-spec-add";
+ case TABLE_ADD_SORT_ORDER -> "table-sort-order-add";
+ case TABLE_SET_DEFAULT_SORT_ORDER -> "table-sort-order-set-default";
+ case TABLE_ADD_SNAPSHOT -> "table-snapshot-add";
+ case TABLE_SET_SNAPSHOT_REF -> "table-snapshot-ref-set";
+ case TABLE_REMOVE_SNAPSHOTS -> "table-snapshots-remove";
+ case TABLE_REMOVE_SNAPSHOT_REF -> "table-snapshot-ref-remove";
+ case TABLE_SET_LOCATION -> "table-location-set";
+ case TABLE_SET_PROPERTIES -> "table-properties-set";
+ case TABLE_REMOVE_PROPERTIES -> "table-properties-remove";
+ case TABLE_SET_STATISTICS -> "table-statistics-set";
+ case TABLE_REMOVE_STATISTICS -> "table-statistics-remove";
+ case TABLE_REMOVE_PARTITION_SPECS -> "table-partition-specs-remove";
+ case TABLE_MANAGE_STRUCTURE -> "table-structure-manage";
+
+ case VIEW_CREATE -> "view-create";
+ case VIEW_DROP -> "view-drop";
+ case VIEW_LIST -> "view-list";
+ case VIEW_READ_PROPERTIES -> "view-properties-read";
+ case VIEW_WRITE_PROPERTIES -> "view-properties-write";
+ case VIEW_FULL_METADATA -> "view-metadata-full";
+
+ case POLICY_CREATE -> "policy-create";
+ case POLICY_READ -> "policy-read";
+ case POLICY_DROP -> "policy-drop";
+ case POLICY_WRITE -> "policy-write";
+ case POLICY_LIST -> "policy-list";
+ case POLICY_FULL_METADATA -> "policy-metadata-full";
+ case POLICY_ATTACH -> "policy-attach";
+ case POLICY_DETACH -> "policy-detach";
+
+ default -> privilege.name();
Review Comment:
Permission names are typically lower-case in Ranger policies. Hence using lower-case to keep this consistent. Is there a reason to require Ranger permission to use `PolarisPrivilege` enum name as-is?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2932492579
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
Review Comment:
1) Ranger authorizer doesn't support entity types `PRINCIPAL_ROLE`, `CATALOG_ROLE` (and operations on them); these are specific to PolarisAuthorizerImpl, but are part of authorizer SPI.
2) Entity types `NULL_TYPE`, `TASK`, `FILE` are not referenced in any `PolarisAuthorizableOperation`. It seems these entity types are unused, hence Ranger authorizer doesn't support them.
3) In Ranger policy model, resources are named in lower case; hence the mapping for entity-types to Ranger resource names. Ref: [Ranger service-def for Polaris](https://github.com/apache/ranger/blob/master/agents-common/src/main/resources/service-defs/ranger-servicedef-polaris.json).
4) Ranger will deny authorization requests on any resource it doesn't support. So, authorizatins for entity types not explicitly mapped above will result in access to be denied. This is by design.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2900013240
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private final RangerPolarisAuthorizerConfig config;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ config.validate();
+ }
+
+ @PreDestroy
+ public void cleanup() {}
+
+ @Override
+ public RangerPolarisAuthorizer create(RealmConfig realmConfig) {
+ LOG.debug("Creating RangerPolarisAuthorizer");
+
+ try {
+ return new RangerPolarisAuthorizer(config, realmConfig);
+ } catch (Throwable t) {
+ LOG.error("Failed to create RangerPolarisAuthorizer", t);
+ }
+
+ return null;
Review Comment:
@flyingImer - This has been addressed in the latest commit. Please review the fixes in the latest code.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2930945415
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
Review Comment:
```suggestion
```
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+ Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerConfig.class);
+
+ String PROP_RANGER_CONFIG_FILE_NAME = "polaris.authorization.ranger.config-file-name";
+ String PROP_POLARIS_SERVICE_NAME = "ranger.plugin.polaris.service.name";
+
+ String ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME =
+ "Invalid Ranger authorizer configuration: missing configuration "
+ + PROP_RANGER_CONFIG_FILE_NAME;
+ String ERR_INVALID_CONFIG_FILE_MISSING_CONFIGURATION =
+ "Invalid Ranger authorizer configuration file %s: missing mandatory configuration %s";
+
+ Optional<String> configFileName();
+
+ default void validate() {
+ boolean isConfigFileNamePresent = configFileName().isPresent();
+
+ if (!isConfigFileNamePresent) {
+ LOG.error(ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME);
+
+ throw new IllegalStateException(ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME);
+ }
+
+ String fileName = configFileName().get();
+
+ Properties prop = RangerUtils.loadProperties(fileName);
Review Comment:
I think this has been voiced already, but this doesn't look very "Quarkus-friendly". Why not include all the required configuration in Quarkus default configuration files?
There are a few ways of achieving this:
### Using pure Quarkus
Just expose the relevant settings in Quarkus:
```java
@ConfigMapping(prefix = "polaris.authorization.ranger")
public interface RangerPolarisAuthorizerConfig {
String serviceName(); // ranger.plugin.polaris.service.name
Optional<String> clusterName(); // ranger.authz.default.access.cluster.name
// etc.
// You can also create inner interfaces to group things together:
RestClientConfig restClient();
AuthenticationConfig auth();
AuditConfig audit();
// Convert to Properties for RangerEmbeddedAuthorizer
default Properties toProperties() { ... }
}
```
Then you can configure the authorizer very simply:
```properties
polaris.authorization.ranger.service-name=dev_polaris
polaris.authorization.ranger.cluster-name=dev
polaris.authorization.ranger.rest-client.url=http://ranger-admin:6080
polaris.authorization.ranger.rest-client.connection-timeout=PT2M
polaris.authorization.ranger.rest-client.read-timeout=PT30S
polaris.authorization.ranger.auth.type=basic
polaris.authorization.ranger.auth.basic.username=admin
polaris.authorization.ranger.auth.basic.password=rangerR0cks!
polaris.authorization.ranger.audit.destination=solr
polaris.authorization.ranger.audit.solr.urls=http://solr-service:8983/solr/ranger_audits
```
This option has several advantages:
* Environment variables automatic support
* Type safety: Duration, URI, Path types are validated at startup
* Secrets management: Can use Quarkus secret stores
* Unified configuration: All config in one place
### Embed Ranger configuration in Quarkus
If you prefer to expose Ranger config options directly in Quarkus:
```java
@ConfigMapping(prefix = "polaris.authorization.ranger")
public interface RangerPolarisAuthorizerConfig {
// Capture ALL ranger.* properties as-is
@WithParentName
Map<String, String> properties();
default Properties toRangerProperties() {
Properties props = new Properties();
props.putAll(properties());
return props;
}
}
```
Example config:
```properties
polaris.authorization.ranger."ranger.plugin.polaris.service.name"=dev_polaris
polaris.authorization.ranger."ranger.authz.default.policy.rest.url"=http://ranger-admin:6080
polaris.authorization.ranger."ranger.authz.default.policy.rest.client.username"=admin
polaris.authorization.ranger."ranger.authz.default.policy.rest.client.password"=rangerR0cks!
polaris.authorization.ranger."xasecure.audit.destination.solr"=enabled
polaris.authorization.ranger."xasecure.audit.destination.solr.urls"=http://solr:8983/solr/ranger_audits
```
This approach is more extensible, but we lose a few things like rich type system.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+ Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerConfig.class);
+
+ String PROP_RANGER_CONFIG_FILE_NAME = "polaris.authorization.ranger.config-file-name";
+ String PROP_POLARIS_SERVICE_NAME = "ranger.plugin.polaris.service.name";
+
+ String ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME =
+ "Invalid Ranger authorizer configuration: missing configuration "
+ + PROP_RANGER_CONFIG_FILE_NAME;
+ String ERR_INVALID_CONFIG_FILE_MISSING_CONFIGURATION =
Review Comment:
Nit: These constants are exposed publicly, but they shouldn't. I'd prefer to have them inlined. Especially having a `LOG` constant exposed in an interface feels odd.
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
Review Comment:
It seems that this dependency brings in a LOT of transitive deps that we may not want/need, e.g.:
```
com.sun.jersey:jersey-bundle:1.19.4
javax.servlet:javax.servlet-api:4.0.0
org.apache.hadoop:hadoop-client-api:3.4.2 (*)
org.apache.hadoop:hadoop-client-runtime:3.4.2 (*)
```
Could you try to evaluate which ones are really needed? I would like to exclude at least the Hadoop ones.
Also FYI my IDE is flagging two CVEs here:
* CVE-2024-29131
* CVE-2024-29133
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
Review Comment:
Why do certain entity types have special names and others don't?
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
+ implementation(libs.commons.lang3)
+ implementation(libs.guava)
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+ compileOnly(project(":polaris-immutables"))
+
+ runtimeOnly(libs.graalvm.graal.sdk)
+ runtimeOnly(libs.graalvm.inspect.community)
+ runtimeOnly(libs.graalvm.js.community)
+ runtimeOnly(libs.graalvm.js.scriptengine)
+ runtimeOnly(libs.graalvm.nativeimage)
Review Comment:
In fact it seems that `nativeimage` remains a transitive dep:
```
+--- org.graalvm.js:js-scriptengine:25.0.2
| \--- org.graalvm.polyglot:polyglot:25.0.2
| +--- org.graalvm.sdk:collections:25.0.2
| \--- org.graalvm.sdk:nativeimage:25.0.2
| \--- org.graalvm.sdk:word:25.0.2
+--- org.graalvm.polyglot:js:25.0.2
| \--- org.graalvm.js:js:25.0.2
| +--- org.graalvm.js:js-language:25.0.2
| | +--- org.graalvm.regex:regex:25.0.2
| | | +--- org.graalvm.truffle:truffle-api:25.0.2
| | | | +--- org.graalvm.sdk:collections:25.0.2
| | | | +--- org.graalvm.sdk:nativeimage:25.0.2 (*)
| | | | \--- org.graalvm.polyglot:polyglot:25.0.2 (*)
| | | \--- org.graalvm.shadowed:icu4j:25.0.2
| | | +--- org.graalvm.sdk:nativeimage:25.0.2 (*)
| | | \--- org.graalvm.shadowed:xz:25.0.2
| | +--- org.graalvm.truffle:truffle-api:25.0.2 (*)
| | +--- org.graalvm.polyglot:polyglot:25.0.2 (*)
| | \--- org.graalvm.shadowed:icu4j:25.0.2 (*)
| \--- org.graalvm.truffle:truffle-runtime:25.0.2
| +--- org.graalvm.sdk:jniutils:25.0.2
| | +--- org.graalvm.sdk:collections:25.0.2
| | \--- org.graalvm.sdk:nativeimage:25.0.2 (*)
| +--- org.graalvm.truffle:truffle-api:25.0.2 (*)
| \--- org.graalvm.truffle:truffle-compiler:25.0.2
```
@mneethiraj I'm a bit worried about the final jar size overhead that this extension could bring. Do you have any numbers to share?
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
Review Comment:
I agree with @flyrain, my recollection from the OPA authorizer is that the common ground that authorizers should rely on is `PolarisAuthorizableOperation`. `PolarisPrivilege` is specific to Polaris built-in RBAC model.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizerConfig.PROP_POLARIS_SERVICE_NAME;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
Review Comment:
```suggestion
Properties rangerProp = RangerUtils.loadProperties(config.configFileName().orElseThrow());
```
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
+ boolean isAllowed = RangerAuthzResult.AccessDecision.ALLOW.equals(authzResult.getDecision());
+
+ if (!isAllowed && LOG.isDebugEnabled()) {
+ for (int i = 0; i < accessInfos.size(); i++) {
+ RangerAccessInfo accessInfo = accessInfos.get(i);
+ RangerAuthzResult accessResult = authzResult.getAccesses().get(i);
+
+ if (!RangerAuthzResult.AccessDecision.ALLOW.equals(accessResult.getDecision())) {
+ LOG.debug(
+ "User {} is not authorized for {} on {}",
+ userInfo.getName(),
+ authzOp,
+ accessInfo.getResource());
+ }
+ }
+ }
+
+ return isAllowed;
+ }
+
+ private static Set<PolarisAuthorizableOperation> initAuthorizedOperations() {
+ Set<PolarisAuthorizableOperation> ret = new HashSet<>();
+
+ for (PolarisAuthorizableOperation op : PolarisAuthorizableOperation.values()) {
+ if (isAuthorizable(op)) {
+ ret.add(op);
+ }
+ }
+
+ return ret;
+ }
+
+ private static boolean isAuthorizable(PolarisAuthorizableOperation op) {
+ switch (op) {
+ case CREATE_PRINCIPAL:
+ case DELETE_PRINCIPAL:
+ case UPDATE_PRINCIPAL:
+ case GET_PRINCIPAL:
+ case LIST_PRINCIPALS:
+ case ROTATE_CREDENTIALS:
+ case RESET_CREDENTIALS:
+ return true;
+
+ case CREATE_CATALOG:
+ case DELETE_CATALOG:
+ case UPDATE_CATALOG:
+ case GET_CATALOG:
+ case LIST_CATALOGS:
+ case ATTACH_POLICY_TO_CATALOG:
+ case DETACH_POLICY_FROM_CATALOG:
+ case GET_APPLICABLE_POLICIES_ON_CATALOG:
+ return true;
+
+ case CREATE_NAMESPACE:
+ case DROP_NAMESPACE:
+ case UPDATE_NAMESPACE_PROPERTIES:
+ case LIST_NAMESPACES:
+ case NAMESPACE_EXISTS:
+ case LOAD_NAMESPACE_METADATA:
+ case ATTACH_POLICY_TO_NAMESPACE:
+ case DETACH_POLICY_FROM_NAMESPACE:
+ case GET_APPLICABLE_POLICIES_ON_NAMESPACE:
+ return true;
+
+ case CREATE_TABLE_DIRECT:
+ case CREATE_TABLE_DIRECT_WITH_WRITE_DELEGATION:
+ case CREATE_TABLE_STAGED:
+ case CREATE_TABLE_STAGED_WITH_WRITE_DELEGATION:
+ case REGISTER_TABLE:
+ case DROP_TABLE_WITHOUT_PURGE:
+ case DROP_TABLE_WITH_PURGE:
+ case UPDATE_TABLE:
+ case UPDATE_TABLE_FOR_STAGED_CREATE:
+ case RENAME_TABLE:
+ case LIST_TABLES:
+ case TABLE_EXISTS:
+ case LOAD_TABLE:
+ case LOAD_TABLE_WITH_READ_DELEGATION:
+ case LOAD_TABLE_WITH_WRITE_DELEGATION:
+ case COMMIT_TRANSACTION:
+ case ATTACH_POLICY_TO_TABLE:
+ case DETACH_POLICY_FROM_TABLE:
+ case GET_APPLICABLE_POLICIES_ON_TABLE:
+ case REPORT_READ_METRICS:
+ case REPORT_WRITE_METRICS:
+ case ASSIGN_TABLE_UUID:
+ case UPGRADE_TABLE_FORMAT_VERSION:
+ case ADD_TABLE_SCHEMA:
+ case SET_TABLE_CURRENT_SCHEMA:
+ case ADD_TABLE_PARTITION_SPEC:
+ case ADD_TABLE_SORT_ORDER:
+ case SET_TABLE_DEFAULT_SORT_ORDER:
+ case ADD_TABLE_SNAPSHOT:
+ case SET_TABLE_SNAPSHOT_REF:
+ case REMOVE_TABLE_SNAPSHOTS:
+ case REMOVE_TABLE_SNAPSHOT_REF:
+ case SET_TABLE_LOCATION:
+ case SET_TABLE_PROPERTIES:
+ case REMOVE_TABLE_PROPERTIES:
+ case SET_TABLE_STATISTICS:
+ case REMOVE_TABLE_STATISTICS:
+ case REMOVE_TABLE_PARTITION_SPECS:
+ return true;
+
+ case CREATE_VIEW:
+ case DROP_VIEW:
+ case REPLACE_VIEW:
+ case RENAME_VIEW:
+ case LIST_VIEWS:
+ case VIEW_EXISTS:
+ case LOAD_VIEW:
+ return true;
+
+ case CREATE_POLICY:
+ case DROP_POLICY:
+ case UPDATE_POLICY:
+ case LIST_POLICY:
+ case LOAD_POLICY:
+ return true;
+
+ case SEND_NOTIFICATIONS:
+ return true;
+
+ case CREATE_PRINCIPAL_ROLE:
+ case DELETE_PRINCIPAL_ROLE:
+ case UPDATE_PRINCIPAL_ROLE:
+ case GET_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES:
+ case ASSIGN_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES_ASSIGNED:
+ case LIST_ASSIGNEE_PRINCIPALS_FOR_PRINCIPAL_ROLE:
+ case ADD_PRINCIPAL_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL:
+ case ADD_PRINCIPAL_ROLE_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL_ROLE:
+ case ADD_ROOT_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_ROOT_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_ROOT:
+ return false;
+
+ case CREATE_CATALOG_ROLE:
+ case DELETE_CATALOG_ROLE:
+ case UPDATE_CATALOG_ROLE:
+ case GET_CATALOG_ROLE:
+ case LIST_CATALOG_ROLES:
+ case ASSIGN_CATALOG_ROLE_TO_PRINCIPAL_ROLE:
+ case REVOKE_CATALOG_ROLE_FROM_PRINCIPAL_ROLE:
+ case LIST_CATALOG_ROLES_FOR_PRINCIPAL_ROLE:
+ case LIST_ASSIGNEE_PRINCIPAL_ROLES_FOR_CATALOG_ROLE:
+ case LIST_GRANTS_FOR_CATALOG_ROLE:
+ case ADD_CATALOG_ROLE_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_CATALOG_ROLE_GRANT_FROM_CATALOG_ROLE:
+ case ADD_NAMESPACE_GRANT_TO_CATALOG_ROLE:
+ case ADD_CATALOG_GRANT_TO_CATALOG_ROLE:
+ case ADD_TABLE_GRANT_TO_CATALOG_ROLE:
+ case ADD_VIEW_GRANT_TO_CATALOG_ROLE:
+ case ADD_POLICY_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_NAMESPACE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_CATALOG_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_TABLE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_VIEW_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_POLICY_GRANT_FROM_CATALOG_ROLE:
+ case LIST_GRANTS_ON_CATALOG_ROLE:
+ return false;
+
+ case LIST_GRANTS_ON_CATALOG:
+ case LIST_GRANTS_ON_NAMESPACE:
+ case LIST_GRANTS_ON_TABLE:
+ case LIST_GRANTS_ON_VIEW:
+ return false;
Review Comment:
Although I like the idea of operation types. Here we just need to remove the operations that are only relevant for the built-in RBAC system, an operation type could solve this elegantly.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
+ case SERVICE_MANAGE_ACCESS -> "service-access-manage";
+
+ case PRINCIPAL_CREATE -> "principal-create";
+ case PRINCIPAL_DROP -> "principal-drop";
+ case PRINCIPAL_LIST -> "principal-list";
+ case PRINCIPAL_READ_PROPERTIES -> "principal-properties-read";
+ case PRINCIPAL_WRITE_PROPERTIES -> "principal-properties-write";
+ case PRINCIPAL_FULL_METADATA -> "principal-metadata-full";
+ case PRINCIPAL_ROTATE_CREDENTIALS -> "principal-credentials-rotate";
+ case PRINCIPAL_RESET_CREDENTIALS -> "principal-credentials-reset";
+
+ case CATALOG_CREATE -> "catalog-create";
+ case CATALOG_DROP -> "catalog-drop";
+ case CATALOG_LIST -> "catalog-list";
+ case CATALOG_READ_PROPERTIES -> "catalog-properties-read";
+ case CATALOG_WRITE_PROPERTIES -> "catalog-properties-write";
+ case CATALOG_FULL_METADATA -> "catalog-metadata-full";
+ case CATALOG_MANAGE_METADATA -> "catalog-metadata-manage";
+ case CATALOG_MANAGE_CONTENT -> "catalog-content-manage";
+ case CATALOG_ATTACH_POLICY -> "catalog-policy-attach";
+ case CATALOG_DETACH_POLICY -> "catalog-policy-detach";
+
+ case NAMESPACE_CREATE -> "namespace-create";
+ case NAMESPACE_DROP -> "namespace-drop";
+ case NAMESPACE_LIST -> "namespace-list";
+ case NAMESPACE_READ_PROPERTIES -> "namespace-properties-read";
+ case NAMESPACE_WRITE_PROPERTIES -> "namespace-properties-write";
+ case NAMESPACE_FULL_METADATA -> "namespace-metadata-full";
+ case NAMESPACE_ATTACH_POLICY -> "namespace-policy-attach";
+ case NAMESPACE_DETACH_POLICY -> "namespace-policy-detach";
+
+ case TABLE_CREATE -> "table-create";
+ case TABLE_DROP -> "table-drop";
+ case TABLE_LIST -> "table-list";
+ case TABLE_READ_PROPERTIES -> "table-properties-read";
+ case TABLE_WRITE_PROPERTIES -> "table-properties-write";
+ case TABLE_READ_DATA -> "table-data-read";
+ case TABLE_WRITE_DATA -> "table-data-write";
+ case TABLE_FULL_METADATA -> "table-metadata-full";
+ case TABLE_ATTACH_POLICY -> "table-policy-attach";
+ case TABLE_DETACH_POLICY -> "table-policy-detach";
+ case TABLE_ASSIGN_UUID -> "table-uuid-assign";
+ case TABLE_UPGRADE_FORMAT_VERSION -> "table-format-version-upgrade";
+ case TABLE_ADD_SCHEMA -> "table-schema-add";
+ case TABLE_SET_CURRENT_SCHEMA -> "table-schema-set-current";
+ case TABLE_ADD_PARTITION_SPEC -> "table-partition-spec-add";
+ case TABLE_ADD_SORT_ORDER -> "table-sort-order-add";
+ case TABLE_SET_DEFAULT_SORT_ORDER -> "table-sort-order-set-default";
+ case TABLE_ADD_SNAPSHOT -> "table-snapshot-add";
+ case TABLE_SET_SNAPSHOT_REF -> "table-snapshot-ref-set";
+ case TABLE_REMOVE_SNAPSHOTS -> "table-snapshots-remove";
+ case TABLE_REMOVE_SNAPSHOT_REF -> "table-snapshot-ref-remove";
+ case TABLE_SET_LOCATION -> "table-location-set";
+ case TABLE_SET_PROPERTIES -> "table-properties-set";
+ case TABLE_REMOVE_PROPERTIES -> "table-properties-remove";
+ case TABLE_SET_STATISTICS -> "table-statistics-set";
+ case TABLE_REMOVE_STATISTICS -> "table-statistics-remove";
+ case TABLE_REMOVE_PARTITION_SPECS -> "table-partition-specs-remove";
+ case TABLE_MANAGE_STRUCTURE -> "table-structure-manage";
+
+ case VIEW_CREATE -> "view-create";
+ case VIEW_DROP -> "view-drop";
+ case VIEW_LIST -> "view-list";
+ case VIEW_READ_PROPERTIES -> "view-properties-read";
+ case VIEW_WRITE_PROPERTIES -> "view-properties-write";
+ case VIEW_FULL_METADATA -> "view-metadata-full";
+
+ case POLICY_CREATE -> "policy-create";
+ case POLICY_READ -> "policy-read";
+ case POLICY_DROP -> "policy-drop";
+ case POLICY_WRITE -> "policy-write";
+ case POLICY_LIST -> "policy-list";
+ case POLICY_FULL_METADATA -> "policy-metadata-full";
+ case POLICY_ATTACH -> "policy-attach";
+ case POLICY_DETACH -> "policy-detach";
+
+ default -> privilege.name();
Review Comment:
Why can't you just use the enum name for all privileges?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2932591858
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
+ case SERVICE_MANAGE_ACCESS -> "service-access-manage";
+
+ case PRINCIPAL_CREATE -> "principal-create";
+ case PRINCIPAL_DROP -> "principal-drop";
+ case PRINCIPAL_LIST -> "principal-list";
+ case PRINCIPAL_READ_PROPERTIES -> "principal-properties-read";
+ case PRINCIPAL_WRITE_PROPERTIES -> "principal-properties-write";
+ case PRINCIPAL_FULL_METADATA -> "principal-metadata-full";
+ case PRINCIPAL_ROTATE_CREDENTIALS -> "principal-credentials-rotate";
+ case PRINCIPAL_RESET_CREDENTIALS -> "principal-credentials-reset";
+
+ case CATALOG_CREATE -> "catalog-create";
+ case CATALOG_DROP -> "catalog-drop";
+ case CATALOG_LIST -> "catalog-list";
+ case CATALOG_READ_PROPERTIES -> "catalog-properties-read";
+ case CATALOG_WRITE_PROPERTIES -> "catalog-properties-write";
+ case CATALOG_FULL_METADATA -> "catalog-metadata-full";
+ case CATALOG_MANAGE_METADATA -> "catalog-metadata-manage";
+ case CATALOG_MANAGE_CONTENT -> "catalog-content-manage";
+ case CATALOG_ATTACH_POLICY -> "catalog-policy-attach";
+ case CATALOG_DETACH_POLICY -> "catalog-policy-detach";
+
+ case NAMESPACE_CREATE -> "namespace-create";
+ case NAMESPACE_DROP -> "namespace-drop";
+ case NAMESPACE_LIST -> "namespace-list";
+ case NAMESPACE_READ_PROPERTIES -> "namespace-properties-read";
+ case NAMESPACE_WRITE_PROPERTIES -> "namespace-properties-write";
+ case NAMESPACE_FULL_METADATA -> "namespace-metadata-full";
+ case NAMESPACE_ATTACH_POLICY -> "namespace-policy-attach";
+ case NAMESPACE_DETACH_POLICY -> "namespace-policy-detach";
+
+ case TABLE_CREATE -> "table-create";
+ case TABLE_DROP -> "table-drop";
+ case TABLE_LIST -> "table-list";
+ case TABLE_READ_PROPERTIES -> "table-properties-read";
+ case TABLE_WRITE_PROPERTIES -> "table-properties-write";
+ case TABLE_READ_DATA -> "table-data-read";
+ case TABLE_WRITE_DATA -> "table-data-write";
+ case TABLE_FULL_METADATA -> "table-metadata-full";
+ case TABLE_ATTACH_POLICY -> "table-policy-attach";
+ case TABLE_DETACH_POLICY -> "table-policy-detach";
+ case TABLE_ASSIGN_UUID -> "table-uuid-assign";
+ case TABLE_UPGRADE_FORMAT_VERSION -> "table-format-version-upgrade";
+ case TABLE_ADD_SCHEMA -> "table-schema-add";
+ case TABLE_SET_CURRENT_SCHEMA -> "table-schema-set-current";
+ case TABLE_ADD_PARTITION_SPEC -> "table-partition-spec-add";
+ case TABLE_ADD_SORT_ORDER -> "table-sort-order-add";
+ case TABLE_SET_DEFAULT_SORT_ORDER -> "table-sort-order-set-default";
+ case TABLE_ADD_SNAPSHOT -> "table-snapshot-add";
+ case TABLE_SET_SNAPSHOT_REF -> "table-snapshot-ref-set";
+ case TABLE_REMOVE_SNAPSHOTS -> "table-snapshots-remove";
+ case TABLE_REMOVE_SNAPSHOT_REF -> "table-snapshot-ref-remove";
+ case TABLE_SET_LOCATION -> "table-location-set";
+ case TABLE_SET_PROPERTIES -> "table-properties-set";
+ case TABLE_REMOVE_PROPERTIES -> "table-properties-remove";
+ case TABLE_SET_STATISTICS -> "table-statistics-set";
+ case TABLE_REMOVE_STATISTICS -> "table-statistics-remove";
+ case TABLE_REMOVE_PARTITION_SPECS -> "table-partition-specs-remove";
+ case TABLE_MANAGE_STRUCTURE -> "table-structure-manage";
+
+ case VIEW_CREATE -> "view-create";
+ case VIEW_DROP -> "view-drop";
+ case VIEW_LIST -> "view-list";
+ case VIEW_READ_PROPERTIES -> "view-properties-read";
+ case VIEW_WRITE_PROPERTIES -> "view-properties-write";
+ case VIEW_FULL_METADATA -> "view-metadata-full";
+
+ case POLICY_CREATE -> "policy-create";
+ case POLICY_READ -> "policy-read";
+ case POLICY_DROP -> "policy-drop";
+ case POLICY_WRITE -> "policy-write";
+ case POLICY_LIST -> "policy-list";
+ case POLICY_FULL_METADATA -> "policy-metadata-full";
+ case POLICY_ATTACH -> "policy-attach";
+ case POLICY_DETACH -> "policy-detach";
+
+ default -> privilege.name();
Review Comment:
Use of underscore in permission names is odd from Ranger policies, and will be inconsistent with Ranger policies for 25+ other services. Shouldn't an authorizer have freedom on its permission naming? :-)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyingImer (via GitHub)" <gi...@apache.org>.
flyingImer commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2908480007
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
Review Comment:
The overall SPI/plugin direction makes sense, but I wonder if we should tighten a couple of correctness edges before merging. In particular, `serviceName` appears to come straight from `Properties.getProperty(...)` without an explicit required-key validation, so a missing config key can pass startup validation and then propagate a null into the live authorizer path.
Separately, the empty `accessInfos` path seems worth guarding explicitly unless Ranger's behavior there is guaranteed-safe. I'd be more comfortable failing loudly on misconfiguration / vacuous authz inputs than relying on downstream defaults.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3051405078
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
Review Comment:
This one should be declared separately as its license is `Unicode/ICU License`.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2998249724
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
Review Comment:
Addressed in 6c005f5.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3067207355
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.context.RealmContext;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private RealmContext realmContext;
+ private String realmConextIdentifier;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ public void setRealmContext(RealmContext aRealmContext) {
+ this.realmContext = aRealmContext;
+ this.realmConextIdentifier = aRealmContext.getRealmIdentifier();
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException("resolveAuthorizationInputs is not implemented yet");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException("authorize is not implemented yet");
Review Comment:
We need to be careful with timing WFT Authorizer SPI refactoring. At some point this needs to be implemented (cf. #3999). I think we can merge "as is" and handle the new methods in a follow-up PR, though.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3077563772
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ } else {
+ props.setProperty(key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
+ if (serviceName().isEmpty()) {
+ throw new IllegalStateException(
Review Comment:
I have to revert this change in the [commit](https://github.com/sneethiraj/polaris/commit/a073e4bbe4da397a34bb0208e3f3ce08bd0fd061) as the regression test(s) without ranger configurations are failing due to serviceName not being defined. So, it make sense to define this as Optional and validate only when RangerAuthorizer is defined and used.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984880574
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
Does presence of this library change logging controlled by Quarkus env? This is a transitive dependency from a Hadoop library.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984929680
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
Yes. Ranger authorizer was tested with this specific version of `graalvm` jars.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984968551
##########
extensions/auth/ranger/README.md:
##########
@@ -0,0 +1,41 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+# Prerequisites
+Ranger authorizer for Polaris requires Apache Ranger version 2.8.0 or later.
+
+# Setup instructions
+1. Enable Ranger authorizer by setting the following property in application.properties:
+```
+polaris.authorization.type=ranger
+```
+
+2. Configure Ranger authorizer by setting configurations having name that start with "polaris.authorization.ranger." in application.properties, for example:
+```
+polaris.authorization.ranger.service-name=dev_polaris
+polaris.authorization.ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.RangerAdminRESTClient
+polaris.authorization.ranger.authz.default.policy.rest.url=http://ranger-admin:6080
Review Comment:
Can you elaborate the purpose of this ask? Are you asking to update README.md with such examples? I am not sure why anyone would want such details here.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2927534396
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
+ boolean isAllowed = RangerAuthzResult.AccessDecision.ALLOW.equals(authzResult.getDecision());
+
+ if (!isAllowed && LOG.isDebugEnabled()) {
+ for (int i = 0; i < accessInfos.size(); i++) {
+ RangerAccessInfo accessInfo = accessInfos.get(i);
+ RangerAuthzResult accessResult = authzResult.getAccesses().get(i);
+
+ if (!RangerAuthzResult.AccessDecision.ALLOW.equals(accessResult.getDecision())) {
+ LOG.debug(
+ "User {} is not authorized for {} on {}",
+ userInfo.getName(),
+ authzOp,
+ accessInfo.getResource());
+ }
+ }
+ }
+
+ return isAllowed;
+ }
+
+ private static Set<PolarisAuthorizableOperation> initAuthorizedOperations() {
+ Set<PolarisAuthorizableOperation> ret = new HashSet<>();
+
+ for (PolarisAuthorizableOperation op : PolarisAuthorizableOperation.values()) {
+ if (isAuthorizable(op)) {
+ ret.add(op);
+ }
+ }
+
+ return ret;
+ }
+
+ private static boolean isAuthorizable(PolarisAuthorizableOperation op) {
+ switch (op) {
+ case CREATE_PRINCIPAL:
+ case DELETE_PRINCIPAL:
+ case UPDATE_PRINCIPAL:
+ case GET_PRINCIPAL:
+ case LIST_PRINCIPALS:
+ case ROTATE_CREDENTIALS:
+ case RESET_CREDENTIALS:
+ return true;
+
+ case CREATE_CATALOG:
+ case DELETE_CATALOG:
+ case UPDATE_CATALOG:
+ case GET_CATALOG:
+ case LIST_CATALOGS:
+ case ATTACH_POLICY_TO_CATALOG:
+ case DETACH_POLICY_FROM_CATALOG:
+ case GET_APPLICABLE_POLICIES_ON_CATALOG:
+ return true;
+
+ case CREATE_NAMESPACE:
+ case DROP_NAMESPACE:
+ case UPDATE_NAMESPACE_PROPERTIES:
+ case LIST_NAMESPACES:
+ case NAMESPACE_EXISTS:
+ case LOAD_NAMESPACE_METADATA:
+ case ATTACH_POLICY_TO_NAMESPACE:
+ case DETACH_POLICY_FROM_NAMESPACE:
+ case GET_APPLICABLE_POLICIES_ON_NAMESPACE:
+ return true;
+
+ case CREATE_TABLE_DIRECT:
+ case CREATE_TABLE_DIRECT_WITH_WRITE_DELEGATION:
+ case CREATE_TABLE_STAGED:
+ case CREATE_TABLE_STAGED_WITH_WRITE_DELEGATION:
+ case REGISTER_TABLE:
+ case DROP_TABLE_WITHOUT_PURGE:
+ case DROP_TABLE_WITH_PURGE:
+ case UPDATE_TABLE:
+ case UPDATE_TABLE_FOR_STAGED_CREATE:
+ case RENAME_TABLE:
+ case LIST_TABLES:
+ case TABLE_EXISTS:
+ case LOAD_TABLE:
+ case LOAD_TABLE_WITH_READ_DELEGATION:
+ case LOAD_TABLE_WITH_WRITE_DELEGATION:
+ case COMMIT_TRANSACTION:
+ case ATTACH_POLICY_TO_TABLE:
+ case DETACH_POLICY_FROM_TABLE:
+ case GET_APPLICABLE_POLICIES_ON_TABLE:
+ case REPORT_READ_METRICS:
+ case REPORT_WRITE_METRICS:
+ case ASSIGN_TABLE_UUID:
+ case UPGRADE_TABLE_FORMAT_VERSION:
+ case ADD_TABLE_SCHEMA:
+ case SET_TABLE_CURRENT_SCHEMA:
+ case ADD_TABLE_PARTITION_SPEC:
+ case ADD_TABLE_SORT_ORDER:
+ case SET_TABLE_DEFAULT_SORT_ORDER:
+ case ADD_TABLE_SNAPSHOT:
+ case SET_TABLE_SNAPSHOT_REF:
+ case REMOVE_TABLE_SNAPSHOTS:
+ case REMOVE_TABLE_SNAPSHOT_REF:
+ case SET_TABLE_LOCATION:
+ case SET_TABLE_PROPERTIES:
+ case REMOVE_TABLE_PROPERTIES:
+ case SET_TABLE_STATISTICS:
+ case REMOVE_TABLE_STATISTICS:
+ case REMOVE_TABLE_PARTITION_SPECS:
+ return true;
+
+ case CREATE_VIEW:
+ case DROP_VIEW:
+ case REPLACE_VIEW:
+ case RENAME_VIEW:
+ case LIST_VIEWS:
+ case VIEW_EXISTS:
+ case LOAD_VIEW:
+ return true;
+
+ case CREATE_POLICY:
+ case DROP_POLICY:
+ case UPDATE_POLICY:
+ case LIST_POLICY:
+ case LOAD_POLICY:
+ return true;
+
+ case SEND_NOTIFICATIONS:
+ return true;
+
+ case CREATE_PRINCIPAL_ROLE:
+ case DELETE_PRINCIPAL_ROLE:
+ case UPDATE_PRINCIPAL_ROLE:
+ case GET_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES:
+ case ASSIGN_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES_ASSIGNED:
+ case LIST_ASSIGNEE_PRINCIPALS_FOR_PRINCIPAL_ROLE:
+ case ADD_PRINCIPAL_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL:
+ case ADD_PRINCIPAL_ROLE_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL_ROLE:
+ case ADD_ROOT_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_ROOT_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_ROOT:
+ return false;
+
+ case CREATE_CATALOG_ROLE:
+ case DELETE_CATALOG_ROLE:
+ case UPDATE_CATALOG_ROLE:
+ case GET_CATALOG_ROLE:
+ case LIST_CATALOG_ROLES:
+ case ASSIGN_CATALOG_ROLE_TO_PRINCIPAL_ROLE:
+ case REVOKE_CATALOG_ROLE_FROM_PRINCIPAL_ROLE:
+ case LIST_CATALOG_ROLES_FOR_PRINCIPAL_ROLE:
+ case LIST_ASSIGNEE_PRINCIPAL_ROLES_FOR_CATALOG_ROLE:
+ case LIST_GRANTS_FOR_CATALOG_ROLE:
+ case ADD_CATALOG_ROLE_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_CATALOG_ROLE_GRANT_FROM_CATALOG_ROLE:
+ case ADD_NAMESPACE_GRANT_TO_CATALOG_ROLE:
+ case ADD_CATALOG_GRANT_TO_CATALOG_ROLE:
+ case ADD_TABLE_GRANT_TO_CATALOG_ROLE:
+ case ADD_VIEW_GRANT_TO_CATALOG_ROLE:
+ case ADD_POLICY_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_NAMESPACE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_CATALOG_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_TABLE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_VIEW_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_POLICY_GRANT_FROM_CATALOG_ROLE:
+ case LIST_GRANTS_ON_CATALOG_ROLE:
+ return false;
+
+ case LIST_GRANTS_ON_CATALOG:
+ case LIST_GRANTS_ON_NAMESPACE:
+ case LIST_GRANTS_ON_TABLE:
+ case LIST_GRANTS_ON_VIEW:
+ return false;
Review Comment:
agreed that it's safer to deny the new operations by default, and compilation failure seems fine for op removal.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983629243
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
On a second thought, I think we can delegate decisions about operations on local principal entities to Ranger, but I think we should avoid any extra logic grounded in principals names or specific roles and delegate all checks to Ranger rules.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3124810161
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
+* Maven group:artifact IDs: org.graalvm.shadowed:xz
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-api
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-compiler
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-runtime
+
+Home page: https://github.com/oracle/graal/
+License: The GNU General Public License (GPL) - https://github.com/oracle/graal/blob/master/LICENSE
Review Comment:
I will create a another PR for updating the file, runtime/server/distribution/LICENSE for graal to be ***The Universal Permissive License (UPL), Version 1.0*** based on https://github.com/oracle/graaljs/blob/master/LICENSE
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4297724279
> Just a note: GPL 2.0 AND Classpath-Exception is Category B (not X).
Even when we *bundle* it instead of just *linking* to it?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2892743624
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ Properties prop = new Properties();
+
+ if (resourcePath != null) {
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Adding / to the configFileName [{}]", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ prop.load(in);
+ } else {
+ LOG.error("Unable to find ranger config file in the classpath : [{}]", resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load config file: [{}]", resourcePath, e);
+ }
+ }
+
+ return prop;
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
+ case SERVICE_MANAGE_ACCESS -> "service-access-manage";
+
+ case PRINCIPAL_CREATE -> "principal-create";
+ case PRINCIPAL_DROP -> "principal-drop";
+ case PRINCIPAL_LIST -> "principal-list";
+ case PRINCIPAL_READ_PROPERTIES -> "principal-properties-read";
+ case PRINCIPAL_WRITE_PROPERTIES -> "principal-properties-write";
+ case PRINCIPAL_FULL_METADATA -> "principal-metadata-full";
+ case PRINCIPAL_ROTATE_CREDENTIALS -> "principal-credentials-rotate";
+ case PRINCIPAL_RESET_CREDENTIALS -> "principal-credentials-reset";
+
+ case CATALOG_CREATE -> "catalog-create";
+ case CATALOG_DROP -> "catalog-drop";
+ case CATALOG_LIST -> "catalog-list";
+ case CATALOG_READ_PROPERTIES -> "catalog-properties-read";
+ case CATALOG_WRITE_PROPERTIES -> "catalog-properties-write";
+ case CATALOG_FULL_METADATA -> "catalog-metadata-full";
+ case CATALOG_MANAGE_METADATA -> "catalog-metadata-manage";
+ case CATALOG_MANAGE_CONTENT -> "catalog-content-manage";
+ case CATALOG_ATTACH_POLICY -> "catalog-policy-attach";
+ case CATALOG_DETACH_POLICY -> "catalog-policy-detach";
+
+ case NAMESPACE_CREATE -> "namespace-create";
+ case NAMESPACE_DROP -> "namespace-drop";
+ case NAMESPACE_LIST -> "namespace-list";
+ case NAMESPACE_READ_PROPERTIES -> "namespace-properties-read";
+ case NAMESPACE_WRITE_PROPERTIES -> "namespace-properties-write";
+ case NAMESPACE_FULL_METADATA -> "namespace-metadata-full";
+ case NAMESPACE_ATTACH_POLICY -> "namespace-policy-attach";
+ case NAMESPACE_DETACH_POLICY -> "namespace-policy-detach";
+
+ case TABLE_CREATE -> "table-create";
+ case TABLE_DROP -> "table-drop";
+ case TABLE_LIST -> "table-list";
+ case TABLE_READ_PROPERTIES -> "table-properties-read";
+ case TABLE_WRITE_PROPERTIES -> "table-properties-write";
+ case TABLE_READ_DATA -> "table-data-read";
+ case TABLE_WRITE_DATA -> "table-data-write";
+ case TABLE_FULL_METADATA -> "table-metadata-full";
+ case TABLE_ATTACH_POLICY -> "table-policy-attach";
+ case TABLE_DETACH_POLICY -> "table-policy-detach";
+ case TABLE_ASSIGN_UUID -> "table-uuid-assign";
+ case TABLE_UPGRADE_FORMAT_VERSION -> "table-format-version-upgrade";
+ case TABLE_ADD_SCHEMA -> "table-schema-add";
+ case TABLE_SET_CURRENT_SCHEMA -> "table-schema-set-current";
+ case TABLE_ADD_PARTITION_SPEC -> "table-partition-spec-add";
+ case TABLE_ADD_SORT_ORDER -> "table-sort-order-add";
+ case TABLE_SET_DEFAULT_SORT_ORDER -> "table-sort-order-set-default";
+ case TABLE_ADD_SNAPSHOT -> "table-snapshot-add";
+ case TABLE_SET_SNAPSHOT_REF -> "table-snapshot-ref-set";
+ case TABLE_REMOVE_SNAPSHOTS -> "table-snapshots-remove";
+ case TABLE_REMOVE_SNAPSHOT_REF -> "table-snapshot-ref-remove";
+ case TABLE_SET_LOCATION -> "table-location-set";
+ case TABLE_SET_PROPERTIES -> "table-properties-set";
+ case TABLE_REMOVE_PROPERTIES -> "table-properties-remove";
+ case TABLE_SET_STATISTICS -> "table-statistics-set";
+ case TABLE_REMOVE_STATISTICS -> "table-statistics-remove";
+ case TABLE_REMOVE_PARTITION_SPECS -> "table-partition-specs-remove";
+ case TABLE_MANAGE_STRUCTURE -> "table-structure-manage";
+
+ case VIEW_CREATE -> "view-create";
+ case VIEW_DROP -> "view-drop";
+ case VIEW_LIST -> "view-list";
+ case VIEW_READ_PROPERTIES -> "view-properties-read";
+ case VIEW_WRITE_PROPERTIES -> "view-properties-write";
+ case VIEW_FULL_METADATA -> "view-metadata-full";
+
+ case POLICY_CREATE -> "policy-create";
+ case POLICY_READ -> "policy-read";
+ case POLICY_DROP -> "policy-drop";
+ case POLICY_WRITE -> "policy-write";
+ case POLICY_LIST -> "policy-list";
+ case POLICY_FULL_METADATA -> "policy-metadata-full";
+ case POLICY_ATTACH -> "policy-attach";
+ case POLICY_DETACH -> "policy-detach";
+
+ default -> privilege.name();
+ };
+ }
+
+ public static RangerUserInfo toUserInfo(PolarisPrincipal principal) {
+ return new RangerUserInfo(
+ principal.getName(), getUserAttributes(principal), null, principal.getRoles());
+ }
+
+ public static RangerAccessInfo toAccessInfo(
+ PolarisResolvedPathWrapper entity,
+ PolarisAuthorizableOperation authzOp,
+ EnumSet<PolarisPrivilege> privileges) {
+ return new RangerAccessInfo(
+ RangerUtils.toResourceInfo(entity), authzOp.name(), RangerUtils.toPermissions(privileges));
+ }
+
+ public static String toResourcePath(List<PolarisResolvedPathWrapper> resolvedPaths) {
+ return resolvedPaths.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(","));
+ }
+
+ public static String toResourcePath(PolarisResolvedPathWrapper resolvedPath) {
+ StringBuilder sb = new StringBuilder();
+ String resourceType =
+ toResourceType(resolvedPath.getResolvedLeafEntity().getEntity().getType());
+
+ sb.append(resourceType).append(RangerResourceNameParser.RRN_RESOURCE_TYPE_SEP);
+
+ boolean isFirst = true;
+
+ for (ResolvedPolarisEntity entity : resolvedPath.getResolvedFullPath()) {
+ if (!isFirst) {
+ sb.append(RangerResourceNameParser.DEFAULT_RRN_RESOURCE_SEP);
+ } else {
+ isFirst = false;
+ }
+
+ sb.append(entity.getEntity().getName());
+ }
+
+ return sb.toString();
+ }
+
+ private static RangerResourceInfo toResourceInfo(PolarisResolvedPathWrapper resourcePath) {
+ RangerResourceInfo ret = new RangerResourceInfo();
+
+ ret.setName(toResourcePath(resourcePath));
+ ret.setAttributes(getResourceAttributes(resourcePath));
+
+ return ret;
+ }
+
+ private static Set<String> toPermissions(EnumSet<PolarisPrivilege> privileges) {
+ return privileges.stream().map(RangerUtils::toAccessType).collect(Collectors.toSet());
+ }
+
+ private static Map<String, Object> getResourceAttributes(
+ PolarisResolvedPathWrapper resourcePath) {
+ Map<String, Object> ret = null;
+
+ for (ResolvedPolarisEntity resolvedEntity : resourcePath.getResolvedFullPath()) {
+ PolarisEntity entity = resolvedEntity.getEntity();
+
+ if (StringUtils.isNotBlank(entity.getProperties())) {
+ if (ret == null) {
+ ret = new HashMap<>(entity.getPropertiesAsMap());
+ } else {
+ ret.putAll(entity.getPropertiesAsMap());
Review Comment:
It is not clear what attributes are availble via `getPropertiesMap()`. The only attribute currently used by Ranger is `owner`; if this is available in Polaris, the value in the leaf resource is appropriate, hence the override.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2892722907
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
Review Comment:
Will replace use of `org.jspecify.annotations.NonNull` with `jakarta.annotation.Nonnull`. Thanks!
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2900016775
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ Properties prop = new Properties();
+
+ if (resourcePath != null) {
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Adding / to the configFileName [{}]", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
Review Comment:
@flyingImer This has been addressed in the latest commit. Please review the fixes in the latest code.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2920960020
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
+ implementation(libs.commons.lang3)
+ implementation(libs.guava)
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+ compileOnly(project(":polaris-immutables"))
+
+ runtimeOnly(libs.graalvm.graal.sdk)
+ runtimeOnly(libs.graalvm.inspect.community)
+ runtimeOnly(libs.graalvm.js.community)
+ runtimeOnly(libs.graalvm.js.scriptengine)
+ runtimeOnly(libs.graalvm.nativeimage)
Review Comment:
@dimas-b - sorry, I missed that your earlier question was speciifically about `nativeimage`. I reviewed and found that `nativeimage` and few more dependencies are not necessary. I updated the PR by replacing dependencies with the following:
- org.graalvm.js:js-scriptengine
- org.graalvm.polyglot:js
- org.graalvm.polyglot:polyglot
Thank you for flagging this issue.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922559941
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
+ boolean isAllowed = RangerAuthzResult.AccessDecision.ALLOW.equals(authzResult.getDecision());
+
+ if (!isAllowed && LOG.isDebugEnabled()) {
+ for (int i = 0; i < accessInfos.size(); i++) {
+ RangerAccessInfo accessInfo = accessInfos.get(i);
+ RangerAuthzResult accessResult = authzResult.getAccesses().get(i);
+
+ if (!RangerAuthzResult.AccessDecision.ALLOW.equals(accessResult.getDecision())) {
+ LOG.debug(
+ "User {} is not authorized for {} on {}",
+ userInfo.getName(),
+ authzOp,
+ accessInfo.getResource());
+ }
+ }
+ }
+
+ return isAllowed;
+ }
+
+ private static Set<PolarisAuthorizableOperation> initAuthorizedOperations() {
+ Set<PolarisAuthorizableOperation> ret = new HashSet<>();
+
+ for (PolarisAuthorizableOperation op : PolarisAuthorizableOperation.values()) {
+ if (isAuthorizable(op)) {
+ ret.add(op);
+ }
+ }
+
+ return ret;
+ }
+
+ private static boolean isAuthorizable(PolarisAuthorizableOperation op) {
+ switch (op) {
+ case CREATE_PRINCIPAL:
+ case DELETE_PRINCIPAL:
+ case UPDATE_PRINCIPAL:
+ case GET_PRINCIPAL:
+ case LIST_PRINCIPALS:
+ case ROTATE_CREDENTIALS:
+ case RESET_CREDENTIALS:
+ return true;
+
+ case CREATE_CATALOG:
+ case DELETE_CATALOG:
+ case UPDATE_CATALOG:
+ case GET_CATALOG:
+ case LIST_CATALOGS:
+ case ATTACH_POLICY_TO_CATALOG:
+ case DETACH_POLICY_FROM_CATALOG:
+ case GET_APPLICABLE_POLICIES_ON_CATALOG:
+ return true;
+
+ case CREATE_NAMESPACE:
+ case DROP_NAMESPACE:
+ case UPDATE_NAMESPACE_PROPERTIES:
+ case LIST_NAMESPACES:
+ case NAMESPACE_EXISTS:
+ case LOAD_NAMESPACE_METADATA:
+ case ATTACH_POLICY_TO_NAMESPACE:
+ case DETACH_POLICY_FROM_NAMESPACE:
+ case GET_APPLICABLE_POLICIES_ON_NAMESPACE:
+ return true;
+
+ case CREATE_TABLE_DIRECT:
+ case CREATE_TABLE_DIRECT_WITH_WRITE_DELEGATION:
+ case CREATE_TABLE_STAGED:
+ case CREATE_TABLE_STAGED_WITH_WRITE_DELEGATION:
+ case REGISTER_TABLE:
+ case DROP_TABLE_WITHOUT_PURGE:
+ case DROP_TABLE_WITH_PURGE:
+ case UPDATE_TABLE:
+ case UPDATE_TABLE_FOR_STAGED_CREATE:
+ case RENAME_TABLE:
+ case LIST_TABLES:
+ case TABLE_EXISTS:
+ case LOAD_TABLE:
+ case LOAD_TABLE_WITH_READ_DELEGATION:
+ case LOAD_TABLE_WITH_WRITE_DELEGATION:
+ case COMMIT_TRANSACTION:
+ case ATTACH_POLICY_TO_TABLE:
+ case DETACH_POLICY_FROM_TABLE:
+ case GET_APPLICABLE_POLICIES_ON_TABLE:
+ case REPORT_READ_METRICS:
+ case REPORT_WRITE_METRICS:
+ case ASSIGN_TABLE_UUID:
+ case UPGRADE_TABLE_FORMAT_VERSION:
+ case ADD_TABLE_SCHEMA:
+ case SET_TABLE_CURRENT_SCHEMA:
+ case ADD_TABLE_PARTITION_SPEC:
+ case ADD_TABLE_SORT_ORDER:
+ case SET_TABLE_DEFAULT_SORT_ORDER:
+ case ADD_TABLE_SNAPSHOT:
+ case SET_TABLE_SNAPSHOT_REF:
+ case REMOVE_TABLE_SNAPSHOTS:
+ case REMOVE_TABLE_SNAPSHOT_REF:
+ case SET_TABLE_LOCATION:
+ case SET_TABLE_PROPERTIES:
+ case REMOVE_TABLE_PROPERTIES:
+ case SET_TABLE_STATISTICS:
+ case REMOVE_TABLE_STATISTICS:
+ case REMOVE_TABLE_PARTITION_SPECS:
+ return true;
+
+ case CREATE_VIEW:
+ case DROP_VIEW:
+ case REPLACE_VIEW:
+ case RENAME_VIEW:
+ case LIST_VIEWS:
+ case VIEW_EXISTS:
+ case LOAD_VIEW:
+ return true;
+
+ case CREATE_POLICY:
+ case DROP_POLICY:
+ case UPDATE_POLICY:
+ case LIST_POLICY:
+ case LOAD_POLICY:
+ return true;
+
+ case SEND_NOTIFICATIONS:
+ return true;
+
+ case CREATE_PRINCIPAL_ROLE:
+ case DELETE_PRINCIPAL_ROLE:
+ case UPDATE_PRINCIPAL_ROLE:
+ case GET_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES:
+ case ASSIGN_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE:
+ case LIST_PRINCIPAL_ROLES_ASSIGNED:
+ case LIST_ASSIGNEE_PRINCIPALS_FOR_PRINCIPAL_ROLE:
+ case ADD_PRINCIPAL_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL:
+ case ADD_PRINCIPAL_ROLE_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_PRINCIPAL_ROLE_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_PRINCIPAL_ROLE:
+ case ADD_ROOT_GRANT_TO_PRINCIPAL_ROLE:
+ case REVOKE_ROOT_GRANT_FROM_PRINCIPAL_ROLE:
+ case LIST_GRANTS_ON_ROOT:
+ return false;
+
+ case CREATE_CATALOG_ROLE:
+ case DELETE_CATALOG_ROLE:
+ case UPDATE_CATALOG_ROLE:
+ case GET_CATALOG_ROLE:
+ case LIST_CATALOG_ROLES:
+ case ASSIGN_CATALOG_ROLE_TO_PRINCIPAL_ROLE:
+ case REVOKE_CATALOG_ROLE_FROM_PRINCIPAL_ROLE:
+ case LIST_CATALOG_ROLES_FOR_PRINCIPAL_ROLE:
+ case LIST_ASSIGNEE_PRINCIPAL_ROLES_FOR_CATALOG_ROLE:
+ case LIST_GRANTS_FOR_CATALOG_ROLE:
+ case ADD_CATALOG_ROLE_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_CATALOG_ROLE_GRANT_FROM_CATALOG_ROLE:
+ case ADD_NAMESPACE_GRANT_TO_CATALOG_ROLE:
+ case ADD_CATALOG_GRANT_TO_CATALOG_ROLE:
+ case ADD_TABLE_GRANT_TO_CATALOG_ROLE:
+ case ADD_VIEW_GRANT_TO_CATALOG_ROLE:
+ case ADD_POLICY_GRANT_TO_CATALOG_ROLE:
+ case REVOKE_NAMESPACE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_CATALOG_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_TABLE_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_VIEW_GRANT_FROM_CATALOG_ROLE:
+ case REVOKE_POLICY_GRANT_FROM_CATALOG_ROLE:
+ case LIST_GRANTS_ON_CATALOG_ROLE:
+ return false;
+
+ case LIST_GRANTS_ON_CATALOG:
+ case LIST_GRANTS_ON_NAMESPACE:
+ case LIST_GRANTS_ON_TABLE:
+ case LIST_GRANTS_ON_VIEW:
+ return false;
Review Comment:
Removal of any enum listed in here would require a update to this source, to avoid compilation failure - this is good, right? However, introduction of enum would result in Ranger authorizer denying the access. The authorizer will need to be updated to to handle new operations - which seems reasonable.
I don't think the authorizer SPI should distinguish operations implemented by `default-authorizer` vs `other-authorizers`. Instead, the authorizer calls in SPI should capture all input/output details to complete each operation so that implementions can perform or reject operations depending on their model. For example the call for:
- `CREATE_PRINCIPAL_ROLE` must provide all details necessary to create the principal-role, like name, type, property
- `LIST_GRANTS_ON_PRINCIPAL` must provide the principal name and any other relevant details and expect grants to be returned in specific structure
This will make authorizer SPI not make any assumptions on default vs other authorizer implementations.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2934160474
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
Review Comment:
`hadoop-client-api` and `hadoop-client-runtime` are used only when Ranger authorizer is configured to write audit logs to HDFS. Updated dependencies to exclude these libraries - 40ed676.
Removing `javax.servlet-api` dependency will require minor updates in Ranger side. I filed [RANGER-5515](https://issues.apache.org/jira/browse/RANGER-5515) to track this update. Using the updated Ranger release will eliminate the transitive dependency here. Thank you @adutra and @dimas-b for flagging this.
Removing `jersey-bundle` dependency will also require updates in Ranger side, but may not be a minor one. I will look into this update from Ranger side.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922628569
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
+ boolean isAllowed = RangerAuthzResult.AccessDecision.ALLOW.equals(authzResult.getDecision());
+
+ if (!isAllowed && LOG.isDebugEnabled()) {
+ for (int i = 0; i < accessInfos.size(); i++) {
+ RangerAccessInfo accessInfo = accessInfos.get(i);
+ RangerAuthzResult accessResult = authzResult.getAccesses().get(i);
+
+ if (!RangerAuthzResult.AccessDecision.ALLOW.equals(accessResult.getDecision())) {
+ LOG.debug(
+ "User {} is not authorized for {} on {}",
+ userInfo.getName(),
+ authzOp,
+ accessInfo.getResource());
Review Comment:
Addressed in b684de1.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2941993932
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded) {
+ exclude("org.apache.hadoop", "hadoop-client-api")
+ exclude("org.apache.hadoop", "hadoop-client-runtime")
+ }
+ implementation(libs.commons.lang3)
+ implementation(libs.graalvm.js.js.scriptengine)
+ implementation(libs.graalvm.polyglot.js)
+ implementation(libs.graalvm.polyglot.polyglot)
Review Comment:
Yes, that is correct; will change dependency to `runtimeOnly`. Thank you.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2942181206
##########
extensions/auth/ranger/src/test/resources/authz_tests/ranger-plugin.properties:
##########
@@ -0,0 +1,25 @@
+#
Review Comment:
Addressed in e6482c0.
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
Review Comment:
Addressed in e6482c0.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2942118228
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java:
##########
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.polaris.core.config.PolarisConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.CatalogEntity;
+
+public class RangerTestUtils {
+ public static RangerPolarisAuthorizerConfig createConfig() {
Review Comment:
I haven't tried `@QuarkusTest` yet; can this be taken up in a follow-up PR? I would prefer to retain current light-weight unit tests though.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983555443
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
Review Comment:
It would be nice to unify error messages for all authorizers, but that's out of scope of this PR, of course.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983051120
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java:
##########
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.polaris.core.config.PolarisConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.CatalogEntity;
+
+public class RangerTestUtils {
+ public static RangerPolarisAuthorizerConfig createConfig() {
Review Comment:
but, we can do it in a follow-up PR, I agree.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984812482
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
Review Comment:
Ranger authorizer expects property names to start with `ranger.` - like `ranger.authz.default.policy.rest.url`; so property names in `application.properties` would have repeated `ranger.` - for example `polaris.authorizer.ranger.ranger.authz.default.policy.rest.url`. @sneethiraj introduced an enhancement to not require this repeat in `application.properties` - by implicitly adding `ranger.` prefix when it is not present in the property name. `if` at line 41 is a defensive one - to handle properties that already have repeated `ranger.`. Property prefix `xasecure.` is a legacy one..before the code base was contributed to Apache.
It should be okay to drop support for prefixes `xasecure.` and `ranger.ranger.` - eliminating `if` at line 41. @dimas-b - let me know your preference.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984830090
##########
extensions/auth/ranger/README.md:
##########
@@ -0,0 +1,41 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+# Prerequisites
+Ranger authorizer for Polaris requires Apache Ranger version 2.8.0 or later.
+
+# Setup instructions
+1. Enable Ranger authorizer by setting the following property in application.properties:
+```
+polaris.authorization.type=ranger
+```
+
+2. Configure Ranger authorizer by setting configurations having name that start with "polaris.authorization.ranger." in application.properties, for example:
+```
+polaris.authorization.ranger.service-name=dev_polaris
+polaris.authorization.ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.RangerAdminRESTClient
+polaris.authorization.ranger.authz.default.policy.rest.url=http://ranger-admin:6080
Review Comment:
With above configurations, Ranger plugin uses following REST API call to retrieve authorization policies:
- `GET http://ranger-admin:6080/service/plugins/secure/policies/download/dev_polaris`
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4218065706
Thank you @adutra and everyone else who had spend your valuable time to review and provide your suggestions. I have tried the exclude methods for all-of the libraries mentioned by @adutra and after reviewing the runtime tests, I was able to remove 3 dependencies:
```
exclude("org.slf4j", "slf4j-reload4j")
exclude("ch.qos.reload4j", "reload4j")
exclude("io.dropwizard.metrics", "metrics-core")
```
I have made these changes as part of this PR.
1. Jersy libraries have been used in few of the ranger client classes that needs to be remapped to an equivalent (and latest) libraries to be able to remove this dependencies for now.
2. Jetty libraries are used by Solr clients for using Kerberos Authentication.
They both can be targeted to be removed in the upcoming ranger release 2.9.0.
Let me know if there are any more pending items to be addressed for moving this feature to the main branch.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4173942822
This PR LGTM in general, pending the resolution of the dependencies (and LICENSE / NOTICE) discussion.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3090609182
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(key, properties().get(key));
+ } else {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
+ checkState(serviceName().isPresent(), "serviceName is not defined for ranger authorizer");
Review Comment:
The serviceName() is declared as Optional because it is only required when the Ranger authorizer is configured.
The validate() logic is invoked only when Ranger is selected as the authorizer (via the RangerPolarisAuthorizerFactory constructor). If serviceName() were marked as mandatory at the configuration level, the required-field validation would fail even in deployments where Ranger is not configured as the authorizer.
Making it Optional allows the configuration to remain valid for non-Ranger authorizers, while still enforcing the presence of serviceName() during validation when Ranger is explicitly selected.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984912896
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
Review Comment:
I'm a bit lost here :sweat_smile: this is a fresh PR... how can we get properties with repeated `ranger.ranger.` segments?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984916075
##########
extensions/auth/ranger/README.md:
##########
@@ -0,0 +1,41 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+# Prerequisites
+Ranger authorizer for Polaris requires Apache Ranger version 2.8.0 or later.
+
+# Setup instructions
+1. Enable Ranger authorizer by setting the following property in application.properties:
+```
+polaris.authorization.type=ranger
+```
+
+2. Configure Ranger authorizer by setting configurations having name that start with "polaris.authorization.ranger." in application.properties, for example:
+```
+polaris.authorization.ranger.service-name=dev_polaris
+polaris.authorization.ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.RangerAdminRESTClient
+polaris.authorization.ranger.authz.default.policy.rest.url=http://ranger-admin:6080
Review Comment:
I mean if the Ranger server itself requires authentication for its REST API calls, could you add a user-facing example for that?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933433343
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
Review Comment:
> Here we just need to remove the operations that are only relevant for the built-in RBAC system,
Ok. The reason to list all available operations is to make it easier for code readers to grasp operations that are not supported. I will remove these now - ~50 fewers lines of code!
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922483402
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
Review Comment:
Addressed in b684de1.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "kumaab (via GitHub)" <gi...@apache.org>.
kumaab commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2915516525
##########
extensions/auth/ranger/README.txt:
##########
@@ -0,0 +1,49 @@
+#
Review Comment:
Readme files within `apache/polaris` use `.md` extension so this file should be updated to be `extensions/auth/ranger/README.md`
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2915578649
##########
extensions/auth/ranger/README.txt:
##########
@@ -0,0 +1,49 @@
+#
Review Comment:
Addressed in [3d166e9](https://github.com/apache/polaris/commit/3d166e9ee79d3ccd03017067d94b03bda593cb32).
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984957954
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
> Is Hadoop required for audit call paths only?
Hadoop `client libraries` are used for other purposes as well in Ranger authorizer - for example to manage configurations, Kerberos authentication.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2997784783
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
@dimas-b - it seems you are asking to remove the following code from Ranger authorizer. Can you please confirm? I see no issues in removing this block from Ranger authorizer.
```
if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
if (!isRootPrincipal) {
// TODO: enable ranger audit from here to ensure that the request denied captured.
throw new ForbiddenException(
ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
}
```
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2998251366
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
Review Comment:
Addressed in 6c005f5.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
Addressed in 6c005f5.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983431170
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
Review Comment:
It's not a big deal, but I'm just wondering why we need `jackson-jaxrs-json-provider`... I would have thought it is normally uses in HTTP _servers_, but the Ranger Authorizer is still a client π€
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
Review Comment:
Same... How does the Ranger Authorizer depend on `solrj`?
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
Review Comment:
Same for Zookeeper... how does it affect the Ranger Authorizer?
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
Do we need it? Logging should be controlled by the Quarkus env., I think π€
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983461764
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
Review Comment:
Jetty has a NOTICE file: https://github.com/jetty/jetty.project/blob/jetty-12.1.x/NOTICE.txt
We probably need to include it in Polaris' NOTICE. @jbonofre : WDYT?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984851503
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
Review Comment:
Ranger authorizer supports writing audit logs to Solr, which are used for interactive viewing of accesses in a deployment via Ranger admin console. Zookeeper is used by Solr client when Solr is deployed in cloud mode.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983499164
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
Review Comment:
As far as I can tell, `RangerPolarisOperationSemantics` is not a factor in actual authZ decisions... What is the purpose of this class? π€
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4218201464
@adutra - what can I say..I am humbled! At the level of details you went through in finding workable options. Thank you! Ranger community has already addressed some of your concerns, and work is in progress to address others:
1. jersey-bundle: RANGER-5523: replace jersey-bundle dependency with jersey-client & jsersey-core
2. Gethostname4J: RANGER-5549 - replace use of com.kstruct.gethostname4j library
3. Reload4J: @sneethiraj addressed this in a recent commit in this PR
4. Dropwizard Metrics: @sneethiraj addressed this in a recent commit in this PR
(1) & (2) will be included in the next Ranger release 2.9.0 - likely within couple of weeks. Ranger community is actively working to make "remote" policy evaluation option available using `ranger-pdp` server (RANGER-5371). A thin client with a much smaller dependency list is tracked in RANGER-5550. Once these are in place, @sneethiraj and I will update PolarisAuthorizer implementation to eliminate most of the dependencies.
Thank you all for your engagement in this PR and push to making Ranger authorization available to Polaris users.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3067214375
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
@sneethiraj @mneethiraj : WDYT about keeping this version compatible with Ranger?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4214763099
Also: since it seems that the deployment model could evolve towards something different (e.g. sidecar), which would alter the authorizer implementation significantly, I'd suggest releasing the authorizer with an experimental / beta status for now.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3089368160
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(key, properties().get(key));
+ } else {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
+ checkState(serviceName().isPresent(), "serviceName is not defined for ranger authorizer");
Review Comment:
Why declare `serviceName()` as `Optional` when this check treats it as required?
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(key, properties().get(key));
+ } else {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
Review Comment:
Who calls this `validate()` method?
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
Review Comment:
Please see earlier comments in this thread.
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
Please see earlier comments in this thread.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3089351861
##########
extensions/auth/ranger/impl/README.md:
##########
@@ -0,0 +1,41 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+# Prerequisites
+Ranger authorizer for Polaris requires Apache Ranger version 2.8.0 or later.
+
+# Setup instructions
+1. Enable Ranger authorizer by setting the following property in application.properties:
+```
+polaris.authorization.type=ranger
+```
+
+2. Configure Ranger authorizer by setting configurations having name that start with "polaris.authorization.ranger." in application.properties, for example:
+```
+polaris.authorization.ranger.service-name=dev_polaris
+polaris.authorization.ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.RangerAdminRESTClient
+polaris.authorization.ranger.authz.default.policy.rest.url=http://ranger-admin:6080
Review Comment:
Yes, I mean adding docs for authentication between Polaris and Ranger servers (can be done later).
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2942179936
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded) {
+ exclude("org.apache.hadoop", "hadoop-client-api")
+ exclude("org.apache.hadoop", "hadoop-client-runtime")
+ }
+ implementation(libs.commons.lang3)
+ implementation(libs.graalvm.js.js.scriptengine)
+ implementation(libs.graalvm.polyglot.js)
+ implementation(libs.graalvm.polyglot.polyglot)
Review Comment:
Addressed in e6482c0.
##########
extensions/auth/ranger/src/test/resources/authz_tests/ranger-plugin-invalid.properties:
##########
@@ -0,0 +1,26 @@
+#
Review Comment:
Addressed in e6482c0.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2942178601
##########
gradle/libs.versions.toml:
##########
@@ -47,11 +49,16 @@ azuresdk-bom = { module = "com.azure:azure-sdk-bom", version = "1.3.5" }
caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version = "3.2.3" }
cel-bom = { module = "org.projectnessie.cel:cel-bom", version = "0.6.0" }
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } # required by the polaris-java plugin
+commons-collections = { module = "commons-collections:commons-collections", version = "3.2.2" }
Review Comment:
Addressed in e6482c0.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2927759413
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
Review Comment:
> Authorizer SPI requires implementations to ensure that the principal is allowed to perform the operation on specified targets and secondaries.
This feels like a bit of a gray area now, and I'm not sure the statement is necessarily accurate.
Different authorizers may use very different authorization models. For example, OPA or other policy based authorizers may not rely on a privilege model at all. They could evaluate the request directly based on the operation and context, or define completely different permissions for targets and secondaries.
For instance, an authorizer could expose a single permission like `ATTACH_POLICY`, or use a different policy mechanism to allow an operation such as:
```
ATTACH_POLICY_TO_CATALOG(POLICY_ATTACH, CATALOG_ATTACH_POLICY)
```
So requiring implementations to honor `PolarisPrivilege` may be too restrictive for the SPI. It seems more accurate for the SPI to require that the implementation decides whether the principal can perform the operation on the given targets and secondaries, while leaving the internal permission model up to the authorizer.
That said, it still makes sense for a specific authorizer like Ranger to follow the RBAC privilege model internally. I'm mainly worried about the maintenance cost and I don't think privileges should be part of authorizer SPI.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2957322625
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
Can we file an issue for this refactor? So that it won't be forgotten and it may attract new contributors.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3090664201
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
@mneethiraj - Can you please review and provide your feedback here?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4293809102
Thanks for the PR, @sneethiraj @mneethiraj! It's a great feature to have. Thanks everyone for the review.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain merged PR #3928:
URL: https://github.com/apache/polaris/pull/3928
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3122030416
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
+* Maven group:artifact IDs: org.graalvm.shadowed:xz
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-api
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-compiler
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-runtime
+
+Home page: https://github.com/oracle/graal/
+License: The GNU General Public License (GPL) - https://github.com/oracle/graal/blob/master/LICENSE
Review Comment:
Classpath Exception is not relevant if we bundle the dependency.
That should be clarified.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3120921675
##########
gradle/libs.versions.toml:
##########
@@ -25,6 +25,8 @@ immutables = "2.12.1"
jmh = "1.37"
picocli = "4.7.7"
quarkus = "3.32.4"
+ranger = "2.8.0"
+ranger-graalvm = "25.0.2"
Review Comment:
I suspect this declaration will still be subject to automated version bumps by the Renovate bot.
I personally think it's not a good idea (we should pin this version instead). However, @sneethiraj : if you are ok with that, I'm approving the PR.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933676676
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+ Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerConfig.class);
+
+ String PROP_RANGER_CONFIG_FILE_NAME = "polaris.authorization.ranger.config-file-name";
+ String PROP_POLARIS_SERVICE_NAME = "ranger.plugin.polaris.service.name";
+
+ String ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME =
+ "Invalid Ranger authorizer configuration: missing configuration "
+ + PROP_RANGER_CONFIG_FILE_NAME;
+ String ERR_INVALID_CONFIG_FILE_MISSING_CONFIGURATION =
+ "Invalid Ranger authorizer configuration file %s: missing mandatory configuration %s";
+
+ Optional<String> configFileName();
+
+ default void validate() {
+ boolean isConfigFileNamePresent = configFileName().isPresent();
+
+ if (!isConfigFileNamePresent) {
+ LOG.error(ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME);
+
+ throw new IllegalStateException(ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME);
+ }
+
+ String fileName = configFileName().get();
+
+ Properties prop = RangerUtils.loadProperties(fileName);
Review Comment:
Using a separate configuration file keeps the default configuration file less noisy. However, if the guidence is to keep all the configurations in the default file, I would prefer the second suggesion (`Embed Ranger configuration in Quarkus`), as property key names can be dynamic.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2915412794
##########
build.gradle.kts:
##########
@@ -106,6 +106,9 @@ tasks.named<RatTask>("rat").configure {
// Polaris service startup banner
excludes.add("runtime/service/src/**/banner.txt")
+ // Polaris service log files - generated by polaris-server
+ excludes.add("runtime/server/logs/**")
Review Comment:
No, this is not specific to this PR. Will update to remove this change from this PR.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984836274
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
With JDK15 or later, Ranger recommends using `graalvm` to evaluate expression used in advanced policies. 25.0.2 is the latest version available; this version can change in later versions of Ranger.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984837345
##########
runtime/defaults/src/main/resources/application.properties:
##########
@@ -264,6 +264,51 @@ polaris.oidc.principal-roles-mapper.type=default
# polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-refresh=true
# polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-buffer=PT1M
+# Ranger authorizer
+# polaris.authorization.type=ranger
+# polaris.authorization.ranger.service-name=dev_polaris
+
+# polaris.authorization.ranger.authz.default.access.cluster.name=dev
+# polaris.authorization.ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.RangerAdminRESTClient
+# polaris.authorization.ranger.authz.default.policy.rest.url=http://ranger-admin:6080
+# polaris.authorization.ranger.authz.default.policy.rest.ssl.config.file=
+# polaris.authorization.ranger.authz.default.policy.rest.client.connection.timeoutMs=120000
+# polaris.authorization.ranger.authz.default.policy.rest.client.read.timeoutMs=30000
+# polaris.authorization.ranger.authz.default.policy.rest.client.max.retry.attempts=3
+# polaris.authorization.ranger.authz.default.policy.rest.client.retry.interval.ms=1000
+# polaris.authorization.ranger.authz.default.policy.rest.client.cookie.enabled=true
+# polaris.authorization.ranger.authz.default.policy.rest.client.session.cookie.name=RANGERADMINSESSIONID
+
+# Authenticate with Ranger using JWT
+# valid sources for JWT: env, file, cred
+# polaris.authorization.ranger.authz.default.policy.rest.jwt.source=
Review Comment:
Yes, that is correct.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983499164
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
Review Comment:
As far as I can tell, `RangerPolarisOperationSemantics` is not a factor in actual authZ decisions... What is the purpose of this class? π€
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983581432
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
Review Comment:
`PolarisAuthorizableOperation` is not longer hard-wired to `PolarisPrivilege` (per #4006). Could we re-implement this method simply in terms of `PolarisAuthorizableOperation`?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983548645
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
Review Comment:
This can leak information about the server configuration to malicious users. Is there a compelling reason to use a different message for unsupported operations?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2927506457
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
I'm fine to refactor as a followup. The logic duplication is introduced in this PR, it'd be nice to resolve it within the PR though.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2939184431
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
+ implementation(libs.commons.lang3)
+ implementation(libs.guava)
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+ compileOnly(project(":polaris-immutables"))
+
+ runtimeOnly(libs.graalvm.graal.sdk)
+ runtimeOnly(libs.graalvm.inspect.community)
+ runtimeOnly(libs.graalvm.js.community)
+ runtimeOnly(libs.graalvm.js.scriptengine)
+ runtimeOnly(libs.graalvm.nativeimage)
Review Comment:
Isn't 61 mb a bit concerning?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2897425790
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
+ private static final String RESOURCE_TYPE_NAME_SEP = ":";
+ private static final String RESOURCE_ELEMENTS_SEP = "/";
+
+ private final Gson gsonBuilder;
+ private final PolarisAuthorizer authorizer;
+
+ public TestRangerPolarisAuthorizer() throws Exception {
+ gsonBuilder =
+ new GsonBuilder()
+ .setDateFormat("yyyyMMdd-HH:mm:ss.SSSZ")
+ .setPrettyPrinting()
+ .registerTypeAdapter(PolarisPrincipal.class, new PolarisPrincipalDeserializer())
+ .registerTypeAdapter(
+ PolarisResolvedPathWrapper.class, new PolarisResolvedPathWrapperDeserializer())
+ .create();
+
+ RangerPolarisAuthorizerFactory factory =
+ new RangerPolarisAuthorizerFactory(createConfig("authz_tests/ranger-plugin.properties"));
+
+ authorizer = factory.create(createRealmConfig());
+
+ assertNotNull(authorizer);
+ }
+
+ @Test
+ public void testAuthzRoot() {
+ runTests(authorizer, "/authz_tests/tests_authz_root.json");
+ }
+
+ @Test
+ public void testAuthzCatalog() {
+ runTests(authorizer, "/authz_tests/tests_authz_catalog.json");
+ }
+
+ @Test
+ public void testAuthzPrincipal() {
+ runTests(authorizer, "/authz_tests/tests_authz_principal.json");
+ }
+
+ @Test
+ public void testAuthzNamespace() {
+ runTests(authorizer, "/authz_tests/tests_authz_namespace.json");
+ }
+
+ @Test
+ public void testAuthzTable() {
+ runTests(authorizer, "/authz_tests/tests_authz_table.json");
+ }
+
+ @Test
+ public void testAuthzPolicy() {
+ runTests(authorizer, "/authz_tests/tests_authz_policy.json");
+ }
+
+ @Test
+ public void testAuthzUnsupported() {
+ runTests(authorizer, "/authz_tests/tests_authz_unsupported.json");
+ }
+
+ private void runTests(PolarisAuthorizer authorizer, String testFilename) {
+ InputStream inStream = this.getClass().getResourceAsStream(testFilename);
+ InputStreamReader reader = new InputStreamReader(inStream, UTF_8);
+
+ TestSuite testSuite = gsonBuilder.fromJson(reader, TestSuite.class);
+
+ for (TestData test : testSuite.tests) {
+ try {
+ authorizer.authorizeOrThrow(
+ test.request.principal,
+ Collections.emptySet(),
+ test.request.authzOp,
+ test.request.target,
+ test.request.secondary);
+
+ assertEquals(
+ test.result.isAllowed,
+ Boolean.TRUE,
+ () ->
+ test.request.principal
+ + " performed "
+ + test.request.authzOp
+ + " on (target: "
+ + test.request.target
+ + ", secondary: "
+ + test.request.secondary
+ + ")");
+ } catch (Throwable t) {
Review Comment:
Updated tests to expect ForbiddenException when access should be denied.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2892645140
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(fileTree("override-libs") { include("*.jar") })
Review Comment:
Will remove this. This was used to use a custom version of a library in dev environment.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2900002596
##########
extensions/auth/ranger/README.txt:
##########
@@ -0,0 +1,42 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+Before Starting
+=================
+
+1. The Polaris Authorization is integated into Apache Ranger on 2.8.0 release and
Review Comment:
@kumaab - addressed this in commit 83a7a932102761ea89d006f8002ec745128cd78e. Please take another look.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2997891285
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
That code - yes. I'm not sure maybe there are other similar places... In general, I mean that the Ranger Authorizer should treat Polaris "root" as any other ordinary user.
Administrators can, of course, have special rules for it, but the code should not give it special treatment, IMHO.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2982980438
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
Review Comment:
When can this happen in practice?
##########
runtime/defaults/src/main/resources/application.properties:
##########
@@ -264,6 +264,51 @@ polaris.oidc.principal-roles-mapper.type=default
# polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-refresh=true
# polaris.authorization.opa.auth.bearer.file-based.jwt-expiration-buffer=PT1M
+# Ranger authorizer
+# polaris.authorization.type=ranger
+# polaris.authorization.ranger.service-name=dev_polaris
+
+# polaris.authorization.ranger.authz.default.access.cluster.name=dev
+# polaris.authorization.ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.RangerAdminRESTClient
+# polaris.authorization.ranger.authz.default.policy.rest.url=http://ranger-admin:6080
+# polaris.authorization.ranger.authz.default.policy.rest.ssl.config.file=
+# polaris.authorization.ranger.authz.default.policy.rest.client.connection.timeoutMs=120000
+# polaris.authorization.ranger.authz.default.policy.rest.client.read.timeoutMs=30000
+# polaris.authorization.ranger.authz.default.policy.rest.client.max.retry.attempts=3
+# polaris.authorization.ranger.authz.default.policy.rest.client.retry.interval.ms=1000
+# polaris.authorization.ranger.authz.default.policy.rest.client.cookie.enabled=true
+# polaris.authorization.ranger.authz.default.policy.rest.client.session.cookie.name=RANGERADMINSESSIONID
+
+# Authenticate with Ranger using JWT
+# valid sources for JWT: env, file, cred
+# polaris.authorization.ranger.authz.default.policy.rest.jwt.source=
Review Comment:
These properties all handled by the Ranger library, right? Polaris code just passes them through, I guess?
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java:
##########
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.polaris.core.config.PolarisConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.CatalogEntity;
+
+public class RangerTestUtils {
+ public static RangerPolarisAuthorizerConfig createConfig() {
Review Comment:
Having a `@QuarkusTest` is necessary to ensure all pieces work fine in runtime, IMHO.
We can keep current tests, of course, and just do a simple smoke test in a `@QuarkusTest`.
##########
extensions/auth/ranger/README.md:
##########
@@ -0,0 +1,41 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+# Prerequisites
+Ranger authorizer for Polaris requires Apache Ranger version 2.8.0 or later.
+
+# Setup instructions
+1. Enable Ranger authorizer by setting the following property in application.properties:
+```
+polaris.authorization.type=ranger
+```
+
+2. Configure Ranger authorizer by setting configurations having name that start with "polaris.authorization.ranger." in application.properties, for example:
+```
+polaris.authorization.ranger.service-name=dev_polaris
+polaris.authorization.ranger.authz.default.policy.source.impl=org.apache.ranger.admin.client.RangerAdminRESTClient
+polaris.authorization.ranger.authz.default.policy.rest.url=http://ranger-admin:6080
Review Comment:
nit: Add examples for authentication in REST API calls?
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
Does this version depend on the Ranger version in any way?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984882361
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
Review Comment:
Ranger authorizer supports sending audit logs to Solr; `solrj` is used for this.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984937667
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
Review Comment:
Ranger auditing is an integral part of authorization, and is one of the most important feature enterprise mandate. Unless there is a strong reason to disable auditing in Polaris, I wouldn't recommend separating audit.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3051585590
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
Review Comment:
```suggestion
License: CDDL 1.1 - https://javaee.github.io/jaxb-v2/LICENSE
```
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4224190263
@mneethiraj @sneethiraj I'm glad that we are converging towards an acceptable solution!
I took note that Jetty and Jersey 1.x cannot be excluded just yet. That's fine for now, given that Ranger 2.9.0 will improve the situation and given that RANGER-5371 and RANGER-5550 would bring a thin client.
I also appreciate the efforts that you've been putting on the Ranger side to improve the dependency situation.
A few comments:
* I noticed https://github.com/apache/ranger/pull/882: would it be possible to move away from jersey 1.x completely?
* You didn't mention how Jetty is going to be handled on the Ranger side going forward: is there a plan to upgrade to Solr 10 maybe? That would at least bring in a more recent Jetty version.
With that, I think we'll need to proceed with Jersey 1.x and Jetty 9.4.56 for a while. Given the commitment to make this situation as brief as possible, I'm fine with that.
I would still recommend releasing with beta / experimental label, and warn end users that security scans may flag some dependencies.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3046876086
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
Review Comment:
@snazy - how does use of Zookeeper client in Ranger authorizer impact Polaris? Zookeeper is used by Solr client library, when Ranger writes audit logs to SolrCloud.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2899997804
##########
gradle.properties:
##########
@@ -31,3 +31,4 @@ org.gradle.jvmargs=-Xms2g -Xmx4g -XX:MaxMetaspaceSize=768m
# This lets all properties files produced via `java.util.Properties.store()` not contain the generation timestamp.
systemProp.java.properties.date=File generated by Apache Polaris build.
+useApacheSnapshots=true
Review Comment:
addressed in commit 83a7a932102761ea89d006f8002ec745128cd78e. Please take another look.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4026906741
@dimas-b - [POLARIS-274] was just reference to the issue number in the apache polaris project (https://github.com/apache/polaris/issues/274).
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2998946822
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
Review Comment:
Yes, I will do a full review today.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "snazy (via GitHub)" <gi...@apache.org>.
snazy commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3027351108
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
+* Maven group:artifact IDs: org.graalvm.shadowed:xz
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-api
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-compiler
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-runtime
+
+Home page: https://github.com/oracle/graal/
+License: The GNU General Public License (GPL) - https://github.com/oracle/graal/blob/master/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles SLF4J Reload4j Provider library.
+
+* Maven group:artifact IDs: org.slf4j:slf4j-reload4j
Review Comment:
Another reload4j?
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
Review Comment:
Why do we need Jersey, another JAX-RS implementation?
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
+* Maven group:artifact IDs: org.graalvm.shadowed:xz
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-api
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-compiler
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-runtime
+
+Home page: https://github.com/oracle/graal/
+License: The GNU General Public License (GPL) - https://github.com/oracle/graal/blob/master/LICENSE
Review Comment:
GPL is Category X, a strict no-go in Apache projects.
I know, this has the Classpath-Exception, but GPL in general is concerning for many people.
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
I'd really prefer to _not_ have reload4j at all.
Yes, there is slf4j, but why should anything Ranger or Hadoop control (-> reload4j) any logging setting?
It's concerning that it would lead to ClassNotFoundException (or NoClassDefFoundError), because that means it tries to change logging configurations, which should not happen at all.
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
Review Comment:
Zookeeper is a tool for distributed coordination, requiring an odd number of nodes for quorum. This would have direct implications to how Polaris is run. Zookeeper also implements the leader/follower pattern, requiring each write to go through the leader, which has implications to horizontally scalability - contrary to Polaris' stateless approach. IIRC it also brings strong operational I/O requirements.
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
Review Comment:
I wonder why Ranger brings in _two different_ HTTP clients - Jetty and Apache.
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
Review Comment:
> Apache Yetus is a collection of libraries and tools that enable contribution and release processes for software projects.
Why do we need it?
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
Review Comment:
There's already a section for Jackson in this LICENSE file.
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
Review Comment:
This one is concerning, because it's unmaintained and uses JNA.
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
Review Comment:
There's already a section for httpcomponents in this file.
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
Review Comment:
Is this another JSON parser?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4173409526
Let's wait for @jbonofre 's assessment of LICENSE/NOTICE change before merging.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4217952282
+1 to @adutra 's proposal :+1:
Nice investigation!
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2893118953
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (authzOp == PolarisAuthorizableOperation.ROTATE_CREDENTIALS) {
+ boolean enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+
+ if (enforceCredentialRotationRequiredState
+ && !polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPLE_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: users={}, groups={}",
+ polarisPrincipal.getName(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
Review Comment:
PolarisAuthorizerImpl (the default authorizer) uses grants stored in `activatedEntities` to authorize the operation. Ranger authorizer does not use these grants; instead, it uses policies defined in Ranger to authorize the operation. Hence `activatedEntities` are unused here.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922493902
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
Review Comment:
Addressed in b684de1.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922492990
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
@flyrain - can this refactoring be taken up in a separate PR?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922627433
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizerConfig.PROP_POLARIS_SERVICE_NAME;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+
+ authorizer.init();
+
+ this.authorizer = authorizer;
+ this.serviceName = rangerProp.getProperty(PROP_POLARIS_SERVICE_NAME);
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
Review Comment:
Addressed in b684de1.
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizerConfig.PROP_POLARIS_SERVICE_NAME;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+
+ authorizer.init();
+
+ this.authorizer = authorizer;
+ this.serviceName = rangerProp.getProperty(PROP_POLARIS_SERVICE_NAME);
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerAuthorizer initialized successfully");
+ }
+
+ @PreDestroy
+ public void cleanup() {}
+
+ @Override
+ public RangerPolarisAuthorizer create(RealmConfig realmConfig) {
+ LOG.debug("Creating RangerPolarisAuthorizer");
+
+ if (authorizer == null || StringUtils.isBlank(serviceName)) {
+ throw new IllegalStateException(ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED);
+ }
+
+ try {
+ return new RangerPolarisAuthorizer(authorizer, serviceName, realmConfig);
+ } catch (Throwable t) {
+ LOG.error("Failed to create RangerPolarisAuthorizer", t);
+
+ throw t;
Review Comment:
Addressed in b684de1.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983492690
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
... at least initially.
This related to the "mixed mode" authN/Z, so we may need to revisit it later, but for a start, I believe it is much more manageable to deny all operations on internal principals and roles.
OPA does that IIRC. @sungwy : WDYT?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4285313871
@dimas-b β Gentle ping on this PR.
The remaining GraalVM concern was addressed as discussed, and all comments appear to be resolved. Could you please take a final look and approve if everything looks good, so we can proceed with merging into apache/main?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3124867326
##########
gradle/libs.versions.toml:
##########
@@ -25,6 +25,8 @@ immutables = "2.12.1"
jmh = "1.37"
picocli = "4.7.7"
quarkus = "3.32.4"
+ranger = "2.8.0"
+ranger-graalvm = "25.0.2"
Review Comment:
@sneethiraj : FYI: #4272
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2932550162
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
+ case SERVICE_MANAGE_ACCESS -> "service-access-manage";
+
+ case PRINCIPAL_CREATE -> "principal-create";
+ case PRINCIPAL_DROP -> "principal-drop";
+ case PRINCIPAL_LIST -> "principal-list";
+ case PRINCIPAL_READ_PROPERTIES -> "principal-properties-read";
+ case PRINCIPAL_WRITE_PROPERTIES -> "principal-properties-write";
+ case PRINCIPAL_FULL_METADATA -> "principal-metadata-full";
+ case PRINCIPAL_ROTATE_CREDENTIALS -> "principal-credentials-rotate";
+ case PRINCIPAL_RESET_CREDENTIALS -> "principal-credentials-reset";
+
+ case CATALOG_CREATE -> "catalog-create";
+ case CATALOG_DROP -> "catalog-drop";
+ case CATALOG_LIST -> "catalog-list";
+ case CATALOG_READ_PROPERTIES -> "catalog-properties-read";
+ case CATALOG_WRITE_PROPERTIES -> "catalog-properties-write";
+ case CATALOG_FULL_METADATA -> "catalog-metadata-full";
+ case CATALOG_MANAGE_METADATA -> "catalog-metadata-manage";
+ case CATALOG_MANAGE_CONTENT -> "catalog-content-manage";
+ case CATALOG_ATTACH_POLICY -> "catalog-policy-attach";
+ case CATALOG_DETACH_POLICY -> "catalog-policy-detach";
+
+ case NAMESPACE_CREATE -> "namespace-create";
+ case NAMESPACE_DROP -> "namespace-drop";
+ case NAMESPACE_LIST -> "namespace-list";
+ case NAMESPACE_READ_PROPERTIES -> "namespace-properties-read";
+ case NAMESPACE_WRITE_PROPERTIES -> "namespace-properties-write";
+ case NAMESPACE_FULL_METADATA -> "namespace-metadata-full";
+ case NAMESPACE_ATTACH_POLICY -> "namespace-policy-attach";
+ case NAMESPACE_DETACH_POLICY -> "namespace-policy-detach";
+
+ case TABLE_CREATE -> "table-create";
+ case TABLE_DROP -> "table-drop";
+ case TABLE_LIST -> "table-list";
+ case TABLE_READ_PROPERTIES -> "table-properties-read";
+ case TABLE_WRITE_PROPERTIES -> "table-properties-write";
+ case TABLE_READ_DATA -> "table-data-read";
+ case TABLE_WRITE_DATA -> "table-data-write";
+ case TABLE_FULL_METADATA -> "table-metadata-full";
+ case TABLE_ATTACH_POLICY -> "table-policy-attach";
+ case TABLE_DETACH_POLICY -> "table-policy-detach";
+ case TABLE_ASSIGN_UUID -> "table-uuid-assign";
+ case TABLE_UPGRADE_FORMAT_VERSION -> "table-format-version-upgrade";
+ case TABLE_ADD_SCHEMA -> "table-schema-add";
+ case TABLE_SET_CURRENT_SCHEMA -> "table-schema-set-current";
+ case TABLE_ADD_PARTITION_SPEC -> "table-partition-spec-add";
+ case TABLE_ADD_SORT_ORDER -> "table-sort-order-add";
+ case TABLE_SET_DEFAULT_SORT_ORDER -> "table-sort-order-set-default";
+ case TABLE_ADD_SNAPSHOT -> "table-snapshot-add";
+ case TABLE_SET_SNAPSHOT_REF -> "table-snapshot-ref-set";
+ case TABLE_REMOVE_SNAPSHOTS -> "table-snapshots-remove";
+ case TABLE_REMOVE_SNAPSHOT_REF -> "table-snapshot-ref-remove";
+ case TABLE_SET_LOCATION -> "table-location-set";
+ case TABLE_SET_PROPERTIES -> "table-properties-set";
+ case TABLE_REMOVE_PROPERTIES -> "table-properties-remove";
+ case TABLE_SET_STATISTICS -> "table-statistics-set";
+ case TABLE_REMOVE_STATISTICS -> "table-statistics-remove";
+ case TABLE_REMOVE_PARTITION_SPECS -> "table-partition-specs-remove";
+ case TABLE_MANAGE_STRUCTURE -> "table-structure-manage";
+
+ case VIEW_CREATE -> "view-create";
+ case VIEW_DROP -> "view-drop";
+ case VIEW_LIST -> "view-list";
+ case VIEW_READ_PROPERTIES -> "view-properties-read";
+ case VIEW_WRITE_PROPERTIES -> "view-properties-write";
+ case VIEW_FULL_METADATA -> "view-metadata-full";
+
+ case POLICY_CREATE -> "policy-create";
+ case POLICY_READ -> "policy-read";
+ case POLICY_DROP -> "policy-drop";
+ case POLICY_WRITE -> "policy-write";
+ case POLICY_LIST -> "policy-list";
+ case POLICY_FULL_METADATA -> "policy-metadata-full";
+ case POLICY_ATTACH -> "policy-attach";
+ case POLICY_DETACH -> "policy-detach";
+
+ default -> privilege.name();
Review Comment:
> Permission names are typically lower-case in Ranger policies.
And so why not use `privilege.name().toLowerCase()` consistently?
> Is there a reason to require Ranger permission to use PolarisPrivilege enum name as-is?
Remove almost 100 lines of boilerplate code, which requires updates whenever a new privilege is added, sounds like a good enough reason to me π
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2932527727
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
Review Comment:
But that doesn't answer my question π
. If certain entities shouldn't be there, then filter them out. As it stands, the code is a bit strange since the method seems to arbitrarily lower-case certain item names, but not all of them.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4091445625
Unicode license is OK to include, https://www.apache.org/legal/resolved.html#category-a.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2942183778
##########
runtime/defaults/src/main/resources/application.properties:
##########
@@ -306,4 +351,3 @@ quarkus.index-dependency.guava.artifact-id=guava
# force the locale, just in case the system's using another default locale
quarkus.default-locale=en_US
-
Review Comment:
Addressed in e6482c0.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4227433346
Also, this feature probably deserves to be mentioned in `CHANGELOG.md`. That's where we can also put the beta / experimental notice for users.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3067438489
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
@adutra, @dimas-b - `graalvm` is needed only for JDK15+ environments. Ranger libraries are built for JDK8, as many services using Ranger authorizer still require JDK8 support. Hence Ranger poms don't declare `graalvm` dependency; this needs to be explicitly added in services (like Trino, Polaris) that use JDK15+. When Ranger version in updated in these services, `graalvm` version should reviewed and updated if necessary.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3090650527
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(RangerTestProfiles.EmbeddedPolicy.class)
+public class RangerAdminServiceIT extends RangerIntegrationTestBase {
+
+ private String baseCatalogName;
+ private String baseCatalogLocation;
+ private String baseRootToken;
+
+ @BeforeEach
+ void setupBaseCatalog() throws Exception {
+ baseRootToken = getRootToken();
+ baseCatalogName = "ranger-base-cat-" + UUID.randomUUID().toString().replace("-", "");
+ baseCatalogLocation = Files.createTempDirectory("ranger-base-cat").toUri().toString();
+ createFileCatalog(
+ baseRootToken, baseCatalogName, baseCatalogLocation, List.of(baseCatalogLocation));
+ }
+
+ @Test
+ void assignCatalogRoleToPrincipalRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ // create catalog role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ // create principal role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ // stranger cannot bind
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
+ principalRole,
+ baseCatalogName)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ void listCatalogsAuthorization() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ // stranger cannot list catalogs
+ given()
+ .header("Authorization", "Bearer " + strangerToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // root lists catalogs successfully
+ given()
+ .header("Authorization", "Bearer " + rootToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(200);
+ }
+
+ @Test
+ void createCatalogAuthorization() throws Exception {
+ String rootToken = getRootToken();
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogName = "ranger-cat-create-" + UUID.randomUUID().toString().replace("-", "");
+ String baseLocation = Files.createTempDirectory("ranger-cat-create").toUri().toString();
+ Map<String, Object> createCatalogRequest =
+ Map.of(
+ "type",
+ "INTERNAL",
+ "name",
+ catalogName,
+ "properties",
+ Map.of("default-base-location", baseLocation),
+ "storageConfigInfo",
+ Map.of("storageType", "FILE", "allowedLocations", List.of(baseLocation)));
+
+ // Stranger cannot create catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // Root creates catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
+ .then()
+ .statusCode(201);
+
+ given()
+ .header("Authorization", "Bearer " + rootToken)
+ .delete("/api/management/v1/catalogs/{cat}", catalogName)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ void grantTablePrivilegesAuthorization() throws Exception {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+ String catalogName = "ranger-grant-cat-" + UUID.randomUUID().toString().replace("-", "");
+ String namespace = "ns_" + UUID.randomUUID().toString().replace("-", "");
+ String tableName = "tbl_" + UUID.randomUUID().toString().replace("-", "");
+ String catalogRole = "role_" + UUID.randomUUID().toString().replace("-", "");
+
+ Path tempDir = Files.createTempDirectory("ranger-grant");
+ String baseLocation = tempDir.toUri().toString();
+ String allowedPrefix = baseLocation + (baseLocation.endsWith("/") ? "" : "/") + namespace;
+ createFileCatalog(
+ rootToken, catalogName, baseLocation, List.of(allowedPrefix, allowedPrefix + "/"));
+
+ createNamespace(rootToken, catalogName, namespace);
+
+ Map<String, Object> registerPayload =
+ buildRegisterTableRequest(tableName, baseLocation, namespace);
+ Map<String, Object> grantRequest =
+ Map.of(
+ "grant",
+ Map.of(
+ "type",
+ "table",
+ "namespace",
+ List.of(namespace),
+ "tableName",
+ tableName,
+ "privilege",
+ "TABLE_READ_DATA"));
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(registerPayload))
+ .post("/api/catalog/v1/{cat}/namespaces/{ns}/register", catalogName, namespace)
+ .then()
+ .statusCode(200);
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", catalogName)
+ .then()
+ .statusCode(403); // TODO: check if this policy could be defined ?
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/catalogs/{cat}/catalog-roles/{role}/grants",
+ catalogName,
+ catalogRole)
+ .then()
+ .statusCode(404);
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/catalogs/{cat}/catalog-roles/{role}/grants",
+ catalogName,
+ catalogRole)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ void listAssigneePrincipalRolesForCatalogRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
+ principalRole,
+ baseCatalogName)
+ .then()
+ .statusCode(404);
Review Comment:
@dimas-b - You are right that this assertion does not prove much beyond the 403 response already verified on line 255.
It was added mainly to keep the Ranger tests aligned with the existing OPA authorizer test structure, since we had discussed moving toward a shared authorizer test suite. In that sense, it was intended more for structural parity than for validating distinct behavior in this specific case.
Given that, I am fine removing this assertion if you think it makes the test clearer and more focused.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3104331898
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(key, properties().get(key));
+ } else {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
+ checkState(serviceName().isPresent(), "serviceName is not defined for ranger authorizer");
Review Comment:
thx - I missed that `validate()` is called manually. I assumed it was called on config object creation :sweat_smile:
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3104332222
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(key, properties().get(key));
+ } else {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
Review Comment:
thanks for the heads up (TIL)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933812759
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
Review Comment:
From my POV `jersey-bundle` and `servlet-api` are hardly required on the "client side". I assume the new Authorizer impl. acts as a client in this context.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3080865731
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
Review Comment:
That is fair, but there should not be any doubt about whether the extra `ranger` part is present, I guess π€ Why do we need to support both cases (with and without the extra `ranger` prefix)?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3082837221
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
Review Comment:
This logic was added to handle some of the test cases that supplies configuration with ranger prefix. I have removed the ranger prefix from the test code to work correctly. The fix is in commit - [09282a23d](https://github.com/sneethiraj/polaris/commit/09282a23d8a35e3e66e7540f5825c21fa12733fa)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2909476486
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
Review Comment:
@flyingImer - updated configuration validation to fail authroizer factory initialzation when manadatory configuration is not found. If you are looking for a difference approach, can you please provide more guidance?
Currently, empty `accessInfos` will result in the access to be denied (by Ranger policy engine). Are you suggesting to move this denial to RangerPolarisAuthorizer? Or should the authorizer allow the access, given no resource (target or secondary) has been given?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2915462722
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
Review Comment:
There is no I/O during authorization. During initialization, Ranger authorizer retrieves policies from Ranger admin server using REST APIs and builds a policy engine in-memory. This policy engine is used to authorize requests by evaluating policies locally, in Polaris process space. Ranger authorizer uses a background thread to periodically check for changes to policies and keeps the policy engine updated of changes.
Ranger policy engine generates audit logs to record details of the access (user, resource, action, IP-address, time, result, ..) and the policy that allowed or denied the access. These audit logs are sent asynchronously to configured destinations - Solr/Elasticsearch/S3/ABFS-Gen2/HDFS/Ozone/local file. Again, there is no I/O in the authorization path.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2919942780
##########
build.gradle.kts:
##########
@@ -106,6 +106,9 @@ tasks.named<RatTask>("rat").configure {
// Polaris service startup banner
excludes.add("runtime/service/src/**/banner.txt")
+ // Polaris service log files - generated by polaris-server
+ excludes.add("runtime/server/logs/**")
Review Comment:
Thx - please feel free to open a separate PR with this specific change if you find it relevat :slightly_smiling_face:
##########
build.gradle.kts:
##########
@@ -106,6 +106,9 @@ tasks.named<RatTask>("rat").configure {
// Polaris service startup banner
excludes.add("runtime/service/src/**/banner.txt")
+ // Polaris service log files - generated by polaris-server
+ excludes.add("runtime/server/logs/**")
Review Comment:
Thx - please feel free to open a separate PR with this specific change if you find it relevant :slightly_smiling_face:
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933984710
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+ Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerConfig.class);
+
+ String PROP_RANGER_CONFIG_FILE_NAME = "polaris.authorization.ranger.config-file-name";
+ String PROP_POLARIS_SERVICE_NAME = "ranger.plugin.polaris.service.name";
+
+ String ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME =
+ "Invalid Ranger authorizer configuration: missing configuration "
+ + PROP_RANGER_CONFIG_FILE_NAME;
+ String ERR_INVALID_CONFIG_FILE_MISSING_CONFIGURATION =
+ "Invalid Ranger authorizer configuration file %s: missing mandatory configuration %s";
+
+ Optional<String> configFileName();
+
+ default void validate() {
+ boolean isConfigFileNamePresent = configFileName().isPresent();
+
+ if (!isConfigFileNamePresent) {
+ LOG.error(ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME);
+
+ throw new IllegalStateException(ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME);
+ }
+
+ String fileName = configFileName().get();
+
+ Properties prop = RangerUtils.loadProperties(fileName);
Review Comment:
Updated to read Ranger authorizer configurations from application.properties file. Commit: 68870f0
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2934361576
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
+ implementation(libs.commons.lang3)
+ implementation(libs.guava)
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+ compileOnly(project(":polaris-immutables"))
+
+ runtimeOnly(libs.graalvm.graal.sdk)
+ runtimeOnly(libs.graalvm.inspect.community)
+ runtimeOnly(libs.graalvm.js.community)
+ runtimeOnly(libs.graalvm.js.scriptengine)
+ runtimeOnly(libs.graalvm.nativeimage)
Review Comment:
@adutra - here are all `graalvm` libraries found in a Polaris build, total 61.86mb.
```
$ find ./runtime/server/build/quarkus-app/lib -name "*graal*" | xargs du -sk | sort -n
24 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.sdk.word-23.1.2.jar
64 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.truffle.truffle-compiler-25.0.2.jar
128 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.js.js-scriptengine-25.0.2.jar
128 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.sdk.collections-25.0.2.jar
256 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.sdk.nativeimage-23.1.2.jar
320 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.sdk.jniutils-25.0.2.jar
384 ./runtime/server/build/quarkus-app/lib/main/org.graalvm.shadowed.xz-25.0.2.jar
512 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.polyglot.polyglot-25.0.2.jar
896 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.truffle.truffle-runtime-25.0.2.jar
4160 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.regex.regex-25.0.2.jar
14400 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.truffle.truffle-api-25.0.2.jar
18496 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.shadowed.icu4j-25.0.2.jar
26688 ./runtime/server/build/quarkus-app/lib/boot/org.graalvm.js.js-language-25.0.2.jar
```
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4088638066
> Thanks @mneethiraj for working on it. LGTM overall. I'd suggest to file issues for followups and fix the CI failures.
Thanks @flyrain. I updated the LICENSE file to address failures in `polaris-server:generateLicenseReport`. Now, CI fails with the following.
```
{
"dependenciesWithoutAllowedLicenses": [
{
"moduleName": "org.graalvm.shadowed:icu4j",
"moduleLicense": "Unicode/ICU License",
"moduleVersion": "25.0.2"
}
]
}
```
@flyrain, @adutra, @dimas-b - can you please review and confirm that this license is indeed not allowed? If its not allowed, the only option seems to exclude this library. It seems excluding this library can result in failures in [locale-specific handling](https://github.com/oracle/graaljs/issues/864) of custom expressions in Ranger policies. Though this issue may not impact most use cases of Ranger policies, needs to be investigated further and documented.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984945451
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
> I'm not 100% sure, but assuming this library does not affect runtime, it should not be bundled, right?
Not true. Not bundling can result in `ClassNotFoundException` (or `NoClassDefFoundError`) exception. It is not safe to remove transitive dependencies.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2997768673
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
Review Comment:
@dimas-b - it is not clear what an ordinary authZ failure message would look like. I looked at othe 2 authorizer implementations for reference - none of them are usable in another authorizer implementation:
1. PolarisAuthorizerImpl uses message containing authorizer specific terms like PrincipalRoles - `Principal '%s' with activated PrincipalRoles '%s' and activated grants via '%s' is not authorized for op %s"`. This message is not suitable here.
2. Opa authorizer uses similar messages: `OPA denied authorization`, `resolveAuthorizationInputs is not implemented yet for OpaPolarisAuthorizer`, `authorize is not implemented yet for OpaPolarisAuthorizer`
Perhaps you are simply suggesting to remvoe "Ranger" from line 67? It will be huge help if you can specify the error messages to use.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2885365168
##########
gradle.properties:
##########
@@ -31,3 +31,4 @@ org.gradle.jvmargs=-Xms2g -Xmx4g -XX:MaxMetaspaceSize=768m
# This lets all properties files produced via `java.util.Properties.store()` not contain the generation timestamp.
systemProp.java.properties.date=File generated by Apache Polaris build.
+useApacheSnapshots=true
Review Comment:
@sneethiraj - since this PR doesn't introduce use of any SNAPSHOT library, I suggest removing this line.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "snazy (via GitHub)" <gi...@apache.org>.
snazy commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4214977268
Wow, thanks a lot @adutra for the dependency investigation work!
It seems that it's possible to remove the dependencies that have known CVEs, and would be flagged by security scanners. Would that work for you @sneethiraj @mneethiraj ?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3090640326
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(RangerTestProfiles.EmbeddedPolicy.class)
+public class RangerAdminServiceIT extends RangerIntegrationTestBase {
+
+ private String baseCatalogName;
+ private String baseCatalogLocation;
+ private String baseRootToken;
+
+ @BeforeEach
+ void setupBaseCatalog() throws Exception {
+ baseRootToken = getRootToken();
+ baseCatalogName = "ranger-base-cat-" + UUID.randomUUID().toString().replace("-", "");
+ baseCatalogLocation = Files.createTempDirectory("ranger-base-cat").toUri().toString();
+ createFileCatalog(
+ baseRootToken, baseCatalogName, baseCatalogLocation, List.of(baseCatalogLocation));
+ }
+
+ @Test
+ void assignCatalogRoleToPrincipalRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ // create catalog role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ // create principal role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ // stranger cannot bind
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
Review Comment:
@dimas-b - The intent of this test is to keep the Ranger authorizer tests aligned with the existing OPA authorizer test structure.
We had discussed moving toward a shared test suite that can run across multiple authorizer implementations, and these tests were added with that future consolidation in mind. So while this specific assertion may be redundant in the current Ranger flow, it helps maintain parity with the existing authorizer-side test layout.
That said, I agree the test does not provide much standalone value if principalRole is already known not to exist at that point. I am fine removing it if you think that is the better cleanup for this PR.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4272472771
@sneethiraj : the comment thread about `graalvm = "25.0.2"` in the TOML file is my only remaining concern.... otherwise the PR LGTM :+1:
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4272842578
@dimas-b β Regarding the remaining concern about graalvm = "25.0.2" in the TOML file, this has already been updated per the earlier discussion by @mneethiraj.
All GraalVM-related dependencies are now versioned using the ranger-prefixed entry:
```
$ grep graalvm gradle/libs.versions.toml
ranger-graalvm = "25.0.2"
graalvm-js-js-scriptengine = { module = "org.graalvm.js:js-scriptengine", version.ref = "ranger-graalvm" }
graalvm-polyglot-js = { module = "org.graalvm.polyglot:js", version.ref = "ranger-graalvm" }
graalvm-polyglot-polyglot = { module = "org.graalvm.polyglot:polyglot", version.ref = "ranger-graalvm" }
```
Please take a final look at this change and approve if everything looks good.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4297381543
Just a note: GPL 2.0 AND Classpath-Exception is Category B (not X). Usually GPL 2.0 with Classpath-Exception dependencies are also available in EPL and CDDL, in that case we should prefer EPL or CDDL instead of GPL.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4294114707
This PR should not have been merged without clean LICENSE/NOTICE update.
I'm doing a follow up on this one because today LICENSE/NOTICE are wrong (BSD/MIT not inline, dual license, etc).
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4300170821
A followup PR(https://github.com/apache/polaris/pull/3928#discussion_r3124810161) to fix the license SGTM. Sorry I miss that comments.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4295524654
> Some of the legal issues have been [mentioned here](https://github.com/apache/polaris/pull/3928#discussion_r3027346986).
> ... now says that Polaris bundles a Category-X dependency (GPL-only)
Regarding the GPL license being reported for GraalVM deps, as I mentioned [here](https://github.com/apache/polaris/pull/3928#discussion_r3051398586) I think this is not correct. They seem to be almost all licensed with UPL 1.0.
For example, the [POM](https://central.sonatype.com/artifact/org.graalvm.js/js-scriptengine/25.0.2) for `org.graalvm.js/js-scriptengine/25.0.2` contains:
```xml
<licenses>
<license>
<name>Universal Permissive License, Version 1.0</name>
<url>http://opensource.org/licenses/UPL</url>
</license>
</licenses>
```
Our license tool is also reporting UPL 1.0.
I thought that this particular misattribution had been fixed when I approved. My apologies for that.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyrain (via GitHub)" <gi...@apache.org>.
flyrain commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4292961224
I will merge it by EOD if there is no more feedback.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3067211279
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties properties = config.toRangerProperties();
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(properties);
+
+ authorizer.init();
+
+ this.authorizer = authorizer;
+ this.serviceName = config.serviceName().orElseThrow();
Review Comment:
ping
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3067211726
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties properties = config.toRangerProperties();
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(properties);
Review Comment:
ping
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4227409838
+1 to beta / experimental label.
I'd also note that downstream projects have the freedom to exclude the Ranger Authorizer at build time if there are strong concerns with dependencies - thanks for making the impl. modular!
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3077288310
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties properties = config.toRangerProperties();
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(properties);
Review Comment:
+1. Removed the initialize method and moved the code back into the constructor. (see - [commit](https://github.com/sneethiraj/polaris/commit/085bce05113f5b50e198744552c8e3d2a35f7f77) )
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2940978872
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded) {
+ exclude("org.apache.hadoop", "hadoop-client-api")
+ exclude("org.apache.hadoop", "hadoop-client-runtime")
+ }
+ implementation(libs.commons.lang3)
Review Comment:
`commons.lang3` is used in `RangerPolarisAuthorizerFactory` and `RangerUtils`.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2939348461
##########
runtime/defaults/src/main/resources/application.properties:
##########
@@ -306,4 +351,3 @@ quarkus.index-dependency.guava.artifact-id=guava
# force the locale, just in case the system's using another default locale
quarkus.default-locale=en_US
-
Review Comment:
ni: spurious change.
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded) {
+ exclude("org.apache.hadoop", "hadoop-client-api")
+ exclude("org.apache.hadoop", "hadoop-client-runtime")
+ }
+ implementation(libs.commons.lang3)
+ implementation(libs.graalvm.js.js.scriptengine)
+ implementation(libs.graalvm.polyglot.js)
+ implementation(libs.graalvm.polyglot.polyglot)
Review Comment:
All GraalVM dependencies seem unused, did you mean to use `runtimeOnly` instead?
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded) {
+ exclude("org.apache.hadoop", "hadoop-client-api")
+ exclude("org.apache.hadoop", "hadoop-client-runtime")
+ }
+ implementation(libs.commons.lang3)
Review Comment:
commons-lang seems unused.
##########
extensions/auth/ranger/src/test/resources/authz_tests/ranger-plugin.properties:
##########
@@ -0,0 +1,25 @@
+#
Review Comment:
This file seems unused.
##########
extensions/auth/ranger/src/test/resources/authz_tests/ranger-plugin-invalid.properties:
##########
@@ -0,0 +1,26 @@
+#
Review Comment:
This file seems unused.
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
Review Comment:
Nit: the naming convention in Polaris is: `RangerPolarisAuthorizerTest`. Same for `RangerPolarisAuthorizerFactoryTest`.
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
+ private static final String RESOURCE_TYPE_NAME_SEP = ":";
+ private static final String RESOURCE_ELEMENTS_SEP = "/";
+
+ private final PolarisAuthorizer authorizer;
+
+ public TestRangerPolarisAuthorizer() {
+ RangerPolarisAuthorizerFactory factory = new RangerPolarisAuthorizerFactory(createConfig());
+
+ factory.initialize();
+
+ authorizer = factory.create(createRealmConfig());
+
+ assertNotNull(authorizer);
+ }
+
+ @Test
+ public void testAuthzRoot() throws Exception {
+ runTests(authorizer, "/authz_tests/tests_authz_root.json");
Review Comment:
nit: what is the advantage of writing your test cases as JSON, just to have them mapped to Java beans with Jackson? Isn't it simpler to just write your test cases in Java, maybe with parameterized tests? Especially given the significant amount of boilerplate code related to Jackson deserialization that needs to be introduced.
##########
gradle/libs.versions.toml:
##########
@@ -47,11 +49,16 @@ azuresdk-bom = { module = "com.azure:azure-sdk-bom", version = "1.3.5" }
caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version = "3.2.3" }
cel-bom = { module = "org.projectnessie.cel:cel-bom", version = "0.6.0" }
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } # required by the polaris-java plugin
+commons-collections = { module = "commons-collections:commons-collections", version = "3.2.2" }
Review Comment:
These two new dependencies seem unused.
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java:
##########
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.polaris.core.config.PolarisConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.CatalogEntity;
+
+public class RangerTestUtils {
+ public static RangerPolarisAuthorizerConfig createConfig() {
Review Comment:
Have you considered writing `@QuarkusTest`s rather than pure unit tests instead? The advantage is that you don't need to create all the fixtures, and you would be testing the "real thing".
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "kumaab (via GitHub)" <gi...@apache.org>.
kumaab commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2886250843
##########
extensions/auth/ranger/README.txt:
##########
@@ -0,0 +1,42 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+Before Starting
+=================
+
+1. The Polaris Authorization is integated into Apache Ranger on 2.8.0 release and
Review Comment:
minor typo: `integated` ==> `integrated`
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "flyingImer (via GitHub)" <gi...@apache.org>.
flyingImer commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2891599429
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private final RangerPolarisAuthorizerConfig config;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ config.validate();
+ }
+
+ @PreDestroy
+ public void cleanup() {}
+
+ @Override
+ public RangerPolarisAuthorizer create(RealmConfig realmConfig) {
+ LOG.debug("Creating RangerPolarisAuthorizer");
+
+ try {
+ return new RangerPolarisAuthorizer(config, realmConfig);
+ } catch (Throwable t) {
+ LOG.error("Failed to create RangerPolarisAuthorizer", t);
+ }
+
+ return null;
Review Comment:
IMO should throw some SPI exception rather than bubbling up null causing NPE later
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
Review Comment:
are these ready for a review?
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
Review Comment:
are they review ready?
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (authzOp == PolarisAuthorizableOperation.ROTATE_CREDENTIALS) {
+ boolean enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+
+ if (enforceCredentialRotationRequiredState
+ && !polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
This logic seems to be inverted from https://github.com/apache/polaris/blob/main/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizerImpl.java#L802-L813, is this right?
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ Properties prop = new Properties();
+
+ if (resourcePath != null) {
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Adding / to the configFileName [{}]", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
Review Comment:
do you intend to load by classpath or filesystem? they might be different. Your README implies filesystem access.
we should do better in README expectation as well as aligning with the implementation
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (authzOp == PolarisAuthorizableOperation.ROTATE_CREDENTIALS) {
+ boolean enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+
+ if (enforceCredentialRotationRequiredState
+ && !polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPLE_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: users={}, groups={}",
+ polarisPrincipal.getName(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
Review Comment:
info: I may miss some context here: why Ranger AuthZ doesn't need `activatedEntities`? and how is it different from `PolarisPrincipal`? current SPI does not have too much doc around it
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
Review Comment:
typo: `PRINCIPAL`
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(fileTree("override-libs") { include("*.jar") })
Review Comment:
what is this?
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (authzOp == PolarisAuthorizableOperation.ROTATE_CREDENTIALS) {
Review Comment:
should this branch explicitly calls isAccessAuthorized? otherwise `ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING` is false, which is the default, any principal can rotate credentials regardless of Ranger policy
I assume this is not a desired behavior - allowing credentials rotation w/o any Ranger policy check
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
+ private static final String RESOURCE_TYPE_NAME_SEP = ":";
+ private static final String RESOURCE_ELEMENTS_SEP = "/";
+
+ private final Gson gsonBuilder;
Review Comment:
2 cents: using conventional Jackson would be helpful to minimize dep footprint
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
Review Comment:
do we need both `import jakarta.annotation.Nonnull;` and `import org.jspecify.annotations.NonNull;`?
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
+ private static final String RESOURCE_TYPE_NAME_SEP = ":";
+ private static final String RESOURCE_ELEMENTS_SEP = "/";
+
+ private final Gson gsonBuilder;
+ private final PolarisAuthorizer authorizer;
+
+ public TestRangerPolarisAuthorizer() throws Exception {
+ gsonBuilder =
+ new GsonBuilder()
+ .setDateFormat("yyyyMMdd-HH:mm:ss.SSSZ")
+ .setPrettyPrinting()
+ .registerTypeAdapter(PolarisPrincipal.class, new PolarisPrincipalDeserializer())
+ .registerTypeAdapter(
+ PolarisResolvedPathWrapper.class, new PolarisResolvedPathWrapperDeserializer())
+ .create();
+
+ RangerPolarisAuthorizerFactory factory =
+ new RangerPolarisAuthorizerFactory(createConfig("authz_tests/ranger-plugin.properties"));
+
+ authorizer = factory.create(createRealmConfig());
+
+ assertNotNull(authorizer);
+ }
+
+ @Test
+ public void testAuthzRoot() {
+ runTests(authorizer, "/authz_tests/tests_authz_root.json");
+ }
+
+ @Test
+ public void testAuthzCatalog() {
+ runTests(authorizer, "/authz_tests/tests_authz_catalog.json");
+ }
+
+ @Test
+ public void testAuthzPrincipal() {
+ runTests(authorizer, "/authz_tests/tests_authz_principal.json");
+ }
+
+ @Test
+ public void testAuthzNamespace() {
+ runTests(authorizer, "/authz_tests/tests_authz_namespace.json");
+ }
+
+ @Test
+ public void testAuthzTable() {
+ runTests(authorizer, "/authz_tests/tests_authz_table.json");
+ }
+
+ @Test
+ public void testAuthzPolicy() {
+ runTests(authorizer, "/authz_tests/tests_authz_policy.json");
+ }
+
+ @Test
+ public void testAuthzUnsupported() {
+ runTests(authorizer, "/authz_tests/tests_authz_unsupported.json");
+ }
+
+ private void runTests(PolarisAuthorizer authorizer, String testFilename) {
+ InputStream inStream = this.getClass().getResourceAsStream(testFilename);
+ InputStreamReader reader = new InputStreamReader(inStream, UTF_8);
+
+ TestSuite testSuite = gsonBuilder.fromJson(reader, TestSuite.class);
+
+ for (TestData test : testSuite.tests) {
+ try {
+ authorizer.authorizeOrThrow(
+ test.request.principal,
+ Collections.emptySet(),
+ test.request.authzOp,
+ test.request.target,
+ test.request.secondary);
+
+ assertEquals(
+ test.result.isAllowed,
+ Boolean.TRUE,
+ () ->
+ test.request.principal
+ + " performed "
+ + test.request.authzOp
+ + " on (target: "
+ + test.request.target
+ + ", secondary: "
+ + test.request.secondary
+ + ")");
+ } catch (Throwable t) {
Review Comment:
can we narrow it to something like `ForbiddenException` or `AssertionError` specifically?
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizerFactory {
Review Comment:
we should exercise @PostConstruct in TestRangerPolarisAuthorizerFactory by calling `initialize()`
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ Properties prop = new Properties();
+
+ if (resourcePath != null) {
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Adding / to the configFileName [{}]", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ prop.load(in);
+ } else {
+ LOG.error("Unable to find ranger config file in the classpath : [{}]", resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load config file: [{}]", resourcePath, e);
+ }
+ }
+
+ return prop;
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
+ case SERVICE_MANAGE_ACCESS -> "service-access-manage";
+
+ case PRINCIPAL_CREATE -> "principal-create";
+ case PRINCIPAL_DROP -> "principal-drop";
+ case PRINCIPAL_LIST -> "principal-list";
+ case PRINCIPAL_READ_PROPERTIES -> "principal-properties-read";
+ case PRINCIPAL_WRITE_PROPERTIES -> "principal-properties-write";
+ case PRINCIPAL_FULL_METADATA -> "principal-metadata-full";
+ case PRINCIPAL_ROTATE_CREDENTIALS -> "principal-credentials-rotate";
+ case PRINCIPAL_RESET_CREDENTIALS -> "principal-credentials-reset";
+
+ case CATALOG_CREATE -> "catalog-create";
+ case CATALOG_DROP -> "catalog-drop";
+ case CATALOG_LIST -> "catalog-list";
+ case CATALOG_READ_PROPERTIES -> "catalog-properties-read";
+ case CATALOG_WRITE_PROPERTIES -> "catalog-properties-write";
+ case CATALOG_FULL_METADATA -> "catalog-metadata-full";
+ case CATALOG_MANAGE_METADATA -> "catalog-metadata-manage";
+ case CATALOG_MANAGE_CONTENT -> "catalog-content-manage";
+ case CATALOG_ATTACH_POLICY -> "catalog-policy-attach";
+ case CATALOG_DETACH_POLICY -> "catalog-policy-detach";
+
+ case NAMESPACE_CREATE -> "namespace-create";
+ case NAMESPACE_DROP -> "namespace-drop";
+ case NAMESPACE_LIST -> "namespace-list";
+ case NAMESPACE_READ_PROPERTIES -> "namespace-properties-read";
+ case NAMESPACE_WRITE_PROPERTIES -> "namespace-properties-write";
+ case NAMESPACE_FULL_METADATA -> "namespace-metadata-full";
+ case NAMESPACE_ATTACH_POLICY -> "namespace-policy-attach";
+ case NAMESPACE_DETACH_POLICY -> "namespace-policy-detach";
+
+ case TABLE_CREATE -> "table-create";
+ case TABLE_DROP -> "table-drop";
+ case TABLE_LIST -> "table-list";
+ case TABLE_READ_PROPERTIES -> "table-properties-read";
+ case TABLE_WRITE_PROPERTIES -> "table-properties-write";
+ case TABLE_READ_DATA -> "table-data-read";
+ case TABLE_WRITE_DATA -> "table-data-write";
+ case TABLE_FULL_METADATA -> "table-metadata-full";
+ case TABLE_ATTACH_POLICY -> "table-policy-attach";
+ case TABLE_DETACH_POLICY -> "table-policy-detach";
+ case TABLE_ASSIGN_UUID -> "table-uuid-assign";
+ case TABLE_UPGRADE_FORMAT_VERSION -> "table-format-version-upgrade";
+ case TABLE_ADD_SCHEMA -> "table-schema-add";
+ case TABLE_SET_CURRENT_SCHEMA -> "table-schema-set-current";
+ case TABLE_ADD_PARTITION_SPEC -> "table-partition-spec-add";
+ case TABLE_ADD_SORT_ORDER -> "table-sort-order-add";
+ case TABLE_SET_DEFAULT_SORT_ORDER -> "table-sort-order-set-default";
+ case TABLE_ADD_SNAPSHOT -> "table-snapshot-add";
+ case TABLE_SET_SNAPSHOT_REF -> "table-snapshot-ref-set";
+ case TABLE_REMOVE_SNAPSHOTS -> "table-snapshots-remove";
+ case TABLE_REMOVE_SNAPSHOT_REF -> "table-snapshot-ref-remove";
+ case TABLE_SET_LOCATION -> "table-location-set";
+ case TABLE_SET_PROPERTIES -> "table-properties-set";
+ case TABLE_REMOVE_PROPERTIES -> "table-properties-remove";
+ case TABLE_SET_STATISTICS -> "table-statistics-set";
+ case TABLE_REMOVE_STATISTICS -> "table-statistics-remove";
+ case TABLE_REMOVE_PARTITION_SPECS -> "table-partition-specs-remove";
+ case TABLE_MANAGE_STRUCTURE -> "table-structure-manage";
+
+ case VIEW_CREATE -> "view-create";
+ case VIEW_DROP -> "view-drop";
+ case VIEW_LIST -> "view-list";
+ case VIEW_READ_PROPERTIES -> "view-properties-read";
+ case VIEW_WRITE_PROPERTIES -> "view-properties-write";
+ case VIEW_FULL_METADATA -> "view-metadata-full";
+
+ case POLICY_CREATE -> "policy-create";
+ case POLICY_READ -> "policy-read";
+ case POLICY_DROP -> "policy-drop";
+ case POLICY_WRITE -> "policy-write";
+ case POLICY_LIST -> "policy-list";
+ case POLICY_FULL_METADATA -> "policy-metadata-full";
+ case POLICY_ATTACH -> "policy-attach";
+ case POLICY_DETACH -> "policy-detach";
+
+ default -> privilege.name();
+ };
+ }
+
+ public static RangerUserInfo toUserInfo(PolarisPrincipal principal) {
+ return new RangerUserInfo(
+ principal.getName(), getUserAttributes(principal), null, principal.getRoles());
+ }
+
+ public static RangerAccessInfo toAccessInfo(
+ PolarisResolvedPathWrapper entity,
+ PolarisAuthorizableOperation authzOp,
+ EnumSet<PolarisPrivilege> privileges) {
+ return new RangerAccessInfo(
+ RangerUtils.toResourceInfo(entity), authzOp.name(), RangerUtils.toPermissions(privileges));
+ }
+
+ public static String toResourcePath(List<PolarisResolvedPathWrapper> resolvedPaths) {
+ return resolvedPaths.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(","));
+ }
+
+ public static String toResourcePath(PolarisResolvedPathWrapper resolvedPath) {
+ StringBuilder sb = new StringBuilder();
+ String resourceType =
+ toResourceType(resolvedPath.getResolvedLeafEntity().getEntity().getType());
+
+ sb.append(resourceType).append(RangerResourceNameParser.RRN_RESOURCE_TYPE_SEP);
+
+ boolean isFirst = true;
+
+ for (ResolvedPolarisEntity entity : resolvedPath.getResolvedFullPath()) {
+ if (!isFirst) {
+ sb.append(RangerResourceNameParser.DEFAULT_RRN_RESOURCE_SEP);
+ } else {
+ isFirst = false;
+ }
+
+ sb.append(entity.getEntity().getName());
+ }
+
+ return sb.toString();
+ }
+
+ private static RangerResourceInfo toResourceInfo(PolarisResolvedPathWrapper resourcePath) {
+ RangerResourceInfo ret = new RangerResourceInfo();
+
+ ret.setName(toResourcePath(resourcePath));
+ ret.setAttributes(getResourceAttributes(resourcePath));
+
+ return ret;
+ }
+
+ private static Set<String> toPermissions(EnumSet<PolarisPrivilege> privileges) {
+ return privileges.stream().map(RangerUtils::toAccessType).collect(Collectors.toSet());
+ }
+
+ private static Map<String, Object> getResourceAttributes(
+ PolarisResolvedPathWrapper resourcePath) {
+ Map<String, Object> ret = null;
+
+ for (ResolvedPolarisEntity resolvedEntity : resourcePath.getResolvedFullPath()) {
+ PolarisEntity entity = resolvedEntity.getEntity();
+
+ if (StringUtils.isNotBlank(entity.getProperties())) {
+ if (ret == null) {
+ ret = new HashMap<>(entity.getPropertiesAsMap());
+ } else {
+ ret.putAll(entity.getPropertiesAsMap());
Review Comment:
curious - if silently overriding parent properties is intentional or not? could you elaborate the rationale?
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(fileTree("override-libs") { include("*.jar") })
+
+ implementation("org.apache.ranger:ranger-plugins-common:2.8.0")
+
+ implementation("org.apache.ranger:authz-embedded:2.8.0")
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+ implementation(project(":polaris-async-api"))
+ implementation(libs.guava)
+
+ compileOnly(project(":polaris-immutables"))
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+
+ implementation("org.apache.commons:commons-lang3:3.19.0")
+ runtimeOnly("org.apache.commons:commons-configuration2:2.10.1")
+ runtimeOnly("org.apache.commons:commons-text")
+ runtimeOnly("commons-collections:commons-collections:3.2.2")
Review Comment:
pinned version is not consistent with the project conventions
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2983480930
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+
+ RangerPolarisOperationSemantics semantics =
+ RangerPolarisOperationSemantics.forOperation(authzOp);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "authorizeOrThrow(principal={}, activatedEntities={}, authzOp={name: {}, targetPrivileges: {}, secondaryPrivileges: {}), targets={}, secondaries={}",
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ semantics.targetPrivileges(),
+ semantics.secondaryPrivileges(),
+ targets,
+ secondaries);
+ }
+
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
Review Comment:
IIRC, Ranger does not rely on Polaris local principal entities.
The `RESET_CREDENTIALS` is relevant only to principals managed by Polaris (kind of internal IdP).
I believe the Ranger Authorizer should deny this operation unconditionally.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4110547974
With the patch allowing the Unicode/ICU License as an approved license specifically for the org.graalvm.shadowed:icu4j module, all CI checks are now passing.
@dimas-b / @jbonofre ,
Can you please review and provide final approval of this PR for merge into the apache:main branch?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984926796
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
Review Comment:
I see... for the sake of simplicity, would it be too much trouble to separate the Ranger Authorizer proper from Audit logs (and do audit in a follow-up PR)?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2997794235
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
Review Comment:
@dimas-b - it seems this is for @jbonofre. If any update is needed in this PR, can you please call out?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3025382113
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(RangerTestProfiles.EmbeddedPolicy.class)
+public class RangerAdminServiceIT extends RangerIntegrationTestBase {
+
+ private String baseCatalogName;
+ private String baseCatalogLocation;
+ private String baseRootToken;
+
+ @BeforeEach
+ void setupBaseCatalog() throws Exception {
+ baseRootToken = getRootToken();
+ baseCatalogName = "ranger-base-cat-" + UUID.randomUUID().toString().replace("-", "");
+ baseCatalogLocation = Files.createTempDirectory("ranger-base-cat").toUri().toString();
+ createFileCatalog(
+ baseRootToken, baseCatalogName, baseCatalogLocation, List.of(baseCatalogLocation));
+ }
+
+ @Test
+ void assignCatalogRoleToPrincipalRole() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogRole = "ranger-cat-role-" + UUID.randomUUID().toString().replace("-", "");
+ String principalRole = "ranger-pr-role-" + UUID.randomUUID().toString().replace("-", "");
+
+ // create catalog role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", catalogRole, "properties", Map.of())))
+ .post("/api/management/v1/catalogs/{cat}/catalog-roles", baseCatalogName)
+ .then()
+ .statusCode(403);
+
+ // create principal role
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(Map.of("name", principalRole, "properties", Map.of())))
+ .post("/api/management/v1/principal-roles")
+ .then()
+ .statusCode(403);
+
+ Map<String, Object> grantRequest =
+ Map.of("catalogRole", Map.of("name", catalogRole, "properties", Map.of()));
+
+ // stranger cannot bind
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(grantRequest))
+ .put(
+ "/api/management/v1/principal-roles/{pr}/catalog-roles/{cat}",
+ principalRole,
+ baseCatalogName)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ void listCatalogsAuthorization() {
+ String rootToken = baseRootToken;
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ // stranger cannot list catalogs
+ given()
+ .header("Authorization", "Bearer " + strangerToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // root lists catalogs successfully
+ given()
+ .header("Authorization", "Bearer " + rootToken)
+ .get("/api/management/v1/catalogs")
+ .then()
+ .statusCode(200);
+ }
+
+ @Test
+ void createCatalogAuthorization() throws Exception {
+ String rootToken = getRootToken();
+ String strangerToken = createPrincipalAndGetToken("stranger-" + UUID.randomUUID());
+
+ String catalogName = "ranger-cat-create-" + UUID.randomUUID().toString().replace("-", "");
+ String baseLocation = Files.createTempDirectory("ranger-cat-create").toUri().toString();
+ Map<String, Object> createCatalogRequest =
+ Map.of(
+ "type",
+ "INTERNAL",
+ "name",
+ catalogName,
+ "properties",
+ Map.of("default-base-location", baseLocation),
+ "storageConfigInfo",
+ Map.of("storageType", "FILE", "allowedLocations", List.of(baseLocation)));
+
+ // Stranger cannot create catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + strangerToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
+ .then()
+ .statusCode(403);
+
+ // Root creates catalog
+ given()
+ .contentType(ContentType.JSON)
+ .header("Authorization", "Bearer " + rootToken)
+ .body(toJson(createCatalogRequest))
+ .post("/api/management/v1/catalogs")
Review Comment:
Actually, if `integration-tests` is not a dependency, please ignore my comment above.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3051488710
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
Review Comment:
This is Sun's Jersey (1.x), not Eclipse Jersey (2.x).
Reading its parent POM, it is is dual-licensed under CDDL 1.1 + GPL Version 2 with Classpath Exception.
```suggestion
Home page: https://jersey.java.net/
License: CDDL 1.1 - https://opensource.org/licenses/CDDL-1.1
```
Note: the original license URL mentioned in the POM (http://glassfish.java.net/public/CDDL+GPL_1_1.html) is now dead.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3050600182
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
This is an important caveat indeed: if `graalvm` is declared explicitly, it will get updates _independently of ranger updates_.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3051398586
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
+* Maven group:artifact IDs: org.graalvm.shadowed:xz
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-api
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-compiler
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-runtime
+
+Home page: https://github.com/oracle/graal/
+License: The GNU General Public License (GPL) - https://github.com/oracle/graal/blob/master/LICENSE
Review Comment:
Our license tool is reporting the following GraalVM deps as UPL 1.0 which is compatible:
```
org.graalvm.js:js:25.0.2
org.graalvm.js:js-language:25.0.2
org.graalvm.js:js-scriptengine:25.0.2
org.graalvm.polyglot:js:25.0.2
org.graalvm.polyglot:polyglot:25.0.2
org.graalvm.regex:regex:25.0.2
org.graalvm.sdk:collections:25.0.2
org.graalvm.sdk:jniutils:25.0.2
org.graalvm.sdk:nativeimage:23.1.2
org.graalvm.sdk:word:23.1.2
org.graalvm.shadowed:xz:25.0.2
org.graalvm.truffle:truffle-api:25.0.2
org.graalvm.truffle:truffle-compiler:25.0.2
org.graalvm.truffle:truffle-runtime:25.0.2
```
Indeed the jars seem to have a license section like below:
```xml
<licenses>
<license>
<name>Universal Permissive License, Version 1.0</name>
<url>http://opensource.org/licenses/UPL</url>
</license>
</licenses>
```
Just this one is different: `org.graalvm.shadowed:icu4j:25.0.2` it has `Unicode/ICU License`.
So it seems that the GraalVM GitHub repository license is GPL, but the published GraalVM artifacts are in fact UPL.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "snazy (via GitHub)" <gi...@apache.org>.
snazy commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4294594869
Some of the legal issues have been [mentioned here](https://github.com/apache/polaris/pull/3928#discussion_r3027346986).
`runtime/server/distribution/LICENSE` concerns:
* now says that Polaris bundles a Category-X dependency (GPL-only)
* BSD-3/MIT dependencies are missing mandatory license mentions
* included javax-ws-rs is not mentioned (via jersey-bundle)
* some GraalVM dependencies are mentioned with the [wrong license](https://github.com/smarr/truffle#license)
* Missing notice file content (needs to be individually validated) from:
* Ranger
* Solr
* Zookeeper
* hppc
* joda-time
* Style: duplicated dependency groups.
The effective server runtime dependencies can be inspected using `./gradlew :polaris-server:dependencies --configuration quarkusProdRuntimeClasspathConfiguration`.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3122030416
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
+* Maven group:artifact IDs: org.graalvm.shadowed:xz
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-api
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-compiler
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-runtime
+
+Home page: https://github.com/oracle/graal/
+License: The GNU General Public License (GPL) - https://github.com/oracle/graal/blob/master/LICENSE
Review Comment:
GPL 20 WITH Classpath Exception can be Cat B (not X). But it has to be documented.
That should be clarified.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3126272343
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
+
+Home page: https://github.com/qos-ch/reload4j
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles High Performance Primitive Collections library.
+
+* Maven group:artifact IDs: com.carrotsearch:hppc
+
+Home page: https://github.com/carrotsearch/hppc
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Metrics Core library.
+
+* Maven group:artifact IDs: io.dropwizard.metrics:metrics-core
+
+Home page: https://github.com/dropwizard/metrics
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Joda Time library.
+
+* Maven group:artifact IDs: joda-time:joda-time
+
+Home page: https://github.com/JodaOrg/joda-time
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Solr library.
+
+* Maven group:artifact IDs: org.apache.solr:solr-solrj
+
+Home page: https://github.com/apache/solr
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Yetus library.
+
+* Maven group:artifact IDs: org.apache.yetus:audience-annotations
+
+Home page: https://github.com/apache/yetus
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles ASM library.
+
+* Maven group:artifact IDs: org.ow2.asm:asm
+
+Home page: https://gitlab.ow2.org/asm/asm
+License: BSD 3-Clause - https://gitlab.ow2.org/asm/asm/-/blob/master/LICENSE.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Gethostname4j library.
+
+* Maven group:artifact IDs: com.kstruct:gethostname4j
+
+Home page: https://github.com/mattsheppard/gethostname4j
+License: MIT License - https://mit-license.org/
+
+--------------------------------------------------------------------------------
+
+This product bundles Jersey Bundle library.
+
+* Maven group:artifact IDs: com.sun.jersey:jersey-bundle
+
+Home page: https://github.com/eclipse-ee4j/jersey
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles JAXB API library.
+
+* Maven group:artifact IDs: javax.xml.bind:jaxb-api
+
+Home page: https://javaee.github.io/jaxb-v2/
+License: CDDL - https://javaee.github.io/jaxb-v2/LICENSE
+
+--------------------------------------------------------------------------------
+
+This product bundles GraalVM libraries.
+
+* Maven group:artifact IDs: org.graalvm.js:js
+* Maven group:artifact IDs: org.graalvm.js:js-language
+* Maven group:artifact IDs: org.graalvm.js:js-scriptengine
+* Maven group:artifact IDs: org.graalvm.polyglot:js
+* Maven group:artifact IDs: org.graalvm.polyglot:polyglot
+* Maven group:artifact IDs: org.graalvm.regex:regex
+* Maven group:artifact IDs: org.graalvm.sdk:collections
+* Maven group:artifact IDs: org.graalvm.sdk:jniutils
+* Maven group:artifact IDs: org.graalvm.sdk:nativeimage
+* Maven group:artifact IDs: org.graalvm.sdk:word
+* Maven group:artifact IDs: org.graalvm.shadowed:icu4j
+* Maven group:artifact IDs: org.graalvm.shadowed:xz
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-api
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-compiler
+* Maven group:artifact IDs: org.graalvm.truffle:truffle-runtime
+
+Home page: https://github.com/oracle/graal/
+License: The GNU General Public License (GPL) - https://github.com/oracle/graal/blob/master/LICENSE
Review Comment:
@sneethiraj I will check the other parts of the `LICENSE` file too.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2900023731
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/TestRangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
+ private static final String RESOURCE_TYPE_NAME_SEP = ":";
+ private static final String RESOURCE_ELEMENTS_SEP = "/";
+
+ private final Gson gsonBuilder;
Review Comment:
@flyingImer - The suggestion has been implemented in commit 83a7a932102761ea89d006f8002ec745128cd78e. Please take a look at the latest code in the PR.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2900015558
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(fileTree("override-libs") { include("*.jar") })
Review Comment:
@flyingImer This has been addressed in the latest commit. Please review the fixes in the latest code.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922485791
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
Review Comment:
Addressed in b684de1.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2919933072
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
+ implementation(libs.commons.lang3)
+ implementation(libs.guava)
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+ compileOnly(project(":polaris-immutables"))
+
+ runtimeOnly(libs.graalvm.graal.sdk)
+ runtimeOnly(libs.graalvm.inspect.community)
+ runtimeOnly(libs.graalvm.js.community)
+ runtimeOnly(libs.graalvm.js.scriptengine)
+ runtimeOnly(libs.graalvm.nativeimage)
Review Comment:
Do you mean that some Native GraalVM code is require for evaluating these expressions?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933403695
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
Review Comment:
> arbitrarily lower-case certain item names, but not all of them.
Ok. Will update to throw Unsupported exception for the types not handled by Ranger authorizer.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933433343
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
Review Comment:
> Here we just need to remove the operations that are only relevant for the built-in RBAC system,
Ok. The reason to list all available operations is to make it easier for code readers to grasp operations that are not supported. I will remove these now - ~50 fewers lines of code!
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3077162418
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactory.java:
##########
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.common.annotation.Identifier;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizerFactory;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Identifier("ranger")
+public class RangerPolarisAuthorizerFactory implements PolarisAuthorizerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerFactory.class);
+
+ private static final String ERR_AUTHORIZER_FACTORY_NOT_INITIALIZED =
+ "Ranger authorizer factory was not initialized successfully";
+
+ private final RangerPolarisAuthorizerConfig config;
+ private RangerEmbeddedAuthorizer authorizer;
+ private String serviceName;
+
+ @Inject
+ RangerPolarisAuthorizerFactory(RangerPolarisAuthorizerConfig config) {
+ this.config = config;
+
+ LOG.debug("RangerPolarisAuthorizerFactory has been activated.");
+ }
+
+ @PostConstruct
+ public void initialize() {
+ LOG.info("Initializing RangerAuthorizer");
+
+ config.validate();
+
+ try {
+ Properties properties = config.toRangerProperties();
+ RangerEmbeddedAuthorizer authorizer = new RangerEmbeddedAuthorizer(properties);
+
+ authorizer.init();
+
+ this.authorizer = authorizer;
+ this.serviceName = config.serviceName().orElseThrow();
Review Comment:
+1 to the suggestion. Addressed it in the commit - [234c9f554](https://github.com/sneethiraj/polaris/commit/234c9f5544468b78db35a5c0092b893e31d95351) .
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3077163867
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
+ } else {
+ props.setProperty(key, properties().get(key));
+ }
+ }
+ return props;
+ }
+
+ default void validate() {
+ if (serviceName().isEmpty()) {
+ throw new IllegalStateException(
Review Comment:
addressed in commit - https://github.com/sneethiraj/polaris/commit/234c9f5544468b78db35a5c0092b893e31d95351
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3080865731
##########
extensions/auth/ranger/impl/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
Review Comment:
That is fair, but there should not be a doubt about whether the extra `ranger` part is present, I guess π€ Why do we need to support both cases (with and without the extra `ranger` prefix)?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4127729706
Given the complex and extensive transitive dependencies that Ranger brings, I believe it is essential to have a `@QuarkusIntegrationTest` to cover main Ranger call paths. This is to ensure dependencies stay mutually compatible as the project evolves after merging this PR. Changes may come from components unrelated to Authorization, so contributors of those change may not be aware of Ranger specifics.
For a start we could probably do something similar to https://github.com/apache/polaris/tree/main/extensions/auth/opa/tests
In the longer run, it might be worth refactoring all integration tests to share the same Quarkus server (not in this PR).
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984910176
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
Review Comment:
@dimas-b - can you please suggest the right message to use here?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984926066
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+
+ static final String RANGER_KEY_PREFIX = "ranger.";
+ static final String XASECURE_KEY_PREFIX = "xasecure.";
+
+ Optional<String> serviceName();
+
+ @WithParentName
+ Map<String, String> properties();
+
+ default Properties toRangerProperties() {
+ Properties props = new Properties();
+ for (String key : properties().keySet()) {
+ if (!key.startsWith(RANGER_KEY_PREFIX) && !key.startsWith(XASECURE_KEY_PREFIX)) {
+ props.setProperty(RANGER_KEY_PREFIX + key, properties().get(key));
Review Comment:
1) Ranger authorizer expects properties with names starting with `ranger.authz.`
2) Polaris's `application.properties` requires all properties for Ranger authorizer to have name starting with `polaris.authorizer.ranger.`
3) Hence Ranger authorizer's property `ranger.authz.default.policy.rest.url` becomes `polaris.authorizer.ranger.ranger.authz.default.policy.rest.url` - note `ranger.ranger.` in the name
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2989070139
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
Review Comment:
I'd use the same message as for an ordinary authZ failure. Plus an optional (DEBUG) log message.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "sneethiraj (via GitHub)" <gi...@apache.org>.
sneethiraj commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4127594683
Merged the latest apache:main changes into this PR to resolve conflicts in gradle/libs.versions.toml.
Requesting review and approval to proceed with merging into apache:main.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2989193215
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
Let's have a `dev` email discussion specifically about the Ranger dependencies. I'm personally ok given the discussions in this PR, but it might be good to emphasize it again community-wide... just for awareness. As for me, having this vast transitive dependency trail was a surprise :sweat_smile:
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on PR #3928:
URL: https://github.com/apache/polaris/pull/3928#issuecomment-4025984394
What is `POLARIS-274` (from the PR title)? :sweat_smile:
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2915108508
##########
extensions/auth/ranger/build.gradle.kts:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+plugins {
+ id("polaris-server")
+ id("org.kordamp.gradle.jandex")
+}
+
+dependencies {
+ implementation(project(":polaris-core"))
+
+ implementation(libs.ranger.authz.embedded)
+ implementation(libs.commons.lang3)
+ implementation(libs.guava)
+
+ // Iceberg dependency for ForbiddenException
+ implementation(platform(libs.iceberg.bom))
+ implementation("org.apache.iceberg:iceberg-api")
+
+ compileOnly(libs.jakarta.annotation.api)
+ compileOnly(libs.jakarta.enterprise.cdi.api)
+ compileOnly(libs.jakarta.inject.api)
+ compileOnly(libs.smallrye.config.core)
+ compileOnly(project(":polaris-immutables"))
+
+ runtimeOnly(libs.graalvm.graal.sdk)
+ runtimeOnly(libs.graalvm.inspect.community)
+ runtimeOnly(libs.graalvm.js.community)
+ runtimeOnly(libs.graalvm.js.scriptengine)
+ runtimeOnly(libs.graalvm.nativeimage)
Review Comment:
How is `nativeimage` used?
##########
extensions/auth/ranger/sample-conf/ranger-plugin.properties:
##########
Review Comment:
(repeating from `dev` email / doc): Why not leverage the usual SmallRye config (backed by Quarkus) for this?
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,432 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RangerEmbeddedAuthorizer authorizer;
+ private final String serviceName;
+ private final boolean enforceCredentialRotationRequiredState;
+
+ public RangerPolarisAuthorizer(
+ RangerEmbeddedAuthorizer authorizer, String serviceName, RealmConfig realmConfig) {
+ this.authorizer = authorizer;
+ this.serviceName = serviceName;
+ this.enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @Nonnull AuthorizationDecision authorize(
+ @Nonnull AuthorizationState authzState, @Nonnull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (enforceCredentialRotationRequiredState
+ && authzOp != PolarisAuthorizableOperation.ROTATE_CREDENTIALS
+ && polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+
+ if (authzOp == PolarisAuthorizableOperation.RESET_CREDENTIALS) {
+ boolean isRootPrincipal = getRootPrincipalName().equals(polarisPrincipal.getName());
+
+ if (!isRootPrincipal) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ ROOT_PRINCIPAL_NEEDED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } else if (!AUTHORIZED_OPERATIONS.contains(authzOp)) {
+ throw new ForbiddenException(RANGER_UNSUPPORTED_OPERATION, authzOp.name());
+ } else if (!isAccessAuthorized(
+ polarisPrincipal, activatedEntities, authzOp, targets, secondaries)) {
+ throw new ForbiddenException(
+ RANGER_AUTH_FAILED_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
+ } catch (RangerAuthzException excp) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, excp);
+ throw new IllegalStateException(excp);
+ } catch (IllegalStateException ise) {
+ LOG.error("Failed to authorize principal {} for op {}", polarisPrincipal, authzOp, ise);
+ throw ise;
+ }
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "isAuthorized: user={}, properties={}, groups={}",
+ polarisPrincipal.getName(),
+ polarisPrincipal.getProperties(),
+ String.join(",", polarisPrincipal.getRoles()));
+
+ LOG.debug(
+ "isAuthorized: activatedEntities={}",
+ activatedEntities.stream()
+ .map(e -> RangerUtils.toResourceType(e.getType()) + ":" + e.getName())
+ .collect(Collectors.joining(",")));
+
+ LOG.debug("isAuthorized: authzOp={}", authzOp.name());
+
+ LOG.debug(
+ "isAuthorized: permissions={}",
+ authzOp.getPrivilegesOnTarget().stream()
+ .map(RangerUtils::toAccessType)
+ .collect(Collectors.joining(",")));
+
+ if (targets != null) {
+ LOG.debug(
+ "isAuthorized: targets={}",
+ targets.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+
+ if (secondaries != null) {
+ LOG.debug(
+ "isAuthorized: secondaries={}",
+ secondaries.stream().map(RangerUtils::toResourcePath).collect(Collectors.joining(",")));
+ }
+ }
+
+ return isAccessAuthorized(polarisPrincipal, authzOp, targets, secondaries);
+ }
+
+ private boolean isAccessAuthorized(
+ @Nonnull PolarisPrincipal principal,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries)
+ throws RangerAuthzException {
+ boolean isTargetSpecified = targets != null && !targets.isEmpty();
+ boolean isSecondarySpecified = secondaries != null && !secondaries.isEmpty();
+ List<RangerAccessInfo> accessInfos = new ArrayList<>();
+
+ if (!authzOp.getPrivilegesOnTarget().isEmpty()) {
+ Preconditions.checkState(
+ isTargetSpecified,
+ "No target provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnTarget());
+
+ for (PolarisResolvedPathWrapper target : targets) {
+ accessInfos.add(RangerUtils.toAccessInfo(target, authzOp, authzOp.getPrivilegesOnTarget()));
+ }
+ } else if (isTargetSpecified) {
+ LOG.warn(
+ "No privileges specified for target authorization. Ignoring target {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(targets),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ if (!authzOp.getPrivilegesOnSecondary().isEmpty()) {
+ Preconditions.checkState(
+ isSecondarySpecified,
+ "No secondaries provided to authorize %s for privileges %s",
+ authzOp,
+ authzOp.getPrivilegesOnSecondary());
+
+ for (PolarisResolvedPathWrapper secondary : secondaries) {
+ accessInfos.add(
+ RangerUtils.toAccessInfo(secondary, authzOp, authzOp.getPrivilegesOnSecondary()));
+ }
+ } else if (isSecondarySpecified) {
+ LOG.warn(
+ "No privileges specified for secondary authorization. Ignoring secondaries {}, op: {}, user: {}",
+ RangerUtils.toResourcePath(secondaries),
+ authzOp.name(),
+ principal.getName());
+ }
+
+ RangerUserInfo userInfo = RangerUtils.toUserInfo(principal);
+ RangerAccessContext context = new RangerAccessContext(SERVICE_TYPE, serviceName);
+ RangerMultiAuthzRequest authzRequest =
+ new RangerMultiAuthzRequest(userInfo, accessInfos, context);
+ RangerMultiAuthzResult authzResult = authorizer.authorize(authzRequest);
Review Comment:
What kind of I/O is expected at this point?
##########
extensions/auth/ranger/README.txt:
##########
@@ -0,0 +1,49 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+Prerequisites
+=================
+
+1. Ranger authorizer for Polaris requires Apache Ranger version 2.8.0 or later.
+
+Setup instructions
+=================
+
+1. Enable Ranger authorizer by setting the following property in
+ application.properties:
+#---------------------------------------------
+polaris.authorization.type=ranger
+#---------------------------------------------
+
+2. Specify the location of Ranger authorizer configuration file by setting the
+ following property in application.properties:
+#---------------------------------------------
+polaris.authorization.ranger.config-file-name=ranger-plugin.properties
+#---------------------------------------------
+
+ Ranger authorizer searches for the specified configuration file in classpath.
+ It is recommended to place the configuration file in the same location as
+ application.properties file.
+
+ Consider copying sample file from sample-conf/ranger-plugin.properties to the
+ folder where application.properties file is located and update the config
+ file according your Ranger installation.
+
+3. Restart Polaris to see that all accesses are authorized by Ranger policies,
Review Comment:
Restart or just "run" (including for the first time)?
##########
build.gradle.kts:
##########
@@ -106,6 +106,9 @@ tasks.named<RatTask>("rat").configure {
// Polaris service startup banner
excludes.add("runtime/service/src/**/banner.txt")
+ // Polaris service log files - generated by polaris-server
+ excludes.add("runtime/server/logs/**")
Review Comment:
Is this something specific to this PR or were those logs present before? In the latter case, it might be best to fix that in a separate PR for the sake of clarity π€
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933996544
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
Review Comment:
Addressed in 953eb89.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933988796
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
+@ConfigMapping(prefix = "polaris.authorization.ranger")
+public interface RangerPolarisAuthorizerConfig {
+ Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizerConfig.class);
+
+ String PROP_RANGER_CONFIG_FILE_NAME = "polaris.authorization.ranger.config-file-name";
+ String PROP_POLARIS_SERVICE_NAME = "ranger.plugin.polaris.service.name";
+
+ String ERR_INVALID_AUTHORIZER_CONFIG_MISSING_CONFIG_FILE_NAME =
+ "Invalid Ranger authorizer configuration: missing configuration "
+ + PROP_RANGER_CONFIG_FILE_NAME;
+ String ERR_INVALID_CONFIG_FILE_MISSING_CONFIGURATION =
Review Comment:
Addressed in 953eb89.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2933992800
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import io.smallrye.config.ConfigMapping;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.polaris.immutables.PolarisImmutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PolarisImmutable
Review Comment:
Addressed in 953eb89.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2931956721
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
Review Comment:
Yes, ` PolarisPrivilege` is local to the Polaris native RBAC (`PolarisAuthorizerImpl`).
`PolarisAuthorizableOperation` is the "input" Authorizers should operate on.
Right now it's a bit convoluted, I agree. Ideally, I believe we should remove ` PolarisPrivilege` from the `PolarisAuthorizableOperation` enum and make that association inside `PolarisAuthorizerImpl`... but it's a separate discussion, of course :)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2922625677
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/utils/RangerUtils.java:
##########
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.entity.PolarisPrivilege;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.extension.auth.ranger.RangerPolarisAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerResourceInfo;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RangerUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerUtils.class);
+
+ public static Properties loadProperties(String resourcePath) {
+ if (resourcePath == null) {
+ throw new IllegalStateException("invalid resource path: null");
+ }
+
+ resourcePath = resourcePath.trim();
+
+ if (!resourcePath.startsWith("/")) {
+ LOG.info("Prefixing / to resource path: {}", resourcePath);
+
+ resourcePath = "/" + resourcePath;
+ }
+
+ try (InputStream in = RangerPolarisAuthorizer.class.getResourceAsStream(resourcePath)) {
+ if (in != null) {
+ Properties prop = new Properties();
+
+ prop.load(in);
+
+ return prop;
+ } else {
+ LOG.error("Unable to find {} in the classpath", resourcePath);
+
+ throw new IllegalStateException("failed to find " + resourcePath);
+ }
+ } catch (IOException e) {
+ LOG.error("Unable to load {}", resourcePath, e);
+
+ throw new IllegalStateException("failed to load " + resourcePath);
+ }
+ }
+
+ public static String toResourceType(PolarisEntityType entityType) {
+ return switch (entityType) {
+ case ROOT -> "root";
+ case PRINCIPAL -> "principal";
+ case CATALOG -> "catalog";
+ case NAMESPACE -> "namespace";
+ case TABLE_LIKE -> "table";
+ case POLICY -> "policy";
+ default -> entityType.name(); // NULL_TYPE, PRINCIPAL_ROLE, CATALOG_ROLE, TASK, FILE
+ };
+ }
+
+ public static String toAccessType(PolarisPrivilege privilege) {
+ return switch (privilege) {
Review Comment:
Authorizer SPI requires implementations to ensure that the principal is allowed to perform the operation on specified targets and secondaries. It seems reasonable to require the implementations to honor `PolarisPrivilege` requirements as well on targets and secondaries. An implementation can map multiple `PolarisPrivilege`s into a single permission or a single `PolarisPrivilege`to multiple permissions. It seems SPI will be incomplete without `PolarisPrivilege`.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3052270253
##########
extensions/auth/ranger/tests/src/intTest/java/org/apache/polaris/extension/auth/ranger/test/RangerAdminServiceIT.java:
##########
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger.test;
+
+import static io.restassured.RestAssured.given;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.http.ContentType;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.iceberg.PartitionSpec;
+import org.apache.iceberg.Schema;
+import org.apache.iceberg.TableMetadata;
+import org.apache.iceberg.TableMetadataParser;
+import org.apache.iceberg.types.Types;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
Review Comment:
+1
`@QuarkusIntegrationTest` is the ultimate test when dependencies are a concern (as in this PR). The Polaris Server will run in an isolated JVM with only its declared + transitive runtime dependencies. Test dependencies will not affect the server runtime.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r3074887336
##########
gradle/libs.versions.toml:
##########
@@ -19,12 +19,14 @@
[versions]
checkstyle = "13.3.0"
+graalvm = "25.0.2"
Review Comment:
Thanks for the info, @sneethiraj !
This still feel a bit risky to me. I'd propose two things:
1) rename the reference to be more explicit about Ranger, e.g. `ranger-graalvm` and add a comment about keeping it in sync with Ranger (e.g. what to check on the Ranger side to figure out what the right version should be).
2) Pin the version to prevent Renovate from updating it (e.g. `25.0.2!!`)
CC: @adutra @snazy
WDYT?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2892195752
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable PolarisResolvedPathWrapper target,
+ @Nullable PolarisResolvedPathWrapper secondary) {
+ authorizeOrThrow(
+ polarisPrincipal,
+ activatedEntities,
+ authzOp,
+ target == null ? null : List.of(target),
+ secondary == null ? null : List.of(secondary));
+ }
+
+ @Override
+ public void authorizeOrThrow(
+ @Nonnull PolarisPrincipal polarisPrincipal,
+ @Nonnull Set<PolarisBaseEntity> activatedEntities,
+ @Nonnull PolarisAuthorizableOperation authzOp,
+ @Nullable List<PolarisResolvedPathWrapper> targets,
+ @Nullable List<PolarisResolvedPathWrapper> secondaries) {
+ try {
+ if (authzOp == PolarisAuthorizableOperation.ROTATE_CREDENTIALS) {
+ boolean enforceCredentialRotationRequiredState =
+ realmConfig.getConfig(
+ FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
+
+ if (enforceCredentialRotationRequiredState
+ && !polarisPrincipal
+ .getProperties()
+ .containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) {
+ // TODO: enable ranger audit from here to ensure that the request denied captured.
+ throw new ForbiddenException(
+ OPERATION_NOT_ALLOWED_FOR_USER_ERROR, polarisPrincipal.getName(), authzOp.name());
+ }
Review Comment:
Good catch! Thank you @flyingImer for the reference. Will update shortly.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [POLARIS-274] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2892668163
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthorizer;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+ public static final String SERVICE_NAME_PROPERTY = "ranger.plugin.polaris.service.name";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPLE_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
+
+ private static final Set<PolarisAuthorizableOperation> AUTHORIZED_OPERATIONS =
+ initAuthorizedOperations();
+
+ private final RealmConfig realmConfig;
+ private final RangerAuthorizer authorizer;
+ private final String serviceName;
+
+ public RangerPolarisAuthorizer(RangerPolarisAuthorizerConfig config, RealmConfig realmConfig) {
+ LOG.info("Initializing RangerPolarisAuthorizer");
+
+ Properties rangerProp = RangerUtils.loadProperties(config.configFileName().get());
+
+ this.realmConfig = realmConfig;
+ this.authorizer = new RangerEmbeddedAuthorizer(rangerProp);
+ this.serviceName = rangerProp.getProperty(SERVICE_NAME_PROPERTY);
+
+ try {
+ authorizer.init();
+ } catch (RangerAuthzException t) {
+ LOG.error("Failed to initialize RangerPolarisAuthorizer", t);
+ throw new RuntimeException(t);
+ }
+
+ LOG.info("RangerPolarisAuthorizer initialized successfully");
+ }
+
+ @Override
+ public void resolveAuthorizationInputs(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "resolveAuthorizationInputs is not implemented yet for RangerPolarisAuthorizer");
+ }
+
+ @Override
+ public @NonNull AuthorizationDecision authorize(
+ @NonNull AuthorizationState authzState, @NonNull AuthorizationRequest request) {
+ throw new UnsupportedOperationException(
+ "authorize is not implemented yet for RangerPolarisAuthorizer");
+ }
Review Comment:
Refactoring of authorizer SPI is in progress, tracked by a separate PR #3779. The suggestion is to update authorizer implementations once the refactoring is complete.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2997884405
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
+ private static final String RANGER_UNSUPPORTED_OPERATION =
+ "Operation %s is not supported by Ranger authorizer";
Review Comment:
For this PR, I'd propose to use the same message for all Ranger authZ failures (but do not mention "Ranger").
Aligning other Authrorizers on messages is probably out of scope for this PR :)
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984846129
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
Review Comment:
Ranger uses `JacksonJsonProvider` to deserialize JSON data retrieved via REST APIs - hence this library here.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "dimas-b (via GitHub)" <gi...@apache.org>.
dimas-b commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2984929472
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
+License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
+
+--------------------------------------------------------------------------------
+
+This product bundles FasterXML libraries.
+
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+* Maven group:artifact IDs: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+* Maven group:artifact IDs: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
+
+Home page: https://github.com/FasterXML/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles HttpComponents libraries.
+
+* Maven group:artifact IDs: org.apache.httpcomponents:httpasyncclient
+* Maven group:artifact IDs: org.apache.httpcomponents:httpcore-nio
+* Maven group:artifact IDs: org.apache.httpcomponents:httpmime
+
+Home page: https://hc.apache.org/
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles JSON Smart libraries.
+
+* Maven group:artifact IDs: net.minidev:json-smart
+* Maven group:artifact IDs: net.minidev:accessors-smart
+
+Home page: https://github.com/netplex/json-smart-v2
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Apache Zookeeper libraries.
+
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper
+* Maven group:artifact IDs: org.apache.zookeeper:zookeeper-jute
+
+Home page: https://github.com/apache/zookeeper
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Collections library.
+
+* Maven group:artifact IDs: commons-collections:commons-collections
+
+Home page: https://github.com/apache/commons-collections
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Commons Lang library.
+
+* Maven group:artifact IDs: commons-lang:commons-lang
+
+Home page: https://github.com/apache/commons-lang
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Reload4j library.
+
+* Maven group:artifact IDs: ch.qos.reload4j:reload4j
Review Comment:
I'm not 100% sure, but assuming this library does not affect runtime, it should not be bundled, right?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "adutra (via GitHub)" <gi...@apache.org>.
adutra commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2946023891
##########
extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerTest.java:
##########
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.extension.auth.ranger;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createConfig;
+import static org.apache.polaris.extension.auth.ranger.RangerTestUtils.createRealmConfig;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.entity.PolarisEntity;
+import org.apache.polaris.core.entity.PolarisEntityType;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.junit.jupiter.api.Test;
+
+public class TestRangerPolarisAuthorizer {
+ private static final String RESOURCE_TYPE_NAME_SEP = ":";
+ private static final String RESOURCE_ELEMENTS_SEP = "/";
+
+ private final PolarisAuthorizer authorizer;
+
+ public TestRangerPolarisAuthorizer() {
+ RangerPolarisAuthorizerFactory factory = new RangerPolarisAuthorizerFactory(createConfig());
+
+ factory.initialize();
+
+ authorizer = factory.create(createRealmConfig());
+
+ assertNotNull(authorizer);
+ }
+
+ @Test
+ public void testAuthzRoot() throws Exception {
+ runTests(authorizer, "/authz_tests/tests_authz_root.json");
Review Comment:
Quite frankly, something like this would be way more readable imho:
```java
@ParameterizedTest
@CsvSource({
"CREATE_CATALOG , admin1 , ROOT:root_container , true",
"LIST_CATALOGS , admin1 , ROOT:root_container , true",
"CREATE_PRINCIPAL , admin1 , ROOT:root_container , true",
"LIST_PRINCIPALS , admin1 , ROOT:root_container , true",
"CREATE_CATALOG , user1 , ROOT:root_container , false",
"LIST_CATALOGS , user1 , ROOT:root_container , true",
"CREATE_PRINCIPAL , user1 , ROOT:root_container , false",
"LIST_PRINCIPALS , user1 , ROOT:root_container , true",
"CREATE_CATALOG , user2 , ROOT:root_container , false",
"LIST_CATALOGS , user2 , ROOT:root_container , false",
"CREATE_PRINCIPAL , user2 , ROOT:root_container , false",
"LIST_PRINCIPALS , user2 , ROOT:root_container , false",
})
void testAuthzRoot(
PolarisAuthorizableOperation authzOp,
String principalName,
String target,
boolean isAllowed) {
assertAuthz(authzOp, principalName, target, null, isAllowed);
}
```
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2998948737
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
Review Comment:
@dimas-b no we don't need the Jetty NOTICE in our NOTICE because Jetty is Eclipse Public License (not Apache License).
Anyway, I'm doing a full review.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2997794235
##########
runtime/server/distribution/LICENSE:
##########
@@ -2021,3 +2021,213 @@ Project URL: https://github.com/aeron-io/agrona
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
+
+This product bundles Apache Ranger libraries.
+
+* Maven group:artifact IDs: org.apache.ranger:authz-embedded
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-core
+* Maven group:artifact IDs: org.apache.ranger:ranger-audit-dest-solr
+* Maven group:artifact IDs: org.apache.ranger:ranger-authz-api
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugin-classloader
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-common
+* Maven group:artifact IDs: org.apache.ranger:ranger-plugins-cred
+* Maven group:artifact IDs: org.apache.ranger:ugsync-util
+
+Project URL: https://github.com/apache/ranger
+License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
+
+--------------------------------------------------------------------------------
+
+This product bundles Jetty libraries.
+
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-client
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-http
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-io
+* Maven group:artifact IDs: org.eclipse.jetty:jetty-util
+
+Home page: https://github.com/jetty/jetty.project/
Review Comment:
@dimas-b - it seems this is for. @jbonofre. If any update is needed in this PR, can you please call out?
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Implement Apache Ranger Authorization Plugin for Apache Polaris (#274) [polaris]
Posted by "mneethiraj (via GitHub)" <gi...@apache.org>.
mneethiraj commented on code in PR #3928:
URL: https://github.com/apache/polaris/pull/3928#discussion_r2998249724
##########
extensions/auth/ranger/src/main/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizer.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.extension.auth.ranger;
+
+import static org.apache.polaris.core.entity.PolarisEntityConstants.getRootPrincipalName;
+
+import com.google.common.base.Preconditions;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.iceberg.exceptions.ForbiddenException;
+import org.apache.polaris.core.auth.AuthorizationDecision;
+import org.apache.polaris.core.auth.AuthorizationRequest;
+import org.apache.polaris.core.auth.AuthorizationState;
+import org.apache.polaris.core.auth.PolarisAuthorizableOperation;
+import org.apache.polaris.core.auth.PolarisAuthorizer;
+import org.apache.polaris.core.auth.PolarisPrincipal;
+import org.apache.polaris.core.config.FeatureConfiguration;
+import org.apache.polaris.core.config.RealmConfig;
+import org.apache.polaris.core.entity.PolarisBaseEntity;
+import org.apache.polaris.core.entity.PolarisEntityConstants;
+import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.extension.auth.ranger.utils.RangerUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.embedded.RangerEmbeddedAuthorizer;
+import org.apache.ranger.authz.model.RangerAccessContext;
+import org.apache.ranger.authz.model.RangerAccessInfo;
+import org.apache.ranger.authz.model.RangerAuthzResult;
+import org.apache.ranger.authz.model.RangerMultiAuthzRequest;
+import org.apache.ranger.authz.model.RangerMultiAuthzResult;
+import org.apache.ranger.authz.model.RangerUserInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Authorizes operations based on policies defined in Apache Ranger. */
+public class RangerPolarisAuthorizer implements PolarisAuthorizer {
+ private static final Logger LOG = LoggerFactory.getLogger(RangerPolarisAuthorizer.class);
+
+ public static final String SERVICE_TYPE = "polaris";
+
+ private static final String OPERATION_NOT_ALLOWED_FOR_USER_ERROR =
+ "Principal '%s' is not authorized for op %s due to PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE";
+ private static final String ROOT_PRINCIPAL_NEEDED_ERROR =
+ "Principal '%s' is not authorized for op %s as only root principal can perform this operation";
+ private static final String RANGER_AUTH_FAILED_ERROR =
+ "Principal '%s' is not authorized for op '%s'";
Review Comment:
Addressed in 6c005f5.
--
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: issues-unsubscribe@polaris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org