diff --git a/src/main/java/com/redhat/cloud/policies/app/RbacServer.java b/src/main/java/com/redhat/cloud/policies/app/RbacServer.java index 6c24145c..85746cf0 100644 --- a/src/main/java/com/redhat/cloud/policies/app/RbacServer.java +++ b/src/main/java/com/redhat/cloud/policies/app/RbacServer.java @@ -16,7 +16,6 @@ */ package com.redhat.cloud.policies.app; -import com.redhat.cloud.policies.app.auth.RbacRaw; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; @@ -26,6 +25,8 @@ import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import com.redhat.cloud.policies.app.auth.models.RbacRaw; + @Path("/api/rbac/v1") @RegisterRestClient(configKey = "rbac") @RegisterProvider(RbacRestClientRequestFilter.class) diff --git a/src/main/java/com/redhat/cloud/policies/app/auth/RbacClient.java b/src/main/java/com/redhat/cloud/policies/app/auth/RbacClient.java index bb53aa97..9dc41a65 100644 --- a/src/main/java/com/redhat/cloud/policies/app/auth/RbacClient.java +++ b/src/main/java/com/redhat/cloud/policies/app/auth/RbacClient.java @@ -1,6 +1,8 @@ package com.redhat.cloud.policies.app.auth; import com.redhat.cloud.policies.app.RbacServer; +import com.redhat.cloud.policies.app.auth.models.RbacRaw; + import io.quarkus.cache.CacheResult; import org.eclipse.microprofile.rest.client.inject.RestClient; diff --git a/src/main/java/com/redhat/cloud/policies/app/auth/RbacFilter.java b/src/main/java/com/redhat/cloud/policies/app/auth/RbacFilter.java index 014205a8..f2b00acd 100644 --- a/src/main/java/com/redhat/cloud/policies/app/auth/RbacFilter.java +++ b/src/main/java/com/redhat/cloud/policies/app/auth/RbacFilter.java @@ -34,6 +34,8 @@ import io.quarkus.logging.Log; import org.eclipse.microprofile.config.inject.ConfigProperty; +import com.redhat.cloud.policies.app.auth.models.RbacRaw; + @Provider @Priority(Priorities.HEADER_DECORATOR + 1) public class RbacFilter implements ContainerRequestFilter { diff --git a/src/main/java/com/redhat/cloud/policies/app/auth/models/Access.java b/src/main/java/com/redhat/cloud/policies/app/auth/models/Access.java new file mode 100644 index 00000000..7bff0eed --- /dev/null +++ b/src/main/java/com/redhat/cloud/policies/app/auth/models/Access.java @@ -0,0 +1,26 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed 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 com.redhat.cloud.policies.app.auth.models; + +import java.util.List; + +public class Access { + + public String permission; + public List resourceDefinitions; + +} diff --git a/src/main/java/com/redhat/cloud/policies/app/auth/RbacRaw.java b/src/main/java/com/redhat/cloud/policies/app/auth/models/RbacRaw.java similarity index 75% rename from src/main/java/com/redhat/cloud/policies/app/auth/RbacRaw.java rename to src/main/java/com/redhat/cloud/policies/app/auth/models/RbacRaw.java index a43c1684..bb87c4b1 100644 --- a/src/main/java/com/redhat/cloud/policies/app/auth/RbacRaw.java +++ b/src/main/java/com/redhat/cloud/policies/app/auth/models/RbacRaw.java @@ -14,16 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.redhat.cloud.policies.app.auth; +package com.redhat.cloud.policies.app.auth.models; import java.util.List; import java.util.Map; public class RbacRaw { + public static final String ANY = "*"; + public Map links; public Map meta; - public List> data; + public List data; public boolean canRead(String path) { return findPermission(path, "read"); @@ -34,11 +36,11 @@ public boolean canWrite(String path) { } public boolean canReadAll() { - return canRead("*"); + return canRead(ANY); } public boolean canWriteAll() { - return canWrite("*"); + return canWrite(ANY); } public boolean canDo(String path, String permission) { @@ -51,10 +53,10 @@ private boolean findPermission(String path, String what) { return false; } - for (Map permissionEntry : data) { + for (Access permissionEntry : data) { String[] fields = getPermissionFields(permissionEntry); - if (fields[1].equals(path) || fields[1].equals("*")) { - if (fields[2].equals(what) || fields[2].equals("*")) { + if (fields[1].equals(path) || fields[1].equals(ANY)) { + if (fields[2].equals(what) || fields[2].equals(ANY)) { return true; } } @@ -62,8 +64,7 @@ private boolean findPermission(String path, String what) { return false; } - private String[] getPermissionFields(Map map) { - String perms = (String) map.get("permission"); - return perms.split(":"); + private String[] getPermissionFields(Access map) { + return map.permission.split(":"); } } diff --git a/src/main/java/com/redhat/cloud/policies/app/auth/models/ResourceDefinition.java b/src/main/java/com/redhat/cloud/policies/app/auth/models/ResourceDefinition.java new file mode 100644 index 00000000..e3d74d97 --- /dev/null +++ b/src/main/java/com/redhat/cloud/policies/app/auth/models/ResourceDefinition.java @@ -0,0 +1,21 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed 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 com.redhat.cloud.policies.app.auth.models; + +public class ResourceDefinition { + public ResourceDefinitionFilter attributeFilter; +} diff --git a/src/main/java/com/redhat/cloud/policies/app/auth/models/ResourceDefinitionFilter.java b/src/main/java/com/redhat/cloud/policies/app/auth/models/ResourceDefinitionFilter.java new file mode 100644 index 00000000..5f1e5730 --- /dev/null +++ b/src/main/java/com/redhat/cloud/policies/app/auth/models/ResourceDefinitionFilter.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed 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 com.redhat.cloud.policies.app.auth.models; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; + +public class ResourceDefinitionFilter { + public String key; + public String operation; + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + public List value; +} diff --git a/src/test/java/com/redhat/cloud/policies/app/RbacParsingTest.java b/src/test/java/com/redhat/cloud/policies/app/RbacParsingTest.java index fe4bd21e..01ed15ad 100644 --- a/src/test/java/com/redhat/cloud/policies/app/RbacParsingTest.java +++ b/src/test/java/com/redhat/cloud/policies/app/RbacParsingTest.java @@ -16,27 +16,33 @@ */ package com.redhat.cloud.policies.app; -import com.redhat.cloud.policies.app.auth.RbacRaw; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import javax.json.bind.Jsonb; -import javax.json.bind.JsonbBuilder; +import java.util.List; + +import javax.inject.Inject; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.redhat.cloud.policies.app.auth.models.RbacRaw; + +import io.quarkus.test.junit.QuarkusTest; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNotNull; +@QuarkusTest class RbacParsingTest { + @Inject + ObjectMapper objectMapper; + @Test void testParseExample() throws Exception { File file = new File("src/test/resources/rbac_example.json"); - Jsonb jb = JsonbBuilder.create(); - RbacRaw rbac = jb.fromJson(new FileInputStream(file), RbacRaw.class); - assertEquals(rbac.data.size(), 2); + RbacRaw rbac = objectMapper.readValue(file, RbacRaw.class); + assertEquals(3, rbac.data.size()); assertTrue(rbac.canWrite("resname")); // We don't have explicit read permission for "resname" but we have bar:*:read. @@ -49,8 +55,7 @@ void testParseExample() throws Exception { @Test void testNoAccess() throws Exception { File file = new File("src/test/resources/rbac_example_no_access.json"); - Jsonb jb = JsonbBuilder.create(); - RbacRaw rbac = jb.fromJson(new FileInputStream(file), RbacRaw.class); + RbacRaw rbac = objectMapper.readValue(file, RbacRaw.class); assertFalse(rbac.canReadAll()); assertFalse(rbac.canWriteAll()); @@ -61,8 +66,7 @@ void testNoAccess() throws Exception { @Test void testFullAccess() throws Exception { File file = new File("src/test/resources/rbac_example_full_access.json"); - Jsonb jb = JsonbBuilder.create(); - RbacRaw rbac = jb.fromJson(new FileInputStream(file), RbacRaw.class); + RbacRaw rbac = objectMapper.readValue(file, RbacRaw.class); assertTrue(rbac.canRead("*")); assertTrue(rbac.canRead("anything")); @@ -73,14 +77,31 @@ void testFullAccess() throws Exception { } @Test - void testPartialAccess() throws FileNotFoundException { + void testPartialAccess() throws Exception { File file = new File("src/test/resources/rbac_example_partial_access.json"); - Jsonb jb = JsonbBuilder.create(); - RbacRaw rbac = jb.fromJson(new FileInputStream(file), RbacRaw.class); + RbacRaw rbac = objectMapper.readValue(file, RbacRaw.class); assertTrue(rbac.canReadAll()); assertFalse(rbac.canWriteAll()); assertTrue(rbac.canDo("*", "execute")); assertTrue(rbac.canDo("foobar", "execute")); } + + @Test + void testResourceDefinitionsParsing() throws Exception { + File file = new File("src/test/resources/rbac_example.json"); + RbacRaw rbac = objectMapper.readValue(file, RbacRaw.class); + assertEquals(3, rbac.data.size()); + + assertNotNull(rbac.data.get(0).resourceDefinitions); + assertEquals(0, rbac.data.get(0).resourceDefinitions.size()); + + assertNotNull(rbac.data.get(1).resourceDefinitions); + assertEquals(1, rbac.data.get(1).resourceDefinitions.size()); + assertEquals(List.of("123456"), rbac.data.get(1).resourceDefinitions.get(0).attributeFilter.value); + + assertNotNull(rbac.data.get(2).resourceDefinitions); + assertEquals(1, rbac.data.get(2).resourceDefinitions.size()); + assertEquals(List.of("654321"), rbac.data.get(2).resourceDefinitions.get(0).attributeFilter.value); + } } diff --git a/src/test/resources/rbac_example.json b/src/test/resources/rbac_example.json index de3a2049..41331a62 100644 --- a/src/test/resources/rbac_example.json +++ b/src/test/resources/rbac_example.json @@ -26,6 +26,18 @@ } } ] + }, + { + "permission": "foo:*:read", + "resourceDefinitions": [ + { + "attributeFilter": { + "key": "hulla.accounts", + "operation": "in", + "value": ["654321"] + } + } + ] } ] }