Skip to content
Snippets Groups Projects
Commit eb9d89d5 authored by Alok Joshi's avatar Alok Joshi
Browse files

add cache for entitltments

parent 5f3db9da
No related branches found
No related tags found
1 merge request!553Add cache for entitlements authorize mechanism
Pipeline #303152 failed
......@@ -18,9 +18,12 @@ package org.opengroup.osdu.notification.auth;
import org.apache.commons.lang3.StringUtils;
import org.opengroup.osdu.core.common.model.entitlements.AuthorizationResponse;
import org.opengroup.osdu.core.common.model.entitlements.Groups;
import org.opengroup.osdu.core.common.model.http.AppException;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.provider.interfaces.IAuthorizationService;
import org.opengroup.osdu.core.common.util.Crc32c;
import org.opengroup.osdu.notification.di.GroupVmCache;
import org.opengroup.osdu.notification.di.RequestInfoExt;
import org.opengroup.osdu.notification.utils.Config;
import org.opengroup.osdu.notification.provider.interfaces.IServiceAccountValidator;
......@@ -44,6 +47,8 @@ public class AuthorizationFilter {
private RequestInfoExt requestInfoExt;
@Autowired
private IServiceAccountValidator validator;
@Autowired
private GroupVmCache groupVmCache;
public boolean hasAnyPermission(String... requiredRoles) {
DpsHeaders dpsHeaders = requestInfoExt.getHeaders();
......@@ -66,20 +71,44 @@ public class AuthorizationFilter {
} else if (Arrays.asList(requiredRoles).contains(Config.PUBSUB)) {
String jwt = dpsHeaders.getAuthorization().substring(BEARER_PREFIX.length());
if (!this.validator.isValidPublisherServiceAccount(jwt)) {
this.authorizeWithEntitlements(requiredRoles);
return this.authorizeWithCacheOrEntitlements(requiredRoles, dpsHeaders);
} else {
return false;
}
} else {
authorizeWithEntitlements(requiredRoles);
return this.authorizeWithCacheOrEntitlements(requiredRoles, dpsHeaders);
}
return true;
}
private void authorizeWithEntitlements(String... requiredRoles) {
DpsHeaders dpsHeaders = requestInfoExt.getHeaders();
private boolean authorizeWithCacheOrEntitlements(String[] requiredRoles, DpsHeaders dpsHeaders) {
String cacheKey = getGroupCacheKey(dpsHeaders);
Groups groups = groupVmCache.get(cacheKey);
if(groups == null) {
AuthorizationResponse authorizationResponse = this.authorizeWithEntitlements(requiredRoles, dpsHeaders);
groupVmCache.put(cacheKey, authorizationResponse.getGroups());
return true;
} else {
return authorizeWithCache(requiredRoles, groups);
}
}
private boolean authorizeWithCache(String[] requiredRoles, Groups groups) {
if(groups.any(requiredRoles))
return true;
return false;
}
private String getGroupCacheKey(DpsHeaders dpsHeaders) {
String key = String.format("notification-entitlement-groups:%s:%s", dpsHeaders.getPartitionIdWithFallbackToAccountId(),
dpsHeaders.getAuthorization());
return Crc32c.hashToBase64EncodedString(key);
}
private AuthorizationResponse authorizeWithEntitlements(String[] requiredRoles, DpsHeaders dpsHeaders) {
AuthorizationResponse authorizationResponse = authService.authorizeAny(dpsHeaders, requiredRoles);
dpsHeaders.put(DpsHeaders.USER_EMAIL, authorizationResponse.getUser());
requestInfoExt.setHeaders(dpsHeaders);
return authorizationResponse;
}
}
// Copyright 2017-2024, SLB
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.opengroup.osdu.notification.di;
import org.opengroup.osdu.core.common.cache.VmCache;
import org.opengroup.osdu.core.common.model.entitlements.Groups;
import org.opengroup.osdu.notification.utils.MathUtils;
import org.springframework.stereotype.Component;
@Component
public class GroupVmCache extends VmCache<String, Groups> {
public GroupVmCache() {
super(MathUtils.generateRandomNumberBetweenBounds(30, 60), 1000);
}
}
\ No newline at end of file
......@@ -23,6 +23,7 @@ import org.opengroup.osdu.core.common.model.http.AppException;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
import org.opengroup.osdu.notification.utils.MathUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
......@@ -37,7 +38,7 @@ public class SubscriptionCacheFactory implements ICache<String, String> {
private MultiTenantCache<String> caches;
public SubscriptionCacheFactory(@Value("${app.expireTime}") int expireTime, @Value("${app.maxCacheSize}") int maxCacheSize) {
this.caches = new MultiTenantCache<>(new VmCache<>(expireTime, maxCacheSize));
this.caches = new MultiTenantCache<>(new VmCache<>(MathUtils.generateRandomNumberBetweenBounds(expireTime/2, expireTime), maxCacheSize));
}
@Override
......
// Copyright 2017-2024, SLB
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.opengroup.osdu.notification.utils;
import java.util.Random;
public class MathUtils {
/*
Returns a random number between lower(inclusive) and upper(exclusive)
*/
public static int generateRandomNumberBetweenBounds(int lower, int upper) {
Random random = new Random();
return random.nextInt(upper - lower) + lower;
}
}
......@@ -22,9 +22,12 @@ import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.opengroup.osdu.core.common.model.entitlements.AuthorizationResponse;
import org.opengroup.osdu.core.common.model.entitlements.GroupInfo;
import org.opengroup.osdu.core.common.model.entitlements.Groups;
import org.opengroup.osdu.core.common.model.http.AppException;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.provider.interfaces.IAuthorizationService;
import org.opengroup.osdu.notification.di.GroupVmCache;
import org.opengroup.osdu.notification.di.RequestInfoExt;
import org.opengroup.osdu.notification.provider.interfaces.IPubsubRequestBodyExtractor;
import org.opengroup.osdu.notification.provider.interfaces.IServiceAccountValidator;
......@@ -32,13 +35,17 @@ import org.opengroup.osdu.notification.utils.Config;
import org.powermock.modules.junit4.PowerMockRunner;
import jakarta.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
......@@ -69,6 +76,9 @@ public class AuthorizationFilterTest {
@Mock
private IPubsubRequestBodyExtractor extractor;
@Mock
private GroupVmCache groupVmCache;
@InjectMocks
private AuthorizationFilter sut;
......@@ -84,6 +94,7 @@ public class AuthorizationFilterTest {
final String USER_EMAIL = "test@test.com";
AuthorizationResponse authorizationResponse = AuthorizationResponse.builder().user(USER_EMAIL).build();
when(this.authorizationService.authorizeAny(any(), eq(ROLE1), eq(ROLE2))).thenReturn(authorizationResponse);
//when(this.groupVmCache.get("8Z2MjQ==")).thenReturn(null);
assertTrue(this.sut.hasAnyPermission(ROLE1, ROLE2));
verify(headers).put(DpsHeaders.USER_EMAIL, "test@test.com");
......@@ -142,4 +153,21 @@ public class AuthorizationFilterTest {
this.sut.hasAnyPermission(ROLE4, ROLE2);
verify(headers).put(DpsHeaders.USER_EMAIL, USER_EMAIL);
}
@Test
public void should_authenticateRequest_when_groupsAreAvailableInCache() {
Groups groups = new Groups();
List<GroupInfo> groupInfos = new ArrayList<>();
GroupInfo groupInfo = new GroupInfo();
groupInfo.setEmail("groupInfoEmail");
groupInfo.setDescription("description");
groupInfo.setName("role1");
groupInfos.add(groupInfo);
groups.setGroups(groupInfos);
groups.setDesId("desid");
groups.setMemberEmail("memberEmail");
when(this.groupVmCache.get("8Z2MjQ==")).thenReturn(groups);
assertTrue(this.sut.hasAnyPermission(ROLE1, ROLE2));
verify(authorizationService, never()).authorizeAny(any(DpsHeaders.class), any(String[].class));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment