You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by cw...@apache.org on 2021/03/30 03:22:52 UTC
[druid] branch 0.21.0 updated: [Backport] basic security extension
ignore permissions that use unknown ResourceType or Action (#10919)
This is an automated email from the ASF dual-hosted git repository.
cwylie pushed a commit to branch 0.21.0
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/0.21.0 by this push:
new dec53c9 [Backport] basic security extension ignore permissions that use unknown ResourceType or Action (#10919)
dec53c9 is described below
commit dec53c9a9cb4b4d901ba32f7ea680e5c4266e92b
Author: Clint Wylie <cw...@apache.org>
AuthorDate: Mon Mar 29 20:22:21 2021 -0700
[Backport] basic security extension ignore permissions that use unknown ResourceType or Action (#10919)
* basic security extension ignore permissions that use unknown ResourceType or Action (#10896)
* suppress unknown ResourceType and Action for basic-security authorizer stuff
* fix pom
* print failed role, test logs
* fix test for backport
---
extensions-core/druid-basic-security/pom.xml | 7 ++
.../entity/BasicAuthorizerPermission.java | 9 ++
.../authorization/entity/BasicAuthorizerRole.java | 45 +++++++-
.../apache/druid/security/BasicAuthUtilsTest.java | 123 +++++++++++++++++++++
.../src/test/resources/log4j2.xml | 35 ++++++
5 files changed, 218 insertions(+), 1 deletion(-)
diff --git a/extensions-core/druid-basic-security/pom.xml b/extensions-core/druid-basic-security/pom.xml
index 3db5f4c..514bc43 100644
--- a/extensions-core/druid-basic-security/pom.xml
+++ b/extensions-core/druid-basic-security/pom.xml
@@ -147,5 +147,12 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.druid</groupId>
+ <artifactId>druid-processing</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
</dependencies>
</project>
diff --git a/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerPermission.java b/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerPermission.java
index 8efddac..6316976 100644
--- a/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerPermission.java
+++ b/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerPermission.java
@@ -119,4 +119,13 @@ public class BasicAuthorizerPermission
: 0);
return result;
}
+
+ @Override
+ public String toString()
+ {
+ return "BasicAuthorizerPermission{" +
+ "resourceAction=" + resourceAction +
+ ", resourceNamePattern=" + resourceNamePattern +
+ '}';
+ }
}
diff --git a/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerRole.java b/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerRole.java
index 83b2d55..f04f088 100644
--- a/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerRole.java
+++ b/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/entity/BasicAuthorizerRole.java
@@ -21,19 +21,31 @@ package org.apache.druid.security.basic.authorization.entity;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.druid.java.util.common.RE;
+import org.apache.druid.java.util.common.logger.Logger;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class BasicAuthorizerRole
{
+ private static final Logger log = new Logger(BasicAuthorizerRole.class);
+
private final String name;
private final List<BasicAuthorizerPermission> permissions;
@JsonCreator
public BasicAuthorizerRole(
@JsonProperty("name") String name,
- @JsonProperty("permissions") List<BasicAuthorizerPermission> permissions
+ @JsonProperty("permissions") @JsonDeserialize(using = PermissionsDeserializer.class) List<BasicAuthorizerPermission> permissions
)
{
this.name = name;
@@ -78,4 +90,35 @@ public class BasicAuthorizerRole
result = 31 * result + (getPermissions() != null ? getPermissions().hashCode() : 0);
return result;
}
+
+
+ static class PermissionsDeserializer extends JsonDeserializer<List<BasicAuthorizerPermission>>
+ {
+ @Override
+ public List<BasicAuthorizerPermission> deserialize(
+ JsonParser jsonParser,
+ DeserializationContext deserializationContext
+ ) throws IOException
+ {
+ List<BasicAuthorizerPermission> permissions = new ArrayList<>();
+ // sanity check
+ ObjectCodec codec = jsonParser.getCodec();
+ JsonNode hopefullyAnArray = codec.readTree(jsonParser);
+ if (!hopefullyAnArray.isArray()) {
+ throw new RE("Failed to deserialize authorizer role list");
+ }
+
+ for (JsonNode node : hopefullyAnArray) {
+ try {
+ permissions.add(codec.treeToValue(node, BasicAuthorizerPermission.class));
+ }
+ catch (JsonProcessingException e) {
+ // ignore unparseable, it might be resource types we don't know about
+ log.warn(e, "Failed to deserialize authorizer role, ignoring: %s", node.toPrettyString());
+ }
+ }
+
+ return permissions;
+ }
+ }
}
diff --git a/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java b/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java
index 142e44a..dfbb183 100644
--- a/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java
+++ b/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java
@@ -19,10 +19,25 @@
package org.apache.druid.security;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import org.apache.druid.security.basic.BasicAuthUtils;
+import org.apache.druid.security.basic.BasicSecurityDruidModule;
+import org.apache.druid.security.basic.authorization.entity.BasicAuthorizerPermission;
+import org.apache.druid.security.basic.authorization.entity.BasicAuthorizerRole;
+import org.apache.druid.segment.TestHelper;
+import org.apache.druid.server.security.Action;
+import org.apache.druid.server.security.Resource;
+import org.apache.druid.server.security.ResourceAction;
+import org.apache.druid.server.security.ResourceType;
import org.junit.Assert;
import org.junit.Test;
+import java.util.HashMap;
+import java.util.Map;
+
public class BasicAuthUtilsTest
{
@Test
@@ -36,4 +51,112 @@ public class BasicAuthUtilsTest
Assert.assertEquals(BasicAuthUtils.SALT_LENGTH, salt.length);
Assert.assertEquals(BasicAuthUtils.KEY_LENGTH / 8, hash.length);
}
+
+ @Test
+ public void testPermissionSerdeIsChillAboutUnknownEnumStuffs() throws JsonProcessingException
+ {
+ final String someRoleName = "some-role";
+ final String otherRoleName = "other-role";
+ final String thirdRoleName = "third-role";
+ final ResourceAction fooRead = new ResourceAction(new Resource("foo", ResourceType.DATASOURCE), Action.READ);
+ final ResourceAction barRead = new ResourceAction(new Resource("bar", ResourceType.DATASOURCE), Action.READ);
+
+ final ObjectMapper mapper = TestHelper.makeJsonMapper();
+ mapper.registerModules(new BasicSecurityDruidModule().getJacksonModules());
+ Map<String, Object> rawMap = new HashMap<>();
+ rawMap.put(
+ someRoleName,
+ new BasicAuthorizerRole(
+ someRoleName,
+ BasicAuthorizerPermission.makePermissionList(
+ ImmutableList.of(
+ fooRead,
+ barRead
+ )
+ )
+ )
+ );
+ // bad ResourceType
+ rawMap.put(
+ otherRoleName,
+ ImmutableMap.of(
+ "name",
+ otherRoleName,
+ "permissions",
+ ImmutableList.of(
+ ImmutableMap.of(
+ "resourceAction", fooRead,
+ "resourceNamePattern", "foo"
+ ),
+ ImmutableMap.of(
+ "resourceAction",
+ ImmutableMap.of(
+ "resource",
+ ImmutableMap.of("name", "bar", "type", "UNKNOWN"),
+ "action", "READ"
+ ),
+ "resourceNamePattern", "bar"
+ )
+ )
+ )
+ );
+ // bad Action
+ rawMap.put(
+ thirdRoleName,
+ ImmutableMap.of(
+ "name",
+ thirdRoleName,
+ "permissions",
+ ImmutableList.of(
+ ImmutableMap.of(
+ "resourceAction",
+ ImmutableMap.of(
+ "resource",
+ ImmutableMap.of("name", "some-table", "type", "DATASOURCE"),
+ "action", "READ"
+ ),
+ "resourceNamePattern", "some-table"
+ ),
+ ImmutableMap.of(
+ "resourceAction",
+ ImmutableMap.of(
+ "resource",
+ ImmutableMap.of("name", "foo", "type", "DATASOURCE"),
+ "action", "UNKNOWN"
+ ),
+ "resourceNamePattern", "foo"
+ )
+ )
+ )
+ );
+ byte[] mapBytes = mapper.writeValueAsBytes(rawMap);
+ Map<String, BasicAuthorizerRole> roleMap = BasicAuthUtils.deserializeAuthorizerRoleMap(mapper, mapBytes);
+ Assert.assertNotNull(roleMap);
+ Assert.assertEquals(3, roleMap.size());
+
+ Assert.assertTrue(roleMap.containsKey(someRoleName));
+ Assert.assertEquals(2, roleMap.get(someRoleName).getPermissions().size());
+ Assert.assertEquals(
+ BasicAuthorizerPermission.makePermissionList(ImmutableList.of(fooRead, barRead)),
+ roleMap.get(someRoleName).getPermissions()
+ );
+
+ // this one has an unknown ResourceType, expect only 1 permission to deserialize correctly and failure ignored
+ Assert.assertTrue(roleMap.containsKey(otherRoleName));
+ Assert.assertEquals(1, roleMap.get(otherRoleName).getPermissions().size());
+ Assert.assertEquals(
+ BasicAuthorizerPermission.makePermissionList(ImmutableList.of(fooRead)),
+ roleMap.get(otherRoleName).getPermissions()
+ );
+
+ // this one has an unknown Action, expect only 1 permission to deserialize correctly and failure ignored
+ Assert.assertTrue(roleMap.containsKey(thirdRoleName));
+ Assert.assertEquals(1, roleMap.get(thirdRoleName).getPermissions().size());
+ Assert.assertEquals(
+ BasicAuthorizerPermission.makePermissionList(
+ ImmutableList.of(new ResourceAction(new Resource("some-table", ResourceType.DATASOURCE), Action.READ))
+ ),
+ roleMap.get(thirdRoleName).getPermissions()
+ );
+ }
}
diff --git a/extensions-core/druid-basic-security/src/test/resources/log4j2.xml b/extensions-core/druid-basic-security/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..bca6c69
--- /dev/null
+++ b/extensions-core/druid-basic-security/src/test/resources/log4j2.xml
@@ -0,0 +1,35 @@
+<?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.
+ -->
+
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{ISO8601} %p [%t] %c - %m%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="info">
+ <AppenderRef ref="Console"/>
+ </Root>
+ <Logger level="debug" name="org.apache.druid" additivity="false">
+ <AppenderRef ref="Console"/>
+ </Logger>
+ </Loggers>
+</Configuration>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org