Skip to content

Commit 8bbe124

Browse files
authored
Improves access rule processing algorithm for performance optimization (#367)
* Initial commit Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Improves access rule processing algorithm for performance optimization Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Modifies remove Rbac rule parameter Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Fixes incorrect Javadoc Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> --------- Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]>
1 parent 938397f commit 8bbe124

File tree

14 files changed

+185
-45
lines changed

14 files changed

+185
-45
lines changed

basyx.aasenvironment/basyx.aasenvironment-feature-authorization/Readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ Note:
9090
* The Action are fixed as of now and limited to (CREATE, READ, UPDATE, DELETE, and EXECUTE) but later user configurable mapping of these actions would be provided.
9191
* For the serialization related requests there should be defined rules for accessing the AASs/Submodels/Concept Descriptions, as the serialization requires all of these elements. For e.g, a role with serialization is configured for Aas Environment target information but if there is no role for reading the AAS/Submodel/Concept Description then the request will be denied.
9292
* For the upload related requests there should be defined rules for reading, creating, and updating the AASs/Submodels/Concept Descriptions, as the upload requests performs creation, updation, and request operations on the AASs/Submodels/Concept Descriptions contained in the uploaded file, hence appropriate rules should be configured for the subject in consideration.
93+
* Each rule should be unique in combination of role + action + target information
9394

9495
## Action table for RBAC
9596

basyx.aasregistry/basyx.aasregistry-feature-authorization/Readme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ The role defines which role is allowed to perform the defined actions. The role
6363

6464
The targetInformation defines coarse-grained control over the resource, you may define the aasId with a wildcard (\*), it means the defined role x with action y can access any Asset Administration Shell Descriptors on the registry. You can also define a specific AAS Identifier in place of the wildcard (\*), then the role x with action y could be performed only on that particular AAS Descriptor.
6565

66-
Note: The Action are fixed as of now and limited to (CREATE, READ, UPDATE, DELETE, and EXECUTE) but later user configurable mapping of these actions would be provided.
66+
Note:
67+
* The Action are fixed as of now and limited to (CREATE, READ, UPDATE, DELETE, and EXECUTE) but later user configurable mapping of these actions would be provided.
68+
* Each rule should be unique in combination of role + action + target information
6769

6870
## Action table for RBAC
6971

basyx.aasrepository/basyx.aasrepository-feature-authorization/Readme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ The role defines which role is allowed to perform the defined actions. The role
6363

6464
The targetInformation defines coarse-grained control over the resource, you may define the aasIds with a wildcard (\*), it means the defined role x with action y can access any Asset Administration Shell on the repository. You can also define a specific AAS Identifier in place of the wildcard (\*), then the role x with action y could be performed only on that particular AAS. There could be a single aasId or multiple aasIds as a list (cf. basyx-deleter above).
6565

66-
Note: The Action are fixed as of now and limited to (CREATE, READ, UPDATE, DELETE, and EXECUTE) but later user configurable mapping of these actions would be provided.
66+
Note:
67+
* The Action are fixed as of now and limited to (CREATE, READ, UPDATE, DELETE, and EXECUTE) but later user configurable mapping of these actions would be provided.
68+
* Each rule should be unique in combination of role + action + target information
6769

6870
## Action table for RBAC
6971

basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/CommonRbacConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
package org.eclipse.digitaltwin.basyx.authorization.rbac;
2727

28+
import java.util.HashMap;
2829
import java.util.Objects;
2930
import java.util.Set;
3031

@@ -37,6 +38,7 @@
3738

3839
import com.fasterxml.jackson.databind.ObjectMapper;
3940
import com.fasterxml.jackson.databind.jsontype.NamedType;
41+
import com.fasterxml.jackson.databind.module.SimpleModule;
4042

4143
/**
4244
* A base configuration for Rbac based authorization
@@ -55,6 +57,10 @@ public ObjectMapper getAasMapper(Jackson2ObjectMapperBuilder builder) {
5557
Set<Class<?>> subtypes = reflections.getTypesAnnotatedWith(TargetInformationSubtype.class);
5658

5759
subtypes.stream().map(this::createNamedType).filter(Objects::nonNull).forEach(mapper::registerSubtypes);
60+
61+
SimpleModule module = new SimpleModule();
62+
module.addDeserializer(HashMap.class, new RbacRuleDeserializer());
63+
mapper.registerModule(module);
5864

5965
return mapper;
6066
}

basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/InMemoryAuthorizationRbacStorage.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,47 @@
2525

2626
package org.eclipse.digitaltwin.basyx.authorization.rbac;
2727

28-
import java.util.List;
28+
import java.util.Map;
2929

3030
/**
3131
* InMemory implementation of the {@link RbacStorage}
3232
*
3333
* @author danish
3434
*/
3535
public class InMemoryAuthorizationRbacStorage implements RbacStorage {
36-
private final List<RbacRule> rbacRules;
36+
private final Map<String, RbacRule> rbacRules;
3737

38-
public InMemoryAuthorizationRbacStorage(List<RbacRule> rbacRuleList) {
39-
this.rbacRules = rbacRuleList;
38+
public InMemoryAuthorizationRbacStorage(Map<String, RbacRule> rbacRules) {
39+
this.rbacRules = rbacRules;
4040
}
4141

42-
public List<RbacRule> getRbacRules() {
42+
public Map<String, RbacRule> getRbacRules() {
4343
return rbacRules;
4444
}
4545

4646
public void addRule(RbacRule rbacRule) {
47-
rbacRules.add(rbacRule);
47+
48+
rbacRule.getAction().stream().map(action -> RbacRuleKeyGenerator.generateKey(rbacRule.getRole(), action.toString(), rbacRule.getTargetInformation().getClass().getName())).filter(key -> !rbacRules.containsKey(key)).map(key -> rbacRules.put(key, rbacRule));
4849
}
4950

50-
public void removeRule(RbacRule rbacRule) {
51-
rbacRules.remove(rbacRule);
51+
public void removeRule(String key) {
52+
if (!exist(key))
53+
throw new RuntimeException("Rule doesn't exist in policy store");
54+
55+
rbacRules.remove(key);
5256
}
57+
58+
@Override
59+
public RbacRule getRbacRule(String key) {
60+
if (!exist(key))
61+
throw new RuntimeException("Rule doesn't exist in policy store");
62+
63+
return rbacRules.get(key);
64+
}
65+
66+
@Override
67+
public boolean exist(String key) {
68+
return rbacRules.containsKey(key);
69+
}
70+
5371
}

basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/RbacRuleConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import org.eclipse.digitaltwin.basyx.authorization.CommonAuthorizationProperties;
3535
import com.fasterxml.jackson.databind.ObjectMapper;
3636
import java.io.IOException;
37-
import java.util.ArrayList;
37+
import java.util.HashMap;
3838

3939
/**
4040
* Configurations for {@link RbacRule}
@@ -63,7 +63,7 @@ public RbacRuleConfiguration(ObjectMapper objectMapper, ResourceLoader resourceL
6363
public RbacStorage createInMemoryRbacStorage() throws IOException {
6464

6565
if (filePath.isBlank())
66-
return new InMemoryAuthorizationRbacStorage(new ArrayList<>());
66+
return new InMemoryAuthorizationRbacStorage(new HashMap<>());
6767

6868
return new InMemoryAuthorizationRbacStorage(new RbacRuleInitializer(objectMapper, filePath, resourceLoader).deserialize());
6969
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2024 the Eclipse BaSyx Authors
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*
23+
* SPDX-License-Identifier: MIT
24+
******************************************************************************/
25+
26+
package org.eclipse.digitaltwin.basyx.authorization.rbac;
27+
28+
import com.fasterxml.jackson.core.JsonParser;
29+
import com.fasterxml.jackson.core.type.TypeReference;
30+
import com.fasterxml.jackson.databind.DeserializationContext;
31+
import com.fasterxml.jackson.databind.JsonDeserializer;
32+
import com.fasterxml.jackson.databind.ObjectMapper;
33+
34+
import java.io.IOException;
35+
import java.util.HashMap;
36+
import java.util.List;
37+
38+
/**
39+
* A specific deserializer for deserializing list of {@link RbacRule} into HashMap
40+
*
41+
* @author danish
42+
*/
43+
public class RbacRuleDeserializer extends JsonDeserializer<HashMap<String, RbacRule>> {
44+
45+
@Override
46+
public HashMap<String, RbacRule> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
47+
ObjectMapper mapper = (ObjectMapper) p.getCodec();
48+
List<RbacRule> rbacRules = mapper.readValue(p, new TypeReference<List<RbacRule>>() {
49+
});
50+
HashMap<String, RbacRule> result = new HashMap<>();
51+
52+
for (RbacRule rule : rbacRules) {
53+
rule.getAction().stream().map(action -> RbacRuleKeyGenerator.generateKey(rule.getRole(), action.toString(), rule.getTargetInformation().getClass().getName())).forEach(key -> result.put(key, rule));
54+
}
55+
56+
return result;
57+
}
58+
59+
}
60+

basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/RbacRuleInitializer.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import com.fasterxml.jackson.databind.ObjectMapper;
3030
import java.io.File;
3131
import java.io.IOException;
32-
import java.util.List;
32+
import java.util.HashMap;
3333

3434
import org.eclipse.digitaltwin.basyx.core.exceptions.MissingAuthorizationConfigurationException;
3535
import org.springframework.core.io.ResourceLoader;
@@ -54,23 +54,26 @@ public RbacRuleInitializer(ObjectMapper objectMapper, String filePath, ResourceL
5454
}
5555

5656
/**
57-
* Provides the list of {@link RbacRule} from the resource
57+
* Provides the Map of {@link RbacRule} from the resource
5858
*
59-
* @return list of rbac rules
59+
* It auto-generates the key based on hash of combination of role, {@link Action}, and the concrete {@link TargetInformation}
60+
* class.
61+
*
62+
* @return map of rbac rules
6063
* @throws IOException
6164
*/
62-
public List<RbacRule> deserialize() throws IOException {
63-
return objectMapper.readValue(getFile(rbacJsonFilePath), new TypeReference<List<RbacRule>>() {
65+
public HashMap<String, RbacRule> deserialize() throws IOException {
66+
return objectMapper.readValue(getFile(rbacJsonFilePath), new TypeReference<HashMap<String, RbacRule>>() {
6467
});
6568
}
6669

6770
private File getFile(String filePath) {
68-
71+
6972
try {
7073
return resourceLoader.getResource(filePath).getFile();
71-
} catch(IOException e) {
74+
} catch (IOException e) {
7275
throw new MissingAuthorizationConfigurationException(filePath);
7376
}
74-
77+
7578
}
7679
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2024 the Eclipse BaSyx Authors
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*
23+
* SPDX-License-Identifier: MIT
24+
******************************************************************************/
25+
26+
package org.eclipse.digitaltwin.basyx.authorization.rbac;
27+
28+
/**
29+
* A helper class to generate the key based on hash of combination of role, {@link Action}, and the concrete {@link TargetInformation}
30+
* class.
31+
*
32+
* @author danish
33+
*/
34+
public class RbacRuleKeyGenerator {
35+
36+
/**
37+
* Generates the key based on hash of combination of role, {@link Action}, and the concrete {@link TargetInformation}
38+
* class.
39+
*
40+
* <p> For e.g., role = Engineer, Action = READ, TargetInformation Class = org.eclipse.digitaltwin.basyx.aasrepository.feature.authorization.AasTargetInformation.java
41+
* <br>
42+
* So the hash code of concatenation of these is: -1428731317.
43+
*
44+
* </p>
45+
*
46+
* @param role
47+
* @param action
48+
* @param clazz
49+
* @return
50+
*/
51+
public static String generateKey(String role, String action, String clazz) {
52+
return String.valueOf((role + action + clazz).hashCode());
53+
}
54+
55+
}

basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/RbacStorage.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,18 @@
2525

2626
package org.eclipse.digitaltwin.basyx.authorization.rbac;
2727

28-
import java.util.List;
28+
import java.util.Map;
2929

3030
/**
31-
* An interface for definig storage of {@link RbacRule}
31+
* An interface for defining storage of {@link RbacRule}
3232
*
3333
* @author danish
3434
*/
3535
public interface RbacStorage {
3636

37-
public List<RbacRule> getRbacRules();
37+
public Map<String, RbacRule> getRbacRules();
38+
public RbacRule getRbacRule(String key);
3839
public void addRule(RbacRule rbacRule);
39-
public void removeRule(RbacRule rbacRule);
40+
public void removeRule(String key);
41+
public boolean exist(String key);
4042
}

0 commit comments

Comments
 (0)