From 219ad873f11cb288a1f3a318a0a1618e29b6babe Mon Sep 17 00:00:00 2001 From: pujavs Date: Mon, 27 Jan 2025 22:25:30 +0530 Subject: [PATCH 1/3] test(config-api) scim test failure #10749 Signed-off-by: pujavs --- .../docs/jans-config-api-swagger.yaml | 16 ++++----- .../configapi/plugin/scim/ScimBaseTest.java | 3 -- .../auth/AgamaDeploymentsResource.java | 33 +++++++++++++------ .../service/auth/AgamaDeploymentsService.java | 5 ++- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index ec235485d21..9d835a04cf5 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -9337,19 +9337,19 @@ components: type: string selected: type: boolean - adminCanEdit: + whitePagesCanView: type: boolean - userCanView: + adminCanView: type: boolean - userCanEdit: + userCanView: type: boolean - adminCanView: + adminCanEdit: type: boolean - adminCanAccess: + userCanEdit: type: boolean userCanAccess: type: boolean - whitePagesCanView: + adminCanAccess: type: boolean baseDn: type: string @@ -11769,10 +11769,10 @@ components: ttl: type: integer format: int32 - persisted: - type: boolean opbrowserState: type: string + persisted: + type: boolean SessionIdAccessMap: type: object properties: diff --git a/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java b/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java index 4ad647b415b..9277a17b4a8 100644 --- a/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java +++ b/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java @@ -15,9 +15,6 @@ public class ScimBaseTest extends BaseTest { - protected boolean isAvailable(final String url, Map headers, final Map parameters) { - return isEndpointAvailable(url, headers, parameters); - } // Execute before each test is run @BeforeMethod diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java index a84eb57bec4..2f8521d7927 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import static io.jans.as.model.util.Util.escapeLog; import io.jans.ads.model.Deployment; import io.jans.agama.model.Flow; import io.jans.as.model.util.Pair; @@ -77,12 +78,14 @@ public Response getDeployments(@Parameter(description = "Start index for the res @Produces(MediaType.APPLICATION_JSON) @Path(ApiConstants.NAME_PARAM_PATH) public Response getDeployment(@Parameter(description = "Agama project name") @PathParam(ApiConstants.NAME) String projectName) { - + if (logger.isInfoEnabled()) { + logger.info("Get projectName:{}", escapeLog(projectName)); + } Pair p = getDeploymentP(projectName); Deployment d = p.getSecond(); if (d == null) return errorResponse(p.getFirst(), projectName); - + logger.debug("deployment:{}", d); return Response.ok(d).build(); } @@ -102,7 +105,9 @@ public Response getDeployment(@Parameter(description = "Agama project name") @Pa @Path(ApiConstants.NAME_PARAM_PATH) public Response deploy(@Parameter(description = "Agama project name") @PathParam(ApiConstants.NAME) String projectName, @Parameter(description = "Boolean value to indicating to auto configure the project ") @QueryParam("autoconfigure") String autoconfigure, @Parameter(description = "Agama gama file") byte[] gamaBinary) { - + if (logger.isInfoEnabled()) { + logger.info("Deploy projectName:{}, autoconfigure:{}, gamaBinary:{}", escapeLog(projectName), escapeLog(autoconfigure), escapeLog(gamaBinary)); + } if (gamaBinary == null) return Response.status(Response.Status.BAD_REQUEST) .entity("Project name or binary data missing").build(); @@ -131,7 +136,9 @@ public Response deploy(@Parameter(description = "Agama project name") @PathParam superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) @Path(ApiConstants.NAME_PARAM_PATH) public Response undeploy(@Parameter(description = "Agama project name") @PathParam(ApiConstants.NAME) String projectName) { - + if (logger.isInfoEnabled()) { + logger.info("Undeploy projectName:{}", escapeLog(projectName)); + } Boolean result = ads.createUndeploymentTask(projectName); if (result == null) @@ -156,16 +163,18 @@ public Response undeploy(@Parameter(description = "Agama project name") @PathPar @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_READ_ACCESS }, groupScopes = {ApiAccessConstants.AGAMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.CONFIGS + ApiConstants.NAME_PARAM_PATH) public Response getConfigs(@Parameter(description = "Agama project name") @PathParam(ApiConstants.NAME) String projectName) { - + if (logger.isInfoEnabled()) { + logger.info("getConfigs projectName:{}", escapeLog(projectName)); + } Pair p = getDeploymentP(projectName); Deployment d = p.getSecond(); - + logger.debug("Deployment:{}", d); if (d == null) return errorResponse(p.getFirst(), projectName); Map> configs = new HashMap<>(); Set flowIds = Optional.ofNullable(d.getDetails().getFlowsError()) .map(Map::keySet).orElse(Collections.emptySet()); - + logger.debug("flowIds:{}", flowIds); for (String qname : flowIds) { Map config = Optional.ofNullable(flowService.getFlowByName(qname)) .map(f -> f.getMetadata().getProperties()).orElse(null); @@ -177,6 +186,7 @@ public Response getConfigs(@Parameter(description = "Agama project name") @PathP configs.put(qname, config); } } + logger.debug("configs:{}", configs); //Use own mapper so any empty maps/nulls that may be found inside flows configurations are not //ignored. Using @JsonInclude(Include.ALWAYS) in FlowMetadata#properties did not help try { @@ -203,7 +213,9 @@ public Response getConfigs(@Parameter(description = "Agama project name") @PathP @Path(ApiConstants.CONFIGS + ApiConstants.NAME_PARAM_PATH) public Response setConfigs(@Parameter(description = "Agama project name") @PathParam(ApiConstants.NAME) String projectName, @Parameter(description = "Agama flow config, key is `name` of config property and `value` is the property value. ") Map> flowsConfigs) { - + if (logger.isInfoEnabled()) { + logger.info("Set Agama project configs projectName:{}, flowsConfigs:{}", escapeLog(projectName), escapeLog(flowsConfigs)); + } if (flowsConfigs == null) { return Response.status(Response.Status.BAD_REQUEST) .entity("Mapping of flows vs. configs not provided").build(); @@ -211,13 +223,13 @@ public Response setConfigs(@Parameter(description = "Agama project name") @PathP Pair p = getDeploymentP(projectName); Deployment d = p.getSecond(); - + logger.debug("Set Agama project configs projectName:{}, Deployment:{}", projectName, d); if (d == null) return errorResponse(p.getFirst(), projectName); Map results = new HashMap<>(); Set flowIds = Optional.ofNullable(d.getDetails().getFlowsError()) .map(Map::keySet).orElse(Collections.emptySet()); - + logger.debug("Set Agama project configs projectName:{}, flowIds:{}", projectName, flowIds); for (String qname : flowsConfigs.keySet()) { if (qname != null && flowIds.contains(qname)) { @@ -242,6 +254,7 @@ public Response setConfigs(@Parameter(description = "Agama project name") @PathP projectName.replaceAll("[\n\r]", "_")); } } + logger.debug("Final Agama project configs projectName:{}, results:{}", projectName, results); return Response.ok(results).build(); } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaDeploymentsService.java b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaDeploymentsService.java index 554e929e06c..0761e5d3b33 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaDeploymentsService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AgamaDeploymentsService.java @@ -1,5 +1,6 @@ package io.jans.configapi.service.auth; +import static io.jans.as.model.util.Util.escapeLog; import io.jans.ads.model.Deployment; import io.jans.ads.model.DeploymentDetails; import io.jans.orm.model.PagedResult; @@ -55,7 +56,9 @@ public Deployment getDeployment(String name) { } public boolean createDeploymentTask(String name, byte[] gamaBinary, boolean autoconfigure) { - + if (logger.isInfoEnabled()) { + logger.info("AgamaDeploymentsService::createDeploymentTask() - name:{}, gamaBinary:{}, autoconfigure:{}", escapeLog(name), escapeLog(gamaBinary), escapeLog(autoconfigure)); + } Deployment d = null; String id = idFromName(name); try { From 467e1452d55d6a25803439f7b56734ad5b531b43 Mon Sep 17 00:00:00 2001 From: pujavs Date: Mon, 27 Jan 2025 22:39:35 +0530 Subject: [PATCH 2/3] test(config-api) scim test failure #10749 Signed-off-by: pujavs --- .../docs/jans-config-api-swagger.yaml | 20 +++++++++---------- .../configapi/plugin/scim/ScimBaseTest.java | 2 -- .../auth/AgamaDeploymentsResource.java | 6 +++--- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 9d835a04cf5..6ecd450a229 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -9335,22 +9335,22 @@ components: $ref: '#/components/schemas/AttributeValidation' tooltip: type: string - selected: - type: boolean - whitePagesCanView: + userCanEdit: type: boolean adminCanView: type: boolean - userCanView: - type: boolean adminCanEdit: type: boolean - userCanEdit: + userCanView: type: boolean userCanAccess: type: boolean adminCanAccess: type: boolean + selected: + type: boolean + whitePagesCanView: + type: boolean baseDn: type: string PatchRequest: @@ -11333,14 +11333,14 @@ components: type: boolean internal: type: boolean + locationPath: + type: string locationType: type: string enum: - ldap - db - file - locationPath: - type: string baseDn: type: string ScriptError: @@ -11769,10 +11769,10 @@ components: ttl: type: integer format: int32 - opbrowserState: - type: string persisted: type: boolean + opbrowserState: + type: string SessionIdAccessMap: type: object properties: diff --git a/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java b/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java index 9277a17b4a8..14b54f92db6 100644 --- a/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java +++ b/jans-config-api/plugins/scim-plugin/src/test/java/io/jans/configapi/plugin/scim/ScimBaseTest.java @@ -8,8 +8,6 @@ import io.jans.configapi.core.test.BaseTest; -import java.util.Map; - import org.testng.SkipException; import org.testng.annotations.BeforeMethod; diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java index 2f8521d7927..d52a491a8b3 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaDeploymentsResource.java @@ -223,13 +223,13 @@ public Response setConfigs(@Parameter(description = "Agama project name") @PathP Pair p = getDeploymentP(projectName); Deployment d = p.getSecond(); - logger.debug("Set Agama project configs projectName:{}, Deployment:{}", projectName, d); + logger.debug("Set Agama project configs Deployment:{}", d); if (d == null) return errorResponse(p.getFirst(), projectName); Map results = new HashMap<>(); Set flowIds = Optional.ofNullable(d.getDetails().getFlowsError()) .map(Map::keySet).orElse(Collections.emptySet()); - logger.debug("Set Agama project configs projectName:{}, flowIds:{}", projectName, flowIds); + logger.debug("Set Agama project configs flowIds:{}", flowIds); for (String qname : flowsConfigs.keySet()) { if (qname != null && flowIds.contains(qname)) { @@ -254,7 +254,7 @@ public Response setConfigs(@Parameter(description = "Agama project name") @PathP projectName.replaceAll("[\n\r]", "_")); } } - logger.debug("Final Agama project configs projectName:{}, results:{}", projectName, results); + logger.debug("Final Agama project configs results:{}", results); return Response.ok(results).build(); } From d50e8478a77aee4685dfff9e000bfe88e6d4f45a Mon Sep 17 00:00:00 2001 From: pujavs Date: Tue, 28 Jan 2025 22:15:36 +0530 Subject: [PATCH 3/3] feat(config-api): lock stat endpoint and SAML TR documentStore fix Signed-off-by: pujavs --- .../docs/jans-config-api-swagger.yaml | 12 +-- .../plugins/docs/lock-plugin-swagger.yaml | 6 +- .../plugin/saml/service/SamlIdpService.java | 36 ++++----- .../plugin/lock/rest/ApiApplication.java | 1 + .../plugin/lock/rest/LockStatResource.java | 13 ++-- .../plugin/lock/service/LockService.java | 78 +++++++++++++------ .../configapi/plugin/lock/util/Constants.java | 2 +- .../service/OpenIdAuthorizationService.java | 15 +++- .../configapi/service/auth/AssetService.java | 6 -- .../main/resources/config-api-rs-protect.json | 27 +++++++ .../core/service/ConfigHttpService.java | 42 +++++----- .../jans-config-api/dynamic-conf.json | 15 +--- 12 files changed, 153 insertions(+), 100 deletions(-) diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 6ecd450a229..de3ac971a0e 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -9335,14 +9335,14 @@ components: $ref: '#/components/schemas/AttributeValidation' tooltip: type: string - userCanEdit: - type: boolean - adminCanView: - type: boolean adminCanEdit: type: boolean userCanView: type: boolean + adminCanView: + type: boolean + userCanEdit: + type: boolean userCanAccess: type: boolean adminCanAccess: @@ -11769,10 +11769,10 @@ components: ttl: type: integer format: int32 - persisted: - type: boolean opbrowserState: type: string + persisted: + type: boolean SessionIdAccessMap: type: object properties: diff --git a/jans-config-api/plugins/docs/lock-plugin-swagger.yaml b/jans-config-api/plugins/docs/lock-plugin-swagger.yaml index 2b0bbedc06a..dda647c3d48 100644 --- a/jans-config-api/plugins/docs/lock-plugin-swagger.yaml +++ b/jans-config-api/plugins/docs/lock-plugin-swagger.yaml @@ -469,7 +469,7 @@ paths: security: - oauth2: - https://jans.io/oauth/lock-config.write - /lock/stat: + /lock/lockStat: get: tags: - Statistics @@ -488,12 +488,12 @@ paths: is mandatory if start_month and end_month parameters are not present. schema: type: string - - name: start_month + - name: start-month in: query description: Start-Month for which the stat report is to be fetched schema: type: string - - name: end_month + - name: end-month in: query description: End-Month for which the stat report is to be fetched schema: diff --git a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlIdpService.java b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlIdpService.java index 0b7a16077c5..b0b33b2c532 100644 --- a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlIdpService.java +++ b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlIdpService.java @@ -6,7 +6,6 @@ package io.jans.configapi.plugin.saml.service; -import io.jans.service.document.store.service.DocumentStoreService; import io.jans.service.document.store.conf.DocumentStoreType; import io.jans.service.document.store.service.LocalDocumentStoreService; import io.jans.util.exception.InvalidConfigurationException; @@ -38,8 +37,6 @@ public class SamlIdpService { @Inject Logger logger; - @Inject - private DocumentStoreService documentStoreService; @Inject private LocalDocumentStoreService localDocumentStoreService; @@ -58,7 +55,7 @@ public void create() { } public boolean isLocalDocumentStoreType() { - return documentStoreService.getProviderType() == DocumentStoreType.LOCAL; + return localDocumentStoreService.getProviderType() == DocumentStoreType.LOCAL; } public String saveMetadataFile(String metadataDir, String metadataFileName, String documentStoreModuleName, @@ -83,14 +80,13 @@ public String saveMetadataFile(String metadataDir, String metadataFileName, Stri } String metadataFile = metadataDir + File.separator + metadataFileName; - logger.info("documentStoreService:{}, metadataFile:{}, localDocumentStoreService:{} ", documentStoreService, - metadataFile, localDocumentStoreService); + logger.info("metadataFile:{}, localDocumentStoreService:{} ", metadataFile, localDocumentStoreService); try { - String result = documentStoreService.saveDocumentStream(metadataFile, null, - stream, documentStoreModuleName); + String result = localDocumentStoreService.saveDocumentStream(metadataFile, null, stream, + documentStoreModuleName); logger.info("SAML file saving result:{}", result); - InputStream newFile = documentStoreService.readDocumentAsStream(metadataFile); + InputStream newFile = localDocumentStoreService.readDocumentAsStream(metadataFile); logger.info("SAML file read newFile:{}", newFile); if (result != null) { @@ -114,16 +110,16 @@ public GluuErrorHandler validateMetadata(String metadataPath) return new GluuErrorHandler(false, true, validationLog); } - try (InputStream stream = documentStoreService.readDocumentAsStream(metadataPath)) { + try (InputStream stream = localDocumentStoreService.readDocumentAsStream(metadataPath)) { return XMLValidator.validateMetadata(stream, samlSchema); } } public boolean renameMetadata(String metadataPath, String destinationMetadataPath) { logger.debug("Rename metadata file documentStoreService:{},metadataPath:{}, destinationMetadataPath:{}", - documentStoreService, metadataPath, destinationMetadataPath); + localDocumentStoreService, metadataPath, destinationMetadataPath); try { - return documentStoreService.renameDocument(metadataPath, destinationMetadataPath) != null; + return localDocumentStoreService.renameDocument(metadataPath, destinationMetadataPath) != null; } catch (Exception ex) { logger.error("Failed to rename metadata '{}' to '{}'", metadataPath, destinationMetadataPath, ex); } @@ -133,24 +129,24 @@ public boolean renameMetadata(String metadataPath, String destinationMetadataPat public InputStream getFileFromDocumentStore(String path) { - logger.debug("Get file from DocumentStore. Path: {}",path); + logger.debug("Get file from DocumentStore. Path: {}", path); try { - return documentStoreService.readDocumentAsStream(path); - }catch(Exception e) { - logger.error("Failed to get file '{}' from DocumentStore",path); + return localDocumentStoreService.readDocumentAsStream(path); + } catch (Exception e) { + logger.error("Failed to get file '{}' from DocumentStore", path); return null; } } - private String getTempMetadataFilename(String metadataFolder, String fileName) { - logger.info("documentStoreService:{}, localDocumentStoreService:{}, metadataFolder:{}, fileName:{}", - documentStoreService, localDocumentStoreService, metadataFolder, fileName); + public String getTempMetadataFilename(String metadataFolder, String fileName) { + logger.info("localDocumentStoreService:{}, metadataFolder:{}, fileName:{}", localDocumentStoreService, + metadataFolder, fileName); synchronized (SamlIdpService.class) { String possibleTemp; do { possibleTemp = fileName + INumGenerator.generate(2); logger.debug("possibleTemp:{}", possibleTemp); - } while (documentStoreService.hasDocument(metadataFolder + possibleTemp)); + } while (localDocumentStoreService.hasDocument(metadataFolder + possibleTemp)); return possibleTemp; } } diff --git a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/ApiApplication.java b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/ApiApplication.java index fec8a36af05..84b2c47a6a9 100644 --- a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/ApiApplication.java +++ b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/ApiApplication.java @@ -48,6 +48,7 @@ public Set> getClasses() { classes.add(LockConfigResource.class); classes.add(AuditResource.class); + classes.add(LockStatResource.class); return classes; } diff --git a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/LockStatResource.java b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/LockStatResource.java index 86223909970..877f3330075 100644 --- a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/LockStatResource.java +++ b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/rest/LockStatResource.java @@ -6,11 +6,10 @@ package io.jans.configapi.plugin.lock.rest; - - import com.fasterxml.jackson.databind.JsonNode; import static io.jans.as.model.util.Util.escapeLog; +import io.jans.configapi.core.model.exception.ApiApplicationException; import io.jans.configapi.core.rest.BaseResource; import io.jans.configapi.core.rest.ProtectedApi; import io.jans.configapi.plugin.lock.service.LockService; @@ -66,8 +65,8 @@ public class LockStatResource extends BaseResource { public Response getStatistics( @Parameter(description = "Authorization code") @HeaderParam("Authorization") String authorization, @Parameter(description = "Month for which the stat report is to be fetched. The parameter is mandatory if start_month and end_month parameters are not present.") @QueryParam(value = "month") String month, - @Parameter(description = "Start-Month for which the stat report is to be fetched") @QueryParam(value = "start_month") String startMonth, - @Parameter(description = "End-Month for which the stat report is to be fetched") @QueryParam(value = "end_month") String endMonth, + @Parameter(description = "Start-Month for which the stat report is to be fetched") @QueryParam(value = "start-month") String startMonth, + @Parameter(description = "End-Month for which the stat report is to be fetched") @QueryParam(value = "end-month") String endMonth, @Parameter(description = "Report format") @QueryParam(value = "format") String format) { if (StringUtils.isBlank(format)) { format = ""; @@ -77,11 +76,15 @@ public Response getStatistics( if (logger.isInfoEnabled()) { logger.info( "LockStatResource::getStatistics() - authorization:{}, month:{}, startMonth:{}, endMonth:{}, format:{}", - escapeLog(authorization), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth), escapeLog(format)); + escapeLog(authorization), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth), + escapeLog(format)); } String url = getIssuer() + STAT_URL; jsonNode = this.lockService.getStat(url, authorization, month, startMonth, endMonth, format); logger.info("StatResource::getUserStatistics() - jsonNode:{} ", jsonNode); + } catch (ApiApplicationException aex) { + logger.error(" ApiApplicationException while fetching lock stat is", aex); + throwInternalServerException("Stat Error", aex); } catch (Exception ex) { logger.error(" Error while fetching lock stat is", ex); throwBadRequestException(ex); diff --git a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/service/LockService.java b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/service/LockService.java index 3293d795b67..e61366f813e 100644 --- a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/service/LockService.java +++ b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/service/LockService.java @@ -4,23 +4,29 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; + import static io.jans.as.model.util.Util.escapeLog; +import io.jans.configapi.core.model.exception.ApiApplicationException; import io.jans.configapi.core.service.ConfigHttpService; import io.jans.model.net.HttpServiceResponse; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.core.MediaType; + import jakarta.ws.rs.core.Response.Status; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; import org.slf4j.Logger; @ApplicationScoped public class LockService { + private static final String CONTENT_TYPE = "Content-Type"; private static final String AUTHORIZATION = "Authorization"; @@ -31,73 +37,95 @@ public class LockService { ConfigHttpService configHttpService; public JsonNode getStat(String url, String token, String month, String startMonth, String endMonth, String format) - throws JsonProcessingException { + throws ApiApplicationException, JsonProcessingException { if (logger.isInfoEnabled()) { logger.info( "LockStatResource::getStatistics() - url:{}, token:{}, month:{}, startMonth:{}, endMonth:{}, format:{}", - escapeLog(url), escapeLog(token), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth), escapeLog(format)); + escapeLog(url), escapeLog(token), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth), + escapeLog(format)); } + JsonNode jsonNode = null; + + // Request headers Map headers = new HashMap<>(); headers.put(CONTENT_TYPE, MediaType.APPLICATION_JSON); if (StringUtils.isNotBlank(token)) { headers.put(AUTHORIZATION, token); } - // Query Param + // Query Parameter Map data = new HashMap<>(); data.put("month", month); data.put("start-month", startMonth); data.put("end-month", endMonth); data.put("format", format); HttpServiceResponse httpServiceResponse = configHttpService.executeGet(url, headers, data); + logger.info(" stat httpServiceResponse:{}", httpServiceResponse); if (httpServiceResponse != null) { - jsonNode = getResponseJsonNode(httpServiceResponse, Status.OK); + logger.info( + " stat httpServiceResponse.getHttpResponse():{}, httpServiceResponse.getHttpResponse().getStatusLine():{}, httpServiceResponse.getHttpResponse().getEntity():{}", + httpServiceResponse.getHttpResponse(), httpServiceResponse.getHttpResponse().getStatusLine(), + httpServiceResponse.getHttpResponse().getEntity()); + jsonNode = getResponseJsonNode(httpServiceResponse); } logger.info(" stat jsonNode:{}", jsonNode); return jsonNode; } - public String getResponseEntityString(HttpServiceResponse serviceResponse, Status status) { + public JsonNode getResponseJsonNode(HttpServiceResponse serviceResponse) + throws ApiApplicationException, JsonProcessingException { + JsonNode jsonNode = null; + + if (serviceResponse == null) { + return jsonNode; + } + + return getResponseJsonNode(getResponseEntityString(serviceResponse), "response"); + } + + public String getResponseEntityString(HttpServiceResponse serviceResponse) throws ApiApplicationException { String jsonString = null; if (serviceResponse == null) { return jsonString; } - - if (serviceResponse.getHttpResponse() != null && serviceResponse.getHttpResponse().getStatusLine() != null - && serviceResponse.getHttpResponse().getStatusLine().getStatusCode() == status.getStatusCode()) { - HttpEntity entity = serviceResponse.getHttpResponse().getEntity(); + HttpResponse httpResponse = serviceResponse.getHttpResponse(); + if (httpResponse != null) { + HttpEntity entity = httpResponse.getEntity(); + logger.debug("entity:{}, httpResponse.getStatusLine().getStatusCode():{}", entity, + httpResponse.getStatusLine().getStatusCode()); if (entity == null) { return jsonString; } - jsonString = entity.toString(); + try { + jsonString = EntityUtils.toString(entity, "UTF-8"); + } catch (Exception ex) { + logger.error("Error while getting entity using EntityUtils is ", ex); + } + if (httpResponse.getStatusLine() != null + && httpResponse.getStatusLine().getStatusCode() == Status.OK.getStatusCode()) { + return jsonString; + } else { + throw new ApiApplicationException(httpResponse.getStatusLine().getStatusCode(), jsonString); + } } - logger.info(" stat jsonString:{}", jsonString); return jsonString; } - public JsonNode getResponseJsonNode(HttpServiceResponse serviceResponse, Status status) - throws JsonProcessingException { + public JsonNode getResponseJsonNode(String jsonSring, String nodeName) throws JsonProcessingException { JsonNode jsonNode = null; - if (serviceResponse == null) { + if (StringUtils.isBlank(jsonSring)) { return jsonNode; } - - return getResponseJsonNode(getResponseEntityString(serviceResponse, status)); - } - - public JsonNode getResponseJsonNode(String jsonSring) throws JsonProcessingException { - JsonNode jsonNode = null; - - if (StringUtils.isNotBlank(jsonSring)) { - return jsonNode; + jsonNode = Jackson.asJsonNode(jsonSring); + if (StringUtils.isNotBlank(nodeName) && jsonNode != null && jsonNode.get(nodeName) != null) { + jsonNode = jsonNode.get("response"); } - - return Jackson.asJsonNode(jsonSring); + return jsonNode; } } diff --git a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/util/Constants.java b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/util/Constants.java index c3f50d4e373..80d102fcad9 100644 --- a/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/util/Constants.java +++ b/jans-config-api/plugins/lock-plugin/src/main/java/io/jans/configapi/plugin/lock/util/Constants.java @@ -14,7 +14,7 @@ private Constants() { public static final String LOCK = "/lock"; public static final String LOCK_CONFIG = "/lockConfig"; public static final String AUDIT = "/audit"; - public static final String LOCK_STAT = "/stat"; + public static final String LOCK_STAT = "/lockStat"; public static final String HEALTH = "/health"; public static final String LOG = "/log"; public static final String TELEMETRY = "/telemetry"; diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/security/service/OpenIdAuthorizationService.java b/jans-config-api/server/src/main/java/io/jans/configapi/security/service/OpenIdAuthorizationService.java index 30bbe9fcbbb..b93bd743b9c 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/security/service/OpenIdAuthorizationService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/security/service/OpenIdAuthorizationService.java @@ -120,7 +120,7 @@ public String processAuthorization(String token, String issuer, ResourceInfo res private String validateScope(String accessToken, List tokenScopes, ResourceInfo resourceInfo, String issuer) throws WebApplicationException { - logger.debug("Validate scope, accessToken:{}, tokenScopes:{}, resourceInfo: {}, issuer: {}", accessToken, + logger.info("Validate scope, accessToken:{}, tokenScopes:{}, resourceInfo: {}, issuer: {}", accessToken, tokenScopes, resourceInfo, issuer); try { // Get resource scope @@ -131,15 +131,15 @@ private String validateScope(String accessToken, List tokenScopes, Resou // find missing scopes List missingScopes = findMissingScopes(resourceScopesByType, tokenScopes); - logger.debug("missingScopes:{}", missingScopes); + logger.info("missingScopes:{}", missingScopes); // Check if resource requires auth server specific scope List authSpecificScope = getAuthSpecificScopeRequired(resourceInfo); - logger.debug(" resourceScopes:{}, authSpecificScope:{} ", resourceScopes, authSpecificScope); + logger.info(" resourceScopes:{}, authSpecificScope:{} ", resourceScopes, authSpecificScope); // If No auth scope required OR if token contains the authSpecificScope if ((authSpecificScope == null || authSpecificScope.isEmpty())) { - logger.debug("Validating token scopes as no authSpecificScope required"); + logger.info("Validating token scopes as no authSpecificScope required"); if ((missingScopes != null && !missingScopes.isEmpty())) { logger.error("Insufficient scopes! Required scope:{} - however token scopes:{}", resourceScopes, tokenScopes); @@ -160,7 +160,14 @@ private String validateScope(String accessToken, List tokenScopes, Resou + ", however token scopes: " + tokenScopes, Response.status(Response.Status.UNAUTHORIZED).build()); } + + //If no scope is missing + if (missingScopes == null || missingScopes.isEmpty()) { + logger.info(" No missing scopes and hence returning original accessToken"); + return accessToken; + } + logger.info("Generating new token with authSpecificScope"); // Generate token with required resourceScopes resourceScopes.addAll(authSpecificScope); accessToken = openIdService.requestAccessToken(authUtil.getClientId(), resourceScopes); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java index e3c552242f0..aa566f97737 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java @@ -19,7 +19,6 @@ import io.jans.orm.search.filter.Filter; import io.jans.orm.PersistenceEntryManager; import io.jans.service.document.store.model.Document; -import io.jans.service.document.store.provider.DBDocumentStoreProvider; import io.jans.service.document.store.service.DBDocumentService; import io.jans.util.exception.InvalidAttributeException; @@ -33,11 +32,9 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.*; import jakarta.enterprise.context.ApplicationScoped; @@ -66,9 +63,6 @@ public class AssetService { @Inject AuthUtil authUtil; - @Inject - DBDocumentStoreProvider dBDocumentStoreProvider; - @Inject DocumentStoreService documentStoreService; diff --git a/jans-config-api/server/src/main/resources/config-api-rs-protect.json b/jans-config-api/server/src/main/resources/config-api-rs-protect.json index 71e6189a377..f4c277e38f2 100644 --- a/jans-config-api/server/src/main/resources/config-api-rs-protect.json +++ b/jans-config-api/server/src/main/resources/config-api-rs-protect.json @@ -3318,6 +3318,33 @@ ] } ] + }, + { + "path": "/jans-config-api/lock/lockStat", + "conditions": [ + { + "httpMethods": [ + "GET" + ], + "scopes": [ + { + "inum": "1800.03.4", + "name": "https://jans.io/oauth/lock/read-all" + }, + { + "inum": "", + "name": "jans_stat" + } + ], + "groupScopes": [], + "superScopes": [ + { + "inum": "1800.03.1", + "name": "https://jans.io/oauth/config/read-all" + } + ] + } + ] } ] } \ No newline at end of file diff --git a/jans-config-api/shared/src/main/java/io/jans/configapi/core/service/ConfigHttpService.java b/jans-config-api/shared/src/main/java/io/jans/configapi/core/service/ConfigHttpService.java index ada7abc8609..d7489ae3df7 100644 --- a/jans-config-api/shared/src/main/java/io/jans/configapi/core/service/ConfigHttpService.java +++ b/jans-config-api/shared/src/main/java/io/jans/configapi/core/service/ConfigHttpService.java @@ -21,6 +21,7 @@ import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; +import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -30,10 +31,12 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.servlet.http.HttpServletRequest; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.commons.codec.binary.Base64; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; @@ -194,8 +197,8 @@ public HttpServiceResponse executePost(HttpClient httpClient, String uri, String return executePost(httpClient, uri, authCode, null, postData, contentType, null); } - public HttpServiceResponse executePost(String uri, String authCode, String postData, - ContentType contentType, String authType) { + public HttpServiceResponse executePost(String uri, String authCode, String postData, ContentType contentType, + String authType) { return executePost(this.getHttpsClient(), uri, authCode, null, postData, contentType, authType); } @@ -209,32 +212,35 @@ public String encodeUrl(String value) { public HttpServiceResponse executeGet(HttpClient httpClient, String requestUri, Map headers, Map parameters) { - HttpGet httpGet = new HttpGet(requestUri); - if (headers != null) { - for (Entry headerEntry : headers.entrySet()) { - httpGet.setHeader(headerEntry.getKey(), headerEntry.getValue()); - } - } + log.info("\n\n requestUri{}, headers:{}, parameters:{}", requestUri, headers, parameters); if (parameters != null && !parameters.isEmpty()) { - StringBuilder query = new StringBuilder(""); - for (String key : parameters.keySet()) { - + StringBuilder query = new StringBuilder(); + int i = 0; + for (Iterator iterator = parameters.keySet().iterator(); iterator.hasNext();) { + String key = iterator.next(); String value = parameters.get(key); - if (value != null && value.length() > 0) { - - String delim = "&" + URLEncoder.encode(key, StandardCharsets.UTF_8) + "="; - query.append(delim.substring(1)); + if (StringUtils.isNotBlank(value)) { + String delim = (i == 0) ? "?" : "&"; + query.append(delim + URLEncoder.encode(key, StandardCharsets.UTF_8) + "="); query.append(URLEncoder.encode(value, StandardCharsets.UTF_8)); + i++; } } - httpGet = new HttpGet(requestUri + query.toString()); + requestUri = requestUri + query.toString(); + log.info("\n\n\n Final requestUri:{}", requestUri); } + HttpGet httpGet = new HttpGet(requestUri); + if (headers != null) { + for (Entry headerEntry : headers.entrySet()) { + httpGet.setHeader(headerEntry.getKey(), headerEntry.getValue()); + } + } try { HttpResponse httpResponse = httpClient.execute(httpGet); - + log.info("httpResponse:{}", httpResponse); return new HttpServiceResponse(httpGet, httpResponse); } catch (IOException ex) { log.error("Failed to execute get request", ex); diff --git a/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json b/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json index 22919ca6e8a..16917a57127 100644 --- a/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json +++ b/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json @@ -112,7 +112,9 @@ "jans-auth", "jans-config-api", "jans-keycloak-link", - "jans-scim" + "jans-scim", + "jans-lock", + "jans-link" ], "description": "java archive library." }, @@ -261,17 +263,6 @@ ], "description": " FIDO Server Metadata." }, - { - "directory": "/opt/jans/jetty/%s/custom-libs", - "type": [ - "jar" - ], - "jansServiceModule": [ - "jans-lock", - "jans-link" - ], - "description": "java archive library." - }, { "directory": "/var/jans/keycloak-link-snapshots", "type": [