diff --git a/.github/workflows/chart-lint-publish.yml b/.github/workflows/chart-lint-publish.yml index 878861a..a744ab5 100644 --- a/.github/workflows/chart-lint-publish.yml +++ b/.github/workflows/chart-lint-publish.yml @@ -40,7 +40,7 @@ on: - MOSIP* - release* paths: - - './helm/**' + - 'helm/**' jobs: chart-lint-publish: diff --git a/certmanager/Dockerfile b/certmanager/Dockerfile index 6a6fb3c..cbfef22 100644 --- a/certmanager/Dockerfile +++ b/certmanager/Dockerfile @@ -14,6 +14,12 @@ ARG container_user_group=mosip ARG container_user_uid=1001 ARG container_user_gid=1001 +# Install kubectl binary +RUN apt-get -y update \ + && apt-get install -y curl \ + && curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \ + && chmod +x ./kubectl && mv ./kubectl /usr/local/bin/kubectl + # Create user group RUN groupadd -r ${container_user_group} && useradd -u ${container_user_uid} -r -g ${container_user_group} -s /bin/bash -m -d /home/${container_user} ${container_user} RUN chown -R ${container_user}:${container_user} /home/${container_user} @@ -30,6 +36,7 @@ ENV db-server= ENV db-port= ENV db-su-user= ENV postgres-password= +ENV ns_esignet=esignet COPY partner.properties . COPY requirements.txt . diff --git a/certmanager/bootstrap.properties b/certmanager/bootstrap.properties index d88bfea..8391d3d 100644 --- a/certmanager/bootstrap.properties +++ b/certmanager/bootstrap.properties @@ -1,9 +1,10 @@ [Database] -db-host = postgres.qa-platform1.mosip.net +db-host = postgres.sandbox.mosip.net db-port = 5432 db-su-user = postgres -postgres-password = z63RJy8Ldt +postgres-password = HEdMa9Z****Tu** [API] -mosip-api-internal-host=api-internal.qa-platform1.mosip.net -mosip_pms_client_secret=ZapZsW5X8AtrkSai -pre-expiry-days=400 \ No newline at end of file +mosip-api-internal-host=api-internal.sandbox.mosip.net +mosip_deployment_client_secret=w9xp2****Q4N1709B +pre-expiry-days=40 +mosip-api-external-host=api.sandbox.mosip.net diff --git a/certmanager/checkupdate.py b/certmanager/checkupdate.py index 498a372..ef3275d 100644 --- a/certmanager/checkupdate.py +++ b/certmanager/checkupdate.py @@ -2,9 +2,10 @@ import json import psycopg2 import requests +import subprocess from urllib.request import Request, urlopen from urllib.error import HTTPError -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from configparser import ConfigParser # Function to read value from bootstrap.properties @@ -69,6 +70,10 @@ def retrieve_certificate_data(partner_id, db_host, db_port, db_user, db_password print(f"Error retrieving certificate data for Partner ID '{partner_id}': {str(e)}") return None +# Function to get current UTC time in ISO 8601 format with milliseconds +def get_utc_timestamp(): + return datetime.utcnow().replace(tzinfo=timezone.utc).isoformat(timespec='milliseconds').replace('+00:00', 'Z') + # Function to authenticate and retrieve the token def authenticate_and_get_token(base_url, client_secret): auth_url = f"https://{base_url}/v1/authmanager/authenticate/clientidsecretkey" @@ -78,75 +83,139 @@ def authenticate_and_get_token(base_url, client_secret): "metadata": {}, "request": { "appId": "ida", - "clientId": "mosip-pms-client", + "clientId": "mosip-deployment-client", "secretKey": client_secret }, - "requesttime": "", + "requesttime": get_utc_timestamp(), "version": "string" } response = requests.post(auth_url, headers=headers, json=auth_data) if response.status_code == 200: return response.headers.get("authorization") - print("Authentication failed.", response.text) + print("Authentication failed.") return None # Function to upload certificate +# Returns signedCertificateData if successful def upload_certificate_with_token(token, cert_data, partner_id, base_url): upload_url = f"https://{base_url}/v1/partnermanager/partners/certificate/upload" headers = {"Content-Type": "application/json", "Cookie": f"Authorization={token}"} + partner_domain = "MISP" if partner_id == "mpartner-default-esignet" else "AUTH" upload_data = { "id": "string", "metadata": {}, "request": { "certificateData": cert_data.replace("\\n", "\n"), - "partnerDomain": "AUTH", + "partnerDomain": partner_domain, "partnerId": partner_id }, - "requesttime": "", + "requesttime": get_utc_timestamp(), "version": "string" } response = requests.post(upload_url, headers=headers, json=upload_data) if "certificateId" not in response.text: - print("Certificate renewal failed.", response.text) + print(f"[{partner_id}] Certificate renewal failed.") + return None + return json.loads(response.text)['response']['signedCertificateData'] + +# Function to post-upload to dependent systems +def post_upload_to_system(endpoint, token, app_id, cert_data, reference_id, bearer=False): + if bearer: + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {token}" + } else: - print("Certificate renewed successfully.") + headers = { + "Content-Type": "application/json", + "Cookie": f"Authorization={token}" + } + + payload = { + "request": { + "certificateData": cert_data, + "applicationId": app_id, + "referenceId": reference_id + }, + "requestTime": get_utc_timestamp() + } -# Fetching environment variables or values from bootstrap.properties + response = requests.post(endpoint, headers=headers, json=payload) + + if response.status_code == 200 and 'Upload Success' in response.text: + print(f"[{partner_id}] certificate uploaded back to [{app_id}] successfully.") + return True + else: + print(f"[{partner_id}] certificate upload back to [{app_id}] failed.") + return False + +# Load configuration postgres_host = os.environ.get('db-host') or read_bootstrap_properties('db-host') postgres_port = os.environ.get('db-port') or read_bootstrap_properties('db-port') postgres_user = os.environ.get('db-su-user') or read_bootstrap_properties('db-su-user') postgres_password = os.environ.get('postgres-password') or read_bootstrap_properties('postgres-password') base_url = os.environ.get('mosip-api-internal-host') or read_bootstrap_properties('mosip-api-internal-host') -client_secret = os.environ.get('mosip_pms_client_secret') or read_bootstrap_properties('mosip_pms_client_secret') -pre_expiry_days = os.environ.get('pre-expiry-days') or read_bootstrap_properties('pre-expiry-days') +base_esignet_url = os.environ.get('mosip-api-host') or read_bootstrap_properties('mosip-api-external-host') +client_secret = os.environ.get('mosip_deployment_client_secret') or read_bootstrap_properties('mosip_deployment_client_secret') +pre_expiry_days = int(os.environ.get('pre-expiry-days') or read_bootstrap_properties('pre-expiry-days')) +ns_esignet = os.environ.get('ns_esignet') TOKEN = authenticate_and_get_token(base_url, client_secret) if TOKEN: partner_ids = os.environ.get('PARTNER_IDS_ENV') if partner_ids: partner_ids = partner_ids.split(',') - print ("Getting list of partners from env variable") + print("Getting list of partners from env variable") else: with open('partner.properties', 'r') as file: for line in file: if line.startswith('PARTNER_ID'): partner_ids = line.strip().split('=')[1].split(',') - print ("Getting list of partners from local variable") + print("Getting list of partners from local variable") for PARTNER_ID in partner_ids: - print(f"\nProcessing partner ID: {PARTNER_ID.strip()}") + PARTNER_ID = PARTNER_ID.strip() + print(f"\nProcessing partner ID: {PARTNER_ID}") try: - req = Request(f"https://{base_url}/v1/partnermanager/partners/{PARTNER_ID.strip()}/certificate", - headers={"Content-Type": "application/json", "Cookie": f"Authorization={TOKEN}"}, - method="GET") + req = Request( + f"https://{base_url}/v1/partnermanager/partners/{PARTNER_ID}/certificate", + headers={"Content-Type": "application/json", "Cookie": f"Authorization={TOKEN}"}, + method="GET" + ) response = urlopen(req) - response_data = json.loads(response.read().decode('utf-8')) - CERTIFICATE_DATA = response_data.get('response', {}).get('certificateData') + raw_data = response.read().decode('utf-8') + try: + response_data = json.loads(raw_data) + except json.JSONDecodeError: + print(f"[{PARTNER_ID}] Invalid JSON response.") + continue + + if not response_data or not isinstance(response_data, dict): + print(f"[{PARTNER_ID}] Invalid or empty response.") + continue + + cert_info = response_data.get('response') + CERTIFICATE_DATA = cert_info.get('certificateData') if cert_info else None + + if not CERTIFICATE_DATA: + print(f"[{PARTNER_ID}] Certificate data not found.") + continue + expiration_date = os.popen(f"echo '{CERTIFICATE_DATA}' | openssl x509 -noout -enddate").read().split('=')[1].strip() - if is_certificate_expired(expiration_date) or (datetime.strptime(expiration_date, "%b %d %H:%M:%S %Y %Z") - datetime.utcnow()) <= timedelta(days=int(pre_expiry_days)): - write_to_expired_txt(PARTNER_ID.strip()) + expiry_dt = datetime.strptime(expiration_date, "%b %d %H:%M:%S %Y %Z") + days_left = (expiry_dt - datetime.utcnow()).days + + if is_certificate_expired(expiration_date) or days_left <= int(pre_expiry_days): + print(f"[{PARTNER_ID}] Certificate is expired or will expire in {days_left} day(s). Renewing...") + write_to_expired_txt(PARTNER_ID) + else: + print(f"[{PARTNER_ID}] Certificate is valid. {days_left} day(s) left.") + except HTTPError as e: - print(f"Error fetching certificate for {PARTNER_ID}: {e}") + print(f"[{PARTNER_ID}] HTTP error while fetching certificate: {e}") + continue + except Exception as e: + print(f"[{PARTNER_ID}] Unexpected error: {e}") continue if os.path.exists("expired.txt"): @@ -157,8 +226,46 @@ def upload_certificate_with_token(token, cert_data, partner_id, base_url): for partner_id in expired_partner_ids: cert_data = retrieve_certificate_data(partner_id, postgres_host, postgres_port, postgres_user, postgres_password) - if cert_data: - upload_certificate_with_token(TOKEN, cert_data, partner_id, base_url) - print("Certificate check and renewal process completed.") + if not cert_data: + continue + + try: + pem = cert_data.replace("\\n", "\n") + end_date_str = os.popen(f"echo '{pem}' | openssl x509 -noout -enddate").read().split('=')[1].strip() + end_date = datetime.strptime(end_date_str, "%b %d %H:%M:%S %Y %Z") + if (end_date - datetime.utcnow()).days < 365: + print(f"DB cert for {partner_id} has less than 365 days left. Skipping.") + continue + except Exception as e: + print(f"Error validating DB cert for {partner_id}: {e}") + continue + + signed_cert = upload_certificate_with_token(TOKEN, cert_data, partner_id, base_url) + if not signed_cert: + continue + + # Post-upload to relevant systems + success = True + if partner_id == 'mpartner-default-esignet': + success = post_upload_to_system(f"https://{base_esignet_url}/v1/esignet/system-info/uploadCertificate", TOKEN, "OIDC_PARTNER", signed_cert, "", bearer=True) + if success: + if ns_esignet: + subprocess.run(["kubectl", "rollout", "restart", "deployment", "esignet", "-n", ns_esignet], check=True) + else: + print("Environment variable 'ns_esignet' not set. Cannot restart esignet deployment.") + else: + print(f"[{partner_id}] Upload to Esignet failed. Skipping restart.") + elif partner_id == 'mpartner-default-digitalcard': + success = post_upload_to_system(f"https://{base_url}/v1/keymanager/uploadCertificate", TOKEN, "DIGITAL_CARD", signed_cert, partner_id) + elif partner_id == 'mpartner-default-auth': + success = post_upload_to_system(f"https://{base_url}/idauthentication/v1/internal/uploadCertificate", TOKEN, "IDA", signed_cert, partner_id) + elif partner_id == 'mpartner-default-resident': + success = post_upload_to_system(f"https://{base_url}/v1/keymanager/uploadCertificate", TOKEN, "RESIDENT", signed_cert, partner_id) + + if success or partner_id not in [ + 'mpartner-default-esignet', 'mpartner-default-digitalcard', 'mpartner-default-auth', 'mpartner-default-resident']: + print(f"[{partner_id}] certificate renewed successfully and will be valid for 1 more year.") + + print("MOSIP Certificate Manager Run Completed.") else: print("Failed to get auth-token") diff --git a/certmanager/partner.properties b/certmanager/partner.properties index 6aa6403..cc3cba8 100644 --- a/certmanager/partner.properties +++ b/certmanager/partner.properties @@ -1 +1 @@ -PARTNER_ID=mpartner-default-abis \ No newline at end of file +PARTNER_ID=mpartner-default-resident,mpartner-default-abis \ No newline at end of file diff --git a/deploy/mosipcertmanager/README.md b/deploy/mosipcertmanager/README.md index d35d89e..f8c6aec 100644 --- a/deploy/mosipcertmanager/README.md +++ b/deploy/mosipcertmanager/README.md @@ -1,11 +1,12 @@ # mosipcertmanager Helm chart for installing mosipcertmanager -## Introduction -It's a cronjob that checks DBs for partner certificate expiry dates and renews the certificates if expired. +## Introduction +It's a cronjob that checks partner certificate expiry dates and renews the certificates if expired. ## Install -RUN Install script +* Review the `values.yaml` file and ensure that the database parameter values and partner IDs are set according to your environment +* RUN Install script ``` ./install.sh ``` diff --git a/deploy/mosipcertmanager/copy_cm.sh b/deploy/mosipcertmanager/copy_cm.sh index 0279f8f..7cdda1f 100755 --- a/deploy/mosipcertmanager/copy_cm.sh +++ b/deploy/mosipcertmanager/copy_cm.sh @@ -3,7 +3,7 @@ # DST_NS: Destination (current) namespace function copying_cm() { - UTIL_URL=https:https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh + UTIL_URL=https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh COPY_UTIL=./copy_cm_func.sh wget -q $UTIL_URL -O copy_cm_func.sh && chmod +x copy_cm_func.sh diff --git a/deploy/mosipcertmanager/copy_secrets.sh b/deploy/mosipcertmanager/copy_secrets.sh index ae8595f..4c1fbfe 100755 --- a/deploy/mosipcertmanager/copy_secrets.sh +++ b/deploy/mosipcertmanager/copy_secrets.sh @@ -3,13 +3,12 @@ # DST_NS: Destination namespace function copying_secrets() { - UTIL_URL=https:https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh + UTIL_URL=https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh COPY_UTIL=./copy_cm_func.sh wget -q $UTIL_URL -O copy_cm_func.sh && chmod +x copy_cm_func.sh DST_NS=mosipcertmanager - $COPY_UTIL secret s3 s3 $DST_NS $COPY_UTIL secret postgres-postgresql postgres $DST_NS $COPY_UTIL secret keycloak-client-secrets keycloak $DST_NS return 0 diff --git a/deploy/mosipcertmanager/install.sh b/deploy/mosipcertmanager/install.sh index 3211163..af72088 100755 --- a/deploy/mosipcertmanager/install.sh +++ b/deploy/mosipcertmanager/install.sh @@ -27,7 +27,7 @@ function installing_mosipcertmanager() { ./copy_secrets.sh echo Installing mosipcertmanager - helm -n $NS install mosipcertmanager mosip/mosipcertmanager --wait --version $CHART_VERSION + helm -n $NS install mosipcertmanager mosip/mosipcertmanager -f values.yaml --wait --version $CHART_VERSION return 0 } diff --git a/deploy/mosipcertmanager/values.yaml b/deploy/mosipcertmanager/values.yaml new file mode 100644 index 0000000..2c0b6f2 --- /dev/null +++ b/deploy/mosipcertmanager/values.yaml @@ -0,0 +1,14 @@ + +crontime: "0 3 * * *" ## run cronjob every day at 3 AM (time hr: 0-23 ) + +mosipcertmanager: + configmaps: + db: + db-port: '5432' + db-su-user: 'postgres' + db-host: 'postgres.sandbox.mosip.net' + partner-ids-env: + PARTNER_IDS_ENV: mpartner-default-print,mpartner-default-abis,mpartner-default-mobile,mpartner-default-digitalcard,mpartner-default-auth,mpartner-default-resident,mpartner-default-demo-oidc,mpartner-default-resident-oidc,mpartner-default-mimotooidc,mpartner-default-esignet,mpartner-default-mimotokeybinding + mosipcertmanager: + pre-expiry-days: '40' + diff --git a/helm/mosipcertmanager/templates/clusterrole.yaml b/helm/mosipcertmanager/templates/clusterrole.yaml new file mode 100644 index 0000000..9a555c7 --- /dev/null +++ b/helm/mosipcertmanager/templates/clusterrole.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Name }}-deployment-clusterrole +rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "patch", "list", "watch"] \ No newline at end of file diff --git a/helm/mosipcertmanager/templates/clusterrolebinding.yaml b/helm/mosipcertmanager/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..9cc5faa --- /dev/null +++ b/helm/mosipcertmanager/templates/clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Name }}-deployment-clusterrolebinding +subjects: + - kind: ServiceAccount + name: {{ template "mosipcertmanager.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ .Release.Name }}-deployment-clusterrole + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/helm/mosipcertmanager/templates/cronjob.yaml b/helm/mosipcertmanager/templates/cronjob.yaml index de9add5..4603ae6 100644 --- a/helm/mosipcertmanager/templates/cronjob.yaml +++ b/helm/mosipcertmanager/templates/cronjob.yaml @@ -30,6 +30,7 @@ spec: spec: # account configured above restartPolicy: Never + serviceAccountName: {{ template "mosipcertmanager.serviceAccountName" $ }} containers: - name: {{ template "mosipcertmanager.serviceAccountName" $ }} image: {{ template "mosipcertmanager.image" $ }} @@ -47,11 +48,6 @@ spec: args: {{- include "common.tpvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} {{- end }} env: - - name: mosip_pms_client_secret - valueFrom: - secretKeyRef: - key: mosip_pms_client_secret - name: keycloak-client-secrets - name: container_user value: {{ .Values.containerSecurityContext.runAsUser }} {{- if .Values.extraEnvVars }} @@ -70,6 +66,3 @@ spec: name: {{ . }} {{- end }} {{- end }} - ports: - - name: spring-service - containerPort: {{ .Values.springServicePort }} \ No newline at end of file diff --git a/helm/mosipcertmanager/values.yaml b/helm/mosipcertmanager/values.yaml index 9fd39a5..3dec939 100644 --- a/helm/mosipcertmanager/values.yaml +++ b/helm/mosipcertmanager/values.yaml @@ -67,7 +67,7 @@ image: # - myRegistryKeySecretName ## Port on which this particular spring service module is running. -springServicePort: 8083 +# 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 @@ -88,17 +88,17 @@ hostAliases: [] ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ ## -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: 1000m - memory: 3500Mi - requests: - cpu: 1000m - memory: 3500Mi + # limits: + ## cpu: 1000m + ## memory: 3500Mi + # requests: + ## cpu: 1000m + # memory: 3500Mi additionalResources: ## Specify any JAVA_OPTS string here. These typically will be specified in conjunction with above resources @@ -216,10 +216,11 @@ extraEnvVarsCM: - global - db - mosipcertmanager + - partner-ids-env + - esignet-namespace ## Secret with extra environment variables ## extraEnvVarsSecret: - - s3 - postgres-postgresql - keycloak-client-secrets @@ -241,38 +242,6 @@ extraVolumeMounts: [] ## - 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: @@ -286,36 +255,12 @@ initContainers: ## sidecars: {} -persistence: - enabled: true - ## 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: 100m - existingClaim: - nfs: - path: '/srv/nfs/mosip/dsl-scenarios/' - server: '' - # Dir where config and keys are written inside container - mountDir: '/home/mosip/mountvolume/scenarios' ## Init containers parameters: ## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. ## volumePermissions: - enabled: true + enabled: false image: registry: docker.io repository: bitnami/bitnami-shell @@ -425,8 +370,12 @@ mosipcertmanager: db: db-port: '5432' db-su-user: 'postgres' - db-host: 'mosip-api-internal-host' + db-host: 'postgres.sandbox.mosip.net' mosipcertmanager: - pre-expiry-days: '7' + pre-expiry-days: '40' + partner-ids-env: + PARTNER_IDS_ENV: mpartner-default-print,mpartner-default-abis,mpartner-default-mobile,mpartner-default-digitalcard,mpartner-default-auth,mpartner-default-resident,mpartner-default-demo-oidc,mpartner-default-resident-oidc,mpartner-default-mimotooidc,mpartner-default-esignet,mpartner-default-mimotokeybinding + esignet-namespace: + ns_esignet: esignet enable_insecure: false