Prepare environment
Legend
TENANT_ID: Tenant name; must contain only alphanumeric symbols, for example,WiseRealmTENANT_ID_LC: Tenant name in lowercaseTENANT_ID_UC: Tenant name in uppercaseINSTALL_DIR: directory where all components are installed, for example,/opt/workfusionIMPORT_DIR: directory scanned for realm files, for example,INSTALL_DIR/keycloak/realmCONNECTOR_DIR: home directory of the Input REST Connector application on the Agent server, for example,INSTALL_DIR/input-connector-restMARATHON_DIR: home directory of the Marathon application on the Master server, for example,INSTALL_DIR/marathonNGINX_DIR: home directory of the Nginx application on the Agent server, for example,INSTALL_DIR/nginxHAPROXY_DIR: home directory of the HAProxy application on the Master server, for example,INSTALL_DIR/haproxyCONNECTOR_PORT: port used by Input REST Connector to retrieve requestsCT_LB_HOST: lb hostname of Control Tower or Input REST Connector, for example,multi-realm-dw-rest-api-wfaw-10081-workfusion-lb1.wflab.ioAGENT_HOST: hostname of the Agent server, for example,multi-realm-dw-rest-api-wfaw-10081-agent1.wflab.io
Perform manual steps
To prepare your environment for the multi-realm usage, perform the following setup.
Prepare Keycloak
To set up Keycloak, do as follows:
Configure a client secret for the Control Tower application:
keycloak.realm.TENANT_ID.ct.sso.oidc.client.secret, for example,keycloak.realm.WiseRealm.ct.sso.oidc.client.secretkeycloak.realm.TENANT_ID.ws.sso.oidc.client.secretnote
For WorkSpace, use the
loader.shscript to upload the property for theWFAGENTuser, as the property name is not in the whitelist for WorkSpace.
Prepare a realm:
- Replace ID and name in the realm JSON file to
TENANT_NAME. - Replace all WorkfusionRealm UUIDs with new ones. Mind that Keycloak doesn't perform auto-replacement, and you should do it manually.
- Replace client secrets of WorkSpace and Control Tower clients to new ones. For example, for a Control Tower client, replace
${vault.ct.sso.oidc.client.secret}to${vault.keycloak.realm.TENANT_ID.ct.sso.oidc.client.secret}. - Put the realm into
IMPORT_DIR.
- Replace ID and name in the realm JSON file to
Prepare the supervisor startup script to support import from the realm:
- In
/opt/workfusion/supervisord/apps/keycloak.ini, add the following lines for thestandalone.shstart parameters:
-Dkeycloak.migration.action=import \ -Dkeycloak.migration.provider=dir \ -Dkeycloak.migration.dir=IMPORT_DIR \ -Dkeycloak.migration.strategy=IGNORE_EXISTING- To update, run the following command:
wfmanager update- Restart Keycloak:
wfmanager restart keycloak- In
Add the realm to the
keycloak.realms.additionalsecret property, for example,keycloak.realms.additional=IMPORTED_EARLIER_FOR_EXAMPLE,TENANT_ID.
Prepare Marathon
To configure the Marathon application, do as follows:
Make a copy of
run-input-connector-rest.shon each Agent server to a new file, for example,CONNECTOR_DIR/run-input-connector-rest-TENANT_ID.sh.In the script, specify the realm and server port and customize output file locations for logs and other data, for example:
#!/bin/bash REALM_NAME=TENANT_ID APP_PORT=CONNECTOR_PORT set -e echo -e "\n\n$(date) input-connector-rest STARTUP INITIATED" >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log source /opt/workfusion/environment.sh check-vault.sh >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log check-keycloak.sh >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log echo "$(date) Trying to read variables from Vault..." >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log echo "$(date) Trying to get VAULT_TOKEN..." >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log export VAULT_TOKEN=$(get-vault-token.sh) echo "$(date) Trying to read rabbitmq_bep_pass from Vault..." >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log export SPRING_RABBITMQ_PASSWORD=$(get-vault-secret.sh workfusion_ansible_secrets/rabbitmq_bep_pass) unset VAULT_TOKEN echo "$(date) Dependencies check passed. Starting..." >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log echo "$(date) cd /opt/workfusion/input-connector-rest" >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log echo "$(date) export SPRING_RABBITMQ_PASSWORD=..." >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log echo "$(date) exec java -jar input-connector-rest.jar" >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.log cd /opt/workfusion/input-connector-rest exec java -jar input-connector-rest.jar --server.port=$APP_PORT --icr.sso.oidc.realm-name=$REALM_NAME >> /opt/workfusion/logs/input-connector-rest-$REALM_NAME.logAdd the Marathon application on the Master server.
Copy the default
input-connector-rest.jsonfile toinput-connector-rest-TENANT_ID_LC.json, for example,MARATHON_DIR/apps/input-connector-rest-TENANT_ID_LC.json.Fix the ID with the realm prefix (should be in lowercase), for example,
/ia-cloud/input-connector-rest-TENANT_ID_LC.Fix cmd to a customized script, for example:
exec CONNECTOR_DIR/run-input-connector-rest-TENANT_ID.shSpecify a health check endpoint, for example:
curl -s -w '%{http_code}' -o /dev/null http://127.0.0.1:CONNECTOR_PORT/actuator/health | grep 200Deploy to Marathon. In the manual mode, copy the JSON file and put it into the Marathon UI > Create application. For example, a JSON file for the UI can look as follows:
{ "id": "/ia-cloud/input-connector-rest-wiserealm", "cmd": "exec /opt/workfusion/input-connector-rest/run-input-connector-rest-wiserealm.sh", "cpus": 0, "mem": 512, "disk": 0, "instances": 1, "constraints": [ [ "bep-worker", "CLUSTER", "true" ], [ "hostname", "UNIQUE" ] ], "acceptedResourceRoles": [ "*" ], "healthChecks": [ { "command": { "value": "curl -s -w '%{http_code}' -o /dev/null http://127.0.0.1:8082/actuator/health | grep 200" }, "gracePeriodSeconds": 300, "intervalSeconds": 60, "maxConsecutiveFailures": 0, "protocol": "COMMAND", "ipProtocol": "IPv4", "timeoutSeconds": 40 } ], "portDefinitions": [], "taskKillGracePeriodSeconds": 20, "killSelection": "YOUNGEST_FIRST", "unreachableStrategy": { "inactiveAfterSeconds": 0, "expunceAfterSeconds": 0 }, "upgradeStrategy": { "maximumOverCapacity": 0, "minimumHealthCapacity": 0 } }
Prepare Nginx
To prepare Nginx, perform the following steps:
For each Agent server, add the following locations to
NGINX_DIR/sites/input-connector-rest.conf:location = /TENANT_ID/input-connector-rest { rewrite ^ /TENANT_ID/input-connector-rest/; } location /TENANT_ID/input-connector-rest/ { proxy_pass http://127.0.0.1:<connector_port>/; proxy_redirect off; proxy_send_timeout 600; proxy_read_timeout 600; proxy_connect_timeout 600; send_timeout 600; # Increase client_max_body_size for large reguests to automl-model-management-service client_max_body_size 1024m; }Restart Nginx:
wfmanager restart nginx
Prepare HAProxy
To set up HAProxy, add the following sections to HAPROXY_DIR/conf/haproxy.conf on the Master server:
Add ACL:
acl to_input_connector_rest_TENANT_ID_LC path_beg -i /TENANT_ID/input-connector-restExclude the endpoint from the Control Tower backend to ACL mapping by
! to_input_connector_rest_TENANT_ID_LC.For example:
if to_ct ! to_ags ! to_ams ! to_abs ! to_amms ! to_wms ! to_tds ! to_sqc ! to_dataset_management ! to_dataset_management_internal ! to_labeling_service ! to_zo onavigator ! to_manual_task_renderer ! to_task_designer ! to_input_connector_rest ! to_input_connector_rest_TENANT_ID_LCAdd a separate backend to ACL mapping:
use_backend INPUT_CONNECTOR_REST_TENANT_ID_UC if to_input_connector_rest_TENANT_ID_LC to_ctAdd the backend:
# INPUT CONNECTOR REST TENANT_ID_UC backend INPUT_CONNECTOR_REST_TENANT_ID_UC mode http option httpchk GET /TENANT_ID/input-connector-rest/actuator/health HTTP/1.1\r\nHost:\ CT_LB_HOST http-check expect status 200 # describe this mapping for each Agent server server AGENT_HOST AGENT_HOST:8443 ssl verify none on-marked-down shutdown-sessions check check-ssl port 8443 inter 20000 rise 1 fall 1Restart HAProxy:
wfmanager restart haproxy
Modify Input Connector configuration
In the manual steps above, for Input REST Connector, you create separate scripts and pass parameters in the command line of Java startup.
You can also use spring profiles to determine parameters for each application, for example:
Create the base
application.ymlfile:spring: codec: max-in-memory-size: 2MB rabbitmq: addresses: 'multi-realm-dw-rest-api-wfaw-10081-master1.wflab.io:5672' virtual-host: bep username: bep server: address: 127.0.0.1 # port should be specified by profile properties file # port: 8081 connector: response-timeout: 60m record-queue: ct-record-queue icr: sso: oidc: enabled: true auth-url: 'https://multi-realm-dw-rest-api-wfaw-10081-auth-lb1.wflab.io/auth' # realm should be specified by profile properties file # realm-name: WorkfusionRealm client-id: wf-control-tower online-cache-size: 1000 online-cache-ttl-minutes: 3 public-key-update-millis: 120000 update-not-before-millis: 120000For each new Tenant, create a separate
application-TENANT_ID.ymlfile:server: port: CONNECTOR_PORT icr: sso: oidc: realm-name: TENANT_IDRun
run-input-connector-rest.sh. Mind that only one script is used for all Connector instances.#!/bin/bash TENANT_PROFILE=$1 set -e echo -e "\n\n$(date) input-connector-rest STARTUP INITIATED" >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log source /opt/workfusion/environment.sh check-vault.sh >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log check-keycloak.sh >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log echo "$(date) Trying to read variables from Vault..." >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log echo "$(date) Trying to get VAULT_TOKEN..." >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log export VAULT_TOKEN=$(get-vault-token.sh) echo "$(date) Trying to read rabbitmq_bep_pass from Vault..." >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log export SPRING_RABBITMQ_PASSWORD=$(get-vault-secret.sh workfusion_ansible_secrets/rabbitmq_bep_pass) unset VAULT_TOKEN echo "$(date) Dependencies check passed. Starting..." >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log echo "$(date) cd /opt/workfusion/input-connector-rest" >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log echo "$(date) export SPRING_RABBITMQ_PASSWORD=..." >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log echo "$(date) exec java -jar input-connector-rest.jar" >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.log cd /opt/workfusion/input-connector-rest exec java -jar input-connector-rest.jar --spring.profiles.active=$TENANT_PROFILE >> /opt/workfusion/logs/input-connector-rest-$TENANT_PROFILE.logRun the following command for the Marathon application:
exec /opt/workfusion/input-connector-rest/run-input-connector-rest.sh TENANT_ID
With such modifications, perform the following steps for each new Tenant:
- Create a new
application-TENANT_ID.ymlfile. - Pass
TENANT_IDin cmd of the Marathon application.
tip
For Tenant configuration, see Add Tenant.