Skip to content

Commit

Permalink
[apache#4698] feat(core): Extended Apache Ranger authorization by con…
Browse files Browse the repository at this point in the history
…figuration

1

1
  • Loading branch information
xunliu committed Aug 28, 2024
1 parent d68ae44 commit 5d097f6
Show file tree
Hide file tree
Showing 14 changed files with 611 additions and 258 deletions.
24 changes: 21 additions & 3 deletions authorizations/authorization-ranger/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,36 @@ dependencies {

tasks {
val runtimeJars by registering(Copy::class) {
from(configurations.runtimeClasspath)
from(configurations.runtimeClasspath, "src/main/resources")
into("build/libs")
rename { original ->
if (original.endsWith(".properties.template")) {
original.replace(".properties.template", ".properties")
} else {
original
}
}
}

val copyAuthorizationLibs by registering(Copy::class) {
dependsOn("jar", "runtimeJars")
dependsOn("jar", runtimeJars)
from("build/libs")
into("$rootDir/distribution/package/authorizations/ranger/libs")
}

val copyAuthorizationConfig by registering(Copy::class) {
from("src/main/resources")
into("$rootDir/distribution/package/authorizations/ranger/conf")
exclude("META-INF")
fileMode = 0b111101101
}

register("copyLibAndConfig", Copy::class) {
dependsOn(copyAuthorizationLibs)
dependsOn(copyAuthorizationLibs, copyAuthorizationConfig)
}

jar {
dependsOn(runtimeJars)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* 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.gravitino.authorization.ranger;

import com.google.common.collect.Lists;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.apache.gravitino.Config;
import org.apache.gravitino.config.ConfigBuilder;
import org.apache.gravitino.config.ConfigConstants;
import org.apache.gravitino.config.ConfigEntry;

public class AuthorizationConfig extends Config {
public static final ConfigEntry<List<String>> AUTHORIZATION_OWNER_PRIVILEGES =
new ConfigBuilder("gravitino.authorization.owner.privileges")
.doc("The privileges that the owner of a security object has.")
.version(ConfigConstants.VERSION_0_7_0)
.stringConf()
.toSequence()
.checkValue(
valueList ->
valueList != null && valueList.stream().allMatch(StringUtils::isNotBlank),
ConfigConstants.NOT_BLANK_ERROR_MSG)
.createWithDefault(Lists.newArrayList());

public static final ConfigEntry<List<String>> RANGER_POLICY_RESOURCE_DEFINES =
new ConfigBuilder("gravitino.authorization.ranger.policy.resource.defines")
.doc("The resource defines that are used in Ranger policies.")
.version(ConfigConstants.VERSION_0_7_0)
.stringConf()
.toSequence()
.checkValue(
valueList ->
valueList != null && valueList.stream().allMatch(StringUtils::isNotBlank),
ConfigConstants.NOT_BLANK_ERROR_MSG)
.createWithDefault(Lists.newArrayList());

public static final String PRIVILEGE_MAPPING_PREFIX =
"gravitino.authorization.privilege.mapping.";

public static AuthorizationConfig loadConfig(String provideName) {
AuthorizationConfig authorizationConfig = new AuthorizationConfig();
boolean testEnv = System.getenv("GRAVITINO_TEST") != null;
String propertyFilePath =
String.format("authorization-defs/authorization-%s.properties", provideName);

// Only load from resources in test environment
if (testEnv) {
URL resourceUrl = AuthorizationConfig.class.getResource(File.separator + propertyFilePath);
try {
if (resourceUrl != null) {
Properties properties =
authorizationConfig.loadPropertiesFromFile(new File(resourceUrl.getPath()));
authorizationConfig.loadFromProperties(properties);
return authorizationConfig;
}
} catch (IOException e) {
throw new IllegalArgumentException(
"Failed to load authorization config from resource " + resourceUrl, e);
}
}

// Load from configuration directory in production environment
String confPath =
String.join(
File.separator,
System.getenv("GRAVITINO_HOME"),
"authorizations",
provideName,
"conf",
propertyFilePath);
try {
Properties properties = authorizationConfig.loadPropertiesFromFile(new File(confPath));
authorizationConfig.loadFromProperties(properties);
} catch (IOException e) {
throw new IllegalArgumentException(
"Failed to load authorization config from file " + confPath, e);
}
return authorizationConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.time.Instant;
import java.util.Collections;
Expand Down Expand Up @@ -87,7 +86,8 @@ public RangerAuthorizationPlugin(String catalogProvider, Map<String, String> con
RangerHelper.check(password != null, "Ranger password is required");
RangerHelper.check(rangerServiceName != null, "Ranger service name is required");
rangerClient = new RangerClientExtend(rangerUrl, authType, rangerAdminName, password);
rangerHelper = new RangerHelper(this, catalogProvider);
rangerHelper =
new RangerHelper(catalogProvider, rangerClient, rangerAdminName, rangerServiceName);
}

/**
Expand All @@ -97,12 +97,11 @@ public RangerAuthorizationPlugin(String catalogProvider, Map<String, String> con
* @return The corresponding privilege name in the underlying permission system
*/
public Set<String> translatePrivilege(Privilege.Name name) {
return rangerHelper.privilegesMapping.get(name);
return rangerHelper.translatePrivilege(name);
}

@VisibleForTesting
public List<String> getOwnerPrivileges() {
return Lists.newArrayList(rangerHelper.ownerPrivileges);
public Set<String> getOwnerPrivileges() {
return rangerHelper.getOwnerPrivileges();
}

/**
Expand Down
Loading

0 comments on commit 5d097f6

Please sign in to comment.