Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KNOX-2757 - HadoopGroupProvider parameters should be added to the filter even there is a gateway level property with CENTRAL_GROUP_CONFIG_PREFIX #590

Merged
merged 1 commit into from Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -36,6 +36,7 @@ velocity.log
*.pyc
*.py~
*.patch
.checkstyle

# other IDEs and editors
.vscode
Expand Down
4 changes: 4 additions & 0 deletions gateway-provider-identity-assertion-common/pom.xml
Expand Up @@ -37,6 +37,10 @@
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-provider-rewrite</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions gateway-provider-identity-assertion-hadoop-groups/pom.xml
Expand Up @@ -37,6 +37,10 @@
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-provider-identity-assertion-common</artifactId>
Expand Down
Expand Up @@ -18,9 +18,11 @@
package org.apache.knox.gateway.identityasserter.hadoop.groups.filter;

import org.apache.hadoop.conf.Configuration;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.deploy.DeploymentContext;
import org.apache.knox.gateway.descriptor.FilterParamDescriptor;
import org.apache.knox.gateway.descriptor.ResourceDescriptor;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.identityasserter.common.filter.AbstractIdentityAsserterDeploymentContributor;
import org.apache.knox.gateway.topology.Provider;
import org.apache.knox.gateway.topology.Service;
Expand All @@ -46,6 +48,10 @@ public class HadoopGroupProviderDeploymentContributor
*/
public static final String HADOOP_GROUP_PROVIDER = "HadoopGroupProvider";

private static final HadoopGroupProviderMessages LOG = MessagesFactory.get(HadoopGroupProviderMessages.class);

static final String CENTRAL_GROUP_CONFIG_PREFIX_PARAM_NAME = "CENTRAL_GROUP_CONFIG_PREFIX";

/* create an instance */
public HadoopGroupProviderDeploymentContributor() {
super();
Expand All @@ -62,46 +68,57 @@ protected String getFilterClassname() {
}

@Override
public void contributeFilter( DeploymentContext context, Provider provider, Service service,
ResourceDescriptor resource, List<FilterParamDescriptor> params ) {
Map<String, String> p = provider.getParams();
String prefix = p.get("CENTRAL_GROUP_CONFIG_PREFIX");
public void contributeFilter(DeploymentContext context, Provider provider, Service service, ResourceDescriptor resource, List<FilterParamDescriptor> params) {
smolnar82 marked this conversation as resolved.
Show resolved Hide resolved
final List<FilterParamDescriptor> filterParams = params == null ? new ArrayList<>() : new ArrayList<>(params);

// add group mapping parameters from gateway-site.xml, if any
final List<FilterParamDescriptor> groupMappingParamsList = getParamsFromGatewaySiteWithCentralGroupConfigPrefix(provider, context, resource);
filterParams.addAll(groupMappingParamsList);

// add provider parameters except for the CENTRAL_GROUP_CONFIG_PREFIX_PARAM_NAME one (that is used only to provide a bridge between the gateway and provider levels)
provider.getParams().entrySet().stream().filter(entry -> !entry.getKey().startsWith(CENTRAL_GROUP_CONFIG_PREFIX_PARAM_NAME)).forEach(entry -> {
// if a property already exists with the same name as this provider parameter, it
// should be removed because the provider-level property should be able to
// override the gateway-site parameter
filterParams.removeIf(filterParam -> filterParam.name().equals(entry.getKey()));
filterParams.add(createFilterParam(resource, entry.getKey(), entry.getValue()));
});

resource.addFilter().name(getName()).role(getRole()).impl(getFilterClassname()).params(filterParams);
}

private FilterParamDescriptor createFilterParam(ResourceDescriptor resource, String name, String value) {
return resource.createFilterParam().name(name.toLowerCase(Locale.ROOT)).value(value);
}

private List<FilterParamDescriptor> getParamsFromGatewaySiteWithCentralGroupConfigPrefix(Provider provider, DeploymentContext context, ResourceDescriptor resource) {
final List<FilterParamDescriptor> groupMappingParamsList = new ArrayList<>();
final Map<String, String> providerParams = provider.getParams();
String prefix = providerParams.get(CENTRAL_GROUP_CONFIG_PREFIX_PARAM_NAME);
if (prefix != null && !prefix.isEmpty()) {
if (!prefix.endsWith(".")) {
prefix += ".";
prefix += ".";
}
Map<String, String> groupMappingParams =
((Configuration)context.getGatewayConfig()).getPropsWithPrefix(prefix);
if (groupMappingParams != null) {
params = createParamList(resource, params, groupMappingParams);
}
}

if (params == null || params.isEmpty()) {
params = buildFilterInitParms(provider, resource, params);
final GatewayConfig gatewayConfig = context.getGatewayConfig();
final Map<String, String> groupMappingParams = gatewayConfig == null ? null : ((Configuration) gatewayConfig).getPropsWithPrefix(prefix);
if (groupMappingParams != null && !groupMappingParams.isEmpty()) {
LOG.groupMappingFound();
for (Entry<String, String> entry : groupMappingParams.entrySet()) {
groupMappingParamsList.add(createFilterParam(resource, entry.getKey(), entry.getValue()));
}
}
}
resource.addFilter().name(getName()).role(getRole()).impl(getFilterClassname()).params(params);
return groupMappingParamsList;
}

@Override
public List<FilterParamDescriptor> buildFilterInitParms(Provider provider,
ResourceDescriptor resource, List<FilterParamDescriptor> params) {
// blindly add all the provider params as filter init params
if (params == null) {
params = new ArrayList<>();
}
Map<String, String> providerParams = provider.getParams();
return createParamList(resource, params, providerParams);
}

private List<FilterParamDescriptor> createParamList(ResourceDescriptor resource, List<FilterParamDescriptor> params,
Map<String, String> providerParams) {
if (params == null) {
params = new ArrayList<>();
}
for(Entry<String, String> entry : providerParams.entrySet()) {
params.add( resource.createFilterParam().name(entry.getKey().toLowerCase(Locale.ROOT)).value(entry.getValue()));
}
return params;
public List<FilterParamDescriptor> buildFilterInitParms(Provider provider, ResourceDescriptor resource, List<FilterParamDescriptor> params) {
final List<FilterParamDescriptor> filterInitParams = params == null ? new ArrayList<>() : new ArrayList<>(params);
// blindly add all the provider params as filter init params
provider.getParams().forEach((paramName, paramValue) -> {
filterInitParams.add(createFilterParam(resource, paramName, paramValue));
});
return filterInitParams;
}
}
Expand Up @@ -38,4 +38,7 @@ public interface HadoopGroupProviderMessages {

@Message( level = MessageLevel.DEBUG, text = "Found groups for principal {0} : {1}" )
void groupsFound(String principal, String groups );

@Message( level = MessageLevel.DEBUG, text = "Found group mapping configuration in gateway-site" )
void groupMappingFound();
}
Expand Up @@ -18,24 +18,39 @@
package org.apache.knox.gateway.identityasserter.hadoop.groups.filter;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.stream.Collectors;

import org.apache.knox.gateway.GatewayTestConfig;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.deploy.DeploymentContext;
import org.apache.knox.gateway.deploy.ProviderDeploymentContributor;
import org.apache.knox.gateway.descriptor.FilterParamDescriptor;
import org.apache.knox.gateway.descriptor.ResourceDescriptor;
import org.apache.knox.gateway.descriptor.impl.ResourceDescriptorImpl;
import org.apache.knox.gateway.topology.Provider;
import org.easymock.EasyMock;
import org.junit.Test;

/**
* Test for {@link HadoopGroupProviderDeploymentContributor}
*
* @since 0.11
*/
public class HadoopGroupProviderDeploymentContributorTest {

@Test
public void testServiceLoader() throws Exception {
ServiceLoader<ProviderDeploymentContributor> loader = ServiceLoader
.load(ProviderDeploymentContributor.class);
ServiceLoader<ProviderDeploymentContributor> loader = ServiceLoader.load(ProviderDeploymentContributor.class);

Iterator<ProviderDeploymentContributor> iterator = loader.iterator();
assertThat("Service iterator empty.", iterator.hasNext());
Expand All @@ -45,9 +60,73 @@ public void testServiceLoader() throws Exception {
return;
}
}
fail("Failed to find "
+ HadoopGroupProviderDeploymentContributor.class.getName()
+ " via service loader.");
fail("Failed to find " + HadoopGroupProviderDeploymentContributor.class.getName() + " via service loader.");
}

@Test
public void testFilterParametersGenerationOnlyGatewaySiteCentralGroupPrefix() throws Exception {
testilterParametersGeneration(true, false);
}

@Test
public void testilterParametersGenerationOnlyCustomProviderParameter() throws Exception {
testilterParametersGeneration(false, true);
}

@Test
public void testilterParametersGenerationBothGatewaySiteCentralGroupPrefixAndCustomProviderParameter() throws Exception {
testilterParametersGeneration(true, true);
}

private void testilterParametersGeneration(boolean addCentralGroupPrefixParamIntoGatewaySite, boolean haveCustomProviderParameter) throws Exception {
final String centralGroupPrefixParam = "gateway.group.config.";

final DeploymentContext context = EasyMock.createNiceMock(DeploymentContext.class);
final Properties gatewaySiteProperties = new Properties();
if (addCentralGroupPrefixParamIntoGatewaySite) {
gatewaySiteProperties.put(centralGroupPrefixParam + "gateway.site.property", "gateway.site.property.value");
}
final GatewayConfig gatewayConfig = new GatewayTestConfig(gatewaySiteProperties);
EasyMock.expect(context.getGatewayConfig()).andReturn(gatewayConfig).anyTimes();

final Provider provider = EasyMock.createNiceMock(Provider.class);
final Map<String, String> providerParams = new HashMap<>();
providerParams.put(HadoopGroupProviderDeploymentContributor.CENTRAL_GROUP_CONFIG_PREFIX_PARAM_NAME, centralGroupPrefixParam);
if (haveCustomProviderParameter) {
providerParams.put("other.provider.param", "other.provider.param.value");

if (addCentralGroupPrefixParamIntoGatewaySite) {
//provider-level property should override the gateway-level property
providerParams.put("gateway.site.property", "custom.gateway.site.property.value");
}
}
EasyMock.expect(provider.getParams()).andReturn(providerParams).anyTimes();

final ResourceDescriptor resource = new ResourceDescriptorImpl(null);

EasyMock.replay(context, provider);

final HadoopGroupProviderDeploymentContributor deploymentContributor = new HadoopGroupProviderDeploymentContributor();
deploymentContributor.contributeFilter(context, provider, null, resource, null);
assertEquals(1, resource.filters().size());
final int expectedParameterNum = addCentralGroupPrefixParamIntoGatewaySite && haveCustomProviderParameter ? 2 : 1;
assertEquals(expectedParameterNum, resource.filters().get(0).params().size());

final List<FilterParamDescriptor> filterParams = resource.filters().get(0).params();
if (addCentralGroupPrefixParamIntoGatewaySite) {
final String expectedPropertyValue = haveCustomProviderParameter ? "custom.gateway.site.property.value" : "gateway.site.property.value";
assertEquals(expectedPropertyValue, getFilterParam(filterParams, "gateway.site.property").value());
}

if (haveCustomProviderParameter) {
assertEquals("other.provider.param.value", getFilterParam(filterParams, "other.provider.param").value());
}
}

private FilterParamDescriptor getFilterParam(List<FilterParamDescriptor> params, String name) {
final Collection<FilterParamDescriptor> relevantFilterParams = params.stream().filter(param -> param.name().equals(name)).collect(Collectors.toList());
assertEquals(1, relevantFilterParams.size());
return relevantFilterParams.iterator().next();
}

}
4 changes: 4 additions & 0 deletions gateway-provider-security-hadoopauth/pom.xml
Expand Up @@ -45,6 +45,10 @@
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-util-common</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions gateway-server/pom.xml
Expand Up @@ -97,6 +97,10 @@
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-topology-simple</artifactId>
Expand Down
64 changes: 64 additions & 0 deletions gateway-spi-common/pom.xml
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.knox</groupId>
<artifactId>gateway</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>

<artifactId>gateway-spi-common</artifactId>
<name>gateway-spi-common</name>

<dependencies>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<exclusions>
<exclusion>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
</exclusion>
<exclusion>
<groupId>dnsjava</groupId>
<artifactId>dnsjava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>

</project>