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

Merge branch 'ent_cache' into 'master'

Add cache for Entitlements getGroups() call

See merge request !159
parents f4e2ee57 e433126f
No related branches found
No related tags found
2 merge requests!211Updated topics.json - Replace common with osdu as common data partition is not a concept in OSDU.,!159Add cache for Entitlements getGroups() call
Pipeline #92126 passed with warnings
......@@ -170,7 +170,7 @@ The following software have components provided under the terms of this license:
- Non-Blocking Reactive Foundation for the JVM (from https://github.com/reactor/reactor, https://github.com/reactor/reactor-core)
- OAuth 2.0 SDK with OpenID Connect extensions (from https://bitbucket.org/connect2id/oauth-2.0-sdk-with-openid-connect-extensions)
- Objenesis (from http://objenesis.org)
- OkHttp (from https://github.com/square/okhttp, https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp, https://square.github.io/okhttp/)
- OkHttp (from https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp, https://square.github.io/okhttp/)
- OkHttp Logging Interceptor (from https://github.com/square/okhttp, https://repo1.maven.org/maven2/com/squareup/okhttp3/logging-interceptor, https://square.github.io/okhttp/)
- OkHttp URLConnection (from https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp-urlconnection, https://square.github.io/okhttp/)
- Okio (from https://github.com/square/okio/, https://repo1.maven.org/maven2/com/squareup/okio/okio)
......@@ -204,9 +204,9 @@ The following software have components provided under the terms of this license:
- Spring Boot Reactor Netty Starter (from https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-reactor-netty, https://spring.io/projects/spring-boot)
- Spring Boot Security Starter (from http://projects.spring.io/spring-boot/, https://spring.io/projects/spring-boot)
- Spring Boot Starter (from http://projects.spring.io/spring-boot/, https://spring.io/projects/spring-boot)
- Spring Boot Test (from http://projects.spring.io/spring-boot/, https://spring.io/projects/spring-boot)
- Spring Boot Test Auto-Configure (from http://projects.spring.io/spring-boot/, https://spring.io/projects/spring-boot)
- Spring Boot Test Starter (from http://projects.spring.io/spring-boot/, https://spring.io/projects/spring-boot)
- Spring Boot Test (from http://projects.spring.io/spring-boot/, https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-test, https://spring.io/projects/spring-boot)
- Spring Boot Test Auto-Configure (from http://projects.spring.io/spring-boot/, https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-test-autoconfigure, https://spring.io/projects/spring-boot)
- Spring Boot Test Starter (from http://projects.spring.io/spring-boot/, https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-test, https://spring.io/projects/spring-boot)
- Spring Boot Tomcat Starter (from http://projects.spring.io/spring-boot/, https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-tomcat, https://spring.io/projects/spring-boot)
- Spring Boot Validation Starter (from http://projects.spring.io/spring-boot/, https://projects.spring.io/spring-boot/, https://spring.io/projects/spring-boot)
- Spring Boot Web Starter (from http://projects.spring.io/spring-boot/, https://spring.io/projects/spring-boot)
......@@ -775,7 +775,7 @@ MPL-2.0
The following software have components provided under the terms of this license:
- Javassist (from http://www.javassist.org/)
- OkHttp (from https://github.com/square/okhttp, https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp, https://square.github.io/okhttp/)
- OkHttp (from https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp, https://square.github.io/okhttp/)
- RabbitMQ Java Client (from http://www.rabbitmq.com, https://www.rabbitmq.com)
========================================================================
......
......@@ -70,4 +70,8 @@ INTEGRATION_TEST_AUDIENCES=
CRON_JOB_EXPECTED_IP=0:0:0:0:0:0:0:1
SUBSCRIBER_PRIVATE_KEY_ID=
ENVIRONMENT=LOCAL
SUBSCRIBER_SECRET=395f1b05e95171d7c0dde0b19fd6cf
\ No newline at end of file
SUBSCRIBER_SECRET=395f1b05e95171d7c0dde0b19fd6cf
# Entitlements cache settings
app.maxExpireTime=60
app.maxCacheSize=1000
\ No newline at end of file
......@@ -17,15 +17,23 @@
package org.opengroup.osdu.register.provider.gcp;
import javax.annotation.PostConstruct;
import org.opengroup.osdu.core.gcp.multitenancy.StorageFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import javax.annotation.PostConstruct;
@ComponentScan({"org.opengroup.osdu"})
@ComponentScan(value = {"org.opengroup.osdu"},
excludeFilters = {
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = {StorageFactory.class})
}
)
@SpringBootApplication
public class RegisterApplication {
@PostConstruct
void f() {
......
/*
* Copyright 2017-2022, Schlumberger
*
* 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.register.di;
import org.opengroup.osdu.core.common.cache.VmCache;
import org.opengroup.osdu.core.common.model.entitlements.AuthorizationResponse;
import org.opengroup.osdu.register.utils.MathUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class GroupVmCache extends VmCache<String, AuthorizationResponse> {
public GroupVmCache(@Value("${app.maxExpireTime:60}") int maxExpireTime, @Value("${app.maxCacheSize:1000}") int maxCacheSize) {
//randomizing cache TTL will reduce sudden spikes on downstream service because cache in different pods expires at different times
super(MathUtil.generateRandomNumberBetweenBounds(maxExpireTime/2, maxExpireTime), maxCacheSize);
}
}
......@@ -21,6 +21,8 @@ import org.opengroup.osdu.core.common.model.entitlements.AuthorizationResponse;
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.register.di.GroupVmCache;
import org.opengroup.osdu.register.utils.ServiceRequestInfo;
import org.opengroup.osdu.register.utils.ServiceRole;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -42,6 +44,8 @@ public class AuthorizationFilter {
private HttpServletRequest request;
@Autowired
private ServiceRequestInfo requestInfo;
@Autowired
private GroupVmCache groupVmCache;
public boolean hasAnyPermission(String... requiredRoles) {
String path = request.getServletPath();
......@@ -77,7 +81,25 @@ public class AuthorizationFilter {
}
}
/*
Check cache first, fall back to authorization service call otherwise
*/
private AuthorizationResponse checkApiAccess(String[] requiredRoles, DpsHeaders dpsHeaders) {
return authorizationService.authorizeAny(dpsHeaders, requiredRoles);
String cacheKey = getGroupCacheKey(dpsHeaders);
AuthorizationResponse authorizationResponse = groupVmCache.get(cacheKey);
if(authorizationResponse != null && authorizationResponse.getGroups() != null)
return authorizationResponse;
else {
authorizationResponse = authorizationService.authorizeAny(dpsHeaders, requiredRoles);
groupVmCache.put(cacheKey, authorizationResponse);
return authorizationResponse;
}
}
private String getGroupCacheKey(DpsHeaders dpsHeaders) {
String key = String.format("register-entitlement-groups:%s:%s", dpsHeaders.getPartitionId(),
dpsHeaders.getAuthorization());
return Crc32c.hashToBase64EncodedString(key);
}
}
/*
* Copyright 2017-2022, Schlumberger
*
* 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.register.utils;
import java.util.Random;
public class MathUtil {
/*
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,15 +22,21 @@ 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.register.di.GroupVmCache;
import org.opengroup.osdu.register.utils.ServiceRequestInfo;
import org.opengroup.osdu.register.utils.ServiceRole;
import org.powermock.modules.junit4.PowerMockRunner;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
......@@ -53,6 +59,8 @@ public class AuthorizationFilterTest {
private IAuthorizationService authorizationService;
@Mock
private ServiceRequestInfo requestInfo;
@Mock
private GroupVmCache groupVmCache;
@InjectMocks
private AuthorizationFilter sut;
......@@ -61,10 +69,12 @@ public class AuthorizationFilterTest {
when(headers.getAuthorization()).thenReturn("Bearer 123456");
}
private final String USER_EMAIL = "test@slb.com";
@Test
public void should_authenticateRequest_when_resourceIsRolesAllowedAnnotated() {
final String USER_EMAIL = "test@slb.com";
AuthorizationResponse authorizationResponse = AuthorizationResponse.builder().user(USER_EMAIL).build();
when(this.groupVmCache.get("+CjZlg==")).thenReturn(null);
when(this.authorizationService.authorizeAny(any(), eq(ROLE1), eq(ROLE2))).thenReturn(authorizationResponse);
assertTrue(this.sut.hasAnyPermission(ROLE1, ROLE2));
......@@ -74,7 +84,6 @@ public class AuthorizationFilterTest {
@Test(expected = AppException.class)
public void should_throwAppError_when_noAuthzProvided() {
when(headers.getAuthorization()).thenReturn("");
final String USER_EMAIL = "test@slb.com";
this.sut.hasAnyPermission(ROLE1, ROLE2);
assertEquals(USER_EMAIL, this.headers.getUserEmail());
......@@ -95,4 +104,22 @@ public class AuthorizationFilterTest {
when(this.requestInfo.isCronRequest()).thenReturn(false);
this.sut.hasAnyPermission(ROLE3);
}
@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");
AuthorizationResponse authorizationResponse = AuthorizationResponse.builder().groups(groups).user(USER_EMAIL).build();
when(this.groupVmCache.get("+CjZlg==")).thenReturn(authorizationResponse);
assertTrue(this.sut.hasAnyPermission(ROLE1, ROLE2));
verify(headers).put(DpsHeaders.USER_EMAIL, USER_EMAIL);
}
}
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