Skip to content

Commit a0c4fe0

Browse files
committed
WIP for policies
1 parent 433209f commit a0c4fe0

4 files changed

Lines changed: 126 additions & 15 deletions

File tree

server/src/main/java/access/api/ManageController.java

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import access.exception.InvalidInputException;
44
import access.exception.UserRestrictionException;
55
import access.manage.*;
6-
import access.model.*;
6+
import access.model.EntityType;
7+
import access.model.Environment;
8+
import access.model.Institution;
9+
import access.model.User;
710
import access.security.InstitutionAdmin;
811
import com.fasterxml.jackson.core.type.TypeReference;
912
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -31,19 +34,21 @@
3134

3235
@RestController
3336
@RequestMapping(value = {"/api/v1/manage"}, produces = MediaType.APPLICATION_JSON_VALUE)
34-
public class ManageController implements UserAccessRights{
37+
public class ManageController implements UserAccessRights, PolicyAccessRights {
3538

3639
private static final Log LOG = LogFactory.getLog(ManageController.class);
3740

3841
private final MetaDataFeedParser metaDataFeedParser = new MetaDataFeedParser();
3942
private final Manage manage;
43+
private final ObjectMapper objectMapper;
4044
private final Map<String, Object> arpInfo;
4145
private final List<Map<String, Object>> privacyInfo;
4246

4347
@SneakyThrows
4448
public ManageController(Manage manage,
4549
ObjectMapper objectMapper) {
4650
this.manage = manage;
51+
this.objectMapper = objectMapper;
4752
this.arpInfo = objectMapper.readValue(new ClassPathResource("/metadata/ARP.json").getInputStream(), new TypeReference<>() {
4853
});
4954
this.privacyInfo = objectMapper.readValue(new ClassPathResource("/metadata/Privacy.json").getInputStream(), new TypeReference<>() {
@@ -97,24 +102,33 @@ public ResponseEntity<List<Map<String, Object>>> policies(User user,
97102
@RequestParam("entityId") String entityId) {
98103
confirmInstitutionAdmin(user);
99104
//we need to ensure the application is connected to the IdP of the user - realtime
100-
OidcUser oidcUser = (OidcUser) authentication.getPrincipal();
101-
Map<String, Object> claims = oidcUser.getUserInfo().getClaims();
102-
Institution institution = (Institution) claims.get(InstitutionAdmin.INSTITUTION);
103-
//We can't use any cache as this method is called right after automatic connection allowed
104-
Map<String, Object> identityProvider = manage.providerById(EntityType.saml20_idp, institution.getManageIdentifier(), Environment.PROD);
105-
Map<String, Object> data = getData(identityProvider);
106-
boolean noneMatch = ((List<Map<String, String>>) data.getOrDefault("allowedEntities", List.of()))
107-
.stream()
108-
.noneMatch(allowedEntity -> allowedEntity.get("name").equals(entityId));
105+
if (!user.isSuperUser()) {
106+
Map<String, Object> data = getIdentityProvider(authentication);
107+
boolean noneMatch = ((List<Map<String, String>>) data.getOrDefault("allowedEntities", List.of()))
108+
.stream()
109+
.noneMatch(allowedEntity -> allowedEntity.get("name").equals(entityId));
109110

110-
if (noneMatch) {
111-
throw new UserRestrictionException(String.format("User %s is not allowed to request policies for %s",
112-
user.getEmail(), entityId));
111+
if (noneMatch) {
112+
throw new UserRestrictionException(String.format("User %s is not allowed to request policies for %s",
113+
user.getEmail(), entityId));
114+
}
113115
}
114-
List<Map<String, Object>> policies = this.manage.policiesByServiceProvider(institution.getEntityID(), entityId);
116+
List<Map<String, Object>> policies = this.manage
117+
.policiesByServiceProvider(user.getAuthenticatingAuthority(), entityId);
115118
return ResponseEntity.ok(policies);
116119
}
117120

121+
@SneakyThrows
122+
@PostMapping("/policies")
123+
public ResponseEntity<Map<String, Object>> createPolicy(User user,
124+
@RequestBody Map<String, Object> policy) {
125+
confirmInstitutionAdmin(user);
126+
//We don't want to use PolicyDefinition as @RequestBody, because the template from Manage is leading
127+
PolicyDefinition policyDefinition = this.objectMapper.convertValue(policy, PolicyDefinition.class);
128+
confirmPolicyAccess(user, policyDefinition, manage);
129+
return ResponseEntity.ok(policy);
130+
}
131+
118132
@SneakyThrows
119133
@PostMapping("/unique-entity-id/{environment}")
120134
public ResponseEntity<List<Map<String, Object>>> providersByEntityId(@PathVariable("environment") Environment environment,
@@ -131,4 +145,16 @@ public ResponseEntity<Map<String, Object>> rejectChangeRequest(@RequestBody Chan
131145
manage.rejectChangeRequest(Environment.PROD, changeRequest);
132146
return Results.okResult();
133147
}
148+
149+
private Map<String, Object> getIdentityProvider(Authentication authentication) {
150+
OidcUser oidcUser = (OidcUser) authentication.getPrincipal();
151+
Map<String, Object> claims = oidcUser.getUserInfo().getClaims();
152+
Institution institution = (Institution) claims.get(InstitutionAdmin.INSTITUTION);
153+
//We can't use any cache as this method is called right after automatic connection allowed
154+
Map<String, Object> identityProvider = manage.providerById(EntityType.saml20_idp, institution.getManageIdentifier(), Environment.PROD);
155+
Map<String, Object> data = getData(identityProvider);
156+
return data;
157+
}
158+
159+
134160
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package access.manage;
2+
3+
import access.model.User;
4+
5+
import java.util.Map;
6+
7+
public interface PolicyAccessRights {
8+
9+
default void confirmPolicyAccess(User user, PolicyDefinition policyDefinition, Manage manage) {
10+
if (user.isSuperUser()) {
11+
return;
12+
}
13+
//Is the IdP of the Policy the same as the IdP of the User?
14+
15+
//No IdP, all SP's must be owned by the IdP of the user (=organizationGUID of the instituitonAdmin)
16+
}
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package access.manage;
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
import lombok.Setter;
8+
9+
@NoArgsConstructor
10+
@Getter
11+
@Setter
12+
@AllArgsConstructor
13+
@JsonIgnoreProperties(ignoreUnknown = true)
14+
public class PolicyAttribute {
15+
16+
private String name;
17+
18+
private String value;
19+
20+
private boolean negated;
21+
22+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package access.manage;
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
import lombok.Setter;
8+
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
@NoArgsConstructor
14+
@Getter
15+
@Setter
16+
@AllArgsConstructor
17+
@JsonIgnoreProperties(ignoreUnknown = true)
18+
public class PolicyDefinition {
19+
20+
private boolean active;
21+
22+
private boolean allAttributesMustMatch;
23+
24+
private List<PolicyAttribute> attributes = new ArrayList<>();
25+
26+
private String denyAdvice;
27+
28+
private String denyAdviceNl;
29+
30+
private boolean denyRule;
31+
32+
private String description;
33+
34+
private String entityid;
35+
36+
private List<String> identityProviderIds;
37+
38+
private Map<String, String> metaDataFields;
39+
40+
private String name;
41+
42+
private List<String> serviceProviderIds;
43+
44+
private String type;
45+
46+
}

0 commit comments

Comments
 (0)