Skip to content

Commit

Permalink
add ALL option for authz policy enforcement; add test category
Browse files Browse the repository at this point in the history
  • Loading branch information
mmoayyed committed Sep 20, 2024
1 parent 8c43102 commit 5c0b6a1
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions gradle/tests.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum TestCategories {
AuthenticationPolicy(true, true),
AuthenticationMetadata(true, true),
AuthenticationThrottling(false, true),
Authorization(true, true),
Azure(false, true),
CAS(true, true),
CasConfiguration(true, true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.apereo.cas.heimdall.AuthorizationRequest;
import org.apereo.cas.heimdall.authorizer.resource.AuthorizableResource;
import lombok.val;

/**
* This is {@link DefaultResourceAuthorizer}.
Expand All @@ -12,11 +13,22 @@
public class DefaultResourceAuthorizer implements ResourceAuthorizer {
@Override
public AuthorizationResult evaluate(final AuthorizationRequest request, final AuthorizableResource resource) {
if (resource.getPolicies().parallelStream()
val authorized = resource.isEnforceAllPolicies() ? enforceAllPolicies(request, resource) : enforceAnyPolicy(request, resource);
return authorized ? AuthorizationResult.granted("OK") : AuthorizationResult.denied("Denied");
}

protected boolean enforceAnyPolicy(final AuthorizationRequest request, final AuthorizableResource resource) {
return resource.getPolicies()
.parallelStream()
.map(policy -> policy.evaluate(resource, request))
.allMatch(AuthorizationResult::authorized);
}

protected boolean enforceAllPolicies(final AuthorizationRequest request,
final AuthorizableResource resource) {
return resource.getPolicies()
.parallelStream()
.map(policy -> policy.evaluate(resource, request))
.anyMatch(AuthorizationResult::authorized)) {
return AuthorizationResult.granted("OK");
}
return AuthorizationResult.denied("Denied");
.allMatch(AuthorizationResult::authorized);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.val;
import org.apache.commons.io.FileUtils;
import org.hjson.JsonValue;
import org.springframework.util.Assert;
import java.io.File;
import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -69,8 +72,11 @@ private void loadJsonResources() throws Exception {

private void loadJsonResourceFrom(final File jsonFile) {
FunctionUtils.doAndHandle(__ -> {
val loadedResource = MAPPER.readValue(jsonFile, AuthorizableResources.class);
resources.put(loadedResource.getNamespace(), loadedResource.getResources());
try (val reader = new FileReader(jsonFile, StandardCharsets.UTF_8)) {
val json = JsonValue.readHjson(reader).toString();
val loadedResource = MAPPER.readValue(json, AuthorizableResources.class);
resources.put(loadedResource.getNamespace(), loadedResource.getResources());
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ public class AuthorizableResource implements Serializable {
private List<ResourceAuthorizationPolicy> policies = new ArrayList<>();

private Map<String, Object> properties = new HashMap<>();

private boolean enforceAllPolicies;
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@ void verifyOkayOperation() throws Throwable {
).andExpect(status().isOk());
}

@Test
void verifyAllPoliciesForcedOperation() throws Throwable {
val principal = RegisteredServiceTestUtils.getPrincipal(UUID.randomUUID().toString(),
Map.of("color", List.of("red", "green"), "memberOf", List.of("admin")));
val authentication = RegisteredServiceTestUtils.getAuthentication(principal);
val accessToken = buildAccessToken(authentication);
ticketRegistry.addTicket(accessToken);

mockMvc.perform(post("/heimdall/authorize")
.contentType(MediaType.APPLICATION_JSON)
.content(AuthorizationRequest.builder()
.uri("/api/all")
.method("POST")
.namespace("API_ALL")
.build()
.toJson()
)
.header(HttpHeaders.AUTHORIZATION, "Bearer %s".formatted(accessToken.getId()))
.accept(MediaType.APPLICATION_JSON)
).andExpect(status().isForbidden());
}

@Test
void verifyScopesOperation() throws Throwable {
val accessToken = buildAccessToken();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"@class": "org.apereo.cas.heimdall.authorizer.resource.AuthorizableResources",
"resources": [
"java.util.ArrayList",
[
{
"@class": "org.apereo.cas.heimdall.authorizer.resource.AuthorizableResource",
"enforceAllPolicies": true,
"pattern": "/api/all",
"method": "POST",
"policies": [ "java.util.ArrayList", [
{
"@class": "org.apereo.cas.heimdall.authorizer.resource.policy.RequiredAttributesAuthorizationPolicy",
"attributes" : {
"@class" : "java.util.HashMap",
"memberOf" : [ "java.util.HashSet", [ ".*admin.*" ] ]
}
},
{
"@class": "org.apereo.cas.heimdall.authorizer.resource.policy.RequiredScopesAuthorizationPolicy",
"scopes" : [ "java.util.HashSet", [ "unknown-scope" ] ]
}
]]
}
]
],
"namespace": "API_ALL",
}
3 changes: 3 additions & 0 deletions testcas.sh
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ while (( "$#" )); do
authnpolicy|authpolicy|authenticationpolicy)
task+="testAuthenticationPolicy "
;;
authz|heimdall|authorization)
task+="testAuthorization "
;;
auth|authn|authentication)
task+="testAuthentication "
;;
Expand Down

0 comments on commit 5c0b6a1

Please sign in to comment.