diff --git a/README.md b/README.md index 384649b6b..ffe9e5bc8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mosip_esignet&id=mosip_esignet&metric=alert_status)](https://sonarcloud.io/dashboard?id=mosip_esignet) # eSignet Project ## Overview + +eSignet offers a seamless and straightforward solution for incorporating an existing trusted identity database into the digital realm via plugins. + This repository contains limited OpenId protocol implementation with: * OAuth 2.0 RFC 6749 - Authorization code flow support * OAuth 2.0 RFC 7636 - PKCE security extension @@ -9,13 +12,12 @@ This repository contains limited OpenId protocol implementation with: * RFC 7519 - ID token and access token as JWT * OpenID Connect Discovery 1.0 - /.well-known/openid-configuration * RFC 5785 - Followed for both openid and oauth well-knowns -* Identity assurance 1.0 +* Identity Assurance 1.0 ## High level overview of eSignet with external systems -![esignet-architecture-overview.png](docs/esignet-architecture-overview.png) +![esignet-overview.png](docs/esignet-overview.png) -`Note: Kindly refer `[eSignet signup repository](https://github.com/mosip/esignet-signup)` for more details on eSignet signup module.` eSignet repository contains following: @@ -43,7 +45,7 @@ Refer to [SQL scripts](db_scripts). The project requires JDK 11. 1. Build: ``` - $ mvn clean install -Dgpg.skip=true + $ mvn clean install -Dgpg.skip=true -Dmaven.gitcommitid.skip=true ``` ## [Deployment in K8 cluster](deploy/README.md) diff --git a/api-test/pom.xml b/api-test/pom.xml index 0f909aa6f..edbd33246 100644 --- a/api-test/pom.xml +++ b/api-test/pom.xml @@ -8,7 +8,7 @@ apitest-esignet Parent project of MOSIP Esignet apitests https://github.com/mosip/esignet - 1.2.1-SNAPSHOT + 1.5.1-SNAPSHOT @@ -49,14 +49,14 @@ 2.2.1 3.0.1 - apitest-esignet-1.2.1-SNAPSHOT-jar-with-dependencies + apitest-esignet-1.5.1-SNAPSHOT-jar-with-dependencies - io.mosip.testrig.apirig.apitest.commons + io.mosip.testrig.apitest.commons apitest-commons - 1.2.2-SNAPSHOT + 1.3.0 diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testrunner/MosipTestRunner.java b/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testrunner/MosipTestRunner.java index 74d3e0fe7..255c95f5a 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testrunner/MosipTestRunner.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testrunner/MosipTestRunner.java @@ -159,13 +159,13 @@ public static void suiteSetup(String runType) { BaseTestCase.certsForModule = GlobalConstants.ESIGNET; DBManager.executeDBQueries(EsignetConfigManager.getKMDbUrl(), EsignetConfigManager.getKMDbUser(), EsignetConfigManager.getKMDbPass(), EsignetConfigManager.getKMDbSchema(), - getGlobalResourcePath() + "/" + "config/keyManagerCertDataDeleteQueries.txt"); + getGlobalResourcePath() + "/" + "config/keyManagerDataDeleteQueriesForEsignet.txt"); DBManager.executeDBQueries(EsignetConfigManager.getIdaDbUrl(), EsignetConfigManager.getIdaDbUser(), EsignetConfigManager.getPMSDbPass(), EsignetConfigManager.getIdaDbSchema(), - getGlobalResourcePath() + "/" + "config/idaCertDataDeleteQueries.txt"); + getGlobalResourcePath() + "/" + "config/idaDeleteQueriesForEsignet.txt"); DBManager.executeDBQueries(EsignetConfigManager.getMASTERDbUrl(), EsignetConfigManager.getMasterDbUser(), EsignetConfigManager.getMasterDbPass(), EsignetConfigManager.getMasterDbSchema(), - getGlobalResourcePath() + "/" + "config/masterDataCertDataDeleteQueries.txt"); + getGlobalResourcePath() + "/" + "config/masterDataDeleteQueriesForEsignet.txt"); AdminTestUtil.initiateesignetTest(); BaseTestCase.otpListener = new OTPListener(); BaseTestCase.otpListener.run(); diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testscripts/PostWithAutogenIdWithOtpGenerate.java b/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testscripts/PostWithAutogenIdWithOtpGenerate.java index c953c2b45..32de9e2b8 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testscripts/PostWithAutogenIdWithOtpGenerate.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/esignet/testscripts/PostWithAutogenIdWithOtpGenerate.java @@ -93,16 +93,12 @@ public void test(TestCaseDTO testCaseDTO) if (testCaseDTO.getTestCaseName().contains("VID") || testCaseDTO.getTestCaseName().contains("Vid")) { - - - - - if (!BaseTestCase.getSupportedIdTypesValue().contains("VID") && !BaseTestCase.getSupportedIdTypesValue().contains("vid")) { throw new SkipException(GlobalConstants.VID_FEATURE_NOT_SUPPORTED); } } + String inputJson = testCaseDTO.getInput().toString(); JSONObject req = new JSONObject(testCaseDTO.getInput()); diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/esignet/utils/EsignetUtil.java b/api-test/src/main/java/io/mosip/testrig/apirig/esignet/utils/EsignetUtil.java index 71554f745..3dda3ab15 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/esignet/utils/EsignetUtil.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/esignet/utils/EsignetUtil.java @@ -185,9 +185,8 @@ public static String isTestCaseValidForExecution(TestCaseDTO testCaseDTO) { // Let run test cases eSignet & MOSIP API calls --- both UIN and VID // BaseTestCase.setSupportedIdTypes(Arrays.asList("UIN", "VID")); - getSupportedIdTypesValueFromActuator(); - + logger.info("supportedIdType = " + supportedIdType); String endpoint = testCaseDTO.getEndPoint(); @@ -251,4 +250,4 @@ public static String replaceKeywordValue(String jsonString, String keyword, Stri throw new SkipException("Marking testcase as skipped as required fields are empty " + keyword); } -} \ No newline at end of file +} diff --git a/api-test/src/main/resources/config/esignet.properties b/api-test/src/main/resources/config/esignet.properties index b6a0a4ff4..79fbd4cf8 100644 --- a/api-test/src/main/resources/config/esignet.properties +++ b/api-test/src/main/resources/config/esignet.properties @@ -5,9 +5,9 @@ tokenEndpoint=/v1/esignet/oauth/token validateBindingEndpoint=ida-binding esignetWellKnownEndPoint=/v1/esignet/oidc/.well-known/openid-configuration signupSettingsEndPoint=/v1/signup/settings -esignetActuatorPropertySection=application-default.properties +esignetActuatorPropertySection=classpath:/application-default.properties # uncomment below property while executing on camdgc env locally -servicesNotDeployed=resident,ridgenerator,admin,hotlist,preregistration,registrationprocessor,hub,print,packetcreator,packetmanager,mock-abis-service,mockmv,sunbirdrc +servicesNotDeployed=sunbirdrc # uncomment below property while executing on non camdgc env locally #servicesNotDeployed= esignetMockBaseURL=esignet-insurance. @@ -17,4 +17,4 @@ sunBirdBaseURL=https://registry.dev1.mosip.net #------------------------- Need to check if these are used or not ------------------------# OTPTimeOut = 181 -attempt = 10 \ No newline at end of file +attempt = 10 diff --git a/api-test/src/main/resources/esignet/WalletBinding/WalletBinding.yml b/api-test/src/main/resources/esignet/WalletBinding/WalletBinding.yml index 7918c0b42..aaf4092c6 100644 --- a/api-test/src/main/resources/esignet/WalletBinding/WalletBinding.yml +++ b/api-test/src/main/resources/esignet/WalletBinding/WalletBinding.yml @@ -407,7 +407,7 @@ WalletBinding: "errors": [ { "errorCode": "IDA-MLC-009", - "errorMessage": "request.individualId: invalid_individual_id" + "errorMessage": "$IGNORE$" } ], "sendOtpResp": { @@ -2789,4 +2789,4 @@ WalletBinding: "sendOtpResTemplate":"esignet/SendBindingOtp/SendBindingOtpResult", "maskedEmail": "$IGNORE$" } -}' \ No newline at end of file +}' diff --git a/api-test/testNgXmlFiles/esignetSuite.xml b/api-test/testNgXmlFiles/esignetSuite.xml index 9c0ae6a95..5763e2215 100644 --- a/api-test/testNgXmlFiles/esignetSuite.xml +++ b/api-test/testNgXmlFiles/esignetSuite.xml @@ -7,6 +7,7 @@ + @@ -494,6 +495,5 @@ - --> - - \ No newline at end of file + --> + diff --git a/deploy/.gitignore b/deploy/.gitignore new file mode 100644 index 000000000..5440660c2 --- /dev/null +++ b/deploy/.gitignore @@ -0,0 +1 @@ +esignet-global-cm.yaml diff --git a/deploy/README.md b/deploy/README.md index d1ca09675..22ba37543 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -24,19 +24,51 @@ * __Logging__ : Setup logging as per [steps](https://github.com/mosip/k8s-infra/tree/v1.2.0.2/logging). * __Monitoring__ : Setup monitoring consisting elasticsearch, kibana, grafana using [steps](https://github.com/mosip/k8s-infra/tree/v1.2.0.2/monitoring). ### Install Pre-requisites -``` -./install-prereq.sh -``` +* `esignet-global` configmap: For eSignet K8's env, `esignet-global` configmap in `esignet` namespace contains Domain related information. Follow below steps to add domain details for `esignet-global` configmap. + * Copy `esignet-global-cm.yaml.sample` to `esignet-global-cm.yaml`. + * Update the domain names in `esignet-global-cm.yaml` correctly for your environment. + * Create a google recaptcha v2 ("I am not a Robot") from Google with required domain name ex:[sandbox.mosip.net] [Recaptcha Admin](https://www.google.com/recaptcha/about/) and set esignet captcha. +* Install pre-requisites + ``` + ./install-prereq.sh + ``` ### Initialise pre-requisites * Update values file for postgres init [here](postgres/init_values.yaml). -* Execute `initialise-prereq.sh` script to initialise postgres and keycloak and set esignet captcha. +* Execute `initialise-prereq.sh` script to initialise postgres and keycloak. ``` ./initialise-prereq.sh ``` -### Install esignet, oidc and captcha service +### Install esignet and oidc +During deployment, the system will prompt for user input to select the appropriate plugin. The available options are listed below: +1. esignet-mock-plugin.jar +2. mosip-identity-plugin.jar + +For current scope of deployment, as it is limited to mock functionality, +select option 1 (esignet-mock-plugin.jar). ``` ./install-esignet.sh ``` ## Onboarder -* If Esignet is getting deployed with MOSIP than we need to execute the onboarder for MISP partner. +* There are two ways to proceed, either with mosip identity plugin or with mock plugin. +### MOSIP Identity Plugin +* If Esignet is getting deployed with MOSIP then we need to execute the onboarder for MISP partner and mock-rp oidc clientId. * Onboarder [scripts](../partner-onboarder/). + +### MOCK Plugin +* Download postman collection from [here](../postman-collection) +* Fetch auth token from esignet keycloak. Update the "client_secret" in the request body. +* Run the request under "OIDC Client Mgmt" -> "Mock" -> "Get Auth token" +* Run the requests under + + a. "OIDC Client Mgmt" -> "Mock" -> "Get CSRF token" + + b. "OIDC Client Mgmt" -> "Mock" -> "Create OIDC client" + +### NOTE: +This deployment is limited to mock +Below section related to configuring IDA is not tested. Still it can be tried out + +### CONFIGURE IDA for Esignet : +Onboard eSignet as MISP partner in MOSIP PMS using our onboarder script +We should override properties defined [here](https://github.com/mosip/esignet-plugins/blob/release-1.3.x/mosip-identity-plugin/src/main/resources/application.properties) if there is any change in the MOSIP IDA domain names. +Update the 'MOSIP_ESIGNET_AUTHENTICATOR_IDA_SECRET_KEY' property with MOSIP IDA keycloak client secret. diff --git a/deploy/captcha/install.sh b/deploy/captcha/install.sh index 6ba347253..a1878aee7 100755 --- a/deploy/captcha/install.sh +++ b/deploy/captcha/install.sh @@ -1,20 +1,31 @@ #!/bin/bash -## Installing captcha validation server. +## Combined Script: Installing Captcha Validation Server and Initializing Prerequisites ## Usage: ./install.sh [kubeconfig] if [ $# -ge 1 ] ; then export KUBECONFIG=$1 fi +ROOT_DIR=`pwd` NS=captcha CHART_VERSION=0.1.0-develop -echo Create $NS namespace -kubectl create ns $NS - function installing_captcha() { - echo Istio label + while true; do + read -p "Do you want to continue installing captcha validation service? (y/n): " ans + if [ "$ans" = "Y" ] || [ "$ans" = "y" ]; then + break + elif [ "$ans" = "N" ] || [ "$ans" = "n" ]; then + exit 1 + else + echo "Please provide a correct option (Y or N)" + fi + done + + echo "Creating $NS namespace" + kubectl create ns $NS || true + echo "Applying Istio label to namespace" kubectl label ns $NS istio-injection=disabled --overwrite helm repo update @@ -31,11 +42,47 @@ function installing_captcha() { fi done - echo Installing captcha + echo "Installing captcha" helm -n $NS install captcha mosip/captcha --version $CHART_VERSION --set metrics.serviceMonitor.enabled=$servicemonitorflag --wait - echo Installed captcha service - return 0 + echo "Installed captcha service" + + # Set up Captcha secrets for eSignet + while true; do + read -p "Do you want to continue configuring Captcha secrets for esignet? (y/n): " ans + if [[ "$ans" == "Y" || "$ans" == "y" ]]; then + ESIGNET_HOST=$(kubectl -n esignet get cm esignet-global -o jsonpath={.data.mosip-esignet-host}) + echo "Please create captcha site and secret key for esignet domain: $ESIGNET_HOST" + + echo "Please enter the reCAPTCHA admin site key for domain $ESIGNET_HOST:" + read ESITE_KEY + echo "Please enter the reCAPTCHA admin secret key for domain $ESIGNET_HOST:" + read ESECRET_KEY + + echo "Setting up Captcha secrets" + kubectl -n esignet create secret generic esignet-captcha --from-literal=esignet-captcha-site-key=$ESITE_KEY --from-literal=esignet-captcha-secret-key=$ESECRET_KEY --dry-run=client -o yaml | kubectl apply -f - + echo "Captcha secrets for esignet configured successfully" + + ../copy_cm_func.sh secret esignet-captcha esignet $NS + + # Update or add environment variable + ENV_VAR_EXISTS=$(kubectl -n $NS get deployment captcha -o jsonpath="{.spec.template.spec.containers[0].env[?(@.name=='MOSIP_CAPTCHA_SECRET_ESIGNET')].name}") + if [[ -z "$ENV_VAR_EXISTS" ]]; then + echo "Environment variable 'MOSIP_CAPTCHA_SECRET_ESIGNET' does not exist. Adding it..." + kubectl patch deployment -n $NS captcha --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/env/-", "value": {"name": "MOSIP_CAPTCHA_SECRET_ESIGNET", "valueFrom": {"secretKeyRef": {"name": "esignet-captcha", "key": "esignet-captcha-secret-key"}}}}]' + else + echo "Environment variable 'MOSIP_CAPTCHA_SECRET_ESIGNET' exists. Updating it..." + kubectl patch deployment -n $NS captcha --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/env[?(@.name==\"MOSIP_CAPTCHA_SECRET_ESIGNET\")]", "value": {"name": "MOSIP_CAPTCHA_SECRET_ESIGNET", "valueFrom": {"secretKeyRef": {"name": "esignet-captcha", "key": "esignet-captcha-secret-key"}}}}]' + fi + + break + elif [[ "$ans" == "N" || "$ans" == "n" ]]; then + echo "Skipping Captcha secrets configuration." + break + else + echo "Please provide a correct option (Y or N)" + fi + done } # set commands for error handling. diff --git a/deploy/config-server/install.sh b/deploy/config-server/install.sh index eee57f6d6..83ec9c90a 100755 --- a/deploy/config-server/install.sh +++ b/deploy/config-server/install.sh @@ -6,17 +6,18 @@ if [ $# -ge 1 ] ; then export KUBECONFIG=$1 fi +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes + NS=esignet CHART_VERSION=0.0.1-develop echo Create $NS namespace - kubectl create ns $NS - # set commands for error handling. - set -e - set -o errexit ## set -e : exit the script if any statement returns a non-true return value - set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - set -o errtrace # trace ERR through 'time command' and other functions - set -o pipefail # trace ERR through pipes + kubectl create ns $NS || true echo Istio label kubectl label ns $NS istio-injection=enabled --overwrite diff --git a/deploy/esignet-apitestrig/README.md b/deploy/esignet-apitestrig/README.md index a5e277981..e2647c3d9 100644 --- a/deploy/esignet-apitestrig/README.md +++ b/deploy/esignet-apitestrig/README.md @@ -2,13 +2,25 @@ ## Introduction ApiTestRig will test the working of APIs of the MOSIP modules. - ## Install +* Create a directory for apitestrig on the NFS server at `/srv/nfs/mosip//apitestrig/`: +``` +mkdir -p /srv/nfs/mosip//apitestrig/ +``` +* Ensure the directory has 777 permissions: +``` +chmod 777 /srv/nfs/mosip//apitestrig +``` +* Add the following entry to the /etc/exports file: +``` +/srv/nfs/mosip//apitestrig *(ro,sync,no_root_squash,no_all_squash,insecure,subtree_check) +``` * Review `values.yaml` and, Make sure to enable required modules for apitestrig operation. -* Install -```sh +* run `./install.sh`. +``` ./install.sh ``` + * During the execution of the `install.sh` script, a prompt appears requesting information regarding the presence of a public domain and a valid SSL certificate on the server. * If the server lacks a public domain and a valid SSL certificate, it is advisable to select the `n` option. Opting it will enable the `init-container` with an `emptyDir` volume and include it in the deployment process. * The init-container will proceed to download the server's self-signed SSL certificate and mount it to the specified location within the container's Java keystore (i.e., `cacerts`) file. @@ -41,4 +53,4 @@ ApiTestRig will test the working of APIs of the MOSIP modules. example: ``` kubectl --kubeconfig=/home/xxx/Downloads/qa4.config -n apitestrig create job --from=cronjob/cronjob-apitestrig-masterdata cronjob-apitestrig-masterdata - ``` \ No newline at end of file + ``` diff --git a/deploy/esignet-apitestrig/delete.sh b/deploy/esignet-apitestrig/delete.sh index 38c79022c..bdd4ca061 100755 --- a/deploy/esignet-apitestrig/delete.sh +++ b/deploy/esignet-apitestrig/delete.sh @@ -27,4 +27,4 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true set -o nounset ## set -u : exit the script if you try to use an uninitialised variable set -o errtrace # trace ERR through 'time command' and other functions set -o pipefail # trace ERR through pipes -deleting_apitestrig # calling function \ No newline at end of file +deleting_apitestrig # calling function diff --git a/deploy/esignet-apitestrig/install.sh b/deploy/esignet-apitestrig/install.sh index 7fed643b6..564b9e599 100755 --- a/deploy/esignet-apitestrig/install.sh +++ b/deploy/esignet-apitestrig/install.sh @@ -7,7 +7,7 @@ if [ $# -ge 1 ] ; then fi NS=esignet -CHART_VERSION=0.0.1-develop +CHART_VERSION=1.5.0-develop COPY_UTIL=../copy_cm_func.sh echo Create $NS namespace @@ -19,14 +19,12 @@ function installing_apitestrig() { helm repo update echo Copy Configmaps - $COPY_UTIL configmap global default $NS $COPY_UTIL configmap keycloak-host keycloak $NS $COPY_UTIL configmap artifactory-share artifactory $NS $COPY_UTIL configmap config-server-share config-server $NS echo echo Copy Secrtes $COPY_UTIL secret keycloak-client-secrets keycloak $NS - $COPY_UTIL secret s3 s3 $NS $COPY_UTIL secret postgres-postgresql postgres $NS echo "Delete s3, db, & apitestrig configmap if exists" @@ -34,9 +32,9 @@ function installing_apitestrig() { kubectl -n $NS delete --ignore-not-found=true configmap db kubectl -n $NS delete --ignore-not-found=true configmap apitestrig - DB_HOST=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' ) - API_INTERNAL_HOST=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' ) - ENV_USER=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' | awk -F '.' '/api-internal/{print $1"."$2}') + DB_HOST=$( kubectl -n esignet get cm esignet-global -o json |jq -r '.data."mosip-api-internal-host"' ) + API_INTERNAL_HOST=$( kubectl -n esignet get cm esignet-global -o json |jq -r '.data."mosip-api-internal-host"' ) + ENV_USER=$( kubectl -n esignet get cm esignet-global -o json |jq -r '.data."mosip-api-internal-host"' | awk -F '.' '/api-internal/{print $1"."$2}') read -p "Please enter the time(hr) to run the cronjob every day (time: 0-23) : " time if [ -z "$time" ]; then @@ -96,29 +94,80 @@ function installing_apitestrig() { else echo "eSignet service is not deployed. hence will be skipping esignet related test-cases..." fi - - echo Installing esignet apitestrig - helm -n $NS install esignet-apitestrig mosip/apitestrig \ - --set crontime="0 $time * * *" \ - -f values.yaml \ - --version $CHART_VERSION \ - --set apitestrig.configmaps.s3.s3-host='http://minio.minio:9000' \ - --set apitestrig.configmaps.s3.s3-user-key='admin' \ - --set apitestrig.configmaps.s3.s3-region='' \ - --set apitestrig.configmaps.db.db-server="$DB_HOST" \ - --set apitestrig.configmaps.db.db-su-user="postgres" \ - --set apitestrig.configmaps.db.db-port="5432" \ - --set apitestrig.configmaps.apitestrig.ENV_USER="$ENV_USER" \ - --set apitestrig.configmaps.apitestrig.ENV_ENDPOINT="https://$API_INTERNAL_HOST" \ - --set apitestrig.configmaps.apitestrig.ENV_TESTLEVEL="smokeAndRegression" \ - --set apitestrig.configmaps.apitestrig.reportExpirationInDays="$reportExpirationInDays" \ - --set apitestrig.configmaps.apitestrig.slack-webhook-url="$slackWebhookUrl" \ - --set apitestrig.configmaps.apitestrig.eSignetDeployed="$eSignetDeployed" \ - --set apitestrig.configmaps.apitestrig.NS="$NS" \ - $ENABLE_INSECURE - - echo Installed esignet apitestrig. - return 0 + read -p "Is values.yaml for apitestrig chart set correctly as part of pre-requisites? (Y/n) : " yn; + if [[ $yn = "Y" ]] || [[ $yn = "y" ]] ; then + NFS_OPTION='' + S3_OPTION='' + config_complete=false # flag to check if S3 or NFS is configured + while [ "$config_complete" = false ]; do + read -p "Do you have S3 details for storing apitestrig reports? (Y/n) : " ans + if [[ "$ans" == "y" || "$ans" == "Y" ]]; then + read -p "Please provide S3 host: " s3_host + if [[ -z $s3_host ]]; then + echo "S3 host not provided; EXITING;" + exit 1; + fi + read -p "Please provide S3 region: " s3_region + if [[ $s3_region == *[' !@#$%^&*()+']* ]]; then + echo "S3 region should not contain spaces or special characters; EXITING;" + exit 1; + fi + + read -p "Please provide S3 access key: " s3_user_key + if [[ -z $s3_user_key ]]; then + echo "S3 access key not provided; EXITING;" + exit 1; + fi + S3_OPTION="--set apitestrig.configmaps.s3.s3-host=$s3_host --set apitestrig.configmaps.s3.s3-user-key=$s3_user_key --set apitestrig.configmaps.s3.s3-region=$s3_region" + push_reports_to_s3="yes" + config_complete=true + elif [[ "$ans" == "n" || "$ans" == "N" ]]; then + push_reports_to_s3="no" + read -p "Since S3 details are not available, do you want to use NFS directory mount for storing reports? (y/n) : " answer + if [[ $answer == "Y" ]] || [[ $answer == "y" ]]; then + read -p "Please provide NFS Server IP: " nfs_server + if [[ -z $nfs_server ]]; then + echo "NFS server not provided; EXITING." + exit 1; + fi + read -p "Please provide NFS directory to store reports from NFS server (e.g. /srv/nfs/mosip//apitestrig/), make sure permission is 777 for the folder: " nfs_path + if [[ -z $nfs_path ]]; then + echo "NFS Path not provided; EXITING." + exit 1; + fi + NFS_OPTION="--set apitestrig.volumes.reports.nfs.server=$nfs_server --set apitestrig.volumes.reports.nfs.path=$nfs_path" + config_complete=true + else + echo "Please rerun the script with either S3 or NFS server details." + exit 1; + fi + else + echo "Invalid input. Please respond with Y (yes) or N (no)." + fi + done + echo Installing esignet apitestrig + helm -n $NS install esignet-apitestrig mosip/apitestrig \ + --set crontime="0 $time * * *" \ + -f values.yaml \ + --version $CHART_VERSION \ + $NFS_OPTION \ + $S3_OPTION \ + --set apitestrig.variables.push_reports_to_s3=$push_reports_to_s3 \ + --set apitestrig.configmaps.db.db-server="$DB_HOST" \ + --set apitestrig.configmaps.db.db-su-user="postgres" \ + --set apitestrig.configmaps.db.db-port="5432" \ + --set apitestrig.configmaps.apitestrig.ENV_USER="$ENV_USER" \ + --set apitestrig.configmaps.apitestrig.ENV_ENDPOINT="https://$API_INTERNAL_HOST" \ + --set apitestrig.configmaps.apitestrig.ENV_TESTLEVEL="smokeAndRegression" \ + --set apitestrig.configmaps.apitestrig.reportExpirationInDays="$reportExpirationInDays" \ + --set apitestrig.configmaps.apitestrig.slack-webhook-url="$slackWebhookUrl" \ + --set apitestrig.configmaps.apitestrig.eSignetDeployed="$eSignetDeployed" \ + --set apitestrig.configmaps.apitestrig.NS="$NS" \ + $ENABLE_INSECURE + + echo Installed esignet apitestrig. + return 0 + fi } # set commands for error handling. @@ -127,4 +176,4 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true set -o nounset ## set -u : exit the script if you try to use an uninitialised variable set -o errtrace # trace ERR through 'time command' and other functions set -o pipefail # trace ERR through pipes -installing_apitestrig # calling function \ No newline at end of file +installing_apitestrig # calling function diff --git a/deploy/esignet-apitestrig/values.yaml b/deploy/esignet-apitestrig/values.yaml index 0d4623d75..d3c38f391 100644 --- a/deploy/esignet-apitestrig/values.yaml +++ b/deploy/esignet-apitestrig/values.yaml @@ -2,6 +2,14 @@ modules: esignet: enabled: true image: - repository: mosipqa/apitest-esignet - tag: develop + repository: mosipdev/apitest-esignet + tag: release-1.5.x pullPolicy: Always + +resources: + limits: + cpu: 300m + memory: 500Mi + requests: + cpu: 300m + memory: 500Mi diff --git a/deploy/esignet-global-cm.yaml b/deploy/esignet-global-cm.yaml.sample similarity index 100% rename from deploy/esignet-global-cm.yaml rename to deploy/esignet-global-cm.yaml.sample diff --git a/deploy/esignet/install.sh b/deploy/esignet/install.sh index c17d41f92..080f10721 100755 --- a/deploy/esignet/install.sh +++ b/deploy/esignet/install.sh @@ -6,16 +6,31 @@ if [ $# -ge 1 ] ; then export KUBECONFIG=$1 fi -NS=esignet -CHART_VERSION=0.0.1-test - -ESIGNET_HOST=$(kubectl -n esignet get cm esignet-global -o jsonpath={.data.mosip-esignet-host}) - echo Create $NS namespace kubectl create ns $NS function installing_esignet() { + while true; do + read -p "Do you want to continue installing esignet services? (y/n): " ans + if [ "$ans" = "Y" ] || [ "$ans" = "y" ]; then + break + elif [ "$ans" = "N" ] || [ "$ans" = "n" ]; then + exit 1 + else + echo "Please provide a correct option (Y or N)" + fi + done + + + NS=esignet + CHART_VERSION=1.5.0-develop + + ESIGNET_HOST=$(kubectl -n esignet get cm esignet-global -o jsonpath={.data.mosip-esignet-host}) + + echo Create $NS namespace + kubectl create ns $NS || true + echo Istio label kubectl label ns $NS istio-injection=enabled --overwrite helm repo add mosip https://mosip.github.io/mosip-helm @@ -23,6 +38,7 @@ function installing_esignet() { COPY_UTIL=../copy_cm_func.sh $COPY_UTIL configmap esignet-softhsm-share softhsm $NS + $COPY_UTIL configmap postgres-config postgres $NS $COPY_UTIL configmap redis-config redis $NS $COPY_UTIL secret esignet-softhsm softhsm $NS $COPY_UTIL secret redis redis $NS @@ -63,10 +79,10 @@ function installing_esignet() { read -p "Enter the plugin number: " plugin_no while true; do if [[ "$plugin_no" == "1" ]]; then - plugin_option="--set plugin_name_env=esignet-mock-plugin.jar" + plugin_option="--set pluginNameEnv=esignet-mock-plugin.jar" break elif [[ "$plugin_no" == "2" ]]; then - plugin_option="--set plugin_name_env=mosip-identity-plugin.jar" + plugin_option="--set pluginNameEnv=mosip-identity-plugin.jar" break else echo "please provide the correct plugin number (1 or 2)." diff --git a/deploy/initialise-prereq.sh b/deploy/initialise-prereq.sh index a8259252f..df5ceabde 100755 --- a/deploy/initialise-prereq.sh +++ b/deploy/initialise-prereq.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Initialises prerequisite services for Esignet +# Initializes prerequisite services for Esignet ## Usage: ./install.sh [kubeconfig] if [ $# -ge 1 ] ; then @@ -23,38 +23,28 @@ function prompt_for_initialisation() { cd $ROOT_DIR/"$module_name" ./"$module_name"-init.sh else - echo "Skipping initialising of $module_name." + echo "Skipping initialization of $module_name." fi } -function initialising_Prerequisites() { - - declare -a modules=("postgres" "keycloak" ) +function initialising_prerequisites() { + declare -a modules=("postgres" "keycloak") declare -A prompts=( ["postgres"]="Do you want to continue executing postgres init?" ["keycloak"]="Do you want to continue executing keycloak init?" ) - echo "Initialising prerequisite services" + echo "Initializing prerequisite services" for module in "${modules[@]}" do prompt_for_initialisation "$module" "${prompts[$module]}" done - ESIGNET_HOST=$(kubectl -n esignet get cm esignet-global -o jsonpath={.data.mosip-esignet-host}) - echo Please enter the recaptcha admin site key for domain $ESIGNET_HOST - read ESITE_KEY - echo Please enter the recaptcha admin secret key for domain $ESIGNET_HOST - read ESECRET_KEY - - echo Setting up captcha secrets - kubectl -n $NS create secret generic esignet-captcha --from-literal=esignet-captcha-site-key=$ESITE_KEY --from-literal=esignet-captcha-secret-key=$ESECRET_KEY --dry-run=client -o yaml | kubectl apply -f - - - echo Setting up dummy values for esignet misp license key + echo "Setting up dummy values for Esignet MISP license key" kubectl -n $NS create secret generic esignet-misp-onboarder-key --from-literal=mosip-esignet-misp-key='' --dry-run=client -o yaml | kubectl apply -f - - echo "All prerequisite services initialised successfully." + echo "All prerequisite services initialized successfully." return 0 } @@ -64,4 +54,4 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true set -o nounset ## set -u : exit the script if you try to use an uninitialized variable set -o errtrace # trace ERR through 'time command' and other functions set -o pipefail # trace ERR through pipes -initialising_Prerequisites # calling function +initialising_prerequisites # calling function diff --git a/deploy/install-esignet.sh b/deploy/install-esignet.sh index 4888a39b2..4c3c606ec 100755 --- a/deploy/install-esignet.sh +++ b/deploy/install-esignet.sh @@ -13,7 +13,7 @@ function installing_eSignet() { helm repo add mosip https://mosip.github.io/mosip-helm # List of modules to install - declare -a modules=("esignet" "oidc-ui" "captcha") + declare -a modules=("esignet" "oidc-ui") echo "Installing eSignet services" diff --git a/deploy/install-prereq.sh b/deploy/install-prereq.sh index ee18d008c..1fcc442cb 100755 --- a/deploy/install-prereq.sh +++ b/deploy/install-prereq.sh @@ -8,8 +8,7 @@ if [ $# -ge 1 ]; then fi ROOT_DIR=$(pwd) -SOFTHSM_NS=softhsm -SOFTHSM_CHART_VERSION=12.0.1 +kubectl create ns esignet || true function prompt_for_deployment() { local module_name=$1 @@ -30,36 +29,25 @@ function prompt_for_deployment() { function installing_prerequisites() { - helm repo add mosip https://mosip.github.io/mosip-helm - helm repo update - - # Create esignet, softhsm namespace if not present - kubectl create ns esignet || true - kubectl create ns "$SOFTHSM_NS" || true - # Apply esignet-global config-map - kubectl apply -f esignet-global-cm.yaml - - echo "Istio label" - kubectl label ns "$SOFTHSM_NS" istio-injection=enabled --overwrite - - # Deploy Softhsm for Esignet. - echo "Installing Softhsm for esignet" - helm -n "$SOFTHSM_NS" install esignet-softhsm mosip/softhsm -f softhsm-values.yaml --version "$SOFTHSM_CHART_VERSION" --wait - echo "Installed Softhsm for esignet" + echo "Creating esignet-global configmap in esignet namespace" + kubectl -n esignet apply -f esignet-global-cm.yaml - declare -a modules=("istio-gateway" "postgres" "keycloak" "kafka" "redis") + declare -a modules=("istio-gateway" "postgres" "keycloak" "kafka" "redis" "softhsm" "captcha") declare -A prompts=( - ["keycloak"]="Do you want to deploy keycloak in the keycloak namespace?" - ["kafka"]="Do you want to deploy Kafka in the kafka namespace?" + ["softhsm"]="Do you want to install softhsm for esignet service in softhsm namespace? Opt "n" in case it already exists in Softhsm namespace: " + ["keycloak"]="Do you want to deploy keycloak in the keycloak namespace? Opt "n" in case it already exists in keycloak namespace : " + ["kafka"]="Do you want to deploy Kafka in the kafka namespace? Opt "n" in case it already exists in kafka namespace : " ) echo "Installing prerequisite services" for module in "${modules[@]}"; do - if [ "$module" == "istio-gateway" ] || [ "$module" == "redis" ] || [ "$module" == "postgres" ]; then + if [ "$module" == "istio-gateway" ] || [ "$module" == "postgres" ] || [ "$module" == "redis" ] || [ "$module" == "captcha" ]; then cd "$ROOT_DIR/$module" ./install.sh + elif [[ -n "${prompts[$module]}" ]]; then + prompt_for_deployment "$module" "${prompts[$module]}" fi done echo "All prerequisite services deployed successfully." diff --git a/deploy/keycloak/install.sh b/deploy/keycloak/install.sh index 43623a6f7..6f85c7f4d 100755 --- a/deploy/keycloak/install.sh +++ b/deploy/keycloak/install.sh @@ -17,6 +17,7 @@ function installing_keycloak() { ## TODO: enable istio injection after testing well. kubectl label ns $NS istio-injection=disabled --overwrite helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo add mosip https://mosip.github.io/mosip-helm helm repo update echo Installing diff --git a/deploy/keycloak/keycloak-init-values.yaml b/deploy/keycloak/keycloak-init-values.yaml index 3dd04e513..9a8edccc0 100644 --- a/deploy/keycloak/keycloak-init-values.yaml +++ b/deploy/keycloak/keycloak-init-values.yaml @@ -14,8 +14,6 @@ keycloak: "actionTokenGeneratedByUserLifespan": 300 "passwordPolicy": "length(8)" "resetPasswordAllowed": 'True' - "registrationAllowed": 'True' - "verifyEmail": 'True' "bruteForceProtected": 'True' "permanentLockout": 'False' "maxFailureWaitSeconds": 900 diff --git a/deploy/oidc-ui/install.sh b/deploy/oidc-ui/install.sh index 4927f4a58..b458ba682 100755 --- a/deploy/oidc-ui/install.sh +++ b/deploy/oidc-ui/install.sh @@ -6,13 +6,25 @@ if [ $# -ge 1 ] ; then export KUBECONFIG=$1 fi -NS=esignet -CHART_VERSION=0.0.1-test +function installing_oidc-ui() { -echo Create $NS namespace -kubectl create ns $NS + while true; do + read -p "Do you want to continue installing OIDC ui? (y/n) :" ans + if [ "$ans" = "Y" ] || [ "$ans" = "y" ]; then + break + elif [ "$ans" = "N" ] || [ "$ans" = "n" ]; then + exit 1 + else + echo "Please provide a correct option (Y or N)" + fi + done + + NS=esignet + CHART_VERSION=1.5.0-develop + + echo Create $NS namespace + kubectl create ns $NS || true -function installing_oidc-ui() { echo Istio label kubectl label ns $NS istio-injection=enabled --overwrite diff --git a/deploy/postgres/.gitignore b/deploy/postgres/.gitignore index 5e1d061c3..6d5b3a287 100644 --- a/deploy/postgres/.gitignore +++ b/deploy/postgres/.gitignore @@ -1,3 +1,4 @@ db-common-secrets.yaml -esignet-postgres-postgresql.yaml +postgres-postgresql.yaml postgres-host.yaml +.*.swp diff --git a/deploy/postgres/chart/istio-addons/templates/gateway.yaml b/deploy/postgres/chart/istio-addons/templates/gateway.yaml index c1e96ab0e..97619efa1 100644 --- a/deploy/postgres/chart/istio-addons/templates/gateway.yaml +++ b/deploy/postgres/chart/istio-addons/templates/gateway.yaml @@ -11,4 +11,4 @@ spec: name: postgres protocol: TCP hosts: - - {{ .Values.postgresHost }} + - {{ .Values.postgresHost }} \ No newline at end of file diff --git a/deploy/postgres/chart/istio-addons/templates/vs.yaml b/deploy/postgres/chart/istio-addons/templates/vs.yaml index 30843dd48..5cae69b5a 100644 --- a/deploy/postgres/chart/istio-addons/templates/vs.yaml +++ b/deploy/postgres/chart/istio-addons/templates/vs.yaml @@ -1,7 +1,7 @@ apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: - name: esignet-postgres + name: postgres spec: hosts: - "*" @@ -12,8 +12,7 @@ spec: - port: 5432 route: - destination: - host: esignet-postgres-postgresql + host: postgres-postgresql port: number: 5432 - diff --git a/deploy/postgres/chart/istio-addons/values.yaml b/deploy/postgres/chart/istio-addons/values.yaml index c05d63fab..7770edb91 100644 --- a/deploy/postgres/chart/istio-addons/values.yaml +++ b/deploy/postgres/chart/istio-addons/values.yaml @@ -1 +1 @@ -postgresHost: esignet-postgres.sandbox.xyz.net +postgresHost: postgres.sandbox.xyz.net diff --git a/deploy/postgres/delete.sh b/deploy/postgres/delete.sh index 41020f325..61186c043 100755 --- a/deploy/postgres/delete.sh +++ b/deploy/postgres/delete.sh @@ -7,16 +7,16 @@ if [ $# -ge 1 ] ; then fi function deleting_postgres() { - NS=esignet + NS=postgres while true; do read -p "CAUTION: PVC, PV will get deleted. If your PV is not in 'Retain' mode all Postgres data will be lost. Are you sure? (Y/n): " yn if [ "$yn" = "Y" ] || [ "$yn" = "y" ]; then echo "Deleting Postgres resources..." - helm -n $NS delete esignet-postgres || echo "Failed to delete esignet-postgres helm release" + helm -n $NS delete postgres || echo "Failed to delete postgres helm release" helm -n $NS delete istio-addons || echo "Failed to delete istio-addons helm release" - kubectl -n $NS delete pvc data-esignet-postgres-postgresql-0 || echo "Failed to delete PVC" - helm -n $NS delete esignet-postgres-init || echo "Failed to delete esignet-postgres-init helm release" - kubectl -n $NS delete secret esignet-postgres-postgresql || echo "Failed to delete esignet-postgres-init secret" + kubectl -n $NS delete pvc data-postgres-postgresql-0 || echo "Failed to delete PVC" + helm -n $NS delete postgres-init || echo "Failed to delete postgres-init helm release" + kubectl -n $NS delete secret postgres-postgresql || echo "Failed to delete postgres-init secret" kubectl -n $NS delete secret db-common-secrets || echo "Failed to delete db-common-secrets secret" break elif [ "$yn" = "N" ] || [ "$yn" = "n" ]; then diff --git a/deploy/postgres/generate-secret-cm.py b/deploy/postgres/generate-secret-cm.py index 46403b2a6..acf85875f 100644 --- a/deploy/postgres/generate-secret-cm.py +++ b/deploy/postgres/generate-secret-cm.py @@ -73,7 +73,7 @@ def create_or_update_configmap(configmap_name, namespace, postgres_host, postgre os.system(f"kubectl create -f {yaml_file} --save-config") # Main script logic -namespace = "esignet" +namespace = "postgres" check_namespace(namespace) # Handle db-dbuser-password secret @@ -91,7 +91,7 @@ def create_or_update_configmap(configmap_name, namespace, postgres_host, postgre create_or_update_secret(db_secret_name, namespace, "db-dbuser-password", password) # Handle postgres-password secret -postgres_secret_name = "esignet-postgres-postgresql" +postgres_secret_name = "postgres-postgresql" if secret_exists(postgres_secret_name, namespace): overwrite = input(f"Secret '{postgres_secret_name}' already exists in namespace '{namespace}'. Overwrite? (y/n): ") if overwrite.lower() == 'y': @@ -105,7 +105,7 @@ def create_or_update_configmap(configmap_name, namespace, postgres_host, postgre create_or_update_secret(postgres_secret_name, namespace, "postgres-password", postgres_password) # Handle ConfigMap creation for PostgreSQL -configmap_name = "esignet-postgres-config" +configmap_name = "postgres-config" if configmap_exists(configmap_name, namespace): overwrite = input(f"ConfigMap '{configmap_name}' already exists in namespace '{namespace}'. Overwrite? (y/n): ") if overwrite.lower() == 'y': diff --git a/deploy/postgres/init_values.yaml b/deploy/postgres/init_values.yaml index f82530230..ddcdd051f 100644 --- a/deploy/postgres/init_values.yaml +++ b/deploy/postgres/init_values.yaml @@ -4,13 +4,13 @@ dbUserPasswords: databases: mosip_esignet: enabled: true - host: "esignet-postgres-postgresql.esignet" + host: "postgres-postgresql" port: 5432 su: user: postgres secret: - name: esignet-postgres-postgresql + name: postgres-postgresql key: postgres-password dml: 1 repoUrl: https://github.com/mosip/esignet.git - branch: develop + branch: develop \ No newline at end of file diff --git a/deploy/postgres/install.sh b/deploy/postgres/install.sh index 22f017242..e94d6da16 100755 --- a/deploy/postgres/install.sh +++ b/deploy/postgres/install.sh @@ -6,7 +6,7 @@ if [ $# -ge 1 ] ; then export KUBECONFIG=$1 fi -NS=esignet +NS=postgres # Function to check and delete secret if it exists function check_and_delete_secret() { @@ -16,7 +16,8 @@ function check_and_delete_secret() { if kubectl -n $secret_namespace get secret $secret_name > /dev/null 2>&1; then echo "Secret $secret_name exists in namespace $secret_namespace." while true; do - read -p "Do you want to delete secret $secret_name before installation? (Y/n): " yn + POSTGRES_HOST=$(kubectl -n esignet get cm esignet-global -o jsonpath={.data.mosip-postgres-host}) + helm -n $NS install istio-addons chart/istio-addons --set postg read -p "Do you want to delete secret $secret_name before installation? (Y/n): " yn if [ "$yn" = "Y" ] || [ "$yn" = "y" ]; then echo "Deleting secret $secret_name..." kubectl -n $secret_namespace delete secret $secret_name || { echo "Failed to delete secret $secret_name"; exit 1; } @@ -35,7 +36,7 @@ function check_and_delete_secret() { function installing_postgres() { # Check and handle the existing secret - check_and_delete_secret "esignet-postgres-postgresql" $NS + check_and_delete_secret "postgres-postgresql" $NS helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update @@ -44,26 +45,49 @@ function installing_postgres() { kubectl label ns $NS istio-injection=enabled --overwrite echo Installing Postgres - helm -n $NS install esignet-postgres bitnami/postgresql --version 13.1.5 -f values.yaml --wait - echo Installed Postgres + helm -n $NS install postgres bitnami/postgresql --version 13.1.5 -f values.yaml --wait + # Run the Python script to generate secrets and configmap + if [ -f generate-secret-cm.py ]; then + echo "Running generate_secret.py to create Postgres secrets and configmap..." + python3 generate-secret-cm.py || { echo "Failed to run generate_secret.py"; exit 1; } + echo "Secrets and configmap generated successfully." + else + echo "Error: generate-secret-cm.py not found. Ensure the script is in the current directory." + exit 1 + fi echo Installing gateways and virtual services POSTGRES_HOST=$(kubectl -n esignet get cm esignet-global -o jsonpath={.data.mosip-postgres-host}) helm -n $NS install istio-addons chart/istio-addons --set postgresHost=$POSTGRES_HOST --wait - kubectl apply -f postgres-config.yaml return 0 } # Prompt the user if they want to install PostgreSQL while true; do - read -p "Do you want to install Postgres? Opt for 'n' if you have Postgres already installed. (y/n): " answer + read -p "Do you want to install default Postgres ? (y/n): " answer if [ "$answer" = "Y" ] || [ "$answer" = "y" ]; then echo "Continuing with Postgres server deployment..." - break + break # Proceed with the installation elif [ "$answer" = "N" ] || [ "$answer" = "n" ]; then - echo "Skipping Postgres installation. Running generate_secret.py to create Postgres secrets..." - python3 generate-secret-cm.py # Ensure that Python and the script are available in the environment - echo "Secrets generated. Exiting script." - exit 0 # Exit the script after generating secrets + # Prompt the user for further options + while true; do + echo "You opted not to install Postgres. What would you like to do next?" + echo "1. Skip Postgres server installation and configuration." + echo "2. Configure external Postgres details by generating secrets and configmap ." + + read -p "Enter your choice (1/2): " option + + if [ "$option" = "1" ]; then + echo "Skipping Postgres server installation and configuration in namespace." + exit 0 # Exit the script as the user chose to skip Postgres installation + elif [ "$option" = "2" ]; then + echo "Running generate_secret.py to create Postgres secrets and configmap..." + python3 generate-secret-cm.py # Ensure Python and the script are available in the environment + echo "Secrets generated successfully." + exit 0 # Exit the script after generating secrets and configmap + else + echo "Not a correct option. Please try again or press Ctrl + C to exit." + fi + done else echo "Please provide a correct option (Y or N)" fi diff --git a/deploy/postgres/nginx/transportserver.yaml b/deploy/postgres/nginx/transportserver.yaml index c031467aa..9b51871ca 100644 --- a/deploy/postgres/nginx/transportserver.yaml +++ b/deploy/postgres/nginx/transportserver.yaml @@ -9,7 +9,7 @@ spec: protocol: TCP upstreams: - name: postgres - service: esignet-postgres-postgresql + service: postgres-postgresql port: 5432 action: - pass: postgres + pass: postgres \ No newline at end of file diff --git a/deploy/postgres/postgres-config.yaml b/deploy/postgres/postgres-config.yaml index c2eb6276f..6fb3b41ee 100644 --- a/deploy/postgres/postgres-config.yaml +++ b/deploy/postgres/postgres-config.yaml @@ -1,12 +1,12 @@ apiVersion: v1 kind: ConfigMap metadata: - name: esignet-postgres-config - namespace: esignet + name: postgres-config + namespace: postgres labels: app: postgres data: - database-host: "esignet-postgres-postgresql" + database-host: "postgres-postgresql" database-port: "5432" database-username: "esignetuser" - database-name: "mosip_esignet" + database-name: "mosip_esignet" \ No newline at end of file diff --git a/deploy/postgres/postgres-init.sh b/deploy/postgres/postgres-init.sh index 7b0068fdf..33b236907 100755 --- a/deploy/postgres/postgres-init.sh +++ b/deploy/postgres/postgres-init.sh @@ -12,11 +12,11 @@ function initialize_db() { helm repo update while true; do - read -p "Please confirm with "Y" once values-init.yaml is updated correctly with tag, postgres host, and password details else "N" to exit installation: " ans + read -p "Please confirm with "Y" once init-values.yaml is updated correctly with tag, postgres host, and password details else "N" to exit installation: " ans if [ "$ans" = "Y" ] || [ "$ans" = "y" ]; then break elif [ "$ans" = "N" ] || [ "$ans" = "n" ]; then - exit + exit 1 else echo "Please provide a correct option (Y or N)" fi @@ -28,15 +28,16 @@ function initialize_db() { then echo Removing existing mosip_esignet installation and secret helm -n $NS delete esignet-postgres-init || true - kubectl delete secret db-common-secrets -n $NS || true + kubectl -n $NS delete secret db-common-secrets || true + ../copy_cm_func.sh secret postgres-postgresql postgres $NS echo Initializing DB - helm -n $NS install esignet-postgres-init mosip/postgres-init --version $CHART_VERSION -f init_values.yaml --wait --wait-for-jobs + helm -n $NS install postgres-init mosip/postgres-init --set image.repository=mosipdev/postgres-init --set image.tag=develop --version $CHART_VERSION -f init_values.yaml --wait --wait-for-jobs break elif [ "$yn" = "N" ] || [ "$yn" = "n" ]; then - echo "Skipping postgres initialisation as per your input" + echo "Skipping esignet postgres DB initialisation as per your input" break else - echo "Incorrect Input" + echo "Incorrect Input. Please choose again" break fi done diff --git a/deploy/postgres/postgres-postgresql.yaml b/deploy/postgres/postgres-postgresql.yaml new file mode 100644 index 000000000..028dd0ba5 --- /dev/null +++ b/deploy/postgres/postgres-postgresql.yaml @@ -0,0 +1,9 @@ + +apiVersion: v1 +kind: Secret +metadata: + name: postgres-postgresql + namespace: postgres +type: Opaque +data: + postgres-password: cG9zdGdyZXM= diff --git a/deploy/redis/install.sh b/deploy/redis/install.sh index 7a33fd5ae..9bf297b73 100755 --- a/deploy/redis/install.sh +++ b/deploy/redis/install.sh @@ -6,13 +6,37 @@ if [ $# -ge 1 ] ; then export KUBECONFIG=$1 fi -NS=redis -CHART_VERSION=17.3.14 +function installing_redis() { -echo Create $NS namespace -kubectl create ns $NS + while true; do + read -p "Do you want to install Redis in redis namespace? (y/n) :" ans + if [ "$ans" = "n" ] || [ "$ans" = "N" ]; then + read -p "Please confirm if redis-config is already present in redis namespace. (y/n):" response + if [ "$response" = "Y" ] || [ "$response" = "y" ]; then + echo "Skipping Redis installation as well as redis-config creation." + exit 1 + elif [ "$response" = "N" ] || [ "$response" = "n" ]; then + echo "Skipping Redis installation and continuing with redis-config creation." + kubectl apply -f redis-config.yaml + echo "redis-config configmap creation completed." + exit 1 + else + echo "Incorrect response. Please re-execute the redis installation script." + exit 1 + fi + elif [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then + break + else + echo "Please provide a correct option (Y or N)" + fi + done + + NS=redis + CHART_VERSION=17.3.14 + + echo Create $NS namespace + kubectl create ns $NS || true -function installing_redis() { echo Istio label kubectl label ns $NS istio-injection=enabled --overwrite diff --git a/deploy/softhsm/install.sh b/deploy/softhsm/install.sh new file mode 100755 index 000000000..65b14d092 --- /dev/null +++ b/deploy/softhsm/install.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Installs Softhsm service for Esignet +## Usage: ./install.sh [kubeconfig] + +if [ $# -ge 1 ] ; then + export KUBECONFIG=$1 +fi + +SOFTHSM_NS=softhsm +SOFTHSM_CHART_VERSION=12.0.1 + +function installing_softhsm() { + echo Create $SOFTHSM_NS namespaces + kubectl create ns $SOFTHSM_NS || true + + echo Istio label + kubectl label ns $SOFTHSM_NS istio-injection=enabled --overwrite + helm repo update + + # Deploy Softhsm for Esignet. + echo "Installing Softhsm for esignet" + helm -n "$SOFTHSM_NS" install esignet-softhsm mosip/softhsm -f softhsm-values.yaml --version "$SOFTHSM_CHART_VERSION" --wait + echo "Installed Softhsm for esignet" + + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +installing_softhsm # calling function diff --git a/deploy/softhsm-values.yaml b/deploy/softhsm/softhsm-values.yaml similarity index 100% rename from deploy/softhsm-values.yaml rename to deploy/softhsm/softhsm-values.yaml diff --git a/docker-compose/README.md b/docker-compose/README.md index afba8b9a1..3c3c51e80 100644 --- a/docker-compose/README.md +++ b/docker-compose/README.md @@ -4,21 +4,34 @@ This is the docker compose setup to run esignet UI and esignet-service with mock ## I am a developer, how to setup dependent services to edit and test esignet-service? -1. Run `docker compose --file dependent-docker-compose.yml up` to start all the dependent services. -2. Go to command line for the project root directory and run `mvn clean install -Dgpg.skip=true -DskipTests=true` -3. Add [esignet-mock-plugin.jar](../esignet-service/target/esignet-plugins/esignet-mock-plugin.jar) to esignet-service classpath in your IDE. -4. Start the [EsignetServiceApplication.java](../esignet-service/src/main/java/io/mosip/esignet/EsignetServiceApplication.java) from your IDE. -5. Import files under [postman-collection](../postman-collection) folder into your postman to test/validate OIDC flow. +1. Open terminal and go to "docker-compose" folder. +2. Run `docker compose --file dependent-docker-compose.yml up` to start all the dependent services. +3. Go to command line for the project root directory and run `mvn clean install -Dgpg.skip=true -DskipTests=true` +4. Add [esignet-mock-plugin.jar](../esignet-service/target/esignet-plugins/esignet-mock-plugin.jar) to esignet-service classpath in your IDE. +5. Start the [EsignetServiceApplication.java](../esignet-service/src/main/java/io/mosip/esignet/EsignetServiceApplication.java) from your IDE. +6. Import files under [postman-collection](../postman-collection) folder into your postman to test/validate OIDC flow. ## How to bring up the complete eSignet setup for a Demo? -1. Run [docker-compose.yml](docker-compose.yml) to start eSignet UI and backend service. -2. Access eSignet UI at http://localhost:3000 -3. Access eSignet backend services at http://localhost:8088/v1/esignet/swagger-ui.html -4. Onboard relying party in eSignet, import files under [postman-collection](../postman-collection) folder into your postman. And invoke requests under `OIDC Client Mgmt/Mock` folder in postman. Copy the client ID in the `Create OIDC client` response. -5. Add a `SignIn with eSignet` button in the relying party website and embed [eSignet authorize URL](http://localhost:3000/authorize?nonce=ere973eieljznge2311&state=eree2311&client_id=client_id&redirect_uri=redirect_uri&scope=openid&response_type=code&acr_values=mosip:idp:acr:generated-code&claims_locales=en&ui_locales=en-IN) in the button. Make sure to replace the query parameter values in the url before embedding in the button. -6. Add a user in the mock-identity-system. -7. Now the setup is completely ready to start the OIDC flow. [Refer eSignet user guides](https://docs.esignet.io/end-user-guide) for more information. +1. Open terminal and go to "docker-compose" folder. +2. Run `docker compose --file docker-compose.yml up` to start eSignet UI and backend service. +3. Access eSignet UI at http://localhost:3000 +4. Access eSignet backend services at http://localhost:8088/v1/esignet/swagger-ui.html +5. Onboard relying party in eSignet, import all files under [postman-collection](../postman-collection) folder into your postman. Choose `eSignet-with-mock` environment in the postman and invoke below requests under `OIDC Client Mgmt` -> `Mock` folder in postman. + + a. `Get CSRF token` + + b. `Create OIDC client` -> Make sure to update redirect Urls and logo URL as per your requirement in the request body. + +6. Copy the client ID in the `Create OIDC client` response. +7. Add a `SignIn with eSignet` button in the relying party website and embed [eSignet authorize URL](http://localhost:3000/authorize?nonce=ere973eieljznge2311&state=eree2311&client_id=client_id&redirect_uri=redirect_uri&scope=openid&response_type=code&acr_values=mosip:idp:acr:generated-code&claims_locales=en&ui_locales=en-IN) in the button. Update the below query parameter in the eSignet authorize URL before embedding in the button. + + a. `client_id` -> value should be replace with the value copied in the step 6 + + b. `redirect_uri` -> As updated in step 5 + +8. Add a user in the mock-identity-system. Invoke `Creat User` request under `User Mgmt` -> `Mock` folder in the postman. +9. Now the setup is completely ready to start the OIDC flow. [Refer eSignet user guides](https://docs.esignet.io/end-user-guide) for more information. `Note: To know more about the relying party onboard and query parameters used in the eSignet authorize URL `[refer eSignet docs](https://docs.esignet.io/integration/relying-party) diff --git a/docker-compose/dependent-docker-compose.yml b/docker-compose/dependent-docker-compose.yml index b3d462420..c5ea9a107 100644 --- a/docker-compose/dependent-docker-compose.yml +++ b/docker-compose/dependent-docker-compose.yml @@ -23,7 +23,7 @@ services: - 8082:8082 environment: - container_user=mosip - - active_profile_env=local + - active_profile_env=default,local - SPRING_DATASOURCE_URL=jdbc:postgresql://database:5432/mosip_mockidentitysystem?currentSchema=mockidentitysystem - SPRING_DATASOURCE_USERNAME=postgres - SPRING_DATASOURCE_PASSWORD=postgres diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml index 2d438f128..4c97a66c3 100644 --- a/docker-compose/docker-compose.yml +++ b/docker-compose/docker-compose.yml @@ -16,33 +16,32 @@ services: - 8082:8082 environment: - container_user=mosip - - active_profile_env=local + - active_profile_env=default,local - SPRING_DATASOURCE_URL=jdbc:postgresql://database:5432/mosip_mockidentitysystem?currentSchema=mockidentitysystem - SPRING_DATASOURCE_USERNAME=postgres - SPRING_DATASOURCE_PASSWORD=postgres + - MOSIP_MOCK_IDA_KYC_TRANSACTION_TIMEOUT_SECS=900 depends_on: - database esignet: - image: 'mosipdev/esignet:release-1.5.x' + image: 'mosipdev/esignet:develop' user: root ports: - 8088:8088 environment: - container_user=mosip - - active_profile_env=local + - active_profile_env=default,local - plugin_name_env=esignet-mock-plugin.jar - - KAFKA_ENABLED=false - - SPRING_AUTOCONFIGURE_EXCLUDE=org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration - SPRING_DATASOURCE_URL=jdbc:postgresql://database:5432/mosip_esignet?currentSchema=esignet - - SPRING_CACHE_TYPE=simple - MOSIP_ESIGNET_MOCK_DOMAIN_URL=http://mock-identity-system:8082 + - MOSIP_ESIGNET_INTEGRATION_KEY_BINDER=MockKeyBindingWrapperService depends_on: - database - mock-identity-system esignet-ui: - image: 'mosipdev/oidc-ui:release-1.5.x' + image: 'mosipdev/oidc-ui:develop' user: root ports: - 3000:3000 diff --git a/docs/design/eSignet-authorize-flow.md b/docs/design/eSignet-authorize-flow.md new file mode 100644 index 000000000..2e93ef58c --- /dev/null +++ b/docs/design/eSignet-authorize-flow.md @@ -0,0 +1,26 @@ +# Overview + +eSignet offers a seamless and straightforward solution for incorporating an existing trusted identity database into the +digital realm via plugins. + +## Design Objectives + +1. Should be an overlay solution on top of any of the existing identity API. Users can adopt the IDP solution and plugin the backend identity verification against their existing identity registry. +2. Should be able to independently operate without much dependency on existing services of MOSIP +3. Support all the mandatory features of OIDC (Open ID Connect) specification so the solution can be OIDC certified +4. When there are multiple options for a OIDC feature, support only the most secure option. +5. All integration libraries to ID system should be a runtime plugable to reuse the official container images which helps with easier upgrades. +6. Number of containers / runable applications to be kept to a minimum to avoid management overhead. +7. Standard interfaces to be used as much as possible for integrations between components +8. Should manage all the transactional data in expiring cache to increase data retrieval performance +9. The API endpoint exposed should be stateless (avoid stickiness) to support better horizontal scaling. +10. IAM based API authorization should have configuration to switched off to allow external network based mechanisms to control authorization and avoid high dependency on IAM system +11. All personally identifiable information (PII) should be kept encrypted in storage and transit + +## Authorization code flow + +![eSignet-design-OIDC-authorize-flow.png](../eSignet-design-OIDC-authorize-flow.png) + +## Authorization code flow using biometric authentication + +![esignet-with-bio-auth.png](../esignet-with-bio-auth.png) diff --git a/docs/design/eSignet-authorize-qr-code-flow.md b/docs/design/eSignet-authorize-qr-code-flow.md new file mode 100644 index 000000000..e0baea0a6 --- /dev/null +++ b/docs/design/eSignet-authorize-qr-code-flow.md @@ -0,0 +1,20 @@ +# Overview + +eSignet offers QR code based login using Wallet apps. Wallet apps store verifiable credentials(VC). Both demographic and biometric data +are available in the VC. Biometric data in the VC could be leveraged to perform local 1:1 biometric match to authenticate into eSignet and access any relying party services. + +## Binding Process + +VC issued by an identity system against an individual ID. Issued VC should be mapped to a key pair, private key resides in the wallet app's secure storage. +The corresponding public key is mapped to the same individual ID in the identity system (VC issuer). + +![esignet-wallet-binding.png](../esignet-wallet-binding.png) + +## Wallet based authentication using QR code + +Below diagram depicts the QR code based authorization code flow in eSignet. + +![esignet-authorize-qr-code-flow.png](../esignet-authorize-qr-code-flow.png) + + + diff --git a/docs/eSignet-design-OIDC-authorize-flow.png b/docs/eSignet-design-OIDC-authorize-flow.png new file mode 100644 index 000000000..2f57339ab Binary files /dev/null and b/docs/eSignet-design-OIDC-authorize-flow.png differ diff --git a/docs/esignet-authorize-qr-code-flow.png b/docs/esignet-authorize-qr-code-flow.png new file mode 100644 index 000000000..c27dcec78 Binary files /dev/null and b/docs/esignet-authorize-qr-code-flow.png differ diff --git a/docs/esignet-openapi.yaml b/docs/esignet-openapi.yaml index 8da7669b9..d2e0a5f9f 100644 --- a/docs/esignet-openapi.yaml +++ b/docs/esignet-openapi.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 x-stoplight: - id: 2vyk8uw76c0j6 + id: 7oz4lmhu3pf6b info: version: '1.0' title: eSignet @@ -255,7 +255,7 @@ paths: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-internal: false x-stoplight: - id: 6pu0p3a6mhqvr + id: ufuc57uqvy8nd /client-mgmt/oauth-client: post: tags: @@ -488,7 +488,7 @@ paths: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-internal: false x-stoplight: - id: 91b3a1508w0a5 + id: llrtvbxzzypg9 '/client-mgmt/oidc-client/{client_id}': put: tags: @@ -687,7 +687,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: zr1f21tws4y9y + id: twjsfa0yqpyej '/client-mgmt/oauth-client/{client_id}': put: tags: @@ -900,7 +900,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: dnbbtzbmppcsl + id: xwqybfwp9me23 /authorize: get: tags: @@ -1041,7 +1041,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: xel51v9q4xtvm + id: bx55bzakduy97 /authorization/oauth-details: post: tags: @@ -1062,7 +1062,7 @@ paths: 4. scope / acrValues / claims / locales / claim_locales - unknown values are ignored. Only valid values are considered. 5. scopes like profile, email and phone are allowed only if "openid" is also part of the requested scope. 6. Claims request parameter is allowed, only if 'openid' is part of the scope request parameter - 7. claims considered only if part of registered claims. + 7. Claims considered only if part of registered claims. 8. ACR in claims request parameter is given the first priority over acr_values query parameter. if none of them are part of the registered acrs, registered ACRs are only considered to derive the auth factors. operationId: post-oauth-details parameters: @@ -1261,7 +1261,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: plbkmewzwbi21 + id: bhi8yst5xtovl /authorization/v2/oauth-details: post: tags: @@ -1503,7 +1503,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: i5ht0irlohp9g + id: f8fifvn9td0n1 /authorization/v3/oauth-details: post: tags: @@ -1526,9 +1526,8 @@ paths: 6. Claims request parameter is allowed, only if 'openid' is part of the scope request parameter 7. claims considered only if part of registered claims. 8. ACR in claims request parameter is given the first priority over acr_values query parameter. if none of them are part of the registered acrs, registered ACRs are only considered to derive the auth factors. - 9. Verified claims in the 'claims' request parameter is supported only if the 'verified_claims_supported' flag is enabled. - 10. Unknown or supported claims in the verified_claims parameter are ignored. - 11. idTokenHint is optional, if provided then it MUST be a valid JWT. 'sub' claim in the idTokenHint JWT payload must match the cookie name(set on the domain).If the cookie is not found with same name as of 'sub' claim, then the error is thrown. + 9. Unknown or unsupported claims in the verified_claims parameter are ignored. + 10. idTokenHint is optional, if provided then it MUST be a valid JWT. 'sub' claim in the idTokenHint JWT payload must match the cookie name(set on the domain).If the cookie is not found with same name as of 'sub' claim, then the error is thrown. operationId: post-oauth-details-v3 parameters: - name: X-XSRF-TOKEN @@ -1755,7 +1754,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 0d1dmkcadb7iu + id: 5kwsv2k5932g8 /authorization/send-otp: post: tags: @@ -1894,7 +1893,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: olqbk7247688b + id: owaql9khq2ii9 /linked-authorization/send-otp: post: tags: @@ -2008,7 +2007,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: ww5t6kob3q1sc + id: b3138thajn9u4 /authorization/authenticate: post: tags: @@ -2138,7 +2137,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: yo34tum285pjb + id: xt4n2ff4zogdj /authorization/v2/authenticate: post: tags: @@ -2276,7 +2275,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: lrym71d3b78v6 + id: 5obwls7xlixv9 /authorization/v3/authenticate: post: tags: @@ -2420,6 +2419,7 @@ paths: - invalid_challenge - invalid_challenge_length - invalid_challenge_format + - invalid_captcha errorMessage: type: string examples: @@ -2433,7 +2433,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 4kjy5afix1m2p + id: mgs48hfrem91q /authorization/auth-code: post: tags: @@ -2560,7 +2560,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 4nac0grjh3ckp + id: ihwzp1k49ndtp /linked-authorization/link-code: post: tags: @@ -2668,7 +2668,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 3dysrxbef3ht3 + id: flzfkwilbocho /linked-authorization/link-transaction: post: tags: @@ -2799,7 +2799,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 6tybrn5kekolm + id: 3ee98xoyw0bww /linked-authorization/v2/link-transaction: post: tags: @@ -2939,7 +2939,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: t2hbrly00fjl3 + id: zevye0dm733qx /linked-authorization/link-status: post: tags: @@ -3052,7 +3052,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: vj7j4uk0geldw + id: 9gs5mjdlxs88n /linked-authorization/authenticate: post: tags: @@ -3163,7 +3163,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 1gukg1x66cs69 + id: bgjc5950ilnb9 /linked-authorization/v2/authenticate: post: tags: @@ -3282,7 +3282,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: lozvgnj5yg1be + id: r7hj34tn80w9x /linked-authorization/consent: post: tags: @@ -3378,7 +3378,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: w1xz5wefevlib + id: da66r92cxqvam /linked-authorization/v2/consent: post: tags: @@ -3477,7 +3477,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: m3xipj5r1svou + id: xext4ahumzbch /linked-authorization/link-auth-code: post: tags: @@ -3598,7 +3598,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: h35gkz1v60phs + id: 05s8uwy4a3tr6 /authorization/claim-details: get: tags: @@ -3716,7 +3716,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: b7jnx7byz0ek4 + id: fdlzxtdexapsn parameters: [] /authorization/prepare-signup-redirect: post: @@ -3773,7 +3773,7 @@ paths: description: uuid=encoded-json operationId: post-authorization-prepare-signup-redirect x-stoplight: - id: 9wb2ekkaeg7mk + id: d7hwkqd8hta5n parameters: - schema: type: string @@ -3943,7 +3943,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 5nj96giav3npy + id: flbtdntgp97vt /oauth/token: post: tags: @@ -4089,7 +4089,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: cdwhsjgoq9xbf + id: oq5wdn2tl5b68 /oauth/v2/token: post: tags: @@ -4252,7 +4252,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: zkcvd1seyedmd + id: bx4h4esbzst37 /oidc/userinfo: get: tags: @@ -4323,7 +4323,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: 5dgir3dl27lvp + id: 6iqtka3aua3f2 /binding/binding-otp: post: tags: @@ -4410,6 +4410,7 @@ paths: - unknown_error - invalid_individual_id - send_otp_failed + - invalid_captcha errorMessage: type: string required: @@ -4427,113 +4428,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: d3di5edwwt70b - /binding/v2/binding-otp: - post: - tags: - - WALLET BACKEND - summary: Send Binding OTP Endpoint - description: Send wallet binding OTP endpoint is invoked by Mimoto server. - operationId: post-binding-otp - parameters: - - name: partner-api-key - in: header - description: 'API key of the binding partner, this will be passed to binder implementation to interact with authentication system.' - schema: - type: string - - name: partner-id - in: header - description: 'Binding partner Identifier, this will be passed to binder implementation to interact with authentication system.' - schema: - type: string - requestBody: - content: - application/json: - schema: - type: object - properties: - requestTime: - type: string - request: - type: object - properties: - individualId: - type: string - description: User Id (UIN/VID) - otpChannels: - type: array - description: Channels to which OTP should be delivered. - items: - type: string - captchaToken: - type: string - description: 'Captcha token, if enabled.' - required: - - individualId - - otpChannels - required: - - requestTime - - request - examples: - Example 1: - value: - requestTime: '2023-09-22T08:01:13.000Z' - request: - individualId: '24554655645' - otpChannels: - - sms - - email - captchaToken: ALSKDJFURIEOQPZMKFURHFVBH - responses: - '200': - description: OK - content: - application/json: - schema: - type: object - properties: - responseTIme: - type: string - response: - type: object - properties: - maskedEmail: - type: string - description: Masked email id of the individualId user. - maskedMobile: - type: string - description: Masked mobile number of the individualId user. - errors: - type: array - items: - type: object - properties: - errorCode: - type: string - enum: - - invalid_otp_channel - - unknown_error - - invalid_individual_id - - send_otp_failed - - invalid_captcha - errorMessage: - type: string - required: - - responseTIme - examples: - Example 1: - value: - responseTIme: '2023-09-22T08:01:16.000Z' - response: - maskedEmail: XXdXXaXXhXXkX@gmail.com - maskedMobile: XXXXXXX357934 - errors: [ ] - security: - - Authorization-send_binding_otp: [ ] - servers: - - url: 'https://esignet.collab.mosip.net/v1/esignet' - x-stoplight: - id: xnl3gyq4v4bh4 + id: t315hcecaulyy /binding/wallet-binding: post: tags: @@ -4671,7 +4566,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: chsz43i4s7rkd + id: coqr4q7xd7k3x /.well-known/jwks.json: get: tags: @@ -4755,7 +4650,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: azj8cuvdurps6 + id: 4jt4qby3nx2e4 /.well-known/openid-configuration: get: tags: @@ -4952,7 +4847,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: o0uqnqgz9zm7j + id: 0t3znwjii5pcv /oauth/introspect: get: tags: @@ -5008,7 +4903,7 @@ paths: servers: - url: 'https://esignet.collab.mosip.net/v1/esignet' x-stoplight: - id: o9h010bmb1db5 + id: 4m5xw29vz2q9k tags: - name: Management description: Management level API's used for internal use. @@ -5056,7 +4951,7 @@ components: **Note:** Unknown claim names either in userinfo or id_token are ignored. x-stoplight: - id: hhww7s6bqjn8j + id: ia7rtr773oztz properties: userinfo: type: object @@ -5100,7 +4995,7 @@ components: type: object title: ClaimDetail x-stoplight: - id: 4enwly0dhq8tp + id: 6fpl3ntftytb2 properties: essential: type: boolean @@ -5148,13 +5043,13 @@ components: required: - type x-stoplight: - id: 50labrntmysgm + id: tsp0z081f1rag AuthChallenge: type: object title: AuthChallenge description: Model to take any type of challenge from the end user as part of authenticate request. x-stoplight: - id: thl682syr59bm + id: w3az95o1dv9h8 required: - authFactorType - challenge @@ -5186,7 +5081,7 @@ components: ClaimStatus: title: ClaimStatus x-stoplight: - id: o85s4acpltciv + id: dw0e0qr345403 type: object description: Resolved claims among the RP requested claims with their availability and verification status. required: @@ -5209,10 +5104,15 @@ components: x-stoplight: id: 8z1n64eu4tc1f description: True only if the claim is available and verified by atleast one trust framework. And also the verification process completed before the requested max_age. + purpose: + type: string + x-stoplight: + id: lkp89wz5vzwr2 + description: Purpose of the claim as provided in the authorize request by the relying party VerifiedClaimDetail: title: VerifiedClaimDetail x-stoplight: - id: ombll0ox1abk0 + id: aam5fhnleu0tk type: object description: |- Verified claim detail that can be requested by the RP @@ -5396,6 +5296,8 @@ components: + + @@ -5523,7 +5425,7 @@ components: EvidenceCheckDetail: title: EvidenceCheckDetail x-stoplight: - id: 56ntbetl6kt55 + id: z3endvsasoabe type: object description: |- Object representing the checks done in relation to the evidence. @@ -5560,7 +5462,7 @@ components: FilterCriteria: title: FilterCriteria x-stoplight: - id: xvfexlq01bb2w + id: tl65ie7ligsw6 type: object description: Value or values used to filter the verified claims. if provided in the values parameter its a logical OR condition. properties: @@ -5579,7 +5481,7 @@ components: EvidenceIssuer: title: EvidenceIssuer x-stoplight: - id: hia062eivzuvp + id: e24cvlea7chj3 type: object description: ' JSON object containing information about the issuer of this document.' properties: @@ -5606,7 +5508,7 @@ components: ElectronicRecord: title: ElectronicRecord x-stoplight: - id: 79aws43989s8i + id: 85iwcimsvb5yr type: object description: 'JSON object representing the record used to perform the identity verification. It consists of the following properties:' properties: diff --git a/docs/esignet-overview.png b/docs/esignet-overview.png new file mode 100644 index 000000000..3bf116060 Binary files /dev/null and b/docs/esignet-overview.png differ diff --git a/docs/esignet-wallet-binding.png b/docs/esignet-wallet-binding.png new file mode 100644 index 000000000..62d125e23 Binary files /dev/null and b/docs/esignet-wallet-binding.png differ diff --git a/docs/IdP - OIDC Flow - Biometrics.png b/docs/esignet-with-bio-auth.png similarity index 100% rename from docs/IdP - OIDC Flow - Biometrics.png rename to docs/esignet-with-bio-auth.png diff --git a/esignet-service/README.md b/esignet-service/README.md index c14821025..5fb85d12c 100644 --- a/esignet-service/README.md +++ b/esignet-service/README.md @@ -21,7 +21,7 @@ Note: VCI implementations are permanently moved to Inji-Certify. 4. All the required plugins are runtime dependency to esignet-service. -![](/docs/esignet-service-basic-interations.png) +![](../docs/esignet-service-basic-interactions.png) ## Local setup of eSignet with mock plugins @@ -29,6 +29,9 @@ Kindly check our docker compose setup files to run eSignet locally [here](../doc ## Caching details +All the transaction details are stored in cache. We support simple(in-memory) and redis cache. The way transaction is added or evicted from +the caches on every stage of OIDC transaction is detailed in the below tables. + UI transaction | Endpoint | Cache | Evict | @@ -69,12 +72,55 @@ eKYC verification transaction | userinfo | | | +## eSignet Service Configuration + +We've set up the eSignet service and OIDC UI so that they can run independently, without needing an external configuration server or Artifactory server. Here’s a breakdown of how to configure and customize these services in different environments. + +**Profile Configurations** + +The eSignet service comes with two profile-based property files, each designed to help with different deployment needs: + +* Default Profile Properties File (application-default.properties) + +This file contains properties with ideal default values suited for a typical deployment. + +* Local Profile Properties File (application-local.properties) + +This file only includes properties that need to be overridden to run the eSignet service in a local environment. + +**Note:** The bootstrap.properties file is configured to enable multiple profile mode "default,local", allowing easy local setup. + +**Using Placeholders** + +In application-default.properties, we use placeholders for values that are defined in the eSignet deployment scripts. +This allows you to easily substitute values as needed without modifying the properties file directly. + +**Running eSignet in a Docker Container** + +When running eSignet in Docker, you can override properties by setting environment variables. Spring Boot conveniently converts property names to an uppercase format with underscores, making it easy to map properties as needed. + +For example: + +* spring.datasource.url maps to SPRING_DATASOURCE_URL +* mosip.esignet.domain.url maps to MOSIP_ESIGNET_DOMAIN_URL +* mosip.kernel.keymanager.hsm.keystore-type maps to MOSIP_KERNEL_KEYMANAGER_HSM_KEYSTORE_TYPE + +**Flexible Configuration with or without a Config Server** + +The eSignet service can run independently of a config server, yet remains flexible. If you need to connect it to an external configuration server, you can easily do so by setting the following environment variables in the Docker container: + +* SPRING_CONFIG_LABEL_ENV +* ACTIVE_PROFILE_ENV +* SPRING_CONFIG_URL_ENV + +This approach gives you the flexibility to run eSignet in a standalone mode or connect it to an external configuration server as your setup requires. + ## API document eSignet API documentation can be found [here](../docs/esignet-openapi.yaml) ## Databases -Refer to [SQL scripts](db_scripts/mosip_esignet). +Refer to [SQL scripts](../db_scripts/mosip_esignet). ## License -This project is licensed under the terms of [Mozilla Public License 2.0](LICENSE). +This project is licensed under the terms of [Mozilla Public License 2.0](../LICENSE). diff --git a/esignet-service/configure_start.sh b/esignet-service/configure_start.sh index 2f82143f9..19346edb9 100644 --- a/esignet-service/configure_start.sh +++ b/esignet-service/configure_start.sh @@ -69,5 +69,12 @@ else exit 1 fi +## set active profile if not set +if [[ -z "$active_profile_env" ]]; then + echo "Alert: active_profile_env is not set. setting to default" + active_profile_env="default" + export active_profile_env +fi + cd $work_dir exec "$@" diff --git a/esignet-service/src/main/resources/application-default.properties b/esignet-service/src/main/resources/application-default.properties index de1a4a980..0de45f46b 100644 --- a/esignet-service/src/main/resources/application-default.properties +++ b/esignet-service/src/main/resources/application-default.properties @@ -28,15 +28,15 @@ mosip.esignet.auth-challenge.PWD.max-length=30 mosip.esignet.auth-challenge.BIO.format=encoded-json mosip.esignet.auth-challenge.BIO.min-length=500 -mosip.esignet.auth-challenge.BIO.max-length=4000 +mosip.esignet.auth-challenge.BIO.max-length=500000 mosip.esignet.auth-challenge.WLA.format=jwt mosip.esignet.auth-challenge.WLA.min-length=500 -mosip.esignet.auth-challenge.WLA.max-length=800 +mosip.esignet.auth-challenge.WLA.max-length=1000 mosip.esignet.auth-challenge.KBI.format=base64url-encoded-json mosip.esignet.auth-challenge.KBI.min-length=50 -mosip.esignet.auth-challenge.KBI.max-length=100 +mosip.esignet.auth-challenge.KBI.max-length=500 mosip.esignet.auth-challenge.PIN.format=number mosip.esignet.auth-challenge.PIN.min-length=6 @@ -60,16 +60,17 @@ mosip.esignet.header-filter.paths-to-validate={'${server.servlet.path}/authoriza '${server.servlet.path}/authorization/complete-signup-redirect' } ## captcha validation is enabled for the auth-factors - otp, pwd, bio and pin. -mosip.esignet.captcha.required=send-otp,pwd,kbi,binding-otp +mosip.esignet.captcha.required=send-otp,pwd,kbi mosip.esignet.captcha.validator-url=http://captcha.captcha/v1/captcha/validatecaptcha mosip.esignet.captcha.module-name=esignet mosip.esignet.captcha.site-key=${esignet.captcha.site.key} ## Applicable for signup redirection to update profile -mosip.esignet.signup-id-token-expire-seconds=1800 +mosip.esignet.signup-id-token-expire-seconds=300 mosip.esignet.signup-id-token-audience=mosip-signup-oauth-client -mosip.esignet.claims.schema.url=classpath:/verified_claims_request_schema.json +## Transaction halted with prepare-signup-redirect wait time to resume back with complete-signup-redirect API +mosip.esignet.signup.halt.expire-seconds=1800 ## ------------------------------------------ e-Signet binding --------------------------------------------------------- mosip.esignet.binding.salt-length=16 @@ -211,7 +212,7 @@ mosip.esignet.cache.expire-in-seconds={'clientdetails' : 86400, \ 'bindingtransaction': 600, \ 'apiratelimit' : 180, \ 'blocked': 300, \ -'halted' : ${mosip.esignet.signup-id-token-expire-seconds} } +'halted' : ${mosip.esignet.signup.halt.expire-seconds} } ## ------------------------------------------ Discovery openid-configuration ------------------------------------------- @@ -258,7 +259,8 @@ mosip.esignet.discovery.key-values={'issuer': '${mosip.esignet.domain.url}' ,\ \ 'claims_locales_supported' : {'en'}, \ \ 'request_parameter_supported' : false, \ \ 'display_values_supported' : ${mosip.esignet.supported.ui.displays}, \ - \ 'ui_locales_supported' : {'en'} } + \ 'ui_locales_supported' : {'en'},\ + \ 'claims_in_verified_claims_supported' : { 'name','address','gender','birthdate','picture','email','phone_number' } } ##----------------------------------------- Database properties -------------------------------------------------------- mosip.esignet.database.hostname=${database.host} @@ -350,8 +352,8 @@ mosip.kernel.keymgr.hsm.health.check.encrypt=true # 2. A new Qrcode will be autogenerated before the expiry of current qr-code, and the time difference in seconds for the same is defined in wallet.qr-code-buffer-in-secs property # 3. If esignet is deployed with MOSIP IDA, then 'resend.otp.delay.secs' must be the same as 'mosip.kernel.otp.expiry-time' -mosip.esignet.ui.wallet.config={{'wallet.name': 'Inji', 'wallet.logo-url': '/images/qr_code.png', 'wallet.download-uri': '#', \ - 'wallet.deep-link-uri': 'inji://landing-page-name?linkCode=LINK_CODE&linkExpireDateTime=LINK_EXPIRE_DT' }} +mosip.esignet.ui.wallet.config={{'wallet.name': 'walletName', 'wallet.logo-url': '/images/qr_code.png', 'wallet.download-uri': '#', \ + 'wallet.deep-link-uri': 'io.mosip.residentapp.inji://wla-auth?linkCode=LINK_CODE&linkExpireDateTime=LINK_EXPIRE_DT' }} mosip.signup.domain.url=https://${mosip.signup.host} mosip.esignet.ui.signup.config={'signup.banner': true, 'signup.url': '${mosip.signup.domain.url}/signup'} @@ -370,11 +372,15 @@ mosip.esignet.ui.config.otp.length=6 mosip.esignet.ui.config.password.regex=^.{8,20}$ mosip.esignet.ui.config.password.max-length=20 mosip.esignet.ui.config.username.regex=.* + +## Prefix and Postfix support is added to support MOSIP handle feature, Prefix will be visible in the oidc-ui, but +# postfix is automatically added to entered individualId. Finally, the individualId sent to the backend is with both +# prefix and postfix appended if configured. mosip.esignet.ui.config.username.prefix= mosip.esignet.ui.config.username.postfix= + mosip.esignet.ui.config.username.max-length=12 mosip.esignet.ui.config.username.input-type=text -mosip.esignet.ui.config.login-id.options={{ 'id': 'mobile', 'svg': 'mobile_icon', 'prefixes': {{'label': 'KHM', 'value': '+855', 'regex': ''}, {'label': 'IND', 'value': '+91', 'maxLength': '', 'regex': ''}}, 'postfix': '', 'maxLength': '', 'regex': '' }, { 'id': 'nrc', 'svg': 'nrc_id_icon', 'prefixes': '', 'postfix': '', 'maxLength': '', 'regex': '' }, { 'id': 'vid', 'svg': 'vid_icon', 'prefixes': '', 'postfix': '', 'maxLength': '', 'regex': '' }, { 'id': 'email', 'svg': 'email_icon', 'prefixes': '', 'postfix': '', 'maxLength': '', 'regex': '' }} mosip.esignet.ui.config.key-values={'sbi.env': '${mosip.esignet.authenticator.ida-env:Developer}', 'sbi.timeout.DISC': 30, \ 'sbi.timeout.DINFO': 30, 'sbi.timeout.CAPTURE': 30, 'sbi.capture.count.face': 1, 'sbi.capture.count.finger': 1, \ @@ -398,10 +404,9 @@ mosip.esignet.ui.config.key-values={'sbi.env': '${mosip.esignet.authenticator.id 'eKYC-steps.config': '${mosip.esignet.ui.eKYC-steps.url}', \ 'error.banner.close-timer': 10,\ 'auth.factor.kbi.individual-id-field' : '${mosip.esignet.authenticator.default.auth-factor.kbi.individual-id-field}',\ - 'auth.factor.kbi.field-details': ${mosip.esignet.authenticator.default.auth-factor.kbi.field-details}, \ - 'login-id.options': ${mosip.esignet.ui.config.login-id.options}} + 'auth.factor.kbi.field-details': ${mosip.esignet.authenticator.default.auth-factor.kbi.field-details}} ##-------------------------------------------- Default Integrations ----------------------------------------------------- -mosip.esignet.integration.audit-plugin=LoggerAuditService -mosip.esignet.integration.key-binder=NoOpKeyBinder +#mosip.esignet.integration.audit-plugin=LoggerAuditService +#mosip.esignet.integration.key-binder=NoOpKeyBinder diff --git a/esignet-service/src/main/resources/application-local.properties b/esignet-service/src/main/resources/application-local.properties index 5412b7b03..5d2dbba6d 100644 --- a/esignet-service/src/main/resources/application-local.properties +++ b/esignet-service/src/main/resources/application-local.properties @@ -2,397 +2,50 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. +## Domain configurations +mosip.esignet.domain.url=http://localhost:8088 +mosip.signup.domain.url=http://localhost:8089 mosip.esignet.mock.domain.url=http://localhost:8082 -logging.level.io.mosip.esignet=DEBUG - -## eSignet configurations +## ACR & AMR mapping configurations mosip.esignet.amr-acr-mapping-file-path=amr_acr_mapping.json -mosip.esignet.auth-txn-id-length=10 -mosip.esignet.supported-id-regex=\\S* -# Generated ID and access tokens 'exp' depends on the below properties, default value is 1-hour -mosip.esignet.id-token-expire-seconds=3600 -mosip.esignet.access-token-expire-seconds=3600 -# By default, only 2 link codes can be active, and the time period it can be active is defined here, default value is 1 minute -mosip.esignet.link-code-expire-in-secs=600 -# Number of link code allowed to be generated in a transaction, the default value is 10 -mosip.esignet.generate-link-code.limit-per-transaction=10 -# Time to complete consent after successful authentication, the default value is 120 -mosip.esignet.authentication-expire-in-secs=600 -# Time to complete authentication -mosip.esignet.preauthentication-expire-in-secs=600 - -## Auth challenge type & format mapping. Auth challenge length validations for each auth factor type. -mosip.esignet.auth-challenge.OTP.format=alpha-numeric -mosip.esignet.auth-challenge.OTP.min-length=6 -mosip.esignet.auth-challenge.OTP.max-length=6 - -mosip.esignet.auth-challenge.PWD.format=alpha-numeric -mosip.esignet.auth-challenge.PWD.min-length=8 -mosip.esignet.auth-challenge.PWD.max-length=30 - -mosip.esignet.auth-challenge.BIO.format=encoded-json -mosip.esignet.auth-challenge.BIO.min-length=500 -mosip.esignet.auth-challenge.BIO.max-length=4000 - -mosip.esignet.auth-challenge.WLA.format=jwt -mosip.esignet.auth-challenge.WLA.min-length=500 -mosip.esignet.auth-challenge.WLA.max-length=800 -mosip.esignet.auth-challenge.KBI.format=base64url-encoded-json -mosip.esignet.auth-challenge.KBI.min-length=50 -mosip.esignet.auth-challenge.KBI.max-length=100 - -mosip.esignet.auth-challenge.PIN.format=number -mosip.esignet.auth-challenge.PIN.min-length=6 -mosip.esignet.auth-challenge.PIN.max-length=6 - -mosip.esignet.auth-challenge.IDT.format=base64url-encoded-json -mosip.esignet.auth-challenge.IDT.min-length=20 -mosip.esignet.auth-challenge.IDT.max-length=2000 - -mosip.esignet.claim-detail.purpose.min-length=3 -mosip.esignet.claim-detail.purpose.max-length=300 - -## Endpoints required to have oauth-details-hash and oauth-details-key HTTP header -mosip.esignet.header-filter.paths-to-validate={'${server.servlet.path}/authorization/send-otp', \ - '${server.servlet.path}/authorization/authenticate', \ - '${server.servlet.path}/authorization/v2/authenticate', \ - '${server.servlet.path}/authorization/v3/authenticate', \ - '${server.servlet.path}/authorization/auth-code',\ - '${server.servlet.path}/authorization/prepare-signup-redirect',\ - '${server.servlet.path}/authorization/claim-details',\ - '${server.servlet.path}/authorization/complete-signup-redirect' } - -## captcha validation is enabled for the auth-factors - otp, pwd, bio and pin. +## Captcha configurations mosip.esignet.captcha.required= -mosip.esignet.captcha.validator-url=http://captcha.captcha/v1/captcha/validatecaptcha -mosip.esignet.captcha.module-name=esignet mosip.esignet.captcha.site-key=test-site-key -## Applicable for signup redirection to update profile -mosip.esignet.signup-id-token-expire-seconds=1800 -mosip.esignet.signup-id-token-audience=mosip-signup-oauth-client - -mosip.esignet.host=localhost -mosip.esignet.claims.schema.url=classpath:/verified_claims_request_schema.json - -## ------------------------------------------ e-Signet binding --------------------------------------------------------- -mosip.esignet.binding.salt-length=16 -mosip.esignet.binding.audience-id=esignet-binding -mosip.esignet.binding.key-expire-days=10 - -## -------------------------------------- Authentication & Authorization ----------------------------------------------- +## Security configurations mosip.esignet.security.auth.post-urls={} mosip.esignet.security.auth.put-urls={} mosip.esignet.security.auth.get-urls={} +spring.security.oauth2.resourceserver.jwt.issuer-uri= +spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/auth/realms/mosip/protocol/openid-connect/certs -mosip.esignet.security.ignore-csrf-urls=${server.servlet.path}/oidc/**,${server.servlet.path}/oauth/**,\ - ${server.servlet.path}/actuator/**,/favicon.ico,${server.servlet.path}/error,\ - ${server.servlet.path}/swagger-ui/**,${server.servlet.path}/v3/api-docs/**,\ - ${server.servlet.path}/linked-authorization/link-transaction,${server.servlet.path}/linked-authorization/authenticate,\ - ${server.servlet.path}/linked-authorization/consent,${server.servlet.path}/binding/**,${server.servlet.path}/client-mgmt/**,\ - ${server.servlet.path}/system-info/**,${server.servlet.path}/linked-authorization/v2/link-transaction,\ - ${server.servlet.path}/linked-authorization/v2/authenticate,${server.servlet.path}/linked-authorization/v2/consent - -mosip.esignet.security.ignore-auth-urls=${server.servlet.path}/csrf/**,${server.servlet.path}/authorization/**,\ - ${server.servlet.path}/linked-authorization/**,${server.servlet.path}/oidc/**,${server.servlet.path}/oauth/**,\ - ${server.servlet.path}/actuator/**,/favicon.ico,${server.servlet.path}/error,${server.servlet.path}/swagger-ui/**,\ - ${server.servlet.path}/v3/api-docs/**,${server.servlet.path}/binding/** - -##------------------------------------------ Kafka configurations ------------------------------------------------------ +## Kafka configurations kafka.enabled=false spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration spring.kafka.bootstrap-servers=localhost:9092 -spring.kafka.consumer.group-id=esignet-consumer -spring.kafka.consumer.enable-auto-commit=true -#spring.kafka.listener.concurrency=1 - -mosip.esignet.kafka.linked-session.topic=esignet-linked -mosip.esignet.kafka.linked-auth-code.topic=esignet-consented - -## ------------------------------------------ oauth & openid supported values ------------------------------------------ - -## supported scopes -mosip.esignet.supported.authorize.scopes={'Manage-Identity-Data','Manage-VID','Manage-Authentication','Manage-Service-Requests','Manage-Credentials'} -mosip.esignet.supported.openid.scopes={'profile','email','phone'} -mosip.esignet.openid.scope.claims={'profile' : {'name','address','gender','birthdate','picture','email','phone_number','phone_number_verified','registration_type','updated_at'},'email' : {'email'}, 'phone' : {'phone_number','phone_number_verified'}} -mosip.esignet.supported.credential.scopes={'mosip_identity_vc_ldp'} -mosip.esignet.credential.scope-resource-mapping={ 'mosip_identity_vc_ldp': '${mosip.esignet.domain.url}${server.servlet.path}/vci/credential'} - -## supported authorization processing flow to be used, Currently only supports Authorization Code Flow. -mosip.esignet.supported.response.types={'code'} - -## Form of Authorization Grant presented to token endpoint -mosip.esignet.supported.grant.types={'authorization_code'} - -## specifies how the Authorization Server displays the authentication and consent user interface pages to the End-User -# page-The Authorization Server SHOULD display the authentication and consent UI consistent with a full User Agent page view. If the display parameter is not specified, this is the default display mode. -# popup-The Authorization Server SHOULD display the authentication and consent UI consistent with a popup User Agent window. The popup User Agent window should be of an appropriate size for a login-focused dialog and should not obscure the entire window that it is popping up over. -# touch-The Authorization Server SHOULD display the authentication and consent UI consistent with a device that leverages a touch interface. -# wap-The Authorization Server SHOULD display the authentication and consent UI consistent with a "feature phone" type display. -mosip.esignet.supported.ui.displays={'page','popup','touch','wap'} - -## specifies whether the Authorization Server prompts the End-User for reauthentication and consent -# none-The Authorization Server MUST NOT display any authentication or consent user interface pages. -# An error is returned if an End-User is not already authenticated or the Client does not have pre-configured consent -# for the requested Claims or does not fulfill other conditions for processing the request. -# The error code will typically be login_required, interaction_required, or another code defined in Section 3.1.2.6. -# This can be used as a method to check for existing authentication and/or consent. -# login-The Authorization Server SHOULD prompt the End-User for reauthentication. If it cannot reauthenticate the End-User, \ -# it MUST return an error, typically login_required. -# consent-The Authorization Server SHOULD prompt the End-User for consent before returning information to the Client. -# If it cannot obtain consent, it MUST return an error, typically consent_required. -# select_account-The Authorization Server SHOULD prompt the End-User to select a user account. This enables an End-User -# who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they might have current -# sessions for. If it cannot obtain an account selection choice made by the End-User, it MUST return an error, -# typically account_selection_required. -mosip.esignet.supported.ui.prompts={'none','login','consent','select_account'} - -## Type of the client assertion -mosip.esignet.supported.client.assertion.types={'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'} - -## Type of the client authentication methods for token endpoint -mosip.esignet.supported.client.auth.methods={'private_key_jwt'} - -## Only S256 method supported -mosip.esignet.supported-pkce-methods={'S256'} - -## ---------------------------------------- Cache configuration -------------------------------------------------------- - -mosip.esignet.cache.secure.individual-id=true -mosip.esignet.cache.store.individual-id=true -mosip.esignet.cache.security.secretkey.reference-id=TRANSACTION_CACHE -mosip.esignet.cache.security.algorithm-name=AES/ECB/PKCS5Padding -mosip.esignet.cache.key.hash.algorithm=SHA3-256 -mosip.esignet.cache.names=clientdetails,preauth,authenticated,authcodegenerated,userinfo,linkcodegenerated,linked,linkedcode,linkedauth,consented,authtokens,bindingtransaction,apiratelimit,blocked,halted - -# 'simple' cache type is only applicable only for Non-Production setup -spring.cache.type=redis -spring.cache.cache-names=${mosip.esignet.cache.names} +## Redis configuration +spring.cache.type=simple spring.redis.host=localhost spring.redis.port=6379 -management.health.redis.enabled=false - -# Cache size setup is applicable only for 'simple' cache type. -# Cache size configuration will not be considered with 'Redis' cache type -mosip.esignet.cache.size={'clientdetails' : 200, \ -'preauth': 200, \ -'authenticated': 200, \ -'authcodegenerated': 200, \ -'userinfo': 200, \ -'linkcodegenerated' : 500, \ -'linked': 200 , \ -'linkedcode': 200, \ -'linkedauth' : 200 , \ -'consented' :200, \ -'authtokens': 2, \ -'bindingtransaction': 200, \ -'apiratelimit' : 500, \ -'blocked': 500, \ -'halted' : 500 } - -# Cache expire in seconds is applicable for both 'simple' and 'Redis' cache type -mosip.esignet.cache.expire-in-seconds={'clientdetails' : 86400, \ -'preauth': ${mosip.esignet.preauthentication-expire-in-secs},\ -'authenticated': ${mosip.esignet.authentication-expire-in-secs}, \ -'authcodegenerated': 600, \ -'userinfo': ${mosip.esignet.access-token-expire-seconds}, \ -'linkcodegenerated' : ${mosip.esignet.link-code-expire-in-secs}, \ -'linked': 600, \ -'linkedcode': ${mosip.esignet.link-code-expire-in-secs}, \ -'linkedauth' : ${mosip.esignet.authentication-expire-in-secs}, \ -'consented': 600, \ -'authtokens': 86400, \ -'bindingtransaction': 600, \ -'apiratelimit' : 180, \ -'blocked': 300, \ -'halted' : ${mosip.esignet.signup-id-token-expire-seconds} } - -## ------------------------------------------ Discovery openid-configuration ------------------------------------------- - -mosip.esignet.domain.url=http://localhost:8088 -mosip.esignet.discovery.issuer-id=${mosip.esignet.domain.url}${server.servlet.path} - -# This property holds ./wellknown/jwks.json URL, -# for local deployments without esignet-ui nginx change the value to ${mosip.esignet.domain.url}${server.servlet.path}/oauth/.well-known/jwks.json -mosip.esignet.jwks-uri=${mosip.esignet.domain.url}/.well-known/jwks.json - -mosip.esignet.token.endpoint=${mosip.esignet.domain.url}${server.servlet.path}/oauth/v2/token -mosip.esignet.oauth.key-values={'issuer': '${mosip.esignet.domain.url}' ,\ - \ 'authorization_endpoint': '${mosip.esignet.domain.url}/authorize' , \ - \ 'token_endpoint': '${mosip.esignet.token.endpoint}' , \ - \ 'jwks_uri' : '${mosip.esignet.jwks-uri}' , \ - \ 'token_endpoint_auth_methods_supported' : ${mosip.esignet.supported.client.auth.methods}, \ - \ 'token_endpoint_auth_signing_alg_values_supported' : {'RS256'},\ - \ 'scopes_supported' : ${mosip.esignet.supported.openid.scopes}, \ - \ 'response_modes_supported' : { 'query' }, \ - \ 'grant_types_supported' : ${mosip.esignet.supported.grant.types},\ - \ 'response_types_supported' : ${mosip.esignet.supported.response.types}} - -mosip.esignet.discovery.key-values={'issuer': '${mosip.esignet.domain.url}' ,\ - \ 'authorization_endpoint': '${mosip.esignet.domain.url}/authorize' , \ - \ 'token_endpoint': '${mosip.esignet.token.endpoint}' ,\ - \ 'userinfo_endpoint' : '${mosip.esignet.domain.url}${server.servlet.path}/oidc/userinfo' ,\ - \ 'jwks_uri' : '${mosip.esignet.jwks-uri}' , \ - \ 'scopes_supported' : ${mosip.esignet.supported.openid.scopes}, \ - \ 'response_types_supported' : ${mosip.esignet.supported.response.types}, \ - \ 'acr_values_supported' : {'mosip:idp:acr:knowledge', 'mosip:idp:acr:password', 'mosip:idp:acr:static-code', 'mosip:idp:acr:generated-code', 'mosip:idp:acr:linked-wallet', 'mosip:idp:acr:biometrics'},\ - \ 'userinfo_signing_alg_values_supported' : {'RS256'}, \ - \ 'userinfo_encryption_alg_values_supported' : {'RSAXXXXX'},\ - \ 'userinfo_encryption_enc_values_supported' : {'A128GCM'}, \ - \ 'response_modes_supported' : { 'query' }, \ - \ 'token_endpoint_auth_methods_supported' : ${mosip.esignet.supported.client.auth.methods}, \ - \ 'token_endpoint_auth_signing_alg_values_supported' : {'RS256'}, \ - \ 'id_token_signing_alg_values_supported' : {'RS256'}, \ - \ 'claim_types_supported': {'normal'}, \ - \ 'claims_parameter_supported' : true, \ - \ 'display_values_supported' : ${mosip.esignet.supported.ui.displays}, \ - \ 'subject_types_supported' : { 'pairwise' }, \ - \ 'claims_supported' : {'name','address','gender','birthdate','picture','email','phone_number','individual_id','phone_number_verified','registration_type','updated_at'}, \ - \ 'claims_locales_supported' : {'en'}, \ - \ 'request_parameter_supported' : false, \ - \ 'display_values_supported' : ${mosip.esignet.supported.ui.displays}, \ - \ 'ui_locales_supported' : {'en'} } - -##----------------------------------------- Database properties -------------------------------------------------------- +## Database configuration mosip.esignet.database.hostname=localhost mosip.esignet.database.port=5455 mosip.esignet.database.name=mosip_esignet mosip.esignet.database.username=postgres -spring.datasource.url=jdbc:postgresql://${mosip.esignet.database.hostname}:${mosip.esignet.database.port}/${mosip.esignet.database.name}?currentSchema=esignet -spring.datasource.username=${mosip.esignet.database.username} spring.datasource.password=postgres - -spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect -spring.jpa.show-sql=false -spring.jpa.hibernate.ddl-auto=none -spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true - -#------------------------------------ Key-manager specific properties -------------------------------------------------- -#Crypto asymmetric algorithm name -mosip.kernel.crypto.asymmetric-algorithm-name=RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING -#Crypto symmetric algorithm name -mosip.kernel.crypto.symmetric-algorithm-name=AES/GCM/PKCS5Padding -#Keygenerator asymmetric algorithm name -mosip.kernel.keygenerator.asymmetric-algorithm-name=RSA -#Keygenerator symmetric algorithm name -mosip.kernel.keygenerator.symmetric-algorithm-name=AES -#Asymmetric algorithm key length -mosip.kernel.keygenerator.asymmetric-key-length=2048 -#Symmetric algorithm key length -mosip.kernel.keygenerator.symmetric-key-length=256 -#Encrypted data and encrypted symmetric key separator -mosip.kernel.data-key-splitter=#KEY_SPLITTER# -#GCM tag length -mosip.kernel.crypto.gcm-tag-length=128 -#Hash algo name -mosip.kernel.crypto.hash-algorithm-name=PBKDF2WithHmacSHA512 -#Symmtric key length used in hash -mosip.kernel.crypto.hash-symmetric-key-length=256 -#No of iterations in hash -mosip.kernel.crypto.hash-iteration=100000 -#Sign algo name -mosip.kernel.crypto.sign-algorithm-name=RS256 -#Certificate Sign algo name -mosip.kernel.certificate.sign.algorithm=SHA256withRSA - -#Type of keystore, Supported Types: PKCS11, PKCS12, Offline, JCE +## Keymanager configuration mosip.kernel.keymanager.hsm.keystore-type=PKCS12 -# For PKCS11 provide Path of config file. -# For PKCS12 keystore type provide the p12/pfx file path. P12 file will be created internally so provide only file path & file name. -# For Offline & JCE property can be left blank, specified value will be ignored. mosip.kernel.keymanager.hsm.config-path=esignet_local.p12 -# Passkey of keystore for PKCS11, PKCS12 -# For Offline & JCE proer can be left blank. JCE password use other JCE specific properties. mosip.kernel.keymanager.hsm.keystore-pass=localtest -mosip.kernel.keymanager.certificate.default.common-name=www.mosip.io -mosip.kernel.keymanager.certificate.default.organizational-unit=MOSIP-TECH-CENTER -mosip.kernel.keymanager.certificate.default.organization=IITB -mosip.kernel.keymanager.certificate.default.location=BANGALORE -mosip.kernel.keymanager.certificate.default.state=KA -mosip.kernel.keymanager.certificate.default.country=IN - -mosip.kernel.keymanager.softhsm.certificate.common-name=www.mosip.io -mosip.kernel.keymanager.softhsm.certificate.organizational-unit=MOSIP -mosip.kernel.keymanager.softhsm.certificate.organization=IITB -mosip.kernel.keymanager.softhsm.certificate.country=IN - -# Application Id for PMS master key. -mosip.kernel.partner.sign.masterkey.application.id=PMS -mosip.kernel.partner.allowed.domains=DEVICE - -mosip.kernel.keymanager-service-validate-url=https://${mosip.hostname}/keymanager/validate -mosip.kernel.keymanager.jwtsign.validate.json=false -mosip.keymanager.dao.enabled=false -crypto.PrependThumbprint.enable=true - -mosip.kernel.keymgr.hsm.health.check.enabled=true -mosip.kernel.keymgr.hsm.health.key.app-id=OIDC_SERVICE -mosip.kernel.keymgr.hsm.healthkey.ref-id=TRANSACTION_CACHE -mosip.kernel.keymgr.hsm.health.check.encrypt=true - -## -------------------------------------------- IDP-UI config ---------------------------------------------------------- - -# NOTE: -# 1. linked-transaction-expire-in-secs value should be a sum of 'mosip.esignet.authentication-expire-in-secs' and 'linked' cache expire in seconds under mosip.esignet.cache.expire-in-seconds property -# 2. A new Qrcode will be autogenerated before the expiry of current qr-code, and the time difference in seconds for the same is defined in wallet.qr-code-buffer-in-secs property -# 3. If esignet is deployed with MOSIP IDA, then 'resend.otp.delay.secs' must be the same as 'mosip.kernel.otp.expiry-time' - -mosip.esignet.ui.wallet.config={{'wallet.name': 'walletName', 'wallet.logo-url': '/images/qr_code.png', 'wallet.download-uri': '#', \ - 'wallet.deep-link-uri': 'inji://landing-page-name?linkCode=LINK_CODE&linkExpireDateTime=LINK_EXPIRE_DT' }} - -mosip.signup.domain.url=http://localhost:8089 -mosip.esignet.ui.signup.config={'signup.banner': true, 'signup.url': '${mosip.signup.domain.url}/signup'} -mosip.esignet.ui.forgot-password.config={'forgot-password': true, 'forgot-password.url': '${mosip.signup.domain.url}/reset-password'} -mosip.esignet.ui.eKYC-steps.url=${mosip.signup.domain.url}/identity-verification - -## Configuration required to display KBI form. -# individual-id-field is set with field id which should be considered as an individual ID in the authenticate request. -# form-details holds the list of field details like below: -# id -> unique field Id, type -> holds datatype, format -> only supported for date fields, regex -> pattern to validate the input value, maxLength -> number of allowed characters -# Example: mosip.esignet.authenticator.default.auth-factor.kba.field-details={{'id': '${mosip.esignet.authenticator.default.auth-factor.kba.individual-id-field}', 'type':'text', 'format':'', 'maxLength': 50, 'regex': '^\\s*[+-]?(\\d+|\\d*\\.\\d+|\\d+\\.\\d*)([Ee][+-]?\\d*)?\\s*$'},{'id':'fullName', 'type':'text', 'format':'', 'maxLength': 50, 'regex': '^[A-Za-z\\s]{1,}[\\.]{0,1}[A-Za-z\\s]{0,}$'},{'id':'dob', 'type':'date', 'format':'dd/mm/yyyy'}} -mosip.esignet.authenticator.default.auth-factor.kbi.individual-id-field= -mosip.esignet.authenticator.default.auth-factor.kbi.field-details={} - -mosip.esignet.ui.config.otp.length=6 -mosip.esignet.ui.config.password.regex=^.{8,20}$ -mosip.esignet.ui.config.password.max-length=20 -mosip.esignet.ui.config.username.regex=.* -mosip.esignet.ui.config.username.prefix= -mosip.esignet.ui.config.username.postfix= -mosip.esignet.ui.config.username.max-length=12 -mosip.esignet.ui.config.username.input-type=text - -mosip.esignet.ui.config.key-values={'sbi.env': '${mosip.esignet.authenticator.ida-env:Developer}', 'sbi.timeout.DISC': 30, \ - 'sbi.timeout.DINFO': 30, 'sbi.timeout.CAPTURE': 30, 'sbi.capture.count.face': 1, 'sbi.capture.count.finger': 1, \ - 'sbi.capture.count.iris': 1, 'sbi.capture.score.face': 70, 'sbi.capture.score.finger':70, 'sbi.capture.score.iris':70, \ - 'resend.otp.delay.secs': ${mosip.kernel.otp.expiry-time:180}, 'send.otp.channels' : '${mosip.esignet.authenticator.ida.otp-channels:email,phone}', \ - 'captcha.sitekey' : '${mosip.esignet.captcha.site-key}', 'captcha.enable' : '${mosip.esignet.captcha.required}', \ - 'auth.txnid.length' : '${mosip.esignet.auth-txn-id-length}', \ - 'preauth-screen-timeout-in-secs':${mosip.esignet.preauthentication-expire-in-secs}, \ - 'consent.screen.timeout-in-secs':${mosip.esignet.authentication-expire-in-secs}, \ - 'consent.screen.timeout-buffer-in-secs': 5, 'linked-transaction-expire-in-secs': 240, 'sbi.port.range': '4501-4600', \ - 'sbi.bio.subtypes.iris': 'UNKNOWN', 'sbi.bio.subtypes.finger': 'UNKNOWN', 'wallet.qr-code-buffer-in-secs': 10, \ - 'otp.length': ${mosip.esignet.ui.config.otp.length}, \ - 'password.regex': '${mosip.esignet.ui.config.password.regex}', \ - 'password.max-length': ${mosip.esignet.ui.config.password.max-length}, \ - 'username.regex': '${mosip.esignet.ui.config.username.regex}',\ - 'username.prefix': '${mosip.esignet.ui.config.username.prefix}', \ - 'username.postfix': '${mosip.esignet.ui.config.username.postfix}', \ - 'username.max-length': ${mosip.esignet.ui.config.username.max-length}, \ - 'username.input-type': '${mosip.esignet.ui.config.username.input-type}', 'wallet.config': ${mosip.esignet.ui.wallet.config}, \'signup.config': ${mosip.esignet.ui.signup.config}, \ - 'forgot-password.config': ${mosip.esignet.ui.forgot-password.config}, \ - 'eKYC-steps.config': '${mosip.esignet.ui.eKYC-steps.url}', \ - 'error.banner.close-timer': 10,\ - 'auth.factor.kbi.individual-id-field' : '${mosip.esignet.authenticator.default.auth-factor.kbi.individual-id-field}',\ - 'auth.factor.kbi.field-details': ${mosip.esignet.authenticator.default.auth-factor.kbi.field-details}} - -##-------------------------------------------- Default Integrations ----------------------------------------------------- - +## Overridden plugin configurations mosip.esignet.integration.audit-plugin=LoggerAuditService -mosip.esignet.integration.key-binder=NoOpKeyBinder +#mosip.esignet.integration.key-binder=NoOpKeyBinder + +## Logging configuration +logging.level.io.mosip.esignet=DEBUG diff --git a/esignet-service/src/main/resources/bootstrap.properties b/esignet-service/src/main/resources/bootstrap.properties index b79c7e7a3..5549e7880 100644 --- a/esignet-service/src/main/resources/bootstrap.properties +++ b/esignet-service/src/main/resources/bootstrap.properties @@ -5,7 +5,7 @@ ## Application Name spring.application.name=esignet spring.cloud.config.uri=http://localhost:8888 -spring.profiles.active=local +spring.profiles.active=default,local server.port=8088 server.servlet.path=/v1/esignet @@ -46,6 +46,3 @@ management.endpoint.metrics.enabled=true management.endpoints.web.exposure.include=* management.endpoint.prometheus.enabled=true management.metrics.export.prometheus.enabled=true - -# to accept string as valid type for jsonb column -spring.datasource.hikari.data-source-properties=stringtype=unspecified \ No newline at end of file diff --git a/helm/apitestrig/.gitignore b/helm/apitestrig/.gitignore new file mode 100644 index 000000000..ee3892e87 --- /dev/null +++ b/helm/apitestrig/.gitignore @@ -0,0 +1 @@ +charts/ diff --git a/helm/apitestrig/.helmignore b/helm/apitestrig/.helmignore new file mode 100644 index 000000000..f0c131944 --- /dev/null +++ b/helm/apitestrig/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/helm/apitestrig/Chart.yaml b/helm/apitestrig/Chart.yaml new file mode 100644 index 000000000..5815c0228 --- /dev/null +++ b/helm/apitestrig/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: apitestrig +description: A Helm chart to deploy APITESTRIG for MOSIP modules +type: application +version: 1.5.0-develop +appVersion: "" +dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + tags: + - bitnami-common + version: 1.x.x +home: https://mosip.io +keywords: + - mosip + - apitestrig +maintainers: + - email: info@mosip.io + name: MOSIP diff --git a/helm/apitestrig/README.md b/helm/apitestrig/README.md new file mode 100644 index 000000000..25c35e359 --- /dev/null +++ b/helm/apitestrig/README.md @@ -0,0 +1,10 @@ +# APITESTRIG + +Helm chart to deploy APITESTRIG for `MOSIP` modules + +## TL;DR + +```console +$ helm repo add mosip https://mosip.github.io +$ helm install my-release mosip/apitestrig +``` diff --git a/helm/apitestrig/templates/NOTES.txt b/helm/apitestrig/templates/NOTES.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/helm/apitestrig/templates/NOTES.txt @@ -0,0 +1 @@ + diff --git a/helm/apitestrig/templates/_helpers.tpl b/helm/apitestrig/templates/_helpers.tpl new file mode 100644 index 000000000..d99caf0c4 --- /dev/null +++ b/helm/apitestrig/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Return the proper image name +*/}} +{{- define "apitestrig.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "apitestrig.volumePermissions.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "apitestrig.imagePullSecrets" -}} +{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "global" .Values.global) -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "apitestrig.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (printf "%s" (include "common.names.fullname" .)) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message. +*/}} +{{- define "apitestrig.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "apitestrig.validateValues.foo" .) -}} +{{- $messages := append $messages (include "apitestrig.validateValues.bar" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message -}} +{{- end -}} +{{- end -}} + +{{/* +Return podAnnotations +*/}} +{{- define "apitestrig.podAnnotations" -}} +{{- if .Values.podAnnotations }} +{{ include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) }} +{{- end }} +{{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} +{{ include "common.tplvalues.render" (dict "value" .Values.metrics.podAnnotations "context" $) }} +{{- end }} +{{- end -}} + +{{/* Create the name for restart cronjob */}} +{{- define "apitestrig.cronjob" -}} +{{ default (printf "cronjob-%s" (include "common.names.fullname" .)) .Values.serviceAccount.name }} +{{- end -}} \ No newline at end of file diff --git a/helm/apitestrig/templates/clusterrole.yaml b/helm/apitestrig/templates/clusterrole.yaml new file mode 100644 index 000000000..da268fdf5 --- /dev/null +++ b/helm/apitestrig/templates/clusterrole.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "apitestrig.serviceAccountName" . }}-{{ .Release.Namespace }} + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get","patch","list","watch"] diff --git a/helm/esignet/templates/clusterrolebinding.yaml b/helm/apitestrig/templates/clusterrolebinding.yaml similarity index 74% rename from helm/esignet/templates/clusterrolebinding.yaml rename to helm/apitestrig/templates/clusterrolebinding.yaml index e44824537..12594c8d1 100644 --- a/helm/esignet/templates/clusterrolebinding.yaml +++ b/helm/apitestrig/templates/clusterrolebinding.yaml @@ -5,15 +5,15 @@ metadata: {{- if .Values.commonLabels }} {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} {{- end }} - name: {{ template "common.names.fullname" . }} + name: {{ template "common.names.fullname" . }}-{{ .Release.Namespace }} {{- if .Values.commonAnnotations }} annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} {{- end }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: {{ template "common.names.fullname" . }} + name: {{ template "apitestrig.serviceAccountName" . }}-{{ .Release.Namespace }} subjects: - kind: ServiceAccount - name: {{ template "esignet.serviceAccountName" . }} + name: {{ template "apitestrig.serviceAccountName" . }} namespace: {{ .Release.Namespace }} diff --git a/helm/apitestrig/templates/configmaps.yaml b/helm/apitestrig/templates/configmaps.yaml new file mode 100644 index 000000000..492508377 --- /dev/null +++ b/helm/apitestrig/templates/configmaps.yaml @@ -0,0 +1,21 @@ +{{- if .Values.apitestrig.configmaps }} +{{- range $cm_name, $cm_value := .Values.apitestrig.configmaps }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $cm_name }} + namespace: {{ $.Release.Namespace }} + labels: {{- include "common.labels.standard" $ | nindent 8 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} +data: + {{- range $key, $value := $cm_value }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/apitestrig/templates/cronjob.yaml b/helm/apitestrig/templates/cronjob.yaml new file mode 100644 index 000000000..9a87054da --- /dev/null +++ b/helm/apitestrig/templates/cronjob.yaml @@ -0,0 +1,119 @@ +{{- range $modulename, $module := $.Values.modules }} +{{- if $module.enabled }} +--- +apiVersion: {{ include "common.capabilities.cronjob.apiVersion" $ }} +kind: CronJob +metadata: + name: {{ template "apitestrig.cronjob" $ }}-{{ $modulename }} + namespace: {{ $.Release.Namespace }} + annotations: + {{- if $.Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + labels: {{- include "common.labels.standard" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + +spec: + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 1 # remove jobs which are successfully executed + failedJobsHistoryLimit: 1 # except 1 recent failed job, remove jobs which are not successfully executed + #schedule: '*/3 * * * *' # cron spec of time, here, 8 o'clock + schedule: {{ $.Values.crontime }} + jobTemplate: + spec: + backoffLimit: 0 # this has very low chance of failing, as all this does + # is prompt kubernetes to schedule new replica set for + # the deployment + # activeDeadlineSeconds: 600 # timeout, makes most sense with + # "waiting for rollout" variant specified below + template: + spec: + # account configured above + restartPolicy: Never + serviceAccountName: {{ template "apitestrig.serviceAccountName" $ }} + initContainers: + {{- if $.Values.enable_insecure }} + {{- include "common.tplvalues.render" (dict "value" $.Values.initContainers "context" $) | nindent 12 }} + {{- end }} + containers: + - name: {{ template "apitestrig.serviceAccountName" $ }}-{{ $modulename }} + image: {{ $module.image.repository }}:{{ $module.image.tag }} + imagePullPolicy: {{ $module.image.pullPolicy }} + {{- if $.Values.lifecycleHooks }} + lifecycle: {{- include "common.tpvalues.render" (dict "value" $.Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if $.Values.containerSecurityContext.enabled }} + securityContext: {{- omit $.Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if $.Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" $.Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if $.Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" $.Values.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: container_user + value: {{ $.Values.containerSecurityContext.runAsUser }} + - name: JDK_JAVA_OPTIONS + value: {{ $.Values.additionalResources.javaOpts }} + - name: MODULES + value: {{ $modulename }} + - name: push-reports-to-s3 + value: {{ quote $.Values.apitestrig.variables.push_reports_to_s3 }} + {{- if $.Values.extraEnvVars }} + {{- include "common.tpvalues.render" (dict "value" $.Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if $.Values.extraEnvVarsCM }} + {{- range $.Values.extraEnvVarsCM }} + - configMapRef: + name: {{ . }} + {{- end }} + {{- end }} + {{- if $.Values.extraEnvVarsSecret }} + {{- range $.Values.extraEnvVarsSecret }} + - secretRef: + name: {{ . }} + {{- end }} + {{- end }} + ports: + - name: spring-service + containerPort: {{ $.Values.springServicePort }} + volumeMounts: + {{- if $.Values.enable_insecure }} + - mountPath: /usr/local/openjdk-11/lib/security/cacerts + name: cacerts + subPath: cacerts + {{- end }} + {{- if $.Values.apitestrig.volumes }} + {{- range $volume_name, $volume_value := $.Values.apitestrig.volumes.configmaps }} + - name: {{ $volume_name }} + mountPath: {{ $volume_value.volumeMounts.mountPath }} + {{- end }} + {{- end }} + {{- if eq $.Values.apitestrig.variables.push_reports_to_s3 "no" }} + - name: {{ $.Values.apitestrig.volumes.reports.name }} + mountPath: /home/mosip/testrig/report + {{- end }} + volumes: + {{- if $.Values.enable_insecure }} + - name: cacerts + emptyDir: {} + {{- end }} + {{- if $.Values.apitestrig.volumes }} + {{- range $volume_name, $volume_value := $.Values.apitestrig.volumes.configmaps }} + - name: {{ $volume_name }} + configMap: + defaultMode: {{ $volume_value.defaultMode }} + name: {{ $volume_name }} + {{- end }} + {{- end }} + {{- if eq $.Values.apitestrig.variables.push_reports_to_s3 "no" }} + - name: {{ $.Values.apitestrig.volumes.reports.name }} + persistentVolumeClaim: + claimName: {{ $.Values.apitestrig.volumes.reports.name }}-{{ $.Release.Namespace }}-{{ $modulename }}-pvc + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/apitestrig/templates/extra-list.yaml b/helm/apitestrig/templates/extra-list.yaml new file mode 100644 index 000000000..9ac65f9e1 --- /dev/null +++ b/helm/apitestrig/templates/extra-list.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/helm/apitestrig/templates/pv.yaml b/helm/apitestrig/templates/pv.yaml new file mode 100644 index 000000000..0ae1e5472 --- /dev/null +++ b/helm/apitestrig/templates/pv.yaml @@ -0,0 +1,23 @@ +{{- range $modulename, $module := $.Values.modules }} +{{- if $module.enabled }} +{{- if eq $.Values.apitestrig.variables.push_reports_to_s3 "no" }} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ $.Values.apitestrig.volumes.reports.name }}-{{ $.Release.Namespace }}-{{ $modulename }}-pvc + labels: + name: {{ $.Values.apitestrig.volumes.reports.name }} +spec: + storageClassName: {{ $.Values.apitestrig.volumes.reports.storageClass }} + capacity: + storage: {{ $.Values.apitestrig.volumes.reports.size }} + accessModes: + {{- range $.Values.apitestrig.volumes.reports.accessModes }} + - {{ . }} + {{- end }} + nfs: + server: {{ $.Values.apitestrig.volumes.reports.nfs.server }} + path: {{ $.Values.apitestrig.volumes.reports.nfs.path }} +{{- end }} +{{- end }} +{{- end }} diff --git a/helm/apitestrig/templates/pvc.yaml b/helm/apitestrig/templates/pvc.yaml new file mode 100644 index 000000000..605375b0c --- /dev/null +++ b/helm/apitestrig/templates/pvc.yaml @@ -0,0 +1,23 @@ +{{- range $modulename, $module := $.Values.modules }} +{{- if $module.enabled }} +{{- if eq $.Values.apitestrig.variables.push_reports_to_s3 "no" }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ $.Values.apitestrig.volumes.reports.name }}-{{ $.Release.Namespace }}-{{ $modulename }}-pvc + namespace: {{ $.Release.Namespace | quote }} +spec: + storageClassName: {{ $.Values.apitestrig.volumes.reports.storageClass }} + accessModes: + {{- range $.Values.apitestrig.volumes.reports.accessModes }} + - {{ . }} + {{- end }} + resources: + requests: + storage: {{ $.Values.apitestrig.volumes.reports.size }} + selector: + matchLabels: + name: {{ $.Values.apitestrig.volumes.reports.name }} +{{- end }} +{{- end }} +{{- end }} diff --git a/helm/apitestrig/templates/secrets.yaml b/helm/apitestrig/templates/secrets.yaml new file mode 100644 index 000000000..a3b9561dc --- /dev/null +++ b/helm/apitestrig/templates/secrets.yaml @@ -0,0 +1,22 @@ +{{- if .Values.apitestrig.secrets }} +{{- range $secret_name, $secret_value := .Values.apitestrig.secrets }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secret_name }}-{{ $.Release.Name }} + namespace: {{ $.Release.Namespace }} + labels: {{- include "common.labels.standard" $ | nindent 8 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} +type: Opaque +data: + {{- range $key, $value := $secret_value }} + {{ $key }}: {{ $value | b64enc | quote }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/oidc-ui/templates/clusterrolebinding.yaml b/helm/apitestrig/templates/service-account.yaml similarity index 51% rename from helm/oidc-ui/templates/clusterrolebinding.yaml rename to helm/apitestrig/templates/service-account.yaml index a839a9b4c..466590df4 100644 --- a/helm/oidc-ui/templates/clusterrolebinding.yaml +++ b/helm/apitestrig/templates/service-account.yaml @@ -1,19 +1,12 @@ -kind: ClusterRoleBinding -apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +apiVersion: v1 +kind: ServiceAccount metadata: labels: {{- include "common.labels.standard" . | nindent 4 }} {{- if .Values.commonLabels }} {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} {{- end }} - name: {{ template "common.names.fullname" . }} + name: {{ template "apitestrig.serviceAccountName" . }} {{- if .Values.commonAnnotations }} annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} {{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "common.names.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "oidc-ui.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} + namespace: {{ .Release.Namespace }} diff --git a/helm/apitestrig/values.yaml b/helm/apitestrig/values.yaml new file mode 100644 index 000000000..7c22d0a0a --- /dev/null +++ b/helm/apitestrig/values.yaml @@ -0,0 +1,559 @@ +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry and imagePullSecrets +## +# global: +# imageRegistry: myRegistryName +# imagePullSecrets: +# - myRegistryKeySecretName +# storageClass: myStorageClass + +## Add labels to all the deployed resources +## +commonLabels: + app.kubernetes.io/component: mosip + +## Add annotations to all the deployed resources +## +commonAnnotations: {} + +## Kubernetes Cluster Domain +## +clusterDomain: cluster.local + +## Extra objects to deploy (value evaluated as a template) +## +extraDeploy: [] + +## Number of nodes +## +replicaCount: 1 + +service: + type: ClusterIP + port: 80 + ## loadBalancerIP for the SuiteCRM Service (optional, cloud specific) + ## ref: http://kubernetes.io/docs/user-guide/services/#type-loadbalancer + ## + ## loadBalancerIP: + ## + ## nodePorts: + ## http: + ## https: + ## + nodePorts: + http: "" + https: "" + ## Enable client source IP preservation + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + +## Port on which this particular spring service module is running. +springServicePort: 8083 + +## Configure extra options for liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## + +## +# existingConfigmap: + +## Command and args for running the container (set to default if not set). Use array form +## +command: ['/bin/bash'] +args: ['-c', "/home/${container_user}/scripts/fetch_docker_image_hash_ids.sh"] + +## Deployment pod host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] + +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 1500m + memory: 3500Mi + requests: + cpu: 1000m + memory: 3500Mi + +additionalResources: + ## Specify any JAVA_OPTS string here. These typically will be specified in conjunction with above resources + ## Example: java_opts: "-Xms500M -Xmx500M" + javaOpts: "-Xms2600M -Xmx2600M" + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## Clamav container already runs as 'mosip' user, so we may not need to enable this +containerSecurityContext: + enabled: false + runAsUser: mosip + runAsNonRoot: true + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## +podSecurityContext: + enabled: false + fsGroup: 1001 + +## Pod affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAffinityPreset: "" + +## Pod anti-affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAntiAffinityPreset: soft + +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## Allowed values: soft, hard +## +nodeAffinityPreset: + ## Node affinity type + ## Allowed values: soft, hard + ## + type: "" + ## Node label key to match + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## Node label values to match + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + +## Affinity for pod assignment. Evaluated as a template. +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Node labels for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +## Tolerations for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Pod extra labels +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} + +## Annotations for server pods. +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} + +## pods' priority. +## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +# priorityClassName: "" + +## lifecycleHooks for the container to automate configuration before or after startup. +## +lifecycleHooks: {} + +## Custom Liveness probes for +## +customLivenessProbe: {} + +## Custom Rediness probes +## +customReadinessProbe: {} + +## Update strategy - only really applicable for deployments with RWO PVs attached +## If replicas = 1, an update can get "stuck", as the previous pod remains attached to the +## PV, and the "incoming" pod can never start. Changing the strategy to "Recreate" will +## terminate the single previous pod, so that the new, incoming pod can attach to the PV +## +updateStrategy: + type: RollingUpdate + +## Additional environment variables to set +## Example: +## extraEnvVars: +## - name: FOO +## value: "bar" +## +extraEnvVars: [] + +## ConfigMap with extra environment variables +## +extraEnvVarsCM: + - global + - s3 + - keycloak-host + - db + - apitestrig + - config-server-share + - artifactory-share +## Secret with extra environment variables +## +extraEnvVarsSecret: + - apitestrig + - s3 + - keycloak-client-secrets + - postgres-postgresql + +## Extra volumes to add to the deployment +## +extraVolumes: [] + +## Extra volume mounts to add to the container +## +extraVolumeMounts: [] + +## Add init containers to the pods. +## Example: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: + - command: + - /bin/bash + - -c + - if [ "$ENABLE_INSECURE" = "true" ]; then HOST=$( env | grep "mosip-api-internal-host" + |sed "s/mosip-api-internal-host=//g"); if [ -z "$HOST" ]; then echo "HOST + $HOST is empty; EXITING"; exit 1; fi; openssl s_client -servername "$HOST" + -connect "$HOST":443 > "$HOST.cer" 2>/dev/null & sleep 2 ; sed -i -ne '/-BEGIN + CERTIFICATE-/,/-END CERTIFICATE-/p' "$HOST.cer"; cat "$HOST.cer"; /usr/local/openjdk-11/bin/keytool + -delete -alias "$HOST" -keystore $JAVA_HOME/lib/security/cacerts -storepass + changeit; /usr/local/openjdk-11/bin/keytool -trustcacerts -keystore "$JAVA_HOME/lib/security/cacerts" + -storepass changeit -noprompt -importcert -alias "$HOST" -file "$HOST.cer" + ; if [ $? -gt 0 ]; then echo "Failed to add SSL certificate for host $host; + EXITING"; exit 1; fi; cp /usr/local/openjdk-11/lib/security/cacerts /cacerts; + fi + env: + - name: ENABLE_INSECURE + value: "true" + envFrom: + - configMapRef: + name: global + image: docker.io/openjdk:11-jre + imagePullPolicy: Always + name: cacerts + resources: {} + securityContext: + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /cacerts + name: cacerts + +## Add sidecars to the pods. +## Example: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +sidecars: {} + +persistence: + enabled: false + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack). + ## + # storageClass: "-" + ## + ## If you want to reuse an existing claim, you can pass the name of the PVC using + ## the existingClaim variable + # existingClaim: your-claim + ## ReadWriteMany not supported by AWS gp2 + storageClass: + accessModes: + - ReadWriteOnce + size: 10M + existingClaim: + # Dir where config and keys are written inside container + mountDir: + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. +## +volumePermissions: + enabled: false + image: + registry: docker.io + repository: bitnami/bitnami-shell + tag: "10" + pullPolicy: Always + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + pullSecrets: [] + ## - myRegistryKeySecretName + ## Init containers' resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## + limits: {} + ## cpu: 100m + ## memory: 128Mi + ## + requests: {} + ## cpu: 100m + ## memory: 128Mi + ## + +## Specifies whether RBAC resources should be created +## +rbac: + create: true + +## Specifies whether a ServiceAccount should be created +## +serviceAccount: + create: true + ## The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the fullname template + ## + name: + +## Prometheus Metrics +## +metrics: + enabled: false + ## Prometheus pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + + endpointPath: + + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## + serviceMonitor: + ## If the operator is installed in your cluster, set to true to create a Service Monitor Entry + ## + enabled: true + ## Specify the namespace in which the serviceMonitor resource will be created + ## + # namespace: "" + ## Specify the interval at which metrics should be scraped + ## + interval: 10s + ## Specify the timeout after which the scrape is ended + ## + # scrapeTimeout: 30s + ## Specify Metric Relabellings to add to the scrape endpoint + ## + # relabellings: + ## Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + additionalLabels: {} + + ## Custom PrometheusRule to be defined + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + enabled: false + additionalLabels: {} + namespace: '' + ## List of rules, used as template by Helm. + ## These are just examples rules inspired from https://awesome-prometheus-alerts.grep.to/rules.html + # rules: + # - alert: RabbitmqDown + # expr: rabbitmq_up{service="{{ template "rabbitmq.fullname" . }}"} == 0 + # for: 5m + # labels: + # severity: error + rules: [] + +## Admin swagger should have only internal access. Hence linked to internal gateway +istio: + enabled: false + gateways: + - istio-system/internal + prefix: + corsPolicy: + allowOrigins: + - prefix: https://api-internal.sandbox.xyz.net + allowCredentials: true + allowHeaders: + - Accept + - Accept-Encoding + - Accept-Language + - Connection + - Content-Type + - Cookie + - Host + - Referer + - Sec-Fetch-Dest + - Sec-Fetch-Mode + - Sec-Fetch-Site + - Sec-Fetch-User + - Origin + - Upgrade-Insecure-Requests + - User-Agent + - sec-ch-ua + - sec-ch-ua-mobile + - sec-ch-ua-platform + - x-xsrf-token + - xsrf-token + allowMethods: + - GET + - POST + - PATCH + - PUT + - DELETE + +modules: + prereg: + enabled: false + image: + repository: mosipqa/apitest-prereg + tag: develop + pullPolicy: Always + masterdata: + enabled: false + image: + repository: mosipqa/apitest-masterdata + tag: develop + pullPolicy: Always + idrepo: + enabled: false + image: + repository: mosipqa/apitest-idrepo + tag: develop + pullPolicy: Always + partner: + enabled: false + image: + repository: mosipqa/apitest-pms + tag: develop + pullPolicy: Always + pms: + enabled: false + image: + repository: mosipdev/apitest-pms + tag: develop + pullPolicy: Always + resident: + enabled: false + image: + repository: mosipqa/apitest-resident + tag: develop + pullPolicy: Always + auth: + enabled: false + image: + repository: mosipqa/apitest-auth + tag: develop + pullPolicy: Always + esignet: + enabled: false + image: + repository: mosipqa/apitest-esignet + tag: develop + pullPolicy: Always + mimoto: + enabled: false + image: + repository: mosipqa/apitest-mimoto + tag: develop + pullPolicy: Always + +crontime: "0 3 * * *" ## run cronjob every day at 3 AM (time hr: 0-23 ) + +apitestrig: + configmaps: + s3: + s3-host: 'http://minio.minio:9000' + s3-user-key: 'admin' + s3-region: '' + db: + db-port: '5432' + db-su-user: 'postgres' + db-server: 'api-internal.sandbox.xyz.net' + apitestrig: + ENV_USER: 'api-internal.sandbox' + ENV_ENDPOINT: 'https://api-internal.sandbox.xyz.net' + ENV_TESTLEVEL: 'smokeAndRegression' + authDemoServiceBaseURL: http://authdemo.authdemo + authDemoServicePort: 80 + eSignetDeployed: yes or no + authCertsPath: '/home/mosip/authcerts' + scripts: + fetch_docker_image_hash_ids.sh: | + #!/bin/bash + sleep 5 + export DOCKER_HASH_ID=$( kubectl get pod "$HOSTNAME" -n "$NS" -o jsonpath='{.status.containerStatuses[*].imageID}' | sed 's/ /\n/g' | grep -v 'istio' | sed 's/docker\-pullable\:\/\///g' ) + export DOCKER_IMAGE=$( kubectl get pod "$HOSTNAME" -n "$NS" -o jsonpath='{.status.containerStatuses[*].image}' | sed 's/ /\n/g' | grep -v 'istio' | sed 's/docker\-pullable\:\/\///g' ) + if [[ -z $DOCKER_HASH_ID ]]; then + echo "DOCKER_HASH_ID IS EMPTY;EXITING"; + exit 1; + fi + echo "DOCKER_HASH_ID ; $DOCKER_HASH_ID" + echo "DOCKER_IMAGE : $DOCKER_IMAGE" + kubectl get pods -A -o=jsonpath='{range .items[*]}{.metadata.namespace}{","}{.metadata.labels.app\.kubernetes\.io\/name}{","}{.status.containerStatuses[?(@.name!="istio-proxy")].image}{","}{.status.containerStatuses[?(@.name!="istio-proxy")].imageID}{","}{.metadata.creationTimestamp}{"\n"}' | sed 's/ /\n/g' | grep -vE 'istio*|longhorn*|cattle*|rancher|kube' | sed 's/docker\-pullable\:\/\///g' | sort -u | sed '/,,,/d' | awk -F ',' 'BEGIN {print "{ \"POD_NAME\": \"'$(echo $HOSTNAME)'\", \"DOCKER_IMAGE\": \"'$(echo $DOCKER_IMAGE)'\", \"DOCKER_HASH_ID\": \"'$(echo $DOCKER_HASH_ID)'\", \"k8s-cluster-image-list\": ["} {print "{"} {print "\"namespace\": \"" $1 "\","} {print "\"app_name\": \"" $2 "\","} {print "\"docker_image_name\": \"" $3 "\","} {print "\"docker_image_id\": \"" $4 "\","} {print "\"creation_timestamp\": \"" $5 "\"" } {print "},"} END {print "]}"}' | sed -z 's/},\n]/}\n]/g' | jq -r . | tee -a images-list.json + ## run entrypoint script + sleep 5 + cd /home/${container_user}/ + bash ./entrypoint.sh + secrets: + s3: + s3-user-secret: 'password' + apitestrig: + volumes: + configmaps: + scripts: + defaultMode: 0777 + volumeMounts: + mountPath: '/home/mosip/scripts/' + reports: + name: apitestrig-reports + storageClass: nfs-client + accessModes: + - ReadWriteMany + size: 10Mi + existingClaim: + # Dir where config and keys are written inside container + mountDir: /home/mosip/testrig/report + nfs: + path: "/srv/nfs/sandbox/onboarding" # Dir within the nfs server where config repo is cloned/maintained locally. + server: "nfs-server" # Ip address of nfs server. + variables: + push_reports_to_s3: "no" +enable_insecure: false diff --git a/helm/esignet/Chart.yaml b/helm/esignet/Chart.yaml index 265aabe4c..d23e1a56d 100644 --- a/helm/esignet/Chart.yaml +++ b/helm/esignet/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: esignet description: A Helm chart for MOSIP esignet module type: application -version: 0.0.1-test +version: 1.5.0-develop appVersion: "" dependencies: - name: common diff --git a/helm/esignet/values.yaml b/helm/esignet/values.yaml index f394b1e75..db5bb3f51 100644 --- a/helm/esignet/values.yaml +++ b/helm/esignet/values.yaml @@ -53,7 +53,7 @@ service: image: registry: docker.io repository: mosipdev/esignet - tag: develop + tag: release-1.5.x ## Specify a imagePullPolicy ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images @@ -77,10 +77,10 @@ startupProbe: httpGet: path: /v1/esignet/actuator/health port: 8088 - initialDelaySeconds: 0 + initialDelaySeconds: 180 periodSeconds: 10 timeoutSeconds: 5 - failureThreshold: 30 + failureThreshold: 60 successThreshold: 1 livenessProbe: @@ -88,7 +88,7 @@ livenessProbe: httpGet: path: /v1/esignet/actuator/health port: 8088 - initialDelaySeconds: 20 + initialDelaySeconds: 200 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 6 @@ -99,7 +99,7 @@ readinessProbe: httpGet: path: /v1/esignet/actuator/health port: 8088 - initialDelaySeconds: 0 + initialDelaySeconds: 180 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 6 @@ -252,10 +252,14 @@ extraEnvVars: | secretKeyRef: name: esignet-captcha key: esignet-captcha-site-key + - name: MOSIP_ESIGNET_INTEGRATION_AUDIT_PLUGIN + value: LoggerAuditService - name: MOSIP_ESIGNET_CAPTCHA_MODULE_NAME value: esignet - name: IDA_AUTHENTICATOR_ENV value: Staging + - name: MOSIP_ESIGNET_UI_CONFIG_USERNAME_PREFIX + value: '+91' - name: REDIS_HOST valueFrom: configMapKeyRef: diff --git a/helm/oidc-ui/Chart.yaml b/helm/oidc-ui/Chart.yaml index 1993fec29..e54a454e9 100644 --- a/helm/oidc-ui/Chart.yaml +++ b/helm/oidc-ui/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: oidc-ui description: A Helm chart for MOSIP OIDC UI module type: application -version: 0.0.1-test +version: 1.5.0-develop appVersion: "" dependencies: - name: common diff --git a/helm/oidc-ui/values.yaml b/helm/oidc-ui/values.yaml index 5c7b25212..db05da2aa 100755 --- a/helm/oidc-ui/values.yaml +++ b/helm/oidc-ui/values.yaml @@ -52,7 +52,7 @@ service: image: registry: docker.io repository: mosipdev/oidc-ui - tag: develop + tag: release-1.5.x ## Specify a imagePullPolicy ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java index b9405ffd1..a4095bc2e 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java @@ -146,7 +146,7 @@ protected void addEntryInLinkAuthCodeStatusDeferredResultMap(String key, Deferre LINK_AUTH_CODE_STATUS_DEFERRED_RESULT_MAP.put(key, deferredResult); } - @KafkaListener(id = "link-status-consumer", autoStartup = "${kafka.enabled:true}", topics = "${mosip.esignet.kafka.linked-session.topic}") + @KafkaListener(id = "${spring.kafka.consumer.group-id}"+"-link-status", autoStartup = "${kafka.enabled:true}", topics = "${mosip.esignet.kafka.linked-session.topic}") public void consumeLinkStatus(String linkCodeHash) { DeferredResult deferredResult = LINK_STATUS_DEFERRED_RESULT_MAP.get(linkCodeHash); if(deferredResult != null) { @@ -156,7 +156,7 @@ public void consumeLinkStatus(String linkCodeHash) { } } - @KafkaListener(id = "link-auth-code-status-consumer", autoStartup = "${kafka.enabled:true}", topics = "${mosip.esignet.kafka.linked-auth-code.topic}") + @KafkaListener(id = "${spring.kafka.consumer.group-id}"+"-linked-auth-code", autoStartup = "${kafka.enabled:true}", topics = "${mosip.esignet.kafka.linked-auth-code.topic}") public void consumeLinkAuthCodeStatus(String linkTransactionId) { DeferredResult deferredResult = LINK_AUTH_CODE_STATUS_DEFERRED_RESULT_MAP.get(linkTransactionId); if(deferredResult != null) { diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index c485c04c4..6292e24a3 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -277,12 +277,13 @@ public ClaimDetailResponse getClaimDetails(String transactionId) { } //Profile update is mandated only if any essential verified claim is requested - boolean unverifiedEssentialClaimsExist = transaction.getResolvedClaims().getUserinfo() + boolean unverifiedEssentialClaimsExists = transaction.getResolvedClaims().getUserinfo() .entrySet() .stream() .anyMatch( entry -> entry.getValue().stream() - .anyMatch(m -> (boolean) m.getOrDefault("essential", false) && m.get("verification") == null )); - claimDetailResponse.setProfileUpdateRequired(unverifiedEssentialClaimsExist); + .anyMatch(m -> (boolean) m.getOrDefault("essential", false) && m.get("verification") != null && + transaction.getClaimMetadata().getOrDefault(entry.getKey(), Collections.EMPTY_LIST).isEmpty() )); + claimDetailResponse.setProfileUpdateRequired(unverifiedEssentialClaimsExists); claimDetailResponse.setClaimStatus(list); auditWrapper.logAudit(Action.CLAIM_DETAILS, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transactionId, transaction), null); diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ClaimsHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ClaimsHelperService.java index 446875ec4..e3cce84b6 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ClaimsHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ClaimsHelperService.java @@ -164,7 +164,8 @@ protected ClaimStatus getClaimStatus(String claim, List> cla //if the claim is requested without any verification metadata if(CollectionUtils.isEmpty(claimDetails) || claimDetails.stream().allMatch( m -> m.get("verification") == null)) - return new ClaimStatus(claim, false, storedVerificationMetadata.containsKey(claim)); + return new ClaimStatus(claim, !storedVerificationMetadata.getOrDefault(claim, Collections.emptyList()).isEmpty(), + storedVerificationMetadata.containsKey(claim)); log.info("Request to fetch verification metadata for {} with filter criteria : {}", claim, claimDetails); List storedVerificationDetails = storedVerificationMetadata.get(claim); diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java index 3de60b0ce..c982a6ac9 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java @@ -19,6 +19,7 @@ import io.mosip.esignet.api.spi.AuditPlugin; import io.mosip.esignet.api.spi.Authenticator; import io.mosip.esignet.api.util.ConsentAction; +import io.mosip.esignet.api.util.FilterCriteriaMatcher; import io.mosip.esignet.core.constants.Constants; import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.exception.EsignetException; @@ -102,9 +103,14 @@ public void setUp() { claims.put("profile", Arrays.asList("given_name", "profile_picture", "name", "phone_number", "email")); claims.put("email", Arrays.asList("email","email_verified")); claims.put("phone", Arrays.asList("phone_number","phone_number_verified")); + + FilterCriteriaMatcher filterCriteriaMatcher = new FilterCriteriaMatcher(); + ReflectionTestUtils.setField(filterCriteriaMatcher,"objectMapper", new ObjectMapper()); + ClaimsHelperService claimsHelperService = new ClaimsHelperService(); ReflectionTestUtils.setField(claimsHelperService,"claims", claims); ReflectionTestUtils.setField(claimsHelperService,"objectMapper", new ObjectMapper()); + ReflectionTestUtils.setField(claimsHelperService,"filterCriteriaMatcher", filterCriteriaMatcher); ReflectionTestUtils.setField(authorizationHelperService, "credentialScopes", Arrays.asList("sample_ldp_vc")); ReflectionTestUtils.setField(authorizationHelperService, "authorizeScopes", Arrays.asList("resident-service")); @@ -1371,24 +1377,67 @@ public void getAuthCode_withInValidTransactionId_thenFail() { } @Test - public void getClaimDetails_withValidTransaction_thenPass(){ + public void getClaimDetails_withUnVerifiedClaimsRequest_thenPass(){ OIDCTransaction transaction=new OIDCTransaction(); Claims resolvedClaims = new Claims(); resolvedClaims.setUserinfo(new HashMap<>()); Map map = new HashMap<>(); map.put("essential", true); - map.put("verification", new HashMap<>()); resolvedClaims.getUserinfo().put("name", Arrays.asList(map)); - transaction.setResolvedClaims(resolvedClaims); transaction.setEssentialClaims(List.of("name", "email")); transaction.setVoluntaryClaims(List.of("phone_number")); + + Map> claimMetadata = new HashMap<>(); + transaction.setClaimMetadata(claimMetadata); transaction.setConsentAction(ConsentAction.NOCAPTURE); Mockito.when(cacheUtilService.getAuthenticatedTransaction(Mockito.anyString())).thenReturn(transaction); ClaimDetailResponse claimDetailResponse = authorizationServiceImpl.getClaimDetails("transactionId"); Assert.assertEquals(claimDetailResponse.getConsentAction(),ConsentAction.NOCAPTURE); Assert.assertEquals(claimDetailResponse.getTransactionId(),"transactionId"); + Assert.assertFalse(claimDetailResponse.isProfileUpdateRequired()); + } + + @Test + public void getClaimDetails_withVerifiedClaimsRequest_thenPass() throws JsonProcessingException { + OIDCTransaction transaction=new OIDCTransaction(); + Claims resolvedClaims = new Claims(); + resolvedClaims.setUserinfo(new HashMap<>()); + Map map = new HashMap<>(); + map.put("essential", true); + Map requestedVerification = new HashMap<>(); + requestedVerification.put("trust_framework", null); + map.put("verification", requestedVerification); + resolvedClaims.getUserinfo().put("name", Arrays.asList(map)); + transaction.setResolvedClaims(resolvedClaims); + transaction.setEssentialClaims(List.of("name", "email")); + transaction.setVoluntaryClaims(List.of("phone_number")); + + Map> claimMetadata = new HashMap<>(); + transaction.setClaimMetadata(claimMetadata); + transaction.setConsentAction(ConsentAction.CAPTURE); + Mockito.when(cacheUtilService.getAuthenticatedTransaction(Mockito.anyString())).thenReturn(transaction); + + ClaimDetailResponse claimDetailResponse = authorizationServiceImpl.getClaimDetails("transactionId"); + Assert.assertEquals(claimDetailResponse.getConsentAction(),ConsentAction.CAPTURE); + Assert.assertEquals(claimDetailResponse.getTransactionId(),"transactionId"); + Assert.assertTrue(claimDetailResponse.getClaimStatus().stream().allMatch(cs -> !cs.isVerified() && !cs.isAvailable())); + Assert.assertTrue(claimDetailResponse.isProfileUpdateRequired()); + + Map emailMap = new HashMap<>(); + emailMap.put("essential", true); + resolvedClaims.getUserinfo().put("email", Arrays.asList(emailMap)); + Map phoneMap = new HashMap<>(); + phoneMap.put("essential", false); + resolvedClaims.getUserinfo().put("phone_number", Arrays.asList(phoneMap)); + claimMetadata.put("name", Arrays.asList(objectMapper.readTree("{\"verification\": {\"trust_framework\": \"XYZ TF\"}}"))); + claimMetadata.put("phone_number", Arrays.asList()); + claimDetailResponse = authorizationServiceImpl.getClaimDetails("transactionId"); + Assert.assertTrue(claimDetailResponse.getClaimStatus().stream().anyMatch(cs -> cs.getClaim().equals("name") && cs.isVerified() && cs.isAvailable())); + Assert.assertTrue(claimDetailResponse.getClaimStatus().stream().anyMatch(cs -> cs.getClaim().equals("email") && !cs.isVerified() && !cs.isAvailable())); + Assert.assertTrue(claimDetailResponse.getClaimStatus().stream().anyMatch(cs -> cs.getClaim().equals("phone_number") && !cs.isVerified() && cs.isAvailable())); + Assert.assertFalse(claimDetailResponse.isProfileUpdateRequired()); } @Test diff --git a/partner-onboarder/README.md b/partner-onboarder/README.md index 45b62cbb3..1fc1204ee 100644 --- a/partner-onboarder/README.md +++ b/partner-onboarder/README.md @@ -4,6 +4,19 @@ Exchanges certificates for eSignet MISP partner. Refer [mosip-onboarding repo](https://github.com/mosip/mosip-onboarding). ## Install +* Create a directory for onboarder on the NFS server at `/srv/nfs//onboarder/`: +``` +mkdir -p /srv/nfs/mosip//onboarder/ +``` +* Ensure the directory has 777 permissions: +``` +chmod 777 /srv/nfs/mosip//onboarder +``` +* Add the following entry to the /etc/exports file: +``` +/srv/nfs/mosip//onboarder *(ro,sync,no_root_squash,no_all_squash,insecure,subtree_check) +``` + * Set `values.yaml` to run onboarder for specific modules. * run `./install.sh`. ``` diff --git a/partner-onboarder/install.sh b/partner-onboarder/install.sh index ed442938d..82599ed23 100755 --- a/partner-onboarder/install.sh +++ b/partner-onboarder/install.sh @@ -21,7 +21,7 @@ if [ "$flag" = "n" ]; then fi NS=esignet -CHART_VERSION=0.0.1-develop +CHART_VERSION=1.5.0-es-develop echo Create $NS namespace kubectl create ns $NS || true @@ -73,7 +73,7 @@ function installing_onboarder() { echo "NFS server not provided; EXITING." exit 1; fi - read -p "Please provide NFS directory to store reports from NFS server (e.g. /srv/nfs//onboarder/), make sure permission is 777 for the folder: " nfs_path + read -p "Please provide NFS directory to store reports from NFS server (e.g. /srv/nfs/mosip//onboarder/), make sure permission is 777 for the folder: " nfs_path if [[ -z $nfs_path ]]; then echo "NFS Path not provided; EXITING." exit 1; @@ -113,7 +113,9 @@ function installing_onboarder() { -f values.yaml \ --version $CHART_VERSION \ --wait --wait-for-jobs - echo "Partner onboarded successfully and reports are moved to S3 or NFS" + echo "Partner onboarder executed and reports are moved to S3 or NFS please check the same to make sure partner was onboarded sucessfully." + kubectl rollout restart deployment -n esignet esignet + echo eSignet MISP License Key updated successfully to eSignet. return 0 fi } diff --git a/partner-onboarder/values.yaml b/partner-onboarder/values.yaml index c6adfd94c..cb214c694 100644 --- a/partner-onboarder/values.yaml +++ b/partner-onboarder/values.yaml @@ -1,7 +1,14 @@ -image: - registry: docker.io - repository: mosipdev/partner-onboarder - tag: develop +#image: +# registry: docker.io +# repository: mosipdev/partner-onboarder +# tag: develop +resources: + limits: + cpu: 500m + memory: 500Mi + requests: + cpu: 500m + memory: 500Mi onboarding: modules: @@ -17,7 +24,7 @@ onboarding: # ns_esignet: esignet # ns_signup: signup # secrets: -# s3: +# s3: # s3-user-secret: 'password' # volumes: # reports: diff --git a/postman-collection/eSignet-with-MOSIP.postman_environment.json b/postman-collection/eSignet-with-MOSIP.postman_environment.json index ea264c137..043f15d72 100644 --- a/postman-collection/eSignet-with-MOSIP.postman_environment.json +++ b/postman-collection/eSignet-with-MOSIP.postman_environment.json @@ -84,7 +84,7 @@ }, { "key": "claims_v3", - "value": "{\n \"userinfo\": {\n \"name\": {\n \"essential\": false\n },\n \"phone_number\": {\n \"essential\": true\n },\n \"verified_claims\": [\n {\n \"verification\": {\n \"trust_framework\": null,\n \"time\": null\n },\n \"claims\": {\n \"name\": {\n \"essential\": true\n }\n }\n }\n ]\n },\n \"id_token\": {}\n}", + "value": "{\n \"userinfo\": {\n \"name\": {\n \"essential\": false\n },\n \"phone_number\": {\n \"essential\": true\n },\n \"verified_claims\": [\n {\n \"verification\": {\n \"trust_framework\": null,\n \"time\": null\n },\n \"claims\": {\n \"email\": {\n \"essential\": true\n }\n }\n }\n ]\n },\n \"id_token\": {}\n}", "type": "default", "enabled": true }, @@ -96,7 +96,7 @@ }, { "key": "accepted_claims", - "value": "[\"phone_number\", \"name\"]", + "value": "[\"email\", \"name\", \"phone_number\"]", "type": "default", "enabled": true }, @@ -117,9 +117,15 @@ "value": "http://localhost:8082", "type": "default", "enabled": true + }, + { + "key": "iam_url", + "value": "https://iam.collab.mosip.net", + "type": "default", + "enabled": true } ], "_postman_variable_scope": "environment", - "_postman_exported_at": "2024-09-19T19:20:29.482Z", - "_postman_exported_using": "Postman/11.12.0" + "_postman_exported_at": "2024-12-12T18:27:58.549Z", + "_postman_exported_using": "Postman/11.21.0" } \ No newline at end of file diff --git a/postman-collection/eSignet-with-mock.postman_environment.json b/postman-collection/eSignet-with-mock.postman_environment.json index c3e72fe96..7ca9ffef6 100644 --- a/postman-collection/eSignet-with-mock.postman_environment.json +++ b/postman-collection/eSignet-with-mock.postman_environment.json @@ -1,5 +1,5 @@ { - "id": "0affa285-388e-4f7e-8634-f6860ba94edd", + "id": "de435b57-a284-4514-81a9-ce20a91c88be", "name": "eSignet-with-mock", "values": [ { @@ -83,7 +83,7 @@ }, { "key": "accepted_claims", - "value": "[\"phone_number\", \"name\"]", + "value": "[\"email\", \"phone_number\", \"name\"]", "type": "default", "enabled": true }, @@ -98,9 +98,15 @@ "value": "http://localhost:8082", "type": "default", "enabled": true + }, + { + "key": "iam_url", + "value": "https://iam.collab.mosip.net", + "type": "default", + "enabled": true } ], "_postman_variable_scope": "environment", - "_postman_exported_at": "2024-09-19T19:18:36.603Z", - "_postman_exported_using": "Postman/11.12.0" + "_postman_exported_at": "2024-12-12T18:27:48.937Z", + "_postman_exported_using": "Postman/11.21.0" } \ No newline at end of file diff --git a/postman-collection/eSignet.postman_collection.json b/postman-collection/eSignet.postman_collection.json index 7e047571d..06ccc7b1e 100644 --- a/postman-collection/eSignet.postman_collection.json +++ b/postman-collection/eSignet.postman_collection.json @@ -1,10 +1,10 @@ { "info": { - "_postman_id": "702e0fb0-606d-452f-b160-b9bbf6cbe31f", + "_postman_id": "3267907a-75db-4d3c-a42e-89050178c6f4", "name": "eSignet", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "20579541", - "_collection_link": "https://mosip-idp.postman.co/workspace/MOSIP-Team-Workspace~76ac5ada-d630-4817-8d7b-25f499b093d4/collection/20579541-702e0fb0-606d-452f-b160-b9bbf6cbe31f?action=share&source=collection_link&creator=20579541" + "_collection_link": "https://mosip-idp.postman.co/workspace/MOSIP-Team-Workspace~76ac5ada-d630-4817-8d7b-25f499b093d4/collection/20579541-3267907a-75db-4d3c-a42e-89050178c6f4?action=share&source=collection_link&creator=20579541" }, "item": [ { @@ -131,6 +131,63 @@ { "name": "Mock", "item": [ + { + "name": "Get Auth token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = JSON.parse(pm.response.text());", + "var data = jsonData.access_token;", + "console.log(data);", + "pm.environment.set(\"authtoken\",data);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "client_secret", + "value": "ysd1exB4FXsZebbA", + "type": "text" + }, + { + "key": "client_id", + "value": "mosip-pms-client", + "type": "text" + }, + { + "key": "grant_type", + "value": "client_credentials", + "type": "text" + } + ] + }, + "url": { + "raw": "{{iam_url}}/auth/realms/mosip/protocol/openid-connect/token", + "host": [ + "{{iam_url}}" + ], + "path": [ + "auth", + "realms", + "mosip", + "protocol", + "openid-connect", + "token" + ] + } + }, + "response": [] + }, { "name": "Get CSRF token", "event": [ @@ -192,7 +249,8 @@ "const publicKeyPem = pmlib.rs.KEYUTIL.getPEM(kp.pubKeyObj, \"PKCS8PUB\");", "// Convert the PEM format to a simple Base64 string (removing PEM headers)", "const publicKeyBase64 = publicKeyPem.replace(/-----BEGIN PUBLIC KEY-----|-----END PUBLIC KEY-----|\\n/g, '');", - "pm.environment.set(\"client_id\", publicKeyBase64.substring(2, 50));", + "let updatedStr = publicKeyBase64.replace(/\\//g, \"_\");", + "pm.environment.set(\"client_id\", updatedStr.substring(2, 50));", "", "// Log the result to Postman's console (option);", "pm.environment.set(\"client_private_key\", JSON.stringify(privateKey_jwk));", @@ -205,7 +263,14 @@ ], "request": { "auth": { - "type": "noauth" + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{authtoken}}", + "type": "string" + } + ] }, "method": "POST", "header": [ @@ -217,7 +282,7 @@ ], "body": { "mode": "raw", - "raw": "{ \n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"clientId\": \"{{client_id}}\",\n \"clientName\": \"{{$randomCompanyName}}\",\n \"publicKey\": {{client_public_key}},\n \"relyingPartyId\": \"mock-relying-party-id\",\n \"userClaims\": [\n \"name\",\n \"email\",\n \"gender\",\n \"phone_number\",\n \"picture\",\n \"birthdate\"\n ],\n \"authContextRefs\": [\n \"mosip:idp:acr:generated-code\",\n \"mosip:idp:acr:password\",\n \"mosip:idp:acr:linked-wallet\"\n ],\n \"logoUri\": \"{{$randomImageUrl}}\",\n \"redirectUris\": [\n \"{{redirection_url}}\",\n \"io.mosip.residentapp://oauth\",\n \"http://loclahost:3000/**\",\n \"http://loclahost:5000/registration/*\"\n ],\n \"grantTypes\": [\n \"authorization_code\"\n ],\n \"clientAuthMethods\": [\n \"private_key_jwt\"\n ]\n }\n}", + "raw": "{ \n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"clientId\": \"{{client_id}}\",\n \"clientName\": \"{{$randomCompanyName}}\",\n \"publicKey\": {{client_public_key}},\n \"relyingPartyId\": \"mock-relying-party-id\",\n \"userClaims\": [\n \"name\",\n \"email\",\n \"gender\",\n \"phone_number\",\n \"picture\",\n \"birthdate\"\n ],\n \"authContextRefs\": [\n \"mosip:idp:acr:generated-code\",\n \"mosip:idp:acr:password\",\n \"mosip:idp:acr:linked-wallet\"\n ],\n \"logoUri\": \"{{$randomImageUrl}}\",\n \"redirectUris\": [\n \"{{redirection_url}}\",\n \"io.mosip.residentapp://oauth\",\n \"http://localhost:3000/**\",\n \"http://localhost:5000/registration/*\"\n ],\n \"grantTypes\": [\n \"authorization_code\"\n ],\n \"clientAuthMethods\": [\n \"private_key_jwt\"\n ]\n }\n}", "options": { "raw": { "language": "json" @@ -255,7 +320,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"logoUri\": \"{{$randomImageUrl}}\",\n \"redirectUris\": [\n \"{{redirection_url}}\",\n \"io.mosip.residentapp://oauth\",\n \"http://loclahost:3000/**\",\n \"http://loclahost:5000/registration/*\"\n ],\n \"userClaims\": [\n \"name\",\n \"email\",\n \"gender\",\n \"phone_number\",\n \"birthdate\",\n \"picture\",\n \"address\"\n ],\n \"authContextRefs\": [\n \"mosip:idp:acr:generated-code\",\n \"mosip:idp:acr:password\",\n \"mosip:idp:acr:linked-wallet\",\n \"mosip:idp:acr:biometrics\"\n ],\n \"status\": \"ACTIVE\",\n \"grantTypes\": [\n \"authorization_code\"\n ],\n \"clientName\": \"{{$randomCompanyName}}\",\n \"clientAuthMethods\": [\n \"private_key_jwt\"\n ]\n }\n}", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"logoUri\": \"{{$randomImageUrl}}\",\n \"redirectUris\": [\n \"{{redirection_url}}\",\n \"io.mosip.residentapp://oauth\",\n \"http://localhost:3000/**\",\n \"http://localhost:5000/registration/*\"\n ],\n \"userClaims\": [\n \"name\",\n \"email\",\n \"gender\",\n \"phone_number\",\n \"birthdate\",\n \"picture\",\n \"address\"\n ],\n \"authContextRefs\": [\n \"mosip:idp:acr:generated-code\",\n \"mosip:idp:acr:password\",\n \"mosip:idp:acr:linked-wallet\",\n \"mosip:idp:acr:biometrics\",\n \"mosip:idp:acr:static-code\"\n ],\n \"status\": \"ACTIVE\",\n \"grantTypes\": [\n \"authorization_code\"\n ],\n \"clientName\": \"{{$randomCompanyName}}\",\n \"clientAuthMethods\": [\n \"private_key_jwt\"\n ]\n }\n}", "options": { "raw": { "language": "json" @@ -295,7 +360,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\"individualId\":\"{{individual_id}}\",\"pin\":\"545411\",\"email\":\"siddhartha.km@gmail.com\",\"phone\":\"+919427357934\",\"fullName\":[{\"language\":\"fra\",\"value\":\"Siddharth K Mansour\"},{\"language\":\"ara\",\"value\":\"تتگلدكنسَزقهِقِفل دسييسيكدكنوڤو\"},{\"language\":\"eng\",\"value\":\"Siddharth K Mansour\"}],\"gender\":[{\"language\":\"eng\",\"value\":\"Male\"},{\"language\":\"fra\",\"value\":\"Mâle\"},{\"language\":\"ara\",\"value\":\"ذكر\"}],\"dateOfBirth\":\"1987/11/25\",\"streetAddress\":[{\"language\":\"fra\",\"value\":\"yuān⥍\"},{\"language\":\"ara\",\"value\":\"$لُنگᆑ\"},{\"language\":\"eng\",\"value\":\"Slung\"}],\"locality\":[{\"language\":\"fra\",\"value\":\"yuān 2\"},{\"language\":\"ara\",\"value\":\"يَُانꉛ⥍\"},{\"language\":\"eng\",\"value\":\"yuan wee\"}],\"region\":[{\"language\":\"fra\",\"value\":\"yuān 3\"},{\"language\":\"ara\",\"value\":\"$لُنگᆑ\"},{\"language\":\"eng\",\"value\":\"yuan wee 3\"}],\"postalCode\":\"45009\",\"country\":[{\"language\":\"fra\",\"value\":\"CMâttye\"},{\"language\":\"ara\",\"value\":\"دسييسيكدك\"},{\"language\":\"eng\",\"value\":\"Cmattey\"}],\"encodedPhoto\":\"data:image/jpeg;base64,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\"}\n}", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"individualId\": \"{{individual_id}}\",\n \"pin\": \"545411\",\n \"email\": \"siddhartha.km@gmail.com\",\n \"phone\": \"+919427357934\",\n \"fullName\": [\n {\n \"language\": \"fra\",\n \"value\": \"Siddharth K Mansour\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"تتگلدكنسَزقهِقِفل دسييسيكدكنوڤو\"\n },\n {\n \"language\": \"eng\",\n \"value\": \"Siddharth K Mansour\"\n }\n ],\n \"givenName\": [\n {\n \"language\": \"fra\",\n \"value\": \"Siddharth K Mansour\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"تتگلدكنسَزقهِقِفل دسييسيكدكنوڤو\"\n },\n {\n \"language\": \"eng\",\n \"value\": \"Siddharth K Mansour\"\n }\n ],\n \"familyName\": [\n {\n \"language\": \"fra\",\n \"value\": \"Mansour\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"تتگلدكنسَزقهِقِفل\"\n },\n {\n \"language\": \"eng\",\n \"value\": \"Mansour\"\n }\n ],\n \"gender\": [\n {\n \"language\": \"eng\",\n \"value\": \"Male\"\n },\n {\n \"language\": \"fra\",\n \"value\": \"Mâle\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"ذكر\"\n }\n ],\n \"dateOfBirth\": \"1987/11/25\",\n \"streetAddress\": [\n {\n \"language\": \"fra\",\n \"value\": \"yuān⥍\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"$لُنگᆑ\"\n },\n {\n \"language\": \"eng\",\n \"value\": \"Slung\"\n }\n ],\n \"locality\": [\n {\n \"language\": \"fra\",\n \"value\": \"yuān 2\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"يَُانꉛ⥍\"\n },\n {\n \"language\": \"eng\",\n \"value\": \"yuan wee\"\n }\n ],\n \"region\": [\n {\n \"language\": \"fra\",\n \"value\": \"yuān 3\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"$لُنگᆑ\"\n },\n {\n \"language\": \"eng\",\n \"value\": \"yuan wee 3\"\n }\n ],\n \"postalCode\": \"45009\",\n \"country\": [\n {\n \"language\": \"fra\",\n \"value\": \"CMâttye\"\n },\n {\n \"language\": \"ara\",\n \"value\": \"دسييسيكدك\"\n },\n {\n \"language\": \"eng\",\n \"value\": \"Cmattey\"\n }\n ],\n \"encodedPhoto\": \"data:image/jpeg;base64,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\"\n }\n}", "options": { "raw": { "language": "json" @@ -1092,7 +1157,7 @@ "pm.test(\"Validate linkTransactionId\", function () {", " var jsonData = pm.response.json();", " pm.expect(jsonData.response.linkTransactionId).not.equals(null);", - " pm.environment.set(\"linkTransactionId\", jsonData.response.linkTransactionId);", + " pm.environment.set(\"link_transaction_id\", jsonData.response.linkTransactionId);", "});" ], "type": "text/javascript", @@ -1210,7 +1275,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"linkedTransactionId\": \"{{linkTransactionId}}\",\n \"individualId\": \"{{individual_id}}\",\n \"challengeList\" : [\n {\n \"authFactorType\" : \"WLA\",\n \"challenge\" : \"{{wla_challenge}}\",\n \"format\" : \"jwt\"\n }\n ]\n }\n}", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"linkedTransactionId\": \"{{link_transaction_id}}\",\n \"individualId\": \"{{individual_id}}\",\n \"challengeList\" : [\n {\n \"authFactorType\" : \"WLA\",\n \"challenge\" : \"{{wla_challenge}}\",\n \"format\" : \"jwt\"\n }\n ]\n }\n}", "options": { "raw": { "language": "json" @@ -1278,7 +1343,7 @@ "pm.test(\"Validate code\", function () {", " var jsonData = pm.response.json();", " pm.expect(jsonData.response.code).not.equals(null);", - " pm.environment.set(\"code\", jsonData.response.code);", + " pm.collectionVariables.set(\"code\", jsonData.response.code);", "});" ], "type": "text/javascript", @@ -1299,7 +1364,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"linkedTransactionId\": \"{{linkTransactionId}}\",\n \"acceptedClaims\": {{accepted_claims}},\n \"signature\": \"{{detachedSignature}}\"\n }\n}", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"linkedTransactionId\": \"{{link_transaction_id}}\",\n \"acceptedClaims\": {{accepted_claims}},\n \"signature\": \"{{detachedSignature}}\"\n }\n}", "options": { "raw": { "language": "json" @@ -1874,7 +1939,7 @@ "response": [] }, { - "name": "Complete the verification process & Resume Halted Transaction", + "name": "Complete Signup Redirect", "request": { "method": "POST", "header": [ @@ -1970,7 +2035,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"transactionId\": \"{{transaction_id}}\",\n \"acceptedClaims\": {{accepted_claims}},\n \"permittedAuthorizeScopes\" : {{permitted_authorized_scopes}}\n }\n}", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"transactionId\": \"{{transaction_id}}\",\n \"acceptedClaims\": [\"name\",\"phone_number\"],\n \"permittedAuthorizeScopes\" : {{permitted_authorized_scopes}}\n }\n}", "options": { "raw": { "language": "json"