diff --git a/kraken-java-sdk/kraken-java-sdk-auth/src/main/java/com/consoleconnect/kraken/operator/auth/model/AuthDataProperty.java b/kraken-java-sdk/kraken-java-sdk-auth/src/main/java/com/consoleconnect/kraken/operator/auth/model/AuthDataProperty.java index 532cc75d..773874ff 100644 --- a/kraken-java-sdk/kraken-java-sdk-auth/src/main/java/com/consoleconnect/kraken/operator/auth/model/AuthDataProperty.java +++ b/kraken-java-sdk/kraken-java-sdk-auth/src/main/java/com/consoleconnect/kraken/operator/auth/model/AuthDataProperty.java @@ -70,6 +70,7 @@ public static class ResourceServer { private String bearerTokenHeaderName = "Authorization"; private String userId = "x-kraken-userId"; private SecurityFilter securityFilter = new SecurityFilter(); + private Verifier verifier = new Verifier(); } @Data @@ -130,4 +131,9 @@ public static class FilterConfig { private List paths = List.of(); private String filterName; } + + @Data + public static class Verifier { + private String env; + } } diff --git a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/handler/ClientServerAPIHandler.java b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/handler/ClientServerAPIHandler.java index e2f18654..5b4aa15e 100644 --- a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/handler/ClientServerAPIHandler.java +++ b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/handler/ClientServerAPIHandler.java @@ -11,6 +11,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import java.time.ZonedDateTime; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -38,30 +40,31 @@ public HttpResponse onEvent(String envId, String userId, ClientEvent event if (CollectionUtils.isEmpty(serverAPIDtos)) { return HttpResponse.ok(null); } - serverAPIDtos.forEach( - serverAPIDto -> { - EnvironmentClientEntity environmentClientEntity = - environmentClientRepository - .findOneByEnvIdAndClientKeyAndKind( - envId, - serverAPIDto.getServerKey(), - ClientReportTypeEnum.CLIENT_SERVER_API.name()) - .orElseGet( - () -> { - EnvironmentClientEntity entity = new EnvironmentClientEntity(); - entity.setEnvId(envId); - entity.setKind(ClientReportTypeEnum.CLIENT_SERVER_API.name()); - entity.setClientKey(serverAPIDto.getServerKey()); - entity.setCreatedAt(ZonedDateTime.now()); - entity.setCreatedBy(userId); - return entity; - }); - environmentClientEntity.setUpdatedAt(ZonedDateTime.now()); - environmentClientEntity.setUpdatedBy(userId); - environmentClientEntity.setPayload(serverAPIDto); - environmentClientRepository.save(environmentClientEntity); - }); - + Map> serverKeyMap = + serverAPIDtos.stream().collect(Collectors.groupingBy(ServerAPIDto::getServerKey)); + serverKeyMap + .entrySet() + .forEach( + entry -> { + EnvironmentClientEntity environmentClientEntity = + environmentClientRepository + .findOneByEnvIdAndClientKeyAndKind( + envId, entry.getKey(), ClientReportTypeEnum.CLIENT_SERVER_API.name()) + .orElseGet( + () -> { + EnvironmentClientEntity entity = new EnvironmentClientEntity(); + entity.setEnvId(envId); + entity.setKind(ClientReportTypeEnum.CLIENT_SERVER_API.name()); + entity.setClientKey(entry.getKey()); + entity.setCreatedAt(ZonedDateTime.now()); + entity.setCreatedBy(userId); + return entity; + }); + environmentClientEntity.setUpdatedAt(ZonedDateTime.now()); + environmentClientEntity.setUpdatedBy(userId); + environmentClientEntity.setPayload(entry.getValue()); + environmentClientRepository.save(environmentClientEntity); + }); return HttpResponse.ok(null); } } diff --git a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/BuyerService.java b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/BuyerService.java index d04916da..e5cbb449 100644 --- a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/BuyerService.java +++ b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/BuyerService.java @@ -47,6 +47,7 @@ public class BuyerService extends AssetStatusManager { private static final String BUYER_KEY_PREFIX = "mef.sonata.buyer"; private static final String BUYER_NAME = "Buyer"; private static final String BUYER_DESC = "Onboard buyer information"; + public static final String ENV = "env"; @Getter private final UnifiedAssetService unifiedAssetService; private final UnifiedAssetRepository unifiedAssetRepository; @@ -166,7 +167,7 @@ private BuyerAssetDto.BuyerToken generateBuyerToken( if (StringUtils.isNotBlank(envId)) { Environment environment = environmentService.findOne(envId); log.info("generateBuyerToken, envId:{}, envName:{}", envId, environment.getName()); - claims.put("env", environment.getName()); + claims.put(ENV, environment.getName()); } if (authServer.isEnabled()) { String token = diff --git a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/EndPointUsageCalculator.java b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/EndPointUsageCalculator.java index dff3e458..12da1d13 100644 --- a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/EndPointUsageCalculator.java +++ b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/EndPointUsageCalculator.java @@ -94,9 +94,10 @@ default void calculateDataPlane( return; } String json = JsonToolkit.toJson(environmentClientEntity.getPayload()); - ServerAPIDto serverAPIDto = - JsonToolkit.fromJson(json, new TypeReference() {}); - List mapperKeys = List.of(serverAPIDto.getMapperKey()); + List serverAPIDtos = + JsonToolkit.fromJson(json, new TypeReference>() {}); + List mapperKeys = + serverAPIDtos.stream().map(ServerAPIDto::getMapperKey).toList(); List list = getUnifiedAssetService().findByAllKeysIn(mapperKeys, true); list.forEach(this::hiddenMappers); diff --git a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/TemplateUpgradeService.java b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/TemplateUpgradeService.java index 2be48678..f0f620c8 100644 --- a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/TemplateUpgradeService.java +++ b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/TemplateUpgradeService.java @@ -23,10 +23,7 @@ import com.consoleconnect.kraken.operator.core.event.IngestionDataResult; import com.consoleconnect.kraken.operator.core.exception.KrakenException; import com.consoleconnect.kraken.operator.core.ingestion.DataIngestionJob; -import com.consoleconnect.kraken.operator.core.model.AssetLink; -import com.consoleconnect.kraken.operator.core.model.Metadata; -import com.consoleconnect.kraken.operator.core.model.SyncMetadata; -import com.consoleconnect.kraken.operator.core.model.UnifiedAsset; +import com.consoleconnect.kraken.operator.core.model.*; import com.consoleconnect.kraken.operator.core.model.facet.ComponentAPITargetFacets; import com.consoleconnect.kraken.operator.core.repo.UnifiedAssetRepository; import com.consoleconnect.kraken.operator.core.service.CompatibilityCheckService; @@ -73,6 +70,7 @@ public class TemplateUpgradeService { private final TransactionService transactionService; private final CompatibilityCheckService compatibilityCheckService; private final EventSinkService eventSinkService; + private final AppProperty appProperty; protected String deployProduction( String templateUpgradeId, String stageEnvId, String productionEnvId, String userId) { @@ -332,6 +330,7 @@ public Paging listTemplateDeployment( public List templateDeploymentDetailsFromControlDeployment( UnifiedAssetDto templateDeployment) { Map> apiUseCases = apiComponentService.findApiUseCase(); + log.info("apiUseCases : {}", JsonToolkit.toJson(apiUseCases)); ControlDeploymentFacet controlDeploymentFacet = UnifiedAsset.getFacets(templateDeployment, ControlDeploymentFacet.class); UpgradeTuple upgradeTuple = controlDeploymentFacet.getUpgradeTuple(); @@ -347,6 +346,7 @@ public List templateDeploymentDetailsFromControlDeployment( .filter(Optional::isPresent) .map(Optional::get) .map(ApiUseCaseDto::getMapperKey) + .filter(t -> !appProperty.getQueryExcludeAssetKeys().contains(t)) .distinct() .map(this::getMapperTagVOFromDraft) .toList(); diff --git a/kraken-java-sdk/kraken-java-sdk-core/src/main/java/com/consoleconnect/kraken/operator/core/toolkit/Constants.java b/kraken-java-sdk/kraken-java-sdk-core/src/main/java/com/consoleconnect/kraken/operator/core/toolkit/Constants.java index 14a8229e..3f678dcb 100644 --- a/kraken-java-sdk/kraken-java-sdk-core/src/main/java/com/consoleconnect/kraken/operator/core/toolkit/Constants.java +++ b/kraken-java-sdk/kraken-java-sdk-core/src/main/java/com/consoleconnect/kraken/operator/core/toolkit/Constants.java @@ -8,6 +8,7 @@ private Constants() {} public static final String COMMA = ","; public static final String MAPPER_SIGN = "-mapper"; public static final String INIT_VERSION = "1.0"; + public static final String ENV = "env"; public static String formatVersion(String version) { return version.replaceFirst("[V|v]", ""); diff --git a/kraken-java-sdk/kraken-java-sdk-gateway/src/main/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckerService.java b/kraken-java-sdk/kraken-java-sdk-gateway/src/main/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckerService.java index 299d6a67..316bf04a 100644 --- a/kraken-java-sdk/kraken-java-sdk-gateway/src/main/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckerService.java +++ b/kraken-java-sdk/kraken-java-sdk-gateway/src/main/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckerService.java @@ -1,5 +1,6 @@ package com.consoleconnect.kraken.operator.gateway.service; +import com.consoleconnect.kraken.operator.auth.model.AuthDataProperty; import com.consoleconnect.kraken.operator.auth.security.SecurityChecker; import com.consoleconnect.kraken.operator.core.dto.Tuple2; import com.consoleconnect.kraken.operator.core.dto.UnifiedAssetDto; @@ -8,21 +9,27 @@ import com.consoleconnect.kraken.operator.core.exception.KrakenException; import com.consoleconnect.kraken.operator.core.service.UnifiedAssetService; import com.consoleconnect.kraken.operator.core.toolkit.AssetsConstants; +import com.consoleconnect.kraken.operator.core.toolkit.Constants; import com.consoleconnect.kraken.operator.core.toolkit.LabelConstants; import java.time.Instant; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.function.BiConsumer; import lombok.AllArgsConstructor; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.PageRequest; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.ReactiveSecurityContextHolder; +import org.springframework.security.core.context.SecurityContext; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import reactor.core.publisher.SynchronousSink; @Component(value = "securityBuyerChecker") @AllArgsConstructor @@ -30,48 +37,63 @@ public class BuyerCheckerService implements SecurityChecker { public static final int INTERVAL = 60; private UnifiedAssetService unifiedAssetService; + private AuthDataProperty.ResourceServer resourceServer; @Override public Mono internalRun(ServerWebExchange exchange) { return ReactiveSecurityContextHolder.getContext() - .handle( - (securityContext, sink) -> { - Authentication authentication = securityContext.getAuthentication(); - List list = - unifiedAssetService - .findBySpecification( - Tuple2.ofList( - AssetsConstants.FIELD_KIND, AssetKindEnum.PRODUCT_BUYER.getKind()), - Tuple2.ofList(LabelConstants.LABEL_BUYER_ID, authentication.getName()), - null, - PageRequest.ofSize(1), - null) - .getData(); - if (CollectionUtils.isEmpty(list)) { - sink.error(KrakenException.badRequest("buyer not found")); - return; - } - UnifiedAssetDto unifiedAssetDto = list.get(0); - if (AssetStatusEnum.DEACTIVATED - .getKind() - .equalsIgnoreCase(unifiedAssetDto.getMetadata().getStatus())) { - sink.error(KrakenException.badRequest("buyer deactivated")); - return; - } - Map labels = unifiedAssetDto.getMetadata().getLabels(); - Instant dbGeneratedAt = - Optional.ofNullable(labels.get(LabelConstants.LABEL_ISSUE_AT)) - .map(DateTimeFormatter.ISO_INSTANT::parse) - .map(Instant::from) - .orElse(Instant.MIN); - Jwt principal = (Jwt) authentication.getPrincipal(); - Instant issuedAt = principal.getIssuedAt(); - if (issuedAt.isBefore(dbGeneratedAt.minusSeconds(INTERVAL))) { - sink.error(KrakenException.badRequest("Token expired ")); - return; - } - sink.next(new Object()); - }); + .handle(getSecurityContextSynchronousSinkBiConsumer()); + } + + public BiConsumer> + getSecurityContextSynchronousSinkBiConsumer() { + return (securityContext, sink) -> { + Authentication authentication = securityContext.getAuthentication(); + List list = + unifiedAssetService + .findBySpecification( + Tuple2.ofList(AssetsConstants.FIELD_KIND, AssetKindEnum.PRODUCT_BUYER.getKind()), + Tuple2.ofList(LabelConstants.LABEL_BUYER_ID, authentication.getName()), + null, + PageRequest.ofSize(1), + null) + .getData(); + if (CollectionUtils.isEmpty(list)) { + sink.error(KrakenException.badRequest("buyer not found")); + return; + } + UnifiedAssetDto unifiedAssetDto = list.get(0); + if (AssetStatusEnum.DEACTIVATED + .getKind() + .equalsIgnoreCase(unifiedAssetDto.getMetadata().getStatus())) { + sink.error(KrakenException.badRequest("buyer deactivated")); + return; + } + Map labels = unifiedAssetDto.getMetadata().getLabels(); + Instant dbGeneratedAt = + Optional.ofNullable(labels.get(LabelConstants.LABEL_ISSUE_AT)) + .map(DateTimeFormatter.ISO_INSTANT::parse) + .map(Instant::from) + .orElse(Instant.MIN); + Jwt principal = (Jwt) authentication.getPrincipal(); + String signEnv = + Optional.ofNullable(principal.getClaims()) + .map(map -> map.get(Constants.ENV)) + .map(Object::toString) + .orElse(""); + if (!StringUtils.equalsIgnoreCase(resourceServer.getVerifier().getEnv(), signEnv)) { + sink.error( + KrakenException.badRequest( + "Invalid buyer: invalid environment identity env:" + signEnv)); + return; + } + Instant issuedAt = principal.getIssuedAt(); + if (Objects.requireNonNull(issuedAt).isBefore(dbGeneratedAt.minusSeconds(INTERVAL))) { + sink.error(KrakenException.badRequest("Token expired ")); + return; + } + sink.next(new Object()); + }; } @Override diff --git a/kraken-java-sdk/kraken-java-sdk-gateway/src/test/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckServiceTest.java b/kraken-java-sdk/kraken-java-sdk-gateway/src/test/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckServiceTest.java index 9d05fb21..7818205a 100644 --- a/kraken-java-sdk/kraken-java-sdk-gateway/src/test/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckServiceTest.java +++ b/kraken-java-sdk/kraken-java-sdk-gateway/src/test/java/com/consoleconnect/kraken/operator/gateway/service/BuyerCheckServiceTest.java @@ -1,5 +1,7 @@ package com.consoleconnect.kraken.operator.gateway.service; +import static org.mockito.Mockito.when; + import com.consoleconnect.kraken.operator.auth.model.AuthDataProperty; import com.consoleconnect.kraken.operator.core.enums.AssetKindEnum; import com.consoleconnect.kraken.operator.core.enums.AssetStatusEnum; @@ -12,15 +14,19 @@ import com.consoleconnect.kraken.operator.gateway.CustomConfig; import com.consoleconnect.kraken.operator.test.AbstractIntegrationTest; import com.consoleconnect.kraken.operator.test.MockIntegrationTest; -import com.nimbusds.jwt.JWTParser; import java.time.Instant; import java.time.format.DateTimeFormatter; import lombok.SneakyThrows; import org.junit.jupiter.api.*; +import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextImpl; +import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.SynchronousSink; @MockIntegrationTest @ContextConfiguration(classes = CustomConfig.class) @@ -32,6 +38,8 @@ public class BuyerCheckServiceTest extends AbstractIntegrationTest { @Autowired BuyerCheckerService buyerCheckerService; @Autowired WebTestClient webTestClient; @Autowired AuthDataProperty.ResourceServer resourceServer; + @Mock private Authentication principal; + @Mock SynchronousSink sink; private final String xKrakenKeyToken = "eyJhbGciOiJIUzI1NiIsImtpZCI6ImtyYWtlbiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ0Mzg1Mzc5NDIsImlhdCI6MTcyNzMyODM0MiwiaXNzIjoiaHR0cHM6Ly9rcmFrZW4uY29uc29sZWNvbm5lY3QuY29tL2lzc3VlciIsInN1YiI6ImJ1eWVyMDIifQ.9FL7_ph6-NtJg5hNSOqt8HaxwMg66gnEjpb_XCMsXrY"; @@ -42,8 +50,17 @@ void givenBuyer_whenInit_thenReturnData() { UnifiedAsset unifiedAsset = UnifiedAsset.of(AssetKindEnum.PRODUCT_BUYER.getKind(), "buyer02", "buyer02"); unifiedAsset.getMetadata().setStatus(AssetStatusEnum.ACTIVATED.getKind()); - - Instant instant = JWTParser.parse(xKrakenKeyToken).getJWTClaimsSet().getIssueTime().toInstant(); + Jwt jwt = + Jwt.withTokenValue(xKrakenKeyToken) + .headers( + map -> { + map.put("alg", "HS256"); + map.put("typ", "JWT"); + }) + .issuedAt(Instant.now().minusSeconds(60)) + .claim("env", "stage") + .build(); + Instant instant = jwt.getIssuedAt(); unifiedAsset .getMetadata() .getLabels() @@ -57,6 +74,10 @@ void givenBuyer_whenInit_thenReturnData() { unifiedAsset, new SyncMetadata("", "", DateTime.nowInUTCString(), ""), true); + when(principal.getName()).thenReturn("buyer02"); + when(principal.getPrincipal()).thenReturn(jwt); + SecurityContextImpl context = new SecurityContextImpl(this.principal); + buyerCheckerService.getSecurityContextSynchronousSinkBiConsumer().accept(context, sink); Assertions.assertEquals(200, ingestionDataResult.getCode()); } }