From 807859ba19e0aedfbbd6225fe35304f942117d1d Mon Sep 17 00:00:00 2001 From: pujavs <43700552+pujavs@users.noreply.github.com> Date: Thu, 24 Oct 2024 21:51:53 +0530 Subject: [PATCH] fix(config-api): acr enhancement for agama, asset mgt error message made descriptive (#9919) * fix(config-api): asset mgt endpoint fixes Signed-off-by: pujavs * feat(config-api): asset upload mgt ehancement and fido Signed-off-by: pujavs * feat(config-api): asset upload mgt ehancement and fido Signed-off-by: pujavs * feat(config-api): asset upload mgt ehancement and fido Signed-off-by: pujavs * fix(config-api): asset upload Signed-off-by: pujavs * fix(config-api): lock review comments Signed-off-by: pujavs * feat(config-api): lock code review comments Signed-off-by: pujavs * feat(config-api): lock master renamed to lock server Signed-off-by: pujavs * feat(config-api): lock master renamed to lock server Signed-off-by: pujavs * feat(config-api): lock master renamed to lock server Signed-off-by: pujavs * feat(config-api): lock master renamed to lock server Signed-off-by: pujavs * feat(config-api): fido2 delete functionality Signed-off-by: pujavs * fix(config-api): acr validation Signed-off-by: pujavs * feat(config-api): doc(config-api): IDP schema attribute descriptions #9187 Signed-off-by: pujavs * feat(config-api): sync with main Signed-off-by: pujavs * feat(config-api): uploading assets via API generates 2 entries #9178 Signed-off-by: pujavs * feat(config-api): asset mgt, fido and IDP changes Signed-off-by: pujavs * feat(config-api): fido2 device endpoint Signed-off-by: pujavs * feat(config-api): fido2 endpoint Signed-off-by: pujavs * feat(config-api): fido2 endpoint Signed-off-by: pujavs * feat(config-api): sync with main Signed-off-by: pujavs * feat(config-api): sync with main Signed-off-by: pujavs * feat(config-api): sync with main Signed-off-by: pujavs * feat(config-api): resolved sonar review issues Signed-off-by: pujavs * feat(config-api): sonar review comment fix Signed-off-by: pujavs * feat(config-api): swagger spec Signed-off-by: pujavs * feat(config-api): saml config attribute description Signed-off-by: pujavs * doc(config-api): added SAML attribute description Signed-off-by: pujavs * doc(config-api): added SAML attribute description Signed-off-by: pujavs * feat(config-api): sync with main Signed-off-by: pujavs * fix(jans-lock): code review comment fix isssue#9305 Signed-off-by: pujavs * fix(jans-lock): code review comment fix isssue#9305 Signed-off-by: pujavs * feat(config-api): lock review point Signed-off-by: pujavs * fix(lock): code review comment Signed-off-by: pujavs * fix(lock): code review comment Signed-off-by: pujavs * fix(config-api): sync with main Signed-off-by: pujavs * feat(config-api): lock endpoint fixes and SAML IDP NPE Signed-off-by: pujavs * feat(config-api): asset enhancement Signed-off-by: pujavs * feat(config-api): implement timer for asset mgt to fetch and deploy assets forconfig-api #9403 Signed-off-by: pujavs * fix(config-api): scope validation issue #9426 Signed-off-by: pujavs * fix(config-api): asset delete error fix Signed-off-by: pujavs * feat(config-api): sysnc with main Signed-off-by: pujavs * fix(config-ap): lock audit endpoint parameter declaration error#9460 Signed-off-by: pujavs * feat(config-api): client token functionality Signed-off-by: pujavs * fix(Config-api): lock audit endpoint path param rectification Signed-off-by: pujavs * feat(config-api): clint token endpoint - wip Signed-off-by: pujavs * feat(config-api): clint token endpoint Signed-off-by: pujavs * feat(config-api): client token endpoint Signed-off-by: pujavs * feat(config-api): client token endpoint Signed-off-by: pujavs * feat(config-api): token endpoint Signed-off-by: pujavs * feat(config-api): token endpoint Signed-off-by: pujavs * feat(config-api): token endpoint Signed-off-by: pujavs * feat(config-api): session ednpoint wip Signed-off-by: pujavs * feat(config-api): session ednpoint wip Signed-off-by: pujavs * feat(config-api): session and token endpoint Signed-off-by: pujavs * feat(config-api): session endpoint Signed-off-by: pujavs * feat(config-api): session endpoint Signed-off-by: pujavs * feat(config-api): session and fido2 endpoint Signed-off-by: pujavs * test(config-api): marked session failing test case Signed-off-by: pujavs * feat(config-api): asset mgt dir mapping changes wip Signed-off-by: pujavs * feat(config-api): asset mgt dir changes Signed-off-by: pujavs * feat(config-api): asset mgt changes for dir Signed-off-by: pujavs * feat(config-api): asset mgt endpoint -wip Signed-off-by: pujavs * feat(config-api): asset mgt endpoint Signed-off-by: pujavs * feat(config-api): custom asset mgt wip Signed-off-by: pujavs * feat(config-api): custom asset mgt Signed-off-by: pujavs * feat(config-api): custom asset mgt Signed-off-by: pujavs * feat(config-api): session endpoint changes to remove sessionId Signed-off-by: pujavs * feat(config-api) session endpoint changes to hide id Signed-off-by: pujavs * feat(config-api) session endpoint changes to hide id Signed-off-by: pujavs * feat(config-api): session endpoint mgt Signed-off-by: pujavs * feat(config-api): session enhancement for removing id Signed-off-by: pujavs * feat(config-api): session endpoint changes to remove session id Signed-off-by: pujavs * feat(config-api): session endpoint changes to remove session id Signed-off-by: pujavs * feat(config-api): session endpoint changes to remove session id Signed-off-by: pujavs * feat(config-api): session endpoint changes to remove session id Signed-off-by: pujavs * feat(config-api): search fieldValuePair enhancement Signed-off-by: pujavs * feat(config-api): search fieldValuePair enhancement Signed-off-by: pujavs * feat(config-api): session field filter enhancement - wip Signed-off-by: pujavs * feat(config-api): session field search enhancement wip Signed-off-by: pujavs * feat(config-api): session endpoint search enhancemnt Signed-off-by: pujavs * feat(config-api): session endpoint search enhancemnt Signed-off-by: pujavs * feat(config-api): session endpoint search enhancement Signed-off-by: pujavs * feat(config-api): session and token endpoint enhacement Signed-off-by: pujavs * feat(config-api): session and token search enhancement Signed-off-by: pujavs * feat(config-api): session search changes for session attribute Signed-off-by: pujavs * feat(config-api): fido2 search endpoint Signed-off-by: pujavs * feat(config-api): fido2 entry search Signed-off-by: pujavs * feat(config-api): pagination implemented in fido2, session and token endpoints Signed-off-by: pujavs * feat(Config-ap): acr enhacement for agama Signed-off-by: pujavs * feat(Config-ap): made asset error message descriptive Signed-off-by: pujavs --------- Signed-off-by: pujavs Co-authored-by: YuriyZ Former-commit-id: 4e03fe31617b2c1e39708509ac3ba0e9fc7405fc --- .../docs/jans-config-api-swagger.yaml | 6 +- .../rest/resource/auth/AcrsResource.java | 85 ++++++++++++++++-- .../configapi/service/auth/AssetService.java | 6 +- .../configapi/service/auth/TokenService.java | 4 +- .../io/jans/configapi/core/util/DataUtil.java | 90 +++++++++++-------- 5 files changed, 141 insertions(+), 50 deletions(-) diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 330acf30d51..91a1a2d65f1 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -9213,7 +9213,7 @@ components: type: string selected: type: boolean - userCanView: + whitePagesCanView: type: boolean adminCanView: type: boolean @@ -9221,12 +9221,12 @@ components: type: boolean userCanEdit: type: boolean + userCanView: + type: boolean adminCanAccess: type: boolean userCanAccess: type: boolean - whitePagesCanView: - type: boolean baseDn: type: string PatchRequest: diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java index 5c4e334be94..cce2a294349 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java @@ -6,17 +6,20 @@ package io.jans.configapi.rest.resource.auth; +import io.jans.ads.model.Deployment; import io.jans.config.GluuConfiguration; import io.jans.configapi.core.model.ApiError; import io.jans.configapi.core.rest.ProtectedApi; import io.jans.configapi.model.configuration.ApiAppConfiguration; import io.jans.configapi.rest.model.AuthenticationMethod; +import io.jans.configapi.service.auth.AgamaDeploymentsService; import io.jans.configapi.service.auth.ConfigurationService; import io.jans.configapi.service.auth.LdapConfigurationService; import io.jans.configapi.util.ApiAccessConstants; import io.jans.configapi.util.ApiConstants; import io.jans.model.custom.script.model.CustomScript; import io.jans.model.ldap.GluuLdapConfiguration; +import io.jans.orm.model.PagedResult; import io.jans.service.custom.CustomScriptService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.parameters.RequestBody; @@ -28,6 +31,7 @@ import io.swagger.v3.oas.annotations.security.*; import java.util.List; +import java.util.Set; import java.util.Optional; import org.apache.commons.lang.StringUtils; @@ -48,6 +52,9 @@ @Produces(MediaType.APPLICATION_JSON) public class AcrsResource extends ConfigBaseResource { + private static final String AGAMA_PREFIX = "agama_"; + private static final String AGAMA_PREFIX_SEPERATOR = "_"; + @Inject Logger log; @@ -60,6 +67,9 @@ public class AcrsResource extends ConfigBaseResource { @Inject CustomScriptService customScriptService; + @Inject + AgamaDeploymentsService agamaDeploymentsService; + @Inject LdapConfigurationService ldapConfigurationService; @@ -101,7 +111,7 @@ public Response updateDefaultAuthenticationMethod(@NotNull AuthenticationMethod throwBadRequestException("Default authentication method should not be null or empty !"); } - if (StringUtils.isNotBlank(authenticationMethod.getDefaultAcr())) { + if (authenticationMethod != null && StringUtils.isNotBlank(authenticationMethod.getDefaultAcr())) { validateAuthenticationMethod(authenticationMethod.getDefaultAcr()); final GluuConfiguration gluuConfiguration = configurationService.findGluuConfiguration(); @@ -117,7 +127,7 @@ private void validateAuthenticationMethod(String authenticationMode) { // if authentication validation check is enabled then validate boolean isAcrValid = isAcrValid(authenticationMode); - log.debug("isAcrValid:{}",isAcrValid); + log.debug("isAcrValid:{}", isAcrValid); if (appConfiguration.isAcrValidationEnabled() && (!isAcrValid)) { throwBadRequestException("INVALID_ACR", String.format("Authentication script {%s} is not valid/active", authenticationMode)); @@ -127,14 +137,20 @@ private void validateAuthenticationMethod(String authenticationMode) { private boolean isAcrValid(String authenticationMode) { boolean isValid = false; - log.debug(" Validate ACR being set - authenticationMethod:{}, appConfiguration.getAcrExclusionList():{}", authenticationMode, - appConfiguration.getAcrExclusionList()); + log.info(" Validate ACR being set - authenticationMethod:{}, appConfiguration.getAcrExclusionList():{}", + authenticationMode, appConfiguration.getAcrExclusionList()); if (appConfiguration.getAcrExclusionList() != null && appConfiguration.getAcrExclusionList().contains(authenticationMode)) { return true; } + // Agama Flow + if (StringUtils.isNotBlank(authenticationMode) && authenticationMode.startsWith(AGAMA_PREFIX)) { + log.debug(" Agama authenticationMethod provided."); + return isValidAgamaDeployment(authenticationMode); + } + List ldapConfigurations = ldapConfigurationService.findLdapConfigurations(); log.debug(" ldapConfigurations:{}", ldapConfigurations); if (ldapConfigurations != null && !ldapConfigurations.isEmpty()) { @@ -152,7 +168,7 @@ private boolean isAcrValid(String authenticationMode) { // if ACR being set is a script then it should be active CustomScript script = customScriptService.getScriptByDisplayName(authenticationMode); - log.debug(" script:{}", script); + log.debug(" CustomScript:{}", script); if (script != null && script.isEnabled()) { log.debug(" script:{}, script.isEnabled():{}", script, script.isEnabled()); return true; @@ -162,4 +178,63 @@ private boolean isAcrValid(String authenticationMode) { return isValid; } + public boolean isValidAgamaDeployment(String authenticationMode) { + boolean isValid = false; + log.info(" Validate Agama ACR - authenticationMode:{},", authenticationMode); + if (StringUtils.isBlank(authenticationMode)) { + return isValid; + } + + // Get deployed agama projects + PagedResult deploymentPagedResult = agamaDeploymentsService.list(0, 0, getMaxCount()); + log.info(" Agama Deployments - deploymentPagedResult:{},", deploymentPagedResult); + + if (deploymentPagedResult != null && deploymentPagedResult.getEntries() != null + && !deploymentPagedResult.getEntries().isEmpty()) { + List agamaDeploymentList = deploymentPagedResult.getEntries(); + log.debug(" agamaDeploymentList:{},", agamaDeploymentList); + + Set keys = getDirectLaunchFlows(agamaDeploymentList); + log.info("Final DirectLaunchFlows - keys:{}, authenticationMode:{}, authenticationMode.indexOf(AGAMA_PREFIX_SEPERATOR):{} , authenticationMode.indexOf(AGAMA_PREFIX_SEPERATOR)+1:{}", keys, authenticationMode, authenticationMode.indexOf(AGAMA_PREFIX_SEPERATOR) , authenticationMode.indexOf(AGAMA_PREFIX_SEPERATOR)+1); + String agamaAcr = authenticationMode; + if (authenticationMode.indexOf(AGAMA_PREFIX_SEPERATOR) > 0) { + agamaAcr = authenticationMode.substring(authenticationMode.indexOf(AGAMA_PREFIX_SEPERATOR)+1); + } + log.info(" agamaAcr:{},", agamaAcr); + + if (keys != null && !keys.isEmpty() && keys.contains(agamaAcr)) { + log.debug(" keys.contains(agamaAcr):{},", keys.contains(agamaAcr)); + isValid = true; + } + } + log.info(" isValidAgamaDeployment - isValid:{}", isValid); + return isValid; + } + + private Set getDirectLaunchFlows(List agamaDeploymentList) { + log.info(" agamaDeploymentList:{}", agamaDeploymentList); + Set keys = null; + List noDirectLaunchFlows = null; + if (agamaDeploymentList == null || agamaDeploymentList.isEmpty()) { + return keys; + } + for (Deployment deployment : agamaDeploymentList) { + log.debug("Agama deployment:{},", deployment); + if (deployment.getDetails() != null && deployment.getDetails().getFlowsError() != null) { + keys = deployment.getDetails().getFlowsError().keySet(); + log.debug(" Agama flow keys:{},", keys); + + if (deployment.getDetails().getProjectMetadata() != null) { + noDirectLaunchFlows = deployment.getDetails().getProjectMetadata().getNoDirectLaunchFlows(); + } + } + } + log.debug("All deployed agama keys:{}, noDirectLaunchFlows:{}", keys, noDirectLaunchFlows); + if (keys != null && !keys.isEmpty() && noDirectLaunchFlows != null) { + keys.removeAll(noDirectLaunchFlows); + } + log.info("Final agama main flow keys:{}", keys); + return keys; + } + } \ No newline at end of file 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 019251eef4c..f59b4c45e7b 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 @@ -54,7 +54,7 @@ public class AssetService { private static final String ASSET_DIR_STR = "AssetDirMapping for ["; - private static final String NOT_DEFINED_IN_CONFIG = "] is not defined in config!"; + private static final String NOT_DEFINED_IN_CONFIG = " is not defined in config!"; @Inject Logger log; @@ -438,7 +438,7 @@ private String getAssetDir(Document asset) { if (StringUtils.isBlank(assetDir)) { throw new InvalidConfigurationException( - "Directory to save asset [" + assetFileName + NOT_DEFINED_IN_CONFIG); + "Directory to save asset [" + assetFileName +"]"+ NOT_DEFINED_IN_CONFIG); } StringBuilder sb = new StringBuilder(); @@ -480,7 +480,7 @@ private String getAssetDirectory(Document asset) { log.info("Asset dirMapping :{}", dirMapping); if (StringUtils.isBlank(dirMapping)) { - throw new InvalidConfigurationException(ASSET_DIR_STR + serviceModule + NOT_DEFINED_IN_CONFIG); + throw new InvalidConfigurationException(ASSET_DIR_STR + serviceModule +"] for asset type ["+fileExtension+"]"+ NOT_DEFINED_IN_CONFIG); } serviceDir = String.format(dirMapping, serviceModule); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/TokenService.java b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/TokenService.java index 8bd7a93c140..57a1da35f6c 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/TokenService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/TokenService.java @@ -102,8 +102,8 @@ public PagedResult searchToken(SearchRequest searchRequest) { persistenceEntryManager); } - fieldValueFilters.add(Filter.createORFilter(filters)); - searchFilter = Filter.createANDFilter(fieldValueFilters); + searchFilter = Filter.createANDFilter(Filter.createORFilter(filters), + Filter.createANDFilter(fieldValueFilters)); logger.info("Token final searchFilter:{}", searchFilter); diff --git a/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java b/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java index 9e22dd68f0c..cc89562cff8 100644 --- a/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java +++ b/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java @@ -234,6 +234,36 @@ public static Map getFieldType(Class clazz, List createFilter(List fieldFilterData, String primaryKey, PersistenceEntryManager persistenceEntryManager) { logger.info("Create ORM Filter for fieldFilterData:{}, primaryKey:{}, persistenceEntryManager:{}", @@ -288,52 +318,35 @@ private static boolean getBooleanValue(String strValue) { } - private static Date getDate(String dateString, String primaryKey, PersistenceEntryManager persistenceEntryManager) { - logger.info("Get Date Value for dateString:{}, primaryKey:{}, persistenceEntryManager:{}", dateString, - primaryKey, persistenceEntryManager); - Date dateValue = null; - if (StringUtils.isBlank(dateString) || StringUtils.isBlank(primaryKey) || persistenceEntryManager == null) { + private static String encodeDate(Date date, String primaryKey, PersistenceEntryManager persistenceEntryManager) { + logger.info("Encode String Date - date:{}, primaryKey:{}, persistenceEntryManager:{}", date, primaryKey, + persistenceEntryManager); + String dateValue = null; + if (date == null || StringUtils.isBlank(primaryKey) || persistenceEntryManager == null) { return dateValue; } - dateValue = persistenceEntryManager.decodeTime(primaryKey, dateString); - logger.info(" persistenceEntryManager.decodeTime - dateString:{}, dateValue:{}", dateString, dateValue); - - dateValue = formatStrDate(dateString, null); - logger.info(" formatStrDate - dateValue:{}", dateValue); + dateValue = persistenceEntryManager.encodeTime(primaryKey, date); + logger.info(" persistenceEntryManager.decodeTime - date:{}, dateValue:{}", date, dateValue); return dateValue; } - private static Date formatStrDate(String dateString, String datePattern) { - logger.debug("Format String Date - dateString:{}: datePattern:{}", dateString, datePattern); - Date date = null; - try { - if (StringUtils.isBlank(dateString)) { - return date; - } - - if (StringUtils.isBlank(datePattern)) { - if (dateString.contains(":")) { - datePattern = "yyyy-MM-dd HH:mm:ss"; - } else { - datePattern = "yyyy-MM-dd"; - } - } - - SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern); - logger.debug("dateFormat:{} ", dateFormat); + private static Date decodeStringDate(String dateString, String primaryKey, + PersistenceEntryManager persistenceEntryManager) { + logger.info("Decode String Date - dateString:{}, primaryKey:{}, persistenceEntryManager:{}", dateString, + primaryKey, persistenceEntryManager); + Date dateValue = null; + if (StringUtils.isBlank(dateString) || StringUtils.isBlank(primaryKey) || persistenceEntryManager == null) { + return dateValue; + } - date = dateFormat.parse(dateString); - logger.info("Returning dateFormat:{}, date:{} ", dateFormat, date); + dateValue = persistenceEntryManager.decodeTime(primaryKey, dateString); + logger.info(" persistenceEntryManager.decodeTime - dateString:{}, dateValue:{}", dateString, dateValue); - } catch (Exception ex) { - logger.error("Error while formatting String Date - dateString{" + dateString + "}", ex); - return date; - } + return dateValue; - return date; } private static Filter createDateFilter(FieldFilterData fieldFilterData, String primaryKey, @@ -345,10 +358,13 @@ private static Filter createDateFilter(FieldFilterData fieldFilterData, String p if (fieldFilterData == null) { return dateFilter; } - Date dateValue = getDate(fieldFilterData.getValue(), primaryKey, persistenceEntryManager); + + Date dateValue = decodeStringDate(fieldFilterData.getValue(), primaryKey, persistenceEntryManager); + logger.info(" fieldFilterData.getField():{}, fieldFilterData.getValue():{}, dateValue:{}", + fieldFilterData.getField(), fieldFilterData.getValue(), dateValue); if (FilterOperator.EQUALITY.getSign().equalsIgnoreCase(fieldFilterData.getOperator())) { - dateFilter = Filter.createGreaterOrEqualFilter(fieldFilterData.getField(), dateValue); + dateFilter = Filter.createEqualityFilter(fieldFilterData.getField(), dateValue); } else if (FilterOperator.GREATER.getSign().equalsIgnoreCase(fieldFilterData.getOperator()) || FilterOperator.GREATER_OR_EQUAL.getSign().equalsIgnoreCase(fieldFilterData.getOperator())) {