Skip to content

Commit

Permalink
Check improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
BogdanIrimie authored Jan 4, 2024
2 parents dea3316 + 5dc0d13 commit 36fc6f7
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,35 @@
@RestController
public class GenericController {
@DeleteMapping("/todos/{id}")
@PreAuthorize("@aserto.check('group', 'admin', 'member')")
// @PreAuthorize("@check.objectType('group').objectId(new com.aserto.example.mapper.PathObjectIdMapper().fromAttribute('id')).relation('member').allowed()") // we use a custom mapper that extracts the id from the path params
// @PreAuthorize("@check.objectType('group').objectId(@objIdMapper.fromAttribute('id')).relation('member').allowed()") // we use a custom mapper that extracts the id from the path params
// @PreAuthorize("@check.objectType('group').objectId(#id).relation('member').allowed()") // objectId is set to the id variable
// @PreAuthorize("@check.objectId(#id).relation('member').allowed()") // this should throw an exception as no objectType is set
@PreAuthorize("@check.objectType('group').objectId('admin').relation('member').allowed()") // static objectId
public String deleteTodo(@PathVariable String id) {
return "Hello from route DELETE /todos/{" + id + "}";
}

@GetMapping("/todos")
@PreAuthorize("@aserto.check('group', 'viewer', 'member')")
@PreAuthorize("@check.objectType('group').objectId('viewer').relation('member').allowed()")
public String getTodo() {
return "Hello from route GET /todos";
}

@GetMapping("/users/{userID}")
@PreAuthorize("@aserto.check('group', 'viewer', 'member')")
@PreAuthorize("@check.objectType('group').objectId('viewer').relation('member').allowed()")
public String getUsers(@PathVariable String userID) {
return "Hello from route GET /users/{" + userID + "}";
}

@PostMapping("/todos")
@PreAuthorize("@aserto.check('group', 'editor', 'member')")
@PreAuthorize("@check.objectType('group').objectId('editor').relation('member').allowed()")
public String postTodo() {
return "Hello from route POST /todos";
}

@PutMapping("/todos/{id}")
@PreAuthorize("@aserto.check('group', 'editor', 'member')")
@PreAuthorize("@check.objectType('group').objectId('editor').relation('member').allowed()")
public String putTodo(@PathVariable String id) {
return "Hello from route PUT /todos/{" + id + "}";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.aserto.example.mapper;

import com.aserto.authroizer.mapper.check.object.ObjectIdMapper;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerMapping;

import java.util.Map;


@Component("objIdMapper")
public class PathObjectIdMapper implements ObjectIdMapper {
private String attributeName;

public PathObjectIdMapper fromAttribute(String attributeName) {
this.attributeName = attributeName;
return this;
}

@Override
public String getValue(HttpServletRequest httpRequest) {
Map<String, String> pathAttributes = (Map<String, String>)httpRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
return pathAttributes.get(attributeName);
}
}
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>com.aserto</groupId>
<artifactId>aserto-spring</artifactId>
<version>0.0.12</version>
<version>0.1.0</version>

<name>spring-middleware</name>
<description>Spring Security Filter that enables Aserto authorization</description>
Expand Down Expand Up @@ -64,20 +64,20 @@
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.37</version>
<version>9.37.3</version>
</dependency>

<!-- use to convert json to proto -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.24.4</version>
<version>3.25.1</version>
</dependency>

<dependency>
<groupId>com.aserto</groupId>
<artifactId>aserto-java</artifactId>
<version>0.20.9</version>
<version>0.21.1</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ public final class AsertoAuthorizationManager implements AuthorizationManager<Re
private String policyName;
private String policyLabel;
boolean authorizerEnabled;
private IdentityMapper identityMapper;
private IdentityMapper configIdentityMapper;
private PolicyMapper configPolicyMapper;
private ResourceMapper configResourceMapper;
private AuthorizerClient authzClient;

public AsertoAuthorizationManager(AuthzConfig authzConfig) {
this.identityMapper = authzConfig.getIdentityMapper();
this.configIdentityMapper = authzConfig.getIdentityMapper();
this.configPolicyMapper = authzConfig.getPolicyMapper();
this.configResourceMapper = authzConfig.getResourceMapper();
this.authzClient = authzConfig.getAuthzClient();
Expand Down Expand Up @@ -80,6 +80,19 @@ public AuthorizationDecision check(HttpServletRequest httpRequest) {
* @return true if the user is authorized, false otherwise
*/
public AuthorizationDecision check(HttpServletRequest httpRequest, PolicyMapper policyMapper, ResourceMapper resourceMapper) {
return this.check(httpRequest, configIdentityMapper, policyMapper, resourceMapper);
}

/*
* Check if the current user is authorized to perform the action defined in the policy.
*
* @param httpRequest The http request
* @param identityMapper The identity mapper
* @param policyMapper The policy mapper
* @param resourceMapper The resource mapper
* @return true if the user is authorized, false otherwise
*/
public AuthorizationDecision check(HttpServletRequest httpRequest, IdentityMapper identityMapper, PolicyMapper policyMapper, ResourceMapper resourceMapper) {
if (!authorizerEnabled) {
return new AuthorizationDecision(true);
}
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/com/aserto/authroizer/CheckConfig.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.aserto.authroizer;

import com.aserto.authroizer.mapper.object.ObjectIdMapper;
import com.aserto.authroizer.mapper.object.ObjectTypeMapper;
import com.aserto.authroizer.mapper.object.StaticObjectIdMapper;
import com.aserto.authroizer.mapper.object.StaticObjectTypeMapper;
import com.aserto.authroizer.mapper.relation.RelationMapper;
import com.aserto.authroizer.mapper.check.object.ObjectIdMapper;
import com.aserto.authroizer.mapper.check.object.ObjectTypeMapper;
import com.aserto.authroizer.mapper.check.object.StaticObjectIdMapper;
import com.aserto.authroizer.mapper.check.object.StaticObjectTypeMapper;
import com.aserto.authroizer.mapper.check.relation.RelationMapper;
import com.aserto.authroizer.mapper.policy.StaticPolicyMapper;
import com.aserto.authroizer.mapper.relation.StaticRelationMapper;
import com.aserto.authroizer.mapper.check.relation.StaticRelationMapper;
import com.aserto.authroizer.mapper.resource.CheckResourceMapper;

public class CheckConfig {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/aserto/authroizer/DefaultMappers.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.aserto.authroizer;

import com.aserto.AuthorizerClient;
import com.aserto.AuthzClient;
import com.aserto.authorizer.AuthzClient;
import com.aserto.ChannelBuilder;
import com.aserto.authroizer.config.loader.spring.AuhorizerLoader;
import com.aserto.authroizer.mapper.identity.IdentityMapper;
Expand Down
122 changes: 85 additions & 37 deletions src/main/java/com/aserto/authroizer/MethodAuthorization.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package com.aserto.authroizer;

import com.aserto.authroizer.mapper.object.ObjectIdMapper;
import com.aserto.authroizer.mapper.object.ObjectTypeMapper;
import com.aserto.authroizer.mapper.relation.RelationMapper;
import com.aserto.authroizer.mapper.check.subject.StaticSubjectIdMapper;
import com.aserto.authroizer.mapper.check.subject.StaticSubjectTypeMapper;
import com.aserto.authroizer.mapper.check.subject.SubjectIdMapper;
import com.aserto.authroizer.mapper.check.subject.SubjectTypeMapper;
import com.aserto.authroizer.mapper.identity.ManualIdentityMapper;
import com.aserto.authroizer.mapper.check.object.ObjectIdMapper;
import com.aserto.authroizer.mapper.check.object.ObjectTypeMapper;
import com.aserto.authroizer.mapper.check.object.StaticObjectIdMapper;
import com.aserto.authroizer.mapper.check.object.StaticObjectTypeMapper;
import com.aserto.authroizer.mapper.check.relation.RelationMapper;
import com.aserto.authroizer.mapper.policy.StaticPolicyMapper;
import com.aserto.authroizer.mapper.check.relation.StaticRelationMapper;
import com.aserto.authroizer.mapper.resource.CheckResourceMapper;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.authorization.AuthorizationDecision;
Expand All @@ -13,57 +21,97 @@
* This class provides methods to check if the current user is authorized to perform an action.
* It can be used for method level authorization.
*/
@Component("aserto")
@Component("check")
class MethodAuthorization {
private AsertoAuthorizationManager asertoAuthzManager;
private HttpServletRequest httpRequest;
private ObjectTypeMapper objectTypeMapper;
private ObjectIdMapper objectIdMapper;
private RelationMapper relationMapper;
private SubjectTypeMapper subjectTypeMapper;
private SubjectIdMapper subjectIdMapper;

public MethodAuthorization(AuthzConfig authzCfg, HttpServletRequest httpRequest) {
asertoAuthzManager = new AsertoAuthorizationManager(authzCfg);
this.httpRequest = httpRequest;
}

public MethodAuthorization objectType(String objectType) {
objectTypeMapper = new StaticObjectTypeMapper(objectType);
return this;
}

/*
* Check if the current user is authorized to perform the action defined in the policy.
* @return true if the user is authorized, false otherwise
*/
public boolean check() {
AuthorizationDecision decision = asertoAuthzManager.check(httpRequest);
return decision.isGranted();
public MethodAuthorization objectType(ObjectTypeMapper objectTypeMapper) {
this.objectTypeMapper = objectTypeMapper;
return this;
}

/*
* Check if the current user has a relation to the object defined by ObjectType, ObjectId and Relation.
* If the relation exists, the user is authorized.
*
* @param objectType The type of the object
* @param objectId The id of the object
* @param relation The relation to check
* @return true if the user is authorized, false otherwise
*/
public boolean check(String objectType, String objectId, String relation) {
StaticPolicyMapper policyMapper = new StaticPolicyMapper("rebac.check");
CheckResourceMapper checkResourceMapper = new CheckResourceMapper(objectType, objectId, relation);
public MethodAuthorization objectId(String objectId) {
objectIdMapper = new StaticObjectIdMapper(objectId);
return this;
}

AuthorizationDecision decision = asertoAuthzManager.check(httpRequest, policyMapper, checkResourceMapper);
return decision.isGranted();
public MethodAuthorization objectId(ObjectIdMapper objectId) {
this.objectIdMapper = objectId;
return this;
}

public MethodAuthorization relation(String relation) {
relationMapper = new StaticRelationMapper(relation);
return this;
}

public MethodAuthorization relation(RelationMapper relation) {
this.relationMapper = relation;
return this;
}

public MethodAuthorization subjectType(String subjectType) {
subjectTypeMapper = new StaticSubjectTypeMapper(subjectType);
return this;
}

/*
* Check if the current user has a relation to the object defined by objectTypeMapper, ObjectIdMapper and RelationMapper.
* If the relation exists, the user is authorized.
*
* @param objectTypeMapper The mapper for the type of the object
* @param objectIdMapper The mapper for the id of the object
* @param relationMapper The mapper for the relation to check
* @return true if the user is authorized, false otherwise
*/
public boolean check(ObjectTypeMapper objectTypeMapper, ObjectIdMapper objectIdMapper, RelationMapper relationMapper) {
public MethodAuthorization subjectType(SubjectTypeMapper subjectTypeMapper) {
this.subjectTypeMapper = subjectTypeMapper;
return this;
}

public MethodAuthorization subjectId(String subjectId) {
subjectIdMapper = new StaticSubjectIdMapper(subjectId);
return this;
}

public MethodAuthorization subjectId(SubjectIdMapper subjectIdMapper) {
this.subjectIdMapper = subjectIdMapper;
return this;
}

public boolean allowed() {
validateFields();

StaticPolicyMapper policyMapper = new StaticPolicyMapper("rebac.check");
CheckResourceMapper checkResourceMapper = new CheckResourceMapper(objectTypeMapper, objectIdMapper, relationMapper);
CheckResourceMapper checkResourceMapper = new CheckResourceMapper(objectTypeMapper, objectIdMapper, relationMapper, subjectTypeMapper);

AuthorizationDecision decision;
if (subjectIdMapper != null && subjectTypeMapper != null) {
ManualIdentityMapper identityMapper = new ManualIdentityMapper(subjectIdMapper.getValue(httpRequest));
decision = asertoAuthzManager.check(httpRequest, identityMapper, policyMapper, checkResourceMapper);
} else {
decision = asertoAuthzManager.check(httpRequest, policyMapper, checkResourceMapper);
}

AuthorizationDecision decision = asertoAuthzManager.check(httpRequest, policyMapper, checkResourceMapper);
return decision.isGranted();
}

private void validateFields() {
if (objectTypeMapper == null) {
throw new IllegalArgumentException("objectType must be set");
}
if (objectIdMapper == null) {
throw new IllegalArgumentException("objectId must be set");
}
if (relationMapper == null) {
throw new IllegalArgumentException("relation must be set");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.aserto.authroizer.mapper.object;
package com.aserto.authroizer.mapper.check.object;

import jakarta.servlet.http.HttpServletRequest;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.aserto.authroizer.mapper.object;
package com.aserto.authroizer.mapper.check.object;

import jakarta.servlet.http.HttpServletRequest;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.aserto.authroizer.mapper.object;
package com.aserto.authroizer.mapper.check.object;

import jakarta.servlet.http.HttpServletRequest;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.aserto.authroizer.mapper.object;
package com.aserto.authroizer.mapper.check.object;

import jakarta.servlet.http.HttpServletRequest;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.aserto.authroizer.mapper.relation;
package com.aserto.authroizer.mapper.check.relation;

import jakarta.servlet.http.HttpServletRequest;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.aserto.authroizer.mapper.relation;
package com.aserto.authroizer.mapper.check.relation;

import jakarta.servlet.http.HttpServletRequest;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.aserto.authroizer.mapper.check.subject;

import jakarta.servlet.http.HttpServletRequest;

public class StaticSubjectIdMapper implements SubjectIdMapper {
private String subjectId;

public StaticSubjectIdMapper(String subjectId) {
this.subjectId = subjectId;
}

@Override
public String getValue(HttpServletRequest httpRequest) {
return subjectId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.aserto.authroizer.mapper.check.subject;

import jakarta.servlet.http.HttpServletRequest;

public class StaticSubjectTypeMapper implements SubjectTypeMapper {
private String subjectType;

public StaticSubjectTypeMapper(String subjectType) {
this.subjectType = subjectType;
}

@Override
public String getValue(HttpServletRequest httpRequest) {
return subjectType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.aserto.authroizer.mapper.check.subject;

import jakarta.servlet.http.HttpServletRequest;

public interface SubjectIdMapper {
public String getValue(HttpServletRequest httpRequest);
}
Loading

0 comments on commit 36fc6f7

Please sign in to comment.