Skip to content

Commit cd2fa1a

Browse files
committed
WIP for #453
1 parent 6c75e4c commit cd2fa1a

File tree

7 files changed

+147
-9
lines changed

7 files changed

+147
-9
lines changed

client/src/utils/Policy.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export const policyTemplate = {
2+
"active": true,
3+
"allAttributesMustMatch": false,
4+
"attributes": [],
5+
"denyAdvice": "",
6+
"denyAdviceNl": "",
7+
"denyRule": false,
8+
"description": "",
9+
"entityid": "",
10+
"identityProviderIds": [],
11+
"metaDataFields": {},
12+
"name": "",
13+
"serviceProviderIds": [],
14+
"type": "reg"
15+
}

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,11 @@ public ResponseEntity<List<Map<String, Object>>> policies(User user,
103103
//We can't use any cache as this method is called right after automatic connection allowed
104104
Map<String, Object> identityProvider = manage.providerById(EntityType.saml20_idp, institution.getManageIdentifier(), Environment.PROD);
105105
Map<String, Object> data = getData(identityProvider);
106-
List<String> allowedEntities = ((List<Map<String, String>>) data.getOrDefault("allowedEntities", List.of()))
106+
boolean noneMatch = ((List<Map<String, String>>) data.getOrDefault("allowedEntities", List.of()))
107107
.stream()
108-
.map(allowedEntity -> allowedEntity.get("name"))
109-
.toList();
108+
.noneMatch(allowedEntity -> allowedEntity.get("name").equals(entityId));
110109

111-
if (!allowedEntities.contains(entityId)) {
110+
if (noneMatch) {
112111
throw new UserRestrictionException(String.format("User %s is not allowed to request policies for %s",
113112
user.getEmail(), entityId));
114113
}

server/src/main/java/access/manage/LocalManage.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import lombok.SneakyThrows;
88
import org.apache.commons.logging.Log;
99
import org.apache.commons.logging.LogFactory;
10+
import org.springframework.core.io.ClassPathResource;
1011
import org.springframework.core.io.DefaultResourceLoader;
1112
import org.springframework.core.io.Resource;
1213
import org.springframework.util.StringUtils;
@@ -28,6 +29,7 @@ public final class LocalManage implements Manage {
2829
private final DefaultResourceLoader defaultResourceLoader = new DefaultResourceLoader();
2930
private final ConnectionProviderConverter converter;
3031
private final ObjectMapper objectMapper;
32+
private final Map<String, Map<String, Object>> policies = new HashMap<>();
3133

3234
public LocalManage(ConnectionProviderConverter converter, ObjectMapper objectMapper, String staticManageDirectory) {
3335
this.converter = converter;
@@ -262,6 +264,32 @@ public List<Map<String, Object>> policiesByServiceProvider(String identityProvid
262264
.toList();
263265
}
264266

267+
@Override
268+
public Map<String, Object> createPolicy(Map<String, Object> policy) {
269+
String id = UUID.randomUUID().toString();
270+
policy.put("id", id);
271+
policies.put(id, policy);
272+
return policy;
273+
}
274+
275+
@Override
276+
public Map<String, Object> updatePolicy(Map<String, Object> policy) {
277+
policies.put((String) policy.get("id"), policy);
278+
return policy;
279+
}
280+
281+
@SneakyThrows
282+
@Override
283+
public List<Map<String, String>> allowedAttributes() {
284+
return objectMapper.readValue(new ClassPathResource("/manage/allowed_attributes.json").getInputStream(), new TypeReference<>() {
285+
});
286+
}
287+
288+
@Override
289+
public void deletePolicy(Map<String, Object> policy) {
290+
policies.remove((String) policy.get("id"));
291+
}
292+
265293
@Override
266294
public void connectWithoutInteraction(Map<String, Object> identityProvider, Map<String, Object> serviceProvider, User currentUser) {
267295
//nope

server/src/main/java/access/manage/Manage.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ public interface Manage {
4949
List<Map<String, Object>> policiesByServiceProvider(String identityProviderEntityId,
5050
String serviceProviderEntityId);
5151

52+
Map<String, Object> createPolicy(Map<String, Object> policy);
53+
54+
Map<String, Object> updatePolicy(Map<String, Object> policy);
55+
56+
List<Map<String, String>> allowedAttributes();
57+
58+
void deletePolicy(Map<String, Object> policy);
59+
5260
void connectWithoutInteraction(Map<String, Object> identityProvider, Map<String, Object> serviceProvider, User currentUser);
5361

5462
default Map<String, Object> sanitizeProvider(Map<String, Object> provider) {

server/src/main/java/access/manage/RemoteManage.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,38 @@ public List<Map<String, Object>> policiesByServiceProvider(String identityProvid
363363
return restTemplate.postForEntity(url, query, List.class).getBody();
364364
}
365365

366+
@Override
367+
public Map<String, Object> createPolicy(Map<String, Object> policy) {
368+
RestTemplate restTemplate = environmentRestTemplate(Environment.PROD);
369+
String url = String.format("%s/manage/api/internal/internal/metadata",
370+
environmentUrl(Environment.PROD));
371+
return restTemplate.postForEntity(url, policy, Map.class).getBody();
372+
}
373+
374+
@Override
375+
public Map<String, Object> updatePolicy(Map<String, Object> policy) {
376+
RestTemplate restTemplate = environmentRestTemplate(Environment.PROD);
377+
String url = String.format("%s/manage/api/internal/internal/metadata",
378+
environmentUrl(Environment.PROD));
379+
return restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(policy), Map.class).getBody();
380+
}
381+
382+
@Override
383+
public List<Map<String, String>> allowedAttributes() {
384+
RestTemplate restTemplate = environmentRestTemplate(Environment.PROD);
385+
String url = String.format("%s/manage/api/internal/protected/allowed-attributes",
386+
environmentUrl(Environment.PROD));
387+
return restTemplate.getForObject(url, List.class);
388+
}
389+
390+
@Override
391+
public void deletePolicy(Map<String, Object> policy) {
392+
RestTemplate restTemplate = environmentRestTemplate(Environment.PROD);
393+
String url = String.format("%s/manage/api/internal/internal/metadata/%s/%s",
394+
environmentUrl(Environment.PROD), EntityType.policy.name(), policy.get("id"));
395+
restTemplate.delete(url);
396+
}
397+
366398
@Override
367399
public void connectWithoutInteraction(Map<String, Object> identityProvider, Map<String, Object> serviceProvider, User user) {
368400
RestTemplate restTemplate = environmentRestTemplate(Environment.PROD);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
[
2+
{
3+
"value": "urn:mace:terena.org:attribute-def:schacHomeOrganization",
4+
"validationRegex": "^[a-z]+(\\.[a-z]+)+$",
5+
"allowedInDenyRule": true,
6+
"label": "Schac home organization"
7+
},
8+
{
9+
"value": "urn:mace:terena.org:attribute-def:schacHomeOrganizationType",
10+
"validationRegex": "^[a-z]+$",
11+
"allowedInDenyRule": true,
12+
"label": "Schac home organization type"
13+
},
14+
{
15+
"value": "urn:mace:dir:attribute-def:eduPersonAffiliation",
16+
"validationRegex": "^(student|staff|faculty|employee|member)$",
17+
"allowedInDenyRule": true,
18+
"label": "Edu person affiliation"
19+
},
20+
{
21+
"value": "urn:mace:dir:attribute-def:eduPersonScopedAffiliation",
22+
"validationRegex": "^(student|staff|faculty|employee|member)@[a-z]+(\\.[a-z]+)+$",
23+
"allowedInDenyRule": true,
24+
"label": "Edu person scoped affiliation"
25+
},
26+
{
27+
"value": "urn:mace:dir:attribute-def:eduPersonEntitlement",
28+
"validationRegex": "^[a-z]+$",
29+
"allowedInDenyRule": true,
30+
"label": "Edu person entitlement"
31+
},
32+
{
33+
"value": "urn:mace:dir:attribute-def:isMemberOf",
34+
"validationRegex": "^.*$",
35+
"allowedInDenyRule": true,
36+
"label": "Is-member-of"
37+
},
38+
{
39+
"value": "urn:collab:group:surfteams.nl",
40+
"validationRegex": "^(urn:mace:surf\\.nl:invite:|urn:collab:group:)[a-z0-9_]+$",
41+
"allowedInDenyRule": false,
42+
"label": "SURFconext Invite (voot) role urn"
43+
},
44+
{
45+
"value": "urn:collab:sab:surfnet.nl",
46+
"validationRegex": "^(Superuser|Instellingsbevoegde|OperationeelBeheerder|SURFconextbeheerder|DNS-Beheerder)$",
47+
"allowedInDenyRule": false,
48+
"label": "SAB role"
49+
},
50+
{
51+
"value": "urn:mace:dir:attribute-def:mail",
52+
"validationRegex": "^[^@]+@[^@]+\\.[^@]+$",
53+
"allowedInDenyRule": true,
54+
"label": "Mail address"
55+
}
56+
]

server/src/test/java/access/api/ManageControllerTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,15 @@
44
import access.AccessCookieFilter;
55
import access.model.EntityType;
66
import access.model.Environment;
7-
import access.model.Institution;
87
import access.security.InstitutionAdmin;
98
import com.nimbusds.jose.util.IOUtils;
109
import io.restassured.common.mapper.TypeRef;
1110
import io.restassured.http.ContentType;
12-
import io.restassured.response.Response;
1311
import lombok.SneakyThrows;
1412
import org.junit.jupiter.api.Test;
1513
import org.springframework.core.io.ClassPathResource;
1614
import org.springframework.http.HttpStatus;
1715

18-
import java.io.Serializable;
19-
import java.lang.reflect.Type;
2016
import java.util.List;
2117
import java.util.Map;
2218

@@ -109,7 +105,10 @@ void policyByServiceProvider() {
109105
AccessCookieFilter accessCookieFilter = mockLoginFlow(attributes);
110106

111107
String serviceProviderEntityId = "https://network";
108+
//Stub the actual call to fetch the policies for a SP
112109
this.stubForPolicyByServiceProvider("http://mock-idp", serviceProviderEntityId);
110+
//The IdP is fetched to check the allowed entities
111+
this.stubForGetProvider(EntityType.saml20_idp, "7", Environment.PROD);
113112

114113
List<Map<String, Object>> policies = given()
115114
.when()
@@ -119,7 +118,8 @@ void policyByServiceProvider() {
119118
.contentType(ContentType.JSON)
120119
.queryParam("entityId", serviceProviderEntityId)
121120
.get("/api/v1/manage/policies")
122-
.as(new TypeRef<>() {});
121+
.as(new TypeRef<>() {
122+
});
123123
assertEquals(1, policies.size());
124124
}
125125

0 commit comments

Comments
 (0)