Skip to content

Commit 3565034

Browse files
author
Travis Tomsu
authored
Adds command to pull whole permission into security context for @PostFilter optimization. (#27)
1 parent eb2c378 commit 3565034

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

fiat-api/src/main/java/com/netflix/spinnaker/fiat/shared/FiatPermissionEvaluator.java

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@
1717
package com.netflix.spinnaker.fiat.shared;
1818

1919
import com.netflix.spinnaker.fiat.model.Authorization;
20+
import com.netflix.spinnaker.fiat.model.UserPermission;
21+
import com.netflix.spinnaker.fiat.model.resources.Authorizable;
2022
import com.netflix.spinnaker.fiat.model.resources.Resource;
2123
import lombok.Setter;
2224
import lombok.extern.slf4j.Slf4j;
2325
import org.springframework.beans.factory.annotation.Autowired;
2426
import org.springframework.beans.factory.annotation.Value;
2527
import org.springframework.security.access.PermissionEvaluator;
2628
import org.springframework.security.core.Authentication;
29+
import org.springframework.security.core.context.SecurityContext;
30+
import org.springframework.security.core.context.SecurityContextHolder;
2731
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
2832
import org.springframework.stereotype.Component;
2933
import retrofit.RetrofitError;
3034

3135
import java.io.Serializable;
36+
import java.util.Set;
37+
import java.util.function.Function;
3238

3339
@Component
3440
@Slf4j
@@ -57,7 +63,9 @@ public boolean hasPermission(Authentication authentication, Serializable resourc
5763
Resource r = Resource.parse(resourceType);
5864
Authorization a = Authorization.valueOf(authorization.toString());
5965

60-
return isAuthorized(username, r, resourceName.toString(), a);
66+
return isWholePermissionStored(authentication) ?
67+
permissionContains(authentication, resourceName.toString(), r, a) :
68+
isAuthorized(username, r, resourceName.toString(), a);
6169
}
6270

6371
private String getUsername(Authentication authentication) {
@@ -83,4 +91,65 @@ private boolean isAuthorized(String username, Resource resource, String resource
8391
}
8492
return true;
8593
}
94+
95+
@SuppressWarnings("unused")
96+
public boolean storeWholePermission() {
97+
if (!Boolean.valueOf(fiatEnabled)) {
98+
return true;
99+
}
100+
101+
String username = getUsername(SecurityContextHolder.getContext().getAuthentication());
102+
103+
UserPermission.View view;
104+
try {
105+
view = fiatService.getUserPermission(username);
106+
} catch (RetrofitError re) {
107+
String message = String.format("Cannot get whole user permission for user %s", username);
108+
log.debug(message);
109+
log.trace(message, re);
110+
return false;
111+
}
112+
113+
PreAuthenticatedAuthenticationToken auth = new PreAuthenticatedAuthenticationToken(username, null, null);
114+
auth.setDetails(view);
115+
116+
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
117+
ctx.setAuthentication(auth);
118+
SecurityContextHolder.setContext(ctx);
119+
120+
return true;
121+
}
122+
123+
private boolean isWholePermissionStored(Authentication authentication) {
124+
return authentication.getDetails() != null &&
125+
authentication.getDetails() instanceof UserPermission.View;
126+
}
127+
128+
private boolean permissionContains(Authentication authentication,
129+
String resourceName,
130+
Resource resource,
131+
Authorization authorization) {
132+
UserPermission.View permission = (UserPermission.View) authentication.getDetails();
133+
134+
Function<Set<? extends Authorizable>, Boolean> containsAuth = resources ->
135+
resources
136+
.stream()
137+
.anyMatch(view -> view.getName().equalsIgnoreCase(resourceName) &&
138+
view.getAuthorizations().contains(authorization));
139+
140+
141+
switch (resource) {
142+
case ACCOUNT:
143+
return containsAuth.apply(permission.getAccounts());
144+
case APPLICATION:
145+
return containsAuth.apply(permission.getApplications());
146+
default:
147+
return false;
148+
}
149+
}
150+
151+
@SuppressWarnings("unused")
152+
public boolean isAdmin() {
153+
return true; // TODO(ttomsu): Chosen by fair dice roll. Guaranteed to be random.
154+
}
86155
}

fiat-api/src/main/java/com/netflix/spinnaker/fiat/shared/FiatService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616

1717
package com.netflix.spinnaker.fiat.shared;
1818

19+
import com.netflix.spinnaker.fiat.model.UserPermission;
1920
import com.squareup.okhttp.Response;
2021
import retrofit.http.GET;
2122
import retrofit.http.Path;
2223

2324
public interface FiatService {
2425

26+
@GET("/authorize/{userId}")
27+
UserPermission.View getUserPermission(@Path("userId") String userId);
28+
2529
@GET("/authorize/{userId}/{resourceType}/{resourceName}/{authorization}")
2630
Response hasAuthorization(@Path("userId") String userId,
2731
@Path("resourceType") String resourceType,

0 commit comments

Comments
 (0)