Skip to content

Commit

Permalink
DTSCCI-242 CMC Claim Store functional test 429 errors (#2976)
Browse files Browse the repository at this point in the history
* DTSCCI-242: Fix @Cacheable self invocation

* DTSCCI-242: Fix contract test config

* Re-enable pact tests on PR

* DTSCCI-242: Fix @Cacheable self invocation

* DTSCCI-242: Create cacheable beans for user authorisations

* DTSCCI-242: Create cacheable beans for user authorisations

* DTSCCI-242 Caching fix and Jcenter fix

* DTSCCI-242 Checkstyle fix

* DTSCCI-242 Code clean up

* DTSCCI-242: Remove @Cacheable annotation from interface

* DTSCCI-242: Enable cacheable tokens in preview and aat

* DTSCCI-242: update hmcts java to resolve build error

* Revert "DTSCCI-242: update hmcts java to resolve build error"

This reverts commit ad9574a.

* DTSCCI-242: Correct property name

---------

Co-authored-by: Nigel Dunne <12184413+nigeldunne@users.noreply.github.com>
Co-authored-by: AbuSalam22 <136581242+AbuSalam22@users.noreply.github.com>
Co-authored-by: Ruban <ruban72@hotmail.com>
  • Loading branch information
4 people authored Sep 6, 2024
1 parent b746c09 commit e4c1e31
Show file tree
Hide file tree
Showing 18 changed files with 412 additions and 48 deletions.
1 change: 1 addition & 0 deletions Jenkinsfile_CNP
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ withPipeline("java", product, component) {
env.ENVIRONMENT = "preview"
env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
loadVaultSecrets(secrets)
enablePactAs([AppPipelineDsl.PactRoles.PROVIDER])
}

}
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,15 @@ tasks.withType(Test) {
}

task functional(type: Test) {
group = 'Delivery pipeline'
description = 'Executes functional tests against an AAT Claim Store instance'
setTestClassesDirs(sourceSets.aat.output.classesDirs)
setClasspath(sourceSets.aat.runtimeClasspath)
include "uk/gov/hmcts/cmc/claimstore/tests/functional/**"
testLogging.showStandardStreams = true


environment("APPINSIGHTS_INSTRUMENTATIONKEY", "test-key")
}

task smoke(type: Test) {
Expand Down
2 changes: 1 addition & 1 deletion charts/cmc-claim-store/values.aat.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ java:
CLAIM_STAYED_SCHEDULE: "0 0 16 ? * MON-FRI *"
SCHEDULE_TRANSFER_CLAIMS: '0 0 12 1 * ?'
OIDC_ISSUER: https://forgerock-am.service.core-compute-idam-aat2.internal:8443/openam/oauth2/realms/root/realms/hmcts
DUMMY_VAR: test
USER_TOKEN_CACHE_ENABLED: true
1 change: 1 addition & 0 deletions charts/cmc-claim-store/values.preview.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ java:
CORE_CASE_DATA_API_URL: http://${SERVICE_NAME}-ccd-data-store-api
OIDC_ISSUER: https://forgerock-am.service.core-compute-idam-aat2.internal:8443/openam/oauth2/realms/root/realms/hmcts
RPA_NOTIFICATIONS_LEGALSEALEDCLAIMRECIPIENT: civilmoneyclaims+rpa-legal-sealedclaim-issued@gmail.com
USER_TOKEN_CACHE_ENABLED: true
postgresql:
enabled: true
releaseNameOverride: ${SERVICE_NAME}-postgresql
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import uk.gov.hmcts.cmc.claimstore.services.ResponseDeadlineCalculator;
import uk.gov.hmcts.cmc.claimstore.services.UserService;
import uk.gov.hmcts.cmc.claimstore.services.ccd.CoreCaseDataService;
import uk.gov.hmcts.cmc.claimstore.services.user.UserAuthorisationTokenService;
import uk.gov.hmcts.cmc.claimstore.services.user.UserInfoService;
import uk.gov.hmcts.cmc.launchdarkly.LaunchDarklyClient;

@Configuration
Expand Down Expand Up @@ -64,9 +66,19 @@ public ClaimAuthorisationRule claimAuthorisationRule() {
return new ClaimAuthorisationRule(userService());
}

@Bean
public UserInfoService userInfoService() {
return new UserInfoService(idamApi);
}

@Bean
public UserAuthorisationTokenService userAuthorisationTokenService() {
return new UserAuthorisationTokenService(idamApi, oauth2);
}

@Bean
public UserService userService() {
return new UserService(idamApi, idamCaseworkerProperties, oauth2);
return new UserService(idamApi, idamCaseworkerProperties, oauth2, userInfoService(), userAuthorisationTokenService());
}

@Bean
Expand Down
48 changes: 21 additions & 27 deletions src/main/java/uk/gov/hmcts/cmc/claimstore/services/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.config.properties.idam.IdamCaseworker;
import uk.gov.hmcts.cmc.claimstore.config.properties.idam.IdamCaseworkerProperties;
import uk.gov.hmcts.cmc.claimstore.models.idam.*;
import uk.gov.hmcts.cmc.claimstore.models.idam.AuthenticateUserResponse;
import uk.gov.hmcts.cmc.claimstore.models.idam.GeneratePinRequest;
import uk.gov.hmcts.cmc.claimstore.models.idam.GeneratePinResponse;
import uk.gov.hmcts.cmc.claimstore.models.idam.Oauth2;
import uk.gov.hmcts.cmc.claimstore.models.idam.TokenExchangeResponse;
import uk.gov.hmcts.cmc.claimstore.models.idam.User;
import uk.gov.hmcts.cmc.claimstore.models.idam.UserDetails;
import uk.gov.hmcts.cmc.claimstore.models.idam.UserInfo;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;
import uk.gov.hmcts.cmc.claimstore.services.user.IUserAuthorisationTokenService;
import uk.gov.hmcts.cmc.claimstore.services.user.IUserInfoService;
import uk.gov.hmcts.cmc.claimstore.stereotypes.LogExecutionTime;

import java.util.Base64;
Expand All @@ -19,28 +27,32 @@ public class UserService {
public static final String AUTHORIZATION_CODE = "authorization_code";
public static final String CODE = "code";
public static final String BASIC = "Basic ";
public static final String GRANT_TYPE_PASSWORD = "password";
public static final String DEFAULT_SCOPE = "openid profile roles";
private final IdamApi idamApi;
private final IdamCaseworkerProperties idamCaseworkerProperties;
private final Oauth2 oauth2;
private final IUserInfoService userInfoService;
private final IUserAuthorisationTokenService userAuthorisationTokenService;
Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
public UserService(
IdamApi idamApi,
IdamCaseworkerProperties idamCaseworkerProperties,
Oauth2 oauth2
Oauth2 oauth2,
IUserInfoService userInfoService,
IUserAuthorisationTokenService userAuthorisationTokenService
) {
this.idamApi = idamApi;
this.idamCaseworkerProperties = idamCaseworkerProperties;
this.oauth2 = oauth2;
this.userInfoService = userInfoService;
this.userAuthorisationTokenService = userAuthorisationTokenService;
}

@LogExecutionTime
public UserDetails getUserDetails(String authorisation) {
logger.info("User info invoked");
UserInfo userInfo = getUserInfo(authorisation);
UserInfo userInfo = userInfoService.getUserInfo(authorisation);

return UserDetails.builder()
.id(userInfo.getUid())
Expand All @@ -58,7 +70,7 @@ public User getUser(String authorisation) {

public User authenticateUser(String username, String password) {

String authorisation = getAuthorisationToken(username, password);
String authorisation = userAuthorisationTokenService.getAuthorisationToken(username, password);
UserDetails userDetails = getUserDetails(authorisation);
return new User(authorisation, userDetails);
}
Expand All @@ -74,26 +86,8 @@ public GeneratePinResponse generatePin(String name, String authorisation) {
return idamApi.generatePin(new GeneratePinRequest(name), authorisation);
}

@LogExecutionTime
@Cacheable(value = "userOIDTokenCache")
public String getAuthorisationToken(String username, String password) {
logger.info("IDAM /o/token invoked.");
TokenExchangeResponse tokenExchangeResponse = idamApi.exchangeToken(
oauth2.getClientId(),
oauth2.getClientSecret(),
oauth2.getRedirectUrl(),
GRANT_TYPE_PASSWORD,
username,
password,
DEFAULT_SCOPE);
return BEARER + tokenExchangeResponse.getAccessToken();
}

@LogExecutionTime
@Cacheable(value = "userInfoCache")
public UserInfo getUserInfo(String bearerToken) {
logger.info("IDAM /o/userinfo invoked");
return idamApi.retrieveUserInfo(bearerToken);
return userInfoService.getUserInfo(bearerToken);
}

public User authenticateUserForTests(String username, String password) {
Expand All @@ -111,7 +105,7 @@ public String getAuthorisationTokenForTests(String username, String password) {
oauth2.getClientId(),
oauth2.getRedirectUrl()
);
logger.info("IDAM /o/token invoked.");
logger.info("IDAM /o/token invoked for tests.");
TokenExchangeResponse tokenExchangeResponse = idamApi.exchangeTokenForTests(
authenticateUserResponse.getCode(),
AUTHORIZATION_CODE,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package uk.gov.hmcts.cmc.claimstore.services.user;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.models.idam.Oauth2;
import uk.gov.hmcts.cmc.claimstore.models.idam.TokenExchangeResponse;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;
import uk.gov.hmcts.cmc.claimstore.stereotypes.LogExecutionTime;

@Component
@ConditionalOnProperty(prefix = "idam.user.token.cache", name = "enabled", havingValue = "true")
public class CacheableUserAuthorisationTokenService implements IUserAuthorisationTokenService {
public static final String GRANT_TYPE_PASSWORD = "password";
public static final String DEFAULT_SCOPE = "openid profile roles";
public static final String BEARER = "Bearer ";

private final IdamApi idamApi;
private final Oauth2 oauth2;
Logger logger = LoggerFactory.getLogger(this.getClass());

public CacheableUserAuthorisationTokenService(IdamApi idamApi, Oauth2 oauth2) {
this.idamApi = idamApi;
this.oauth2 = oauth2;
}

@Override
@LogExecutionTime
@Cacheable(value = "userOIDTokenCache")
public String getAuthorisationToken(String username, String password) {
logger.info("IDAM /o/token invoked.");
TokenExchangeResponse tokenExchangeResponse = idamApi.exchangeToken(
oauth2.getClientId(),
oauth2.getClientSecret(),
oauth2.getRedirectUrl(),
GRANT_TYPE_PASSWORD,
username,
password,
DEFAULT_SCOPE);
return BEARER + tokenExchangeResponse.getAccessToken();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package uk.gov.hmcts.cmc.claimstore.services.user;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.models.idam.UserInfo;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;
import uk.gov.hmcts.cmc.claimstore.stereotypes.LogExecutionTime;

@Component
@ConditionalOnProperty(prefix = "idam.user.token.cache", name = "enabled", havingValue = "true")
public class CacheableUserInfoService implements IUserInfoService {

private final IdamApi idamApi;
Logger logger = LoggerFactory.getLogger(this.getClass());

public CacheableUserInfoService(IdamApi idamApi) {
this.idamApi = idamApi;
}

@Override
@LogExecutionTime
@Cacheable(value = "userInfoCache")
public UserInfo getUserInfo(String bearerToken) {
logger.info("IDAM /o/userinfo invoked");
return idamApi.retrieveUserInfo(bearerToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package uk.gov.hmcts.cmc.claimstore.services.user;

public interface IUserAuthorisationTokenService {
String getAuthorisationToken(String username, String password);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package uk.gov.hmcts.cmc.claimstore.services.user;

import uk.gov.hmcts.cmc.claimstore.models.idam.UserInfo;

public interface IUserInfoService {
UserInfo getUserInfo(String bearerToken);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package uk.gov.hmcts.cmc.claimstore.services.user;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.models.idam.Oauth2;
import uk.gov.hmcts.cmc.claimstore.models.idam.TokenExchangeResponse;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;
import uk.gov.hmcts.cmc.claimstore.stereotypes.LogExecutionTime;

@Component
@ConditionalOnProperty(prefix = "idam.user.token.cache", name = "enabled", havingValue = "false", matchIfMissing = true)
public class UserAuthorisationTokenService implements IUserAuthorisationTokenService {
public static final String GRANT_TYPE_PASSWORD = "password";
public static final String DEFAULT_SCOPE = "openid profile roles";
public static final String BEARER = "Bearer ";

private final IdamApi idamApi;
private final Oauth2 oauth2;
Logger logger = LoggerFactory.getLogger(this.getClass());

public UserAuthorisationTokenService(IdamApi idamApi, Oauth2 oauth2) {
this.idamApi = idamApi;
this.oauth2 = oauth2;
}

@Override
@LogExecutionTime
public String getAuthorisationToken(String username, String password) {
logger.info("IDAM /o/token invoked.");
TokenExchangeResponse tokenExchangeResponse = idamApi.exchangeToken(
oauth2.getClientId(),
oauth2.getClientSecret(),
oauth2.getRedirectUrl(),
GRANT_TYPE_PASSWORD,
username,
password,
DEFAULT_SCOPE);
return BEARER + tokenExchangeResponse.getAccessToken();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package uk.gov.hmcts.cmc.claimstore.services.user;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.models.idam.UserInfo;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;
import uk.gov.hmcts.cmc.claimstore.stereotypes.LogExecutionTime;

@Component
@ConditionalOnProperty(prefix = "idam.user.token.cache", name = "enabled", havingValue = "false", matchIfMissing = true)
public class UserInfoService implements IUserInfoService {

private final IdamApi idamApi;
Logger logger = LoggerFactory.getLogger(this.getClass());

public UserInfoService(IdamApi idamApi) {
this.idamApi = idamApi;
}

@Override
@LogExecutionTime
public UserInfo getUserInfo(String bearerToken) {
logger.info("IDAM /o/userinfo invoked");
return idamApi.retrieveUserInfo(bearerToken);
}
}
4 changes: 4 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ idam:
url: "http://localhost:4552"
totp_secret: "AAAAAAAAAAAAAAAA"
microservice: "cmc_claim_store"
user:
token:
cache:
enabled: ${USER_TOKEN_CACHE_ENABLED:false}

courtfinder:
api:
Expand Down
Loading

0 comments on commit e4c1e31

Please sign in to comment.