From fdfd7a6809bd03b576be5b5def47dde263e69d79 Mon Sep 17 00:00:00 2001 From: pujavs <43700552+pujavs@users.noreply.github.com> Date: Tue, 17 Dec 2024 20:00:06 +0530 Subject: [PATCH 1/2] fix(config-api): user password being displayed as clear text (#10441) * fix(config-api): missing scope in spec Signed-off-by: pujavs * fix(config-api): missing scope in spec Signed-off-by: pujavs * feat(Config-api): sync with main Signed-off-by: pujavs * feat(config-api): server app status Signed-off-by: pujavs * feat(config-api): server app status Signed-off-by: pujavs * feat(config-api): agama repo endpoin -wip Signed-off-by: pujavs * feat(config-api): sync with main Signed-off-by: pujavs * feat(config-api): agama rep endpoint Signed-off-by: pujavs * feat(config-api): agama endpoint wip Signed-off-by: pujavs * feat(config-api): implemenetd agama repo endpoint and fixed user pwd validation for patch Signed-off-by: pujavs * feat(config-api): implemenetd agama repo endpoint and fixed user pwd validation for patch Signed-off-by: pujavs * fix(Config-api): user password patch fix Signed-off-by: pujavs * fix(config-api): user credentials in plain text Signed-off-by: pujavs * fix(config-api): user password being displayed as clear text Signed-off-by: pujavs * fix(config-api): user password being displayed as clear text Signed-off-by: pujavs --------- Signed-off-by: pujavs --- .../docs/jans-config-api-swagger.yaml | 15 +++++--- .../plugins/docs/fido2-plugin-swagger.yaml | 38 +++++++++++++++---- .../plugin/mgt/model/user/CustomUser.java | 6 +-- .../mgt/model/user/UserPatchRequest.java | 2 +- .../plugin/mgt/service/UserMgmtService.java | 32 ++++++---------- .../interceptor/AuditLogInterceptor.java | 5 ++- 6 files changed, 57 insertions(+), 41 deletions(-) diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index e20a8f666fb..53ae67f689c 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -9305,18 +9305,18 @@ components: type: boolean whitePagesCanView: type: boolean - adminCanEdit: + adminCanView: type: boolean userCanView: type: boolean userCanEdit: type: boolean - adminCanView: - type: boolean - userCanAccess: + adminCanEdit: type: boolean adminCanAccess: type: boolean + userCanAccess: + type: boolean baseDn: type: string PatchRequest: @@ -9692,6 +9692,9 @@ components: accessTokenLifetime: type: integer format: int32 + userInfoLifetime: + type: integer + format: int32 cleanServiceInterval: type: integer format: int32 @@ -11730,10 +11733,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/fido2-plugin-swagger.yaml b/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml index d5b5360939b..0859f6b93a1 100644 --- a/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml +++ b/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml @@ -564,6 +564,8 @@ components: type: boolean sessionIdPersistInCache: type: boolean + oldU2fMigrationEnabled: + type: boolean errorReasonEnabled: type: boolean fido2Configuration: @@ -581,7 +583,7 @@ components: type: string checkU2fAttestations: type: boolean - debugUserAutoEnrollment: + userAutoEnrollment: type: boolean unfinishedRequestExpiration: type: integer @@ -591,17 +593,17 @@ components: format: int32 serverMetadataFolder: type: string - enabledFidoAlgorithms: + requestedCredentialTypes: type: array items: type: string - rp: + requestedParties: type: array items: $ref: '#/components/schemas/RequestedParty' metadataUrlsProvider: type: string - disableMetadataService: + skipDownloadMdsEnabled: type: boolean skipValidateMdsInAttestationEnabled: type: boolean @@ -675,15 +677,15 @@ components: type: string username: type: string - domain: + origin: type: string userId: type: string challenge: type: string - attenstationRequest: + attestationRequest: type: string - attenstationResponse: + attestationResponse: type: string uncompressedECPoint: type: string @@ -706,8 +708,28 @@ components: signatureAlgorithm: type: integer format: int32 - applicationId: + rpId: type: string + backupStateFlag: + type: boolean + backupEligibilityFlag: + type: boolean + attestedCredentialDataFlag: + type: boolean + extensionDataFlag: + type: boolean + userVerifiedFlag: + type: boolean + userPresentFlag: + type: boolean + authentictatorAttachment: + type: string + credId: + type: string + transports: + type: array + items: + type: string Fido2RegistrationEntry: type: object properties: diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/CustomUser.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/CustomUser.java index acd48c390d6..10a0c11b407 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/CustomUser.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/CustomUser.java @@ -59,10 +59,8 @@ public void setUserPassword(String userPassword) { @Override public String toString() { return "CustomUser [inum=" + inum + ", mail=" + mail + ", displayName=" + displayName - + ", givenName=" + givenName + ", userPassword=" + userPassword + "]"; + + ", givenName=" + givenName + "]"; } - - - + } diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/UserPatchRequest.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/UserPatchRequest.java index adcde5126e7..68a0a047515 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/UserPatchRequest.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/UserPatchRequest.java @@ -34,6 +34,6 @@ public void setCustomAttributes(List customAttributes) { @Override public String toString() { - return "UserPatchRequest [jsonPatchString=" + jsonPatchString + ", customAttributes=" + customAttributes + "]"; + return "UserPatchRequest [jsonPatchString=" + jsonPatchString + "]"; } } diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java index e0cd058907d..406c8101670 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java @@ -239,24 +239,23 @@ public User getUserBasedOnInum(String inum) { } private User updateCustomAttributes(User user, List customAttributes) { - logger.info("Custom Attributes to update for - user:{}, customAttributes:{} ", user, customAttributes); + logger.info("Custom Attributes to update for - user:{} ", user); if (customAttributes == null || customAttributes.isEmpty()) { return user; } - //validate custom attribute validation validateAttributes(customAttributes); for (CustomObjectAttribute attribute : customAttributes) { CustomObjectAttribute existingAttribute = userService.getCustomAttribute(user, attribute.getName()); - logger.debug("Existing CustomAttributes with existingAttribute:{} ", existingAttribute); + logger.debug("Existing CustomAttributes with existingAttribute.getName():{} ", existingAttribute.getName()); // add if (existingAttribute == null) { boolean result = userService.addUserAttribute(user, attribute.getName(), attribute.getValues(), attribute.isMultiValued()); - logger.debug("Result of adding CustomAttributes attribute:{} , result:{} ", attribute, result); + logger.debug("Result of adding CustomAttributes attribute.getName():{} , result:{} ", attribute.getName(), result); } // remove attribute else if (attribute.getValue() == null || attribute.getValues() == null) { @@ -268,9 +267,6 @@ else if (attribute.getValue() == null || attribute.getValues() == null) { existingAttribute.setMultiValued(attribute.isMultiValued()); existingAttribute.setValues(attribute.getValues()); } - // Final attribute - logger.info("Finally user CustomAttributes user.getCustomAttributes:{} ", user.getCustomAttributes()); - } return user; @@ -442,8 +438,7 @@ public String getPersistenceType() { } public User addUser(User user, boolean active) { - logger.info("\n Creating user:{}, user.getCustomAttributes():{}, active:{}", user, user.getCustomAttributes(), - active); + logger.info("\n Creating user:{}, active:{}", user, active); user = userService.addUser(user, active); logger.info("New user:{}\n", user); // remove inactive claims @@ -459,7 +454,7 @@ public User addUser(User user, boolean active) { } public User updateUser(User user) { - logger.info("\n Updating user:{}, user.getCustomAttributes():{}", user, user.getCustomAttributes()); + logger.info("\n Updating user:{}", user); user = userService.updateUser(user); logger.info("Updated user:{} \n", user); // remove inactive claims @@ -481,7 +476,6 @@ public List verifyCustomAttributes(List users) { } for (User user : users) { List customAttributes = user.getCustomAttributes(); - logger.debug("customAttributes: {}", customAttributes); // remove inactive attributes removeInActiveCustomAttribute(customAttributes); } @@ -489,7 +483,7 @@ public List verifyCustomAttributes(List users) { } public List removeInActiveCustomAttribute(List customAttributes) { - logger.info("User customAttributes: {}", customAttributes); + if (customAttributes == null || customAttributes.isEmpty()) { return customAttributes; } @@ -525,14 +519,12 @@ private String getDnForAttribute(String inum) { } public void validateAttributes(List customAttributes) { - logger.info("\n **** Validate customAttributes: {}", customAttributes); if (customAttributes == null || customAttributes.isEmpty()) { return; } StringBuilder sb = new StringBuilder(); for (CustomObjectAttribute customObjectAttribute : customAttributes) { - logger.info("customObjectAttribute:{}, customObjectAttribute.getName():{}", customObjectAttribute, - customObjectAttribute.getName()); + logger.info("customObjectAttribute.getName():{}", customObjectAttribute.getName()); JansAttribute attribute = attributeService.getAttributeByName(customObjectAttribute.getName()); AttributeValidation validation = null; if (attribute != null) { @@ -559,8 +551,8 @@ public void validateAttributes(List customAttributes) { private String validateCustomAttributes(CustomObjectAttribute customObjectAttribute, AttributeValidation attributeValidation) { - logger.info("Validate customObjectAttribute:{}, attributeValidation:{}", customObjectAttribute, - attributeValidation); + logger.info("Validate attributeValidation:{}", attributeValidation); + StringBuilder sb = new StringBuilder(); if (customObjectAttribute == null || attributeValidation == null) { return sb.toString(); @@ -568,9 +560,7 @@ private String validateCustomAttributes(CustomObjectAttribute customObjectAttrib String attributeName = customObjectAttribute.getName(); try { - String attributeValue = String.valueOf(customObjectAttribute.getValue()); - logger.info("Validate attributeName:{}, attributeValue:{}", attributeName, attributeValue); if (StringUtils.isBlank(attributeValue)) { return sb.toString(); @@ -579,8 +569,8 @@ private String validateCustomAttributes(CustomObjectAttribute customObjectAttrib Integer maxValue = attributeValidation.getMaxLength(); String regexpValue = attributeValidation.getRegexp(); logger.info( - "Validate attributeValue:{}, attributeValue.length():{}, attributeValidation.getMinLength():{}, attributeValidation.getMaxLength():{}, attributeValidation.getRegexp():{}", - attributeValue, attributeValue.length(), attributeValidation.getMinLength(), + "Validate attributeValue.length():{}, attributeValidation.getMinLength():{}, attributeValidation.getMaxLength():{}, attributeValidation.getRegexp():{}", + attributeValue.length(), attributeValidation.getMinLength(), attributeValidation.getMaxLength(), attributeValidation.getRegexp()); // minvalue Validation diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java b/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java index a65089d2418..06b91fefb93 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java @@ -112,7 +112,10 @@ private void processRequest(InvocationContext context, AuditLogConf auditLogConf clazz.isPrimitive()); Object obj = ctxParameters[i]; - AUDIT_LOG.info("RequestReaderInterceptor final - obj - obj:{} ", obj); + if (obj != null && (!obj.toString().toUpperCase().contains("PASSWORD") + || !obj.toString().toUpperCase().contains("SECRET"))) { + AUDIT_LOG.info("RequestReaderInterceptor final - obj - obj:{} ", obj); + } } } From 6c828507813d83c56acb47320b54fa28f8a23edc Mon Sep 17 00:00:00 2001 From: Isman Firmansyah Date: Wed, 18 Dec 2024 13:58:40 +0700 Subject: [PATCH 2/2] chore(docker-jans-config-api): add external script to poll components healthcheck (#10444) Signed-off-by: iromli --- docker-jans-config-api/Dockerfile | 3 + .../scripts/external_healthcheck.py | 64 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100755 docker-jans-config-api/scripts/external_healthcheck.py diff --git a/docker-jans-config-api/Dockerfile b/docker-jans-config-api/Dockerfile index 79dcda5bbe1..9ee6257b029 100644 --- a/docker-jans-config-api/Dockerfile +++ b/docker-jans-config-api/Dockerfile @@ -102,6 +102,7 @@ RUN cd /tmp/jans \ && cp ${JANS_SETUP_DIR}/templates/jans-config-api/config.ldif /app/templates/jans-config-api/ \ && cp ${JANS_SETUP_DIR}/templates/jans-config-api/dynamic-conf.json /app/templates/jans-config-api/ \ && cp ${JANS_SETUP_DIR}/setup_app/utils/printVersion.py /opt/jans/bin/printVersion.py \ + && chmod +x /opt/jans/bin/printVersion.py \ && ln -s /opt/jans/bin/printVersion.py /opt/jans/bin/show_version.py \ && cp ${JANS_CONFIG_API_RESOURCES}/config-api-rs-protect.json /app/templates/jans-config-api/ \ && mkdir -p org/eclipse/jetty \ @@ -237,6 +238,8 @@ COPY templates /app/templates/ RUN cp /app/templates/jans-config-api/jans-config-api.xml ${JETTY_BASE}/jans-config-api/webapps/ COPY scripts /app/scripts RUN chmod +x /app/scripts/entrypoint.sh +RUN chmod +x /app/scripts/external_healthcheck.py \ + && ln -s /app/scripts/external_healthcheck.py /opt/jans/bin/jans_services_status.py # unquote apiApprovedIssuer RUN sed -i 's/"${apiApprovedIssuer}"/${apiApprovedIssuer}/g' /app/templates/jans-config-api/dynamic-conf.json diff --git a/docker-jans-config-api/scripts/external_healthcheck.py b/docker-jans-config-api/scripts/external_healthcheck.py new file mode 100755 index 00000000000..0e0c3038d02 --- /dev/null +++ b/docker-jans-config-api/scripts/external_healthcheck.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +import json + +import requests + +from jans.pycloudlib import get_manager + + +def poll_healthchecks(manager): + import urllib3 + + hostname = manager.config.get("hostname") + statuses = {} + + for comp, endpoint, status_code_only in [ + ("jans-auth", "/jans-auth/sys/health-check", False), + ("jans-lock", "/jans-auth/sys/health-check", False), + ("jans-config-api", "/jans-config-api/api/v1/health/live", False), + ("jans-casa", "/jans-casa/health-check", False), + ("jans-fido2", "/jans-fido2/sys/health-check", False), + ("jans-scim", "/jans-scim/sys/health-check", False), + ("jans-link", "/jans-link/sys/health-check", False), + # healthcheck endpoint for KC is bind to internal port 9000, + # hence we poll the public endpoint instead + ("keycloak", "/kc", True), + ]: + # default component status + status = "Down" + + scheme = "https" + verify = False + + if scheme == "https" and verify is False: + urllib3.disable_warnings() + + resp = requests.get(f"{scheme}://{hostname}{endpoint}", timeout=5, verify=verify) + + if resp.ok: + if status_code_only: + status = "Running" + else: + try: + if comp == "jans-lock": + healthcheck_data = resp.json().get("jans-lock", {"status": status}) + else: + healthcheck_data = resp.json() + + if healthcheck_data["status"].lower() in ("running", "up"): + status = "Running" + + # response from server is not JSON + except requests.exceptions.JSONDecodeError: + if resp.text.lower() == "ok": + status = "Running" + + # finalized statuses + statuses[comp] = status + + return json.dumps(statuses) + + +if __name__ == "__main__": + manager = get_manager() + print(poll_healthchecks(manager))