Skip to content

Commit 88b2254

Browse files
committed
Implement access-expression access control
1 parent 5823e5b commit 88b2254

5 files changed

Lines changed: 80 additions & 61 deletions

File tree

src/main/java/eu/openanalytics/containerproxy/service/AccessControlService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ public boolean allowedByExpression(Authentication auth, ProxySpec spec) {
136136
// no expression defined -> this user has no access based on the expression
137137
return false;
138138
}
139-
return false;
139+
SpecExpressionContext context = SpecExpressionContext.create(auth, auth.getPrincipal(), auth.getCredentials(), spec);
140+
return specExpressionResolver.evaluateToBoolean(spec.getAccessControl().getExpression(), context);
140141
}
141142

143+
142144
}

src/main/java/eu/openanalytics/containerproxy/service/UserService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public String[] getGroups() {
106106
return getGroups(getCurrentAuth());
107107
}
108108

109-
public String[] getGroups(Authentication auth) {
109+
public static String[] getGroups(Authentication auth) {
110110
List<String> groups = new ArrayList<>();
111111
if (auth != null) {
112112
for (GrantedAuthority grantedAuth: auth.getAuthorities()) {

src/main/java/eu/openanalytics/containerproxy/spec/expression/SpecExpressionContext.java

Lines changed: 63 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,68 +24,82 @@
2424
import eu.openanalytics.containerproxy.model.runtime.Proxy;
2525
import eu.openanalytics.containerproxy.model.spec.ContainerSpec;
2626
import eu.openanalytics.containerproxy.model.spec.ProxySpec;
27+
import eu.openanalytics.containerproxy.service.UserService;
2728
import org.keycloak.KeycloakPrincipal;
29+
import org.springframework.security.core.Authentication;
2830
import org.springframework.security.core.userdetails.User;
2931
import org.springframework.security.ldap.userdetails.LdapUserDetails;
3032
import org.springframework.security.saml.SAMLCredential;
3133

34+
import java.util.Arrays;
35+
import java.util.List;
36+
3237
public class SpecExpressionContext {
3338

34-
private ContainerSpec containerSpec;
35-
private ProxySpec proxySpec;
36-
private Proxy proxy;
37-
private OpenIDAuthenticationBackend.CustomNameOidcUser oicdUser;
38-
private KeycloakPrincipal keycloakUser;
39-
private SAMLCredential samlCredential;
40-
private LdapUserDetails ldapUser;
39+
private ContainerSpec containerSpec;
40+
private ProxySpec proxySpec;
41+
private Proxy proxy;
42+
private OpenIDAuthenticationBackend.CustomNameOidcUser oicdUser;
43+
private KeycloakPrincipal keycloakUser;
44+
private SAMLCredential samlCredential;
45+
private LdapUserDetails ldapUser;
46+
private List<String> groups;
47+
48+
public ContainerSpec getContainerSpec() {
49+
return containerSpec;
50+
}
51+
52+
public ProxySpec getProxySpec() {
53+
return proxySpec;
54+
}
4155

42-
public ContainerSpec getContainerSpec() {
43-
return containerSpec;
44-
}
56+
public Proxy getProxy() {
57+
return proxy;
58+
}
4559

46-
public ProxySpec getProxySpec() {
47-
return proxySpec;
48-
}
60+
public OpenIDAuthenticationBackend.CustomNameOidcUser getOidcUser() {
61+
return oicdUser;
62+
}
4963

50-
public Proxy getProxy() {
51-
return proxy;
52-
}
64+
public KeycloakPrincipal getKeycloakUser() {
65+
return keycloakUser;
66+
}
5367

54-
public OpenIDAuthenticationBackend.CustomNameOidcUser getOidcUser() {
55-
return oicdUser;
56-
}
68+
public SAMLCredential getSamlCredential() {
69+
return samlCredential;
70+
}
5771

58-
public KeycloakPrincipal getKeycloakUser() {
59-
return keycloakUser;
60-
}
72+
public LdapUserDetails getLdapUser() {
73+
return ldapUser;
74+
}
6175

62-
public SAMLCredential getSamlCredential() {
63-
return samlCredential;
64-
}
76+
public List<String> getGroups() {
77+
return groups;
78+
}
6579

66-
public LdapUserDetails getLdapUser() {
67-
return ldapUser;
68-
}
80+
public static SpecExpressionContext create(Object... objects) {
81+
SpecExpressionContext ctx = new SpecExpressionContext();
82+
for (Object o : objects) {
83+
if (o instanceof ContainerSpec) {
84+
ctx.containerSpec = (ContainerSpec) o;
85+
} else if (o instanceof ProxySpec) {
86+
ctx.proxySpec = (ProxySpec) o;
87+
} else if (o instanceof Proxy) {
88+
ctx.proxy = (Proxy) o;
89+
} else if (o instanceof OpenIDAuthenticationBackend.CustomNameOidcUser) {
90+
ctx.oicdUser = (OpenIDAuthenticationBackend.CustomNameOidcUser) o;
91+
} else if (o instanceof KeycloakPrincipal) {
92+
ctx.keycloakUser = (KeycloakPrincipal) o;
93+
} else if (o instanceof SAMLCredential) {
94+
ctx.samlCredential = (SAMLCredential) o;
95+
} else if (o instanceof LdapUserDetails) {
96+
ctx.ldapUser = (LdapUserDetails) o;
97+
}
98+
if (o instanceof Authentication) {
99+
ctx.groups = Arrays.asList(UserService.getGroups((Authentication) o));
100+
}
101+
}
102+
return ctx;
103+
}
69104

70-
public static SpecExpressionContext create(Object...objects) {
71-
SpecExpressionContext ctx = new SpecExpressionContext();
72-
for (Object o: objects) {
73-
if (o instanceof ContainerSpec) {
74-
ctx.containerSpec = (ContainerSpec) o;
75-
} else if (o instanceof ProxySpec) {
76-
ctx.proxySpec = (ProxySpec) o;
77-
} else if (o instanceof Proxy) {
78-
ctx.proxy = (Proxy) o;
79-
} else if (o instanceof OpenIDAuthenticationBackend.CustomNameOidcUser) {
80-
ctx.oicdUser = (OpenIDAuthenticationBackend.CustomNameOidcUser) o;
81-
} else if (o instanceof KeycloakPrincipal) {
82-
ctx.keycloakUser = (KeycloakPrincipal) o;
83-
} else if (o instanceof SAMLCredential) {
84-
ctx.samlCredential = (SAMLCredential) o;
85-
} else if (o instanceof LdapUserDetails) {
86-
ctx.ldapUser = (LdapUserDetails) o;
87-
}
88-
}
89-
return ctx;
90-
}
91105
}

src/main/java/eu/openanalytics/containerproxy/spec/expression/SpecExpressionResolver.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
import java.util.Map;
2424
import java.util.concurrent.ConcurrentHashMap;
2525

26-
import javax.inject.Inject;
27-
2826
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
2927
import org.springframework.context.ApplicationContext;
3028
import org.springframework.context.ConfigurableApplicationContext;
@@ -50,13 +48,10 @@
5048
@Component
5149
public class SpecExpressionResolver {
5250

53-
@Inject
54-
private ApplicationContext appContext;
55-
56-
private ExpressionParser expressionParser;
57-
51+
private final ApplicationContext appContext;
52+
private final ExpressionParser expressionParser;
5853
private final Map<SpecExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8);
59-
54+
6055
private final ParserContext beanExpressionParserContext = new ParserContext() {
6156
@Override
6257
public boolean isTemplate() {
@@ -72,7 +67,8 @@ public String getExpressionSuffix() {
7267
}
7368
};
7469

75-
public SpecExpressionResolver() {
70+
public SpecExpressionResolver(ApplicationContext appContext) {
71+
this.appContext = appContext;
7672
this.expressionParser = new SpelExpressionParser();
7773
}
7874

@@ -105,4 +101,8 @@ public Object evaluate(String expression, SpecExpressionContext context) {
105101
public String evaluateToString(String expression, SpecExpressionContext context) {
106102
return String.valueOf(evaluate(expression, context));
107103
}
104+
105+
public Boolean evaluateToBoolean(String expression, SpecExpressionContext context) {
106+
return Boolean.valueOf(evaluateToString(expression, context));
107+
}
108108
}

src/test/java/eu/openanalytics/containerproxy/test/auth/AccessControlServiceTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import eu.openanalytics.containerproxy.service.AccessControlService;
77
import eu.openanalytics.containerproxy.service.UserService;
88
import eu.openanalytics.containerproxy.spec.IProxySpecProvider;
9+
import eu.openanalytics.containerproxy.spec.expression.SpecExpressionResolver;
910
import org.junit.jupiter.api.Assertions;
1011
import org.junit.jupiter.api.Test;
12+
import org.springframework.context.ApplicationContext;
1113
import org.springframework.security.authentication.AnonymousAuthenticationToken;
1214
import org.springframework.security.core.Authentication;
1315

@@ -25,7 +27,8 @@ public AccessControlServiceTest() {
2527
authBackend = mock(IAuthenticationBackend.class);
2628
userService = mock(UserService.class);
2729
specProvider = mock(IProxySpecProvider.class);
28-
accessControlService = new AccessControlService(authBackend, userService, specProvider);
30+
SpecExpressionResolver specExpressionResolver = new SpecExpressionResolver(mock(ApplicationContext.class));
31+
accessControlService = new AccessControlService(authBackend, userService, specProvider, specExpressionResolver);
2932
}
3033

3134
@Test

0 commit comments

Comments
 (0)