Skip to content

Commit

Permalink
QA-5872: completed the logic to dynamically generate the tracing and …
Browse files Browse the repository at this point in the history
…interop tokens for the QA environment. Additionally, a switch was added to execute the tracing tests in the dev environment
  • Loading branch information
mmancini95 committed Feb 13, 2025
1 parent c7b6c5c commit c17641c
Show file tree
Hide file tree
Showing 17 changed files with 253 additions and 70 deletions.
3 changes: 3 additions & 0 deletions interop-qa-tests/config/application-dev.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#TRACING
pn.interop.tracing.base-url=https://api.dev.tracing.interop.pagopa.it

2 changes: 2 additions & 0 deletions interop-qa-tests/config/application-qa.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#TRACING
pn.interop.tracing.base-url=https://api.qa.tracing.interop.pagopa.it
4 changes: 2 additions & 2 deletions interop-qa-tests/config/application.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
spring.profiles.active=dev
#TRACING
pn.interop.tracing.base-url=https://api.dev.tracing.interop.pagopa.it
pn.interop.tracing.base-url=https://api.qa.tracing.interop.pagopa.it
pn.interop.tracing.bearerToken-1=${interop.configuration.tracing.bearerToken-1}
pn.interop.tracing.bearerToken-2=${interop.configuration.tracing.bearerToken-2}
#PURPOSE_ID 28874634-6ea6-4def-b200-7377182c71be
Expand All @@ -9,7 +10,6 @@ interop.configuration.tracing.bearerToken-2=eyJhbGciOiJSUzI1NiIsInVzZSI6InNpZyIs

#INTEROP GLOBAL PROPERTIES
bff.base-url=https://selfcare.qa.interop.pagopa.it/1.0/backend-for-frontend
remote-wellknown-url=https://qa.interop.pagopa.it/.well-known/jwks.json
session.tokens.duration.seconds=3000
interop-env=qa
max-polling-try-ms=50
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private ApiClient createApiClient(String bearerToken) {

@Override
public CreatedResource createAgreement(String xCorrelationId, AgreementPayload agreementPayload) {
return agreementsApi.createAgreement(xCorrelationId, agreementPayload);
return agreementsApi.createAgreement(agreementPayload);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package it.pagopa.interop.authorization.service.factory;

import it.pagopa.interop.authorization.service.utils.ConfigFileReader;
import it.pagopa.interop.conf.InteropClientConfigs;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Map;

@Slf4j
@Getter
@Setter
public class InteropTokenFactory extends SessionTokenFactory {
private static final String WELLKNOWN_URL = "https://qa.interop.pagopa.it/.well-known/jwks.json";
private Map<String, Map<String, String>> cachedTokens = null;

public InteropTokenFactory(InteropClientConfigs interopClientConfigs, ConfigFileReader configFileReader) {
super(interopClientConfigs, configFileReader);
}

public Map<String, Map<String, String>> loadToken() {
getSessionTokenPayloadTemplate().put("aud", "{{ENVIRONMENT}}.interop.pagopa.it/ui");
try {
if (cachedTokens == null) cachedTokens = generateSessionToken();
} catch (Exception ex) {
throw new IllegalArgumentException("There was an error while creating the session token: " + ex.getMessage(), ex);
}
return cachedTokens;
}

@Override
public String getRemoteWellknownUrl() {
return WELLKNOWN_URL;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@
import software.amazon.awssdk.services.kms.model.VerifyResponse;

@Slf4j
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class SessionTokenFactory {
public abstract class SessionTokenFactory {
private static final Map<String, Map<String, String>> CONFIG = new HashMap<>();
private static final Map<String, Object> SESSION_TOKEN_PAYLOAD_TEMPLATE;
private static final Map<String, String> SESSION_TOKEN_HEADER_TEMPLATE = Map.of(
Expand Down Expand Up @@ -72,45 +70,33 @@ public class SessionTokenFactory {
));
SESSION_TOKEN_PAYLOAD_TEMPLATE.put("uid", "VALUES_UID");
SESSION_TOKEN_PAYLOAD_TEMPLATE.put("iss", "{{ENVIRONMENT}}.interop.pagopa.it");
SESSION_TOKEN_PAYLOAD_TEMPLATE.put("aud", "{{ENVIRONMENT}}.interop.pagopa.it/ui");
SESSION_TOKEN_PAYLOAD_TEMPLATE.put("nbf", 123);
SESSION_TOKEN_PAYLOAD_TEMPLATE.put("iat", 123);
SESSION_TOKEN_PAYLOAD_TEMPLATE.put("exp", 456);
SESSION_TOKEN_PAYLOAD_TEMPLATE.put("jti", "uuid");
}

private final InteropClientConfigs interopClientConfigs;
@Getter
private Map<String, Map<String, String>> cachedTokens = null;
private ConfigFileReader configFileReader;


public SessionTokenFactory(InteropClientConfigs interopClientConfigs, ConfigFileReader configFileReader) {
this.interopClientConfigs = interopClientConfigs;
this.configFileReader = configFileReader;
this.cachedTokens = loadToken();
}

private Map<String, Map<String, String>> loadToken() {
try {
if (cachedTokens == null) {
cachedTokens = generateSessionToken(configFileReader.getTenantList());
}
} catch (Exception ex) {
throw new IllegalArgumentException("There was an error while creating the session token: " + ex.getMessage(), ex);
}
return cachedTokens;
}
public abstract Map<String, Map<String, String>> loadToken();

public abstract String getRemoteWellknownUrl();

public Map<String, Map<String, String>> generateSessionToken(List<Tenant> configFile) throws Exception {
public Map<String, Map<String, String>> generateSessionToken() throws Exception {
// Step 1. Read session token payload values file
log.info("##Generating session token... ##");
log.debug("##Step 1. Read session token payload values file ##");
ObjectMapper objectMapper = new ObjectMapper();

// Step 2. Parse well known
log.debug("##Step 2. Parse well known ##");
URL wellKnownUrl = new URL(interopClientConfigs.getRemoteWellknownUrl());
URL wellKnownUrl = new URL(getRemoteWellknownUrl());
Map<String, String> wellKnownData = fetchWellKnown(wellKnownUrl.toString());
if (!wellKnownData.containsKey("kid") || !wellKnownData.containsKey("alg")) {
throw new IllegalStateException("Kid or alg not found.");
Expand Down Expand Up @@ -152,7 +138,7 @@ public Map<String, Map<String, String>> generateSessionToken(List<Tenant> config
log.debug("ST Payload Compiled: {}", stPayloadCompiled);

log.debug("## Step 5. Generate unsigned STs ##");
Map<String, Map<String, String>> unsignedSTs = unsignedStsGeneration(stHeaderCompiled, stPayloadCompiled, configFile, environment);
Map<String, Map<String, String>> unsignedSTs = unsignedStsGeneration(stHeaderCompiled, stPayloadCompiled, configFileReader.getTenantList(), environment);
log.debug("Unsigned STs: {}", unsignedSTs);

log.debug("## Step 6. Generate signed STs ##");
Expand Down Expand Up @@ -191,9 +177,8 @@ private static Map<String, String> fetchWellKnown(String wellKnownUrl) throws Ex
}


public Map<String, Map<String, String>> unsignedStsGeneration(
Map<String, String> stHeaderCompiled, HashMap<String, Object> stPayloadCompiled, List<Tenant> stPayloadValues, String environment) {

private Map<String, Map<String, String>> unsignedStsGeneration(Map<String, String> stHeaderCompiled,
HashMap<String, Object> stPayloadCompiled, List<Tenant> stPayloadValues, String environment) {
try {
log.debug("unsignedStsGeneration::Phase1:START: Build roles dynamic substitutions");
Map<String, Object> stsSubOutput = new HashMap<>();
Expand Down Expand Up @@ -290,7 +275,7 @@ private Map<String, Map<String, String>> signedStsGeneration(Map<String, Map<Str
}

// Base64 URL-safe encoding function (without padding)
public static String b64UrlEncode(String str) {
private static String b64UrlEncode(String str) {
return Base64.getUrlEncoder().withoutPadding().encodeToString(str.getBytes());
}

Expand Down Expand Up @@ -347,4 +332,8 @@ private boolean kmsVerify(String unsignedToken, SignResponse signature) {
}
}

public Map<String, Object> getSessionTokenPayloadTemplate() {
return SESSION_TOKEN_PAYLOAD_TEMPLATE;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package it.pagopa.interop.authorization.service.factory;

import it.pagopa.interop.authorization.service.utils.ConfigFileReader;
import it.pagopa.interop.conf.InteropClientConfigs;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Map;

@Slf4j
@Getter
@Setter
public class TracingTokenFactory extends SessionTokenFactory {
private static final String WELLKNOWN_URL = "https://tracing-qa-only-well-known-qa.s3.eu-south-1.amazonaws.com/.well-known/jwks.json";
private Map<String, Map<String, String>> cachedTokens = null;

public TracingTokenFactory(InteropClientConfigs interopClientConfigs, ConfigFileReader configFileReader) {
super(interopClientConfigs, configFileReader);
}

@Override
public Map<String, Map<String, String>> loadToken() {
getSessionTokenPayloadTemplate().put("aud", "{{ENVIRONMENT}}.interop.pagopa.it/m2m");
try {
if (cachedTokens == null) cachedTokens = generateSessionToken();
} catch (Exception ex) {
throw new IllegalArgumentException("There was an error while creating the session token: " + ex.getMessage(), ex);
}
return cachedTokens;
}

@Override
public String getRemoteWellknownUrl() {
return WELLKNOWN_URL;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package it.pagopa.interop.authorization.service.utils;

import it.pagopa.interop.authorization.domain.Tenant;
import it.pagopa.interop.authorization.service.factory.InteropTokenFactory;
import it.pagopa.interop.authorization.service.factory.SessionTokenFactory;
import it.pagopa.interop.authorization.service.factory.TracingTokenFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
Expand All @@ -13,8 +15,6 @@
import java.util.UUID;

@Slf4j
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class IdentityService {
private final SessionTokenFactory sessionTokenFactory;
private final List<Tenant> tenantList;
Expand All @@ -26,7 +26,7 @@ public IdentityService(SessionTokenFactory sessionTokenFactory,
}

public String getToken(String tenantType, String role) {
String token = Optional.ofNullable(sessionTokenFactory.getCachedTokens())
String token = Optional.ofNullable(sessionTokenFactory.loadToken())
.map(m -> m.get(tenantType))
.map(m -> (role == null) ? m.get("admin") : m.get(role))
.filter(Objects::nonNull)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package it.pagopa.interop.config.springconfig.springconfig;

import it.pagopa.interop.authorization.service.factory.InteropTokenFactory;
import it.pagopa.interop.authorization.service.factory.TracingTokenFactory;
import it.pagopa.interop.authorization.service.utils.ConfigFileReader;
import it.pagopa.interop.authorization.service.utils.IdentityService;
import it.pagopa.interop.conf.InteropClientConfigs;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;

@Configuration
public class JwtTokenServiceConfiguration {

@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public TracingTokenFactory tracingTokenFactory(InteropClientConfigs interopClientConfigs, ConfigFileReader configFileReader) {
return new TracingTokenFactory(interopClientConfigs, configFileReader);
}

@Bean
@Primary
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public InteropTokenFactory interopTokenFactory(InteropClientConfigs interopClientConfigs, ConfigFileReader configFileReader) {
return new InteropTokenFactory(interopClientConfigs, configFileReader);
}

@Bean(name = "tracingIdentityService")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public IdentityService tracingIdentityService(TracingTokenFactory tracingTokenFactory, ConfigFileReader configFileReader) {
return new IdentityService(tracingTokenFactory, configFileReader);
}

@Bean(name = "interopIdentityService")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public IdentityService interopIdentityService(InteropTokenFactory interopTokenFactory, ConfigFileReader configFileReader) {
return new IdentityService(interopTokenFactory, configFileReader);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ public CreatedResource createProducerDelegation(String xCorrelationId, Delegatio

@Override
public void approveDelegation(String xCorrelationId, UUID delegationId) {
producerDelegationsApi.approveDelegation(xCorrelationId, delegationId);
producerDelegationsApi.approveProducerDelegation(xCorrelationId, delegationId);
}

@Override
public void rejectDelegation(String xCorrelationId, UUID delegationId, RejectDelegationPayload rejectDelegationPayload) {
producerDelegationsApi.rejectDelegation(xCorrelationId, delegationId, rejectDelegationPayload);
producerDelegationsApi.rejectProducerDelegation(xCorrelationId, delegationId, rejectDelegationPayload);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,28 @@
import it.pagopa.interop.client.b2b.generated.openapi.clients.interop.model.TracingState;
import it.pagopa.interop.tracing.config.TracingClientConfigs;
import it.pagopa.interop.tracing.service.IInteropTracingClient;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.UUID;

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class InteropTracingClientImpl implements IInteropTracingClient {
public abstract class AbstractInteropTracingClient implements IInteropTracingClient {
private final RestTemplate restTemplate;
private final TracingsApi tracingsApi;
private final HealthApi healthApi;
protected final TracingsApi tracingsApi;
protected final HealthApi healthApi;
private final TracingClientConfigs tracingClientConfigs;
private BearerTokenType bearerTokenSetted;
protected BearerTokenType bearerTokenSetted;

public InteropTracingClientImpl(RestTemplate restTemplate, TracingClientConfigs tracingClientConfigs) {
public AbstractInteropTracingClient(RestTemplate restTemplate, TracingClientConfigs tracingClientConfigs, String bearerToken) {
this.restTemplate = restTemplate;
this.tracingClientConfigs = tracingClientConfigs;
this.tracingsApi = new TracingsApi(createApiClient(tracingClientConfigs.getBaseUrl(), tracingClientConfigs.getBearerToken1()));
this.healthApi = new HealthApi(createApiClient(tracingClientConfigs.getBaseUrl(), tracingClientConfigs.getBearerToken1()));
this.bearerTokenSetted = BearerTokenType.TENANT_1;
this.tracingsApi = new TracingsApi(createApiClient(tracingClientConfigs.getBaseUrl(), bearerToken));
this.healthApi = new HealthApi(createApiClient(tracingClientConfigs.getBaseUrl(), bearerToken));
}

private ApiClient createApiClient(String basePath, String bearerToken) {
protected ApiClient createApiClient(String basePath, String bearerToken) {
ApiClient apiClient = new ApiClient(restTemplate);
apiClient.setBasePath(basePath);
apiClient.setBearerToken(bearerToken);
Expand Down Expand Up @@ -75,23 +69,11 @@ public void getHealthStatus() {
healthApi.getStatus();
}

@Override
public void setBearerToken(String bearerToken) {
switch (bearerToken) {
case "TENANT_1" -> {
this.tracingsApi.setApiClient(createApiClient(tracingClientConfigs.getBaseUrl(), tracingClientConfigs.getBearerToken1()));
this.bearerTokenSetted = BearerTokenType.TENANT_1;
}
case "TENANT_2" -> {
this.tracingsApi.setApiClient(createApiClient(tracingClientConfigs.getBaseUrl(), tracingClientConfigs.getBearerToken2()));
this.bearerTokenSetted = BearerTokenType.TENANT_2;
}
default -> throw new IllegalStateException("Unexpected value: " + bearerToken);
}
}

public BearerTokenType getBearerTokenSetted() {
return this.bearerTokenSetted;
}

public TracingClientConfigs getTracingClientConfigs() {
return tracingClientConfigs;
}
}
Loading

0 comments on commit c17641c

Please sign in to comment.