diff --git a/ror-demo-cluster/clean.sh b/ror-demo-cluster/clean.sh index 594205f..0266395 100755 --- a/ror-demo-cluster/clean.sh +++ b/ror-demo-cluster/clean.sh @@ -1,3 +1,3 @@ #!/bin/bash -e -docker compose rm --stop --force \ No newline at end of file +docker compose --profile ENT --profile PRO --profile FREE rm --stop --force \ No newline at end of file diff --git a/ror-demo-cluster/conf/es/readonlyrest.yml b/ror-demo-cluster/conf/es/readonlyrest.yml index f0c9811..1b21d4a 100644 --- a/ror-demo-cluster/conf/es/readonlyrest.yml +++ b/ror-demo-cluster/conf/es/readonlyrest.yml @@ -56,3 +56,14 @@ readonlyrest: groups: - id: "EndUsers" name: "End Users" + + - username: "*" + ror_kbn_authentication: + name: "kbn1" + groups: + - id: "EndUsers" + name: "End Users" + + ror_kbn: + - name: kbn1 + signature_key: "9yzBfnLaTYLfGPzyKW9es76RKYhUVgmuv6ZtehaScj5msGpBpa5FWpwk295uJYaaffTFnQC5tsknh2AguVDaTrqCLfM5zCTqdE4UGNL73h28Bg4dPrvTAFQyygQqv4xfgnevBED6VZYdfjXAQLc8J8ywaHQQSmprZqYCWGE6sM3vzNUEWWB3kmGrEKa4sGbXhmXZCvL6NDnEJhXPDJAzu9BMQxn8CzVLqrx6BxDgPYF8gZCxtyxMckXwCaYXrxAGbjkYH69F4wYhuAdHSWgRAQCuWwYmWCA6g39j4VPge5pv962XYvxwJpvn23Y5KvNZ5S5c6crdG4f4gTCXnU36x92fKMQzsQV9K4phcuNvMWkpqVB6xMA5aPzUeHcGytD93dG8D52P5BxsgaJJE6QqDrk3Y2vyLw9ZEbJhPRJxbuBKVCBtVx26Ldd46dq5eyyzmNEyQGLrjQ4qd978VtG8TNT5rkn4ETJQEju5HfCBbjm3urGLFVqxhGVawecT4YM9Rry4EqXWkRJGTFQWQRnweUFbKNbVTC9NxcXEp6K5rSPEy9trb5UYLYhhMJ9fWSBMuenGRjNSJxeurMRCaxPpNppBLFnp8qW5ezfHgCBpEjkSNNzP4uXMZFAXmdUfJ8XQdPTWuYfdHYc5TZWnzrdq9wcfFQRDpDB2zX5Myu96krDt9vA7wNKfYwkSczA6qUQV66jA8nV4Cs38cDAKVBXnxz22ddAVrPv8ajpu7hgBtULMURjvLt94Nc5FDKw79CTTQxffWEj9BJCDCpQnTufmT8xenywwVJvtj49yv2MP2mGECrVDRmcGUAYBKR8G6ZnFAYDVC9UhY46FGWDcyVX3HKwgtHeb45Ww7dsW8JdMnZYctaEU585GZmqTJp2LcAWRcQPH25JewnPX8pjzVpJNcy7avfA2bcU86bfASvQBDUCrhjgRmK2ECR6vzPwTsYKRgFrDqb62FeMdrKgJ9vKs435T5ACN7MNtdRXHQ4fj5pNpUMDW26Wd7tt9bkBTqEGf" diff --git a/ror-demo-cluster/conf/kbn/enterprise-ror-newplatform-kibana.yml b/ror-demo-cluster/conf/kbn/enterprise-ror-newplatform-kibana.yml new file mode 100644 index 0000000..9abf6b5 --- /dev/null +++ b/ror-demo-cluster/conf/kbn/enterprise-ror-newplatform-kibana.yml @@ -0,0 +1,52 @@ +server.name: kibana-ror +server.host: 0.0.0.0 + +elasticsearch.username: kibana +elasticsearch.password: kibana +elasticsearch.ssl.verificationMode: none + +# generated with: +# $ openssl req -x509 -batch -nodes -days 3650 -newkey rsa:2048 -keyout kibana.key -out kibana.crt +server.ssl.enabled: true +server.ssl.certificate: /usr/share/kibana/config/kibana.crt +server.ssl.key: /usr/share/kibana/config/kibana.key +server.ssl.redirectHttpFromPort: 80 + +readonlyrest_kbn.logLevel: info +readonlyrest_kbn.cookiePass: '12312313123213123213123abcdefghijklm' +readonlyrest_kbn: + auth: + signature_key: "9yzBfnLaTYLfGPzyKW9es76RKYhUVgmuv6ZtehaScj5msGpBpa5FWpwk295uJYaaffTFnQC5tsknh2AguVDaTrqCLfM5zCTqdE4UGNL73h28Bg4dPrvTAFQyygQqv4xfgnevBED6VZYdfjXAQLc8J8ywaHQQSmprZqYCWGE6sM3vzNUEWWB3kmGrEKa4sGbXhmXZCvL6NDnEJhXPDJAzu9BMQxn8CzVLqrx6BxDgPYF8gZCxtyxMckXwCaYXrxAGbjkYH69F4wYhuAdHSWgRAQCuWwYmWCA6g39j4VPge5pv962XYvxwJpvn23Y5KvNZ5S5c6crdG4f4gTCXnU36x92fKMQzsQV9K4phcuNvMWkpqVB6xMA5aPzUeHcGytD93dG8D52P5BxsgaJJE6QqDrk3Y2vyLw9ZEbJhPRJxbuBKVCBtVx26Ldd46dq5eyyzmNEyQGLrjQ4qd978VtG8TNT5rkn4ETJQEju5HfCBbjm3urGLFVqxhGVawecT4YM9Rry4EqXWkRJGTFQWQRnweUFbKNbVTC9NxcXEp6K5rSPEy9trb5UYLYhhMJ9fWSBMuenGRjNSJxeurMRCaxPpNppBLFnp8qW5ezfHgCBpEjkSNNzP4uXMZFAXmdUfJ8XQdPTWuYfdHYc5TZWnzrdq9wcfFQRDpDB2zX5Myu96krDt9vA7wNKfYwkSczA6qUQV66jA8nV4Cs38cDAKVBXnxz22ddAVrPv8ajpu7hgBtULMURjvLt94Nc5FDKw79CTTQxffWEj9BJCDCpQnTufmT8xenywwVJvtj49yv2MP2mGECrVDRmcGUAYBKR8G6ZnFAYDVC9UhY46FGWDcyVX3HKwgtHeb45Ww7dsW8JdMnZYctaEU585GZmqTJp2LcAWRcQPH25JewnPX8pjzVpJNcy7avfA2bcU86bfASvQBDUCrhjgRmK2ECR6vzPwTsYKRgFrDqb62FeMdrKgJ9vKs435T5ACN7MNtdRXHQ4fj5pNpUMDW26Wd7tt9bkBTqEGf" + + oidc_keycloak: + buttonName: "Keycloak OIDC" + type: "oidc" + protocol: "https" + issuer: 'http://kc.localhost:8080/realms/ror' + authorizationURL: 'http://kc.localhost:8080/realms/ror/protocol/openid-connect/auth' + tokenURL: 'http://kc.localhost:8080/realms/ror/protocol/openid-connect/token' + userInfoURL: 'http://kc.localhost:8080/realms/ror/protocol/openid-connect/userinfo' + jwksURL: 'http://kc.localhost:8080/realms/ror/protocol/openid-connect/certs' + clientID: 'kibana-ror' + clientSecret: 'kibanasecret123' + scope: 'openid profile email' + usernameParameter: 'preferred_username' + groupsParameter: 'groups' + kibanaExternalHost: 'localhost:15601' + logoutUrl: 'http://kc.localhost:8080/realms/ror/protocol/openid-connect/logout' + oidc_lemon_ldap: + buttonName: "LemonLDAP OpenID" + type: "oidc" + protocol: "https" + issuer: 'https://oidctest.wsweet.org/' + authorizationURL: 'https://oidctest.wsweet.org/oauth2/authorize' + tokenURL: 'https://oidctest.wsweet.org/oauth2/token' + userInfoURL: 'https://oidctest.wsweet.org/oauth2/userinfo' + clientID: 'private' + clientSecret: 'tardis' + scope: 'openid users roles' + usernameParameter: 'sub' + groupsParameter: 'roles' + kibanaExternalHost: 'localhost:15601' + logoutUrl: 'https://oidctest.wsweet.org/oauth2/logout' + jwksURL: 'https://oidctest.wsweet.org/oauth2/jwks' diff --git a/ror-demo-cluster/conf/kbn/ror-newplatform-kibana.yml b/ror-demo-cluster/conf/kbn/free-ror-newplatform-kibana.yml similarity index 100% rename from ror-demo-cluster/conf/kbn/ror-newplatform-kibana.yml rename to ror-demo-cluster/conf/kbn/free-ror-newplatform-kibana.yml diff --git a/ror-demo-cluster/conf/kbn/pro-ror-newplatform-kibana.yml b/ror-demo-cluster/conf/kbn/pro-ror-newplatform-kibana.yml new file mode 100644 index 0000000..3df3d8e --- /dev/null +++ b/ror-demo-cluster/conf/kbn/pro-ror-newplatform-kibana.yml @@ -0,0 +1,16 @@ +server.name: kibana-ror +server.host: 0.0.0.0 + +elasticsearch.username: kibana +elasticsearch.password: kibana +elasticsearch.ssl.verificationMode: none + +# generated with: +# $ openssl req -x509 -batch -nodes -days 3650 -newkey rsa:2048 -keyout kibana.key -out kibana.crt +server.ssl.enabled: true +server.ssl.certificate: /usr/share/kibana/config/kibana.crt +server.ssl.key: /usr/share/kibana/config/kibana.key +server.ssl.redirectHttpFromPort: 80 + +readonlyrest_kbn.logLevel: info +readonlyrest_kbn.cookiePass: '12312313123213123213123abcdefghijklm' diff --git a/ror-demo-cluster/conf/keycloak/ror-realm.json b/ror-demo-cluster/conf/keycloak/ror-realm.json new file mode 100644 index 0000000..3e806f2 --- /dev/null +++ b/ror-demo-cluster/conf/keycloak/ror-realm.json @@ -0,0 +1,58 @@ +{ + "realm": "ror", + "enabled": true, + "clients": [ + { + "clientId": "kibana-ror", + "enabled": true, + "protocol": "openid-connect", + "publicClient": false, + "secret": "kibanasecret123", + "redirectUris": ["*"], + "webOrigins": ["*"], + "attributes": { + "post.logout.redirect.uris": "https://localhost:15601/*" + }, + "protocolMappers": [ + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-group-membership-mapper", + "consentRequired": false, + "config": { + "full.path": "false", + "access.token.claim": "true", + "id.token.claim": "true", + "userinfo.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + } + ], + "groups": [ + {"name": "extEndUsers"} + ], + "users": [ + { + "username": "extUser1", + "enabled": true, + "emailVerified": true, + "credentials": [ { "type": "password", "value": "extUser1", "temporary": false } ], + "groups": ["extEndUsers"], + "realmRoles": ["offline_access", "uma_authorization"] + }, + { + "username": "extUser2", + "enabled": true, + "emailVerified": true, + "credentials": [ { "type": "password", "value": "extUser2", "temporary": false } ], + "groups": ["extEndUsers"], + "realmRoles": ["offline_access", "uma_authorization"] + } + ], + "defaultDefaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "defaultOptionalClientScopes": ["address", "phone", "offline_access"] +} + diff --git a/ror-demo-cluster/docker-compose.yml b/ror-demo-cluster/docker-compose.yml index 411072c..f907d81 100644 --- a/ror-demo-cluster/docker-compose.yml +++ b/ror-demo-cluster/docker-compose.yml @@ -1,4 +1,27 @@ services: + # Enterprise-only service + keycloak: + image: quay.io/keycloak/keycloak:20.0.5 + profiles: ["ENT"] + environment: + - KEYCLOAK_ADMIN=admin + - KEYCLOAK_ADMIN_PASSWORD=admin + - KEYCLOAK_FRONTEND_URL=http://kc.localhost:8080 + volumes: + - ./conf/keycloak/ror-realm.json:/opt/keycloak/data/import/ror-realm.json:ro + command: ["start-dev", "--import-realm", "--hostname=kc.localhost", "--http-enabled=true", "--http-port=8080"] + ports: + - "8080:8080" + healthcheck: + test: ["CMD-SHELL", "curl -fksS --connect-timeout 3 --max-time 5 --retry 5 --retry-connrefused http://127.0.0.1:8080/realms/ror/.well-known/openid-configuration >/dev/null || exit 1"] + interval: 10s + timeout: 10s + retries: 30 + start_period: 40s + networks: + es-ror-network: + aliases: + - kc.localhost es-ror: build: @@ -40,9 +63,13 @@ services: KBN_VERSION: ${KBN_VERSION:-KBN_VERSION_NOT_CONFIGURED} ROR_VERSION: ${ROR_KBN_VERSION:-ROR_KBN_VERSION_NOT_CONFIGURED} ROR_FILE: ${KBN_ROR_FILE:-KBN_ROR_FILE_NOT_CONFIGURED} + ROR_LICENSE_EDITION: ${ROR_LICENSE_EDITION:-ROR_LICENSE_EDITION_NOT_CONFIGURED} depends_on: es-ror: condition: service_healthy + keycloak: + condition: service_healthy + required: false ports: - "15601:5601" environment: diff --git a/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-api b/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-api index 5ebf4d2..4e66c4f 100644 --- a/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-api +++ b/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-api @@ -4,9 +4,12 @@ FROM docker.elastic.co/kibana/kibana:${KBN_VERSION} ARG KBN_VERSION=please_set_kbn_version_arg ARG ROR_VERSION=please_set_ror_version_arg +ARG ROR_LICENSE_EDITION=please_set_ror_license_edition_arg -COPY conf/kbn/ror-newplatform-kibana.yml /usr/share/kibana/config/ror-newplatform-kibana.yml COPY conf/kbn/ror-oldplatform-kibana.yml /usr/share/kibana/config/ror-oldplatform-kibana.yml +COPY conf/kbn/enterprise-ror-newplatform-kibana.yml /usr/share/kibana/config/enterprise-ror-newplatform-kibana.yml +COPY conf/kbn/pro-ror-newplatform-kibana.yml /usr/share/kibana/config/pro-ror-newplatform-kibana.yml +COPY conf/kbn/free-ror-newplatform-kibana.yml /usr/share/kibana/config/free-ror-newplatform-kibana.yml COPY conf/kbn/kibana.crt /usr/share/kibana/config/kibana.crt COPY conf/kbn/kibana.key /usr/share/kibana/config/kibana.key COPY images/kbn/install-ror-kbn-using-api.sh /tmp/install-ror.sh diff --git a/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-file b/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-file index b473b82..8ea7747 100644 --- a/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-file +++ b/ror-demo-cluster/images/kbn/Dockerfile-use-ror-binaries-from-file @@ -4,9 +4,12 @@ FROM docker.elastic.co/kibana/kibana:${KBN_VERSION} ARG KBN_VERSION=please_set_kbn_version_arg ARG ROR_FILE=please_set_ror_file_path +ARG ROR_LICENSE_EDITION=please_set_ror_license_edition_arg -COPY conf/kbn/ror-newplatform-kibana.yml /usr/share/kibana/config/ror-newplatform-kibana.yml COPY conf/kbn/ror-oldplatform-kibana.yml /usr/share/kibana/config/ror-oldplatform-kibana.yml +COPY conf/kbn/enterprise-ror-newplatform-kibana.yml /usr/share/kibana/config/enterprise-ror-newplatform-kibana.yml +COPY conf/kbn/pro-ror-newplatform-kibana.yml /usr/share/kibana/config/pro-ror-newplatform-kibana.yml +COPY conf/kbn/free-ror-newplatform-kibana.yml /usr/share/kibana/config/free-ror-newplatform-kibana.yml COPY conf/kbn/kibana.crt /usr/share/kibana/config/kibana.crt COPY conf/kbn/kibana.key /usr/share/kibana/config/kibana.key COPY images/kbn/install-ror-kbn-using-file.sh /tmp/install-ror.sh diff --git a/ror-demo-cluster/images/kbn/install-ror-kbn-using-api.sh b/ror-demo-cluster/images/kbn/install-ror-kbn-using-api.sh index bb86249..5fa2d92 100755 --- a/ror-demo-cluster/images/kbn/install-ror-kbn-using-api.sh +++ b/ror-demo-cluster/images/kbn/install-ror-kbn-using-api.sh @@ -43,12 +43,32 @@ elif greater_than_or_equal "$KBN_VERSION" "7.9.0" ; then /usr/share/kibana/node/bin/node plugins/readonlyrestkbn/ror-tools.js patch --I_UNDERSTAND_AND_ACCEPT_KBN_PATCHING=yes fi -if greater_than_or_equal "$KBN_VERSION" "7.9.0"; then - mv /usr/share/kibana/config/ror-newplatform-kibana.yml /usr/share/kibana/config/kibana.yml -else - mv /usr/share/kibana/config/ror-oldplatform-kibana.yml /usr/share/kibana/config/kibana.yml - rm -rf /usr/share/kibana/optimize # for some reason we have to remove it and let kibana optimize it on startup -fi + if greater_than_or_equal "$KBN_VERSION" "7.9.0"; then + case "${ROR_LICENSE_EDITION:-}" in + ENT) + mv /usr/share/kibana/config/enterprise-ror-newplatform-kibana.yml \ + /usr/share/kibana/config/kibana.yml + ;; + PRO) + mv /usr/share/kibana/config/pro-ror-newplatform-kibana.yml \ + /usr/share/kibana/config/kibana.yml + ;; + FREE) + mv /usr/share/kibana/config/free-ror-newplatform-kibana.yml \ + /usr/share/kibana/config/kibana.yml + ;; + "") + echo "ERROR: ROR_LICENSE_EDITION is not set" >&2 + exit 1 + ;; + *) + echo "ERROR: Unsupported ROR_LICENSE_EDITION='${ROR_LICENSE_EDITION}'" >&2 + exit 2 + ;; + esac + else + mv /usr/share/kibana/config/ror-oldplatform-kibana.yml /usr/share/kibana/config/kibana.yml + rm -rf /usr/share/kibana/optimize # for some reason we have to remove it and let kibana optimize it on startup + fi echo "DONE!" - diff --git a/ror-demo-cluster/images/kbn/install-ror-kbn-using-file.sh b/ror-demo-cluster/images/kbn/install-ror-kbn-using-file.sh index 7d6ed23..ab04efe 100755 --- a/ror-demo-cluster/images/kbn/install-ror-kbn-using-file.sh +++ b/ror-demo-cluster/images/kbn/install-ror-kbn-using-file.sh @@ -28,11 +28,32 @@ elif greater_than_or_equal "$KBN_VERSION" "7.9.0" ; then /usr/share/kibana/node/bin/node plugins/readonlyrestkbn/ror-tools.js patch --I_UNDERSTAND_AND_ACCEPT_KBN_PATCHING=yes fi -if greater_than_or_equal "$KBN_VERSION" "7.9.0"; then - mv /usr/share/kibana/config/ror-newplatform-kibana.yml /usr/share/kibana/config/kibana.yml -else - mv /usr/share/kibana/config/ror-oldplatform-kibana.yml /usr/share/kibana/config/kibana.yml - rm -rf /usr/share/kibana/optimize # for some reason we have to remove it and let kibana optimize it on startup -fi + if greater_than_or_equal "$KBN_VERSION" "7.9.0"; then + case "${ROR_LICENSE_EDITION:-}" in + ENT) + mv /usr/share/kibana/config/enterprise-ror-newplatform-kibana.yml \ + /usr/share/kibana/config/kibana.yml + ;; + PRO) + mv /usr/share/kibana/config/pro-ror-newplatform-kibana.yml \ + /usr/share/kibana/config/kibana.yml + ;; + FREE) + mv /usr/share/kibana/config/free-ror-newplatform-kibana.yml \ + /usr/share/kibana/config/kibana.yml + ;; + "") + echo "ERROR: ROR_LICENSE_EDITION is not set" >&2 + exit 1 + ;; + *) + echo "ERROR: Unsupported ROR_LICENSE_EDITION='${ROR_LICENSE_EDITION}'" >&2 + exit 2 + ;; + esac + else + mv /usr/share/kibana/config/ror-oldplatform-kibana.yml /usr/share/kibana/config/kibana.yml + rm -rf /usr/share/kibana/optimize # for some reason we have to remove it and let kibana optimize it on startup + fi echo "DONE!" \ No newline at end of file diff --git a/ror-demo-cluster/readonlyrest-1.67.0-pre6_es9.1.4.zip b/ror-demo-cluster/readonlyrest-1.67.0-pre6_es9.1.4.zip new file mode 100644 index 0000000..bd00890 Binary files /dev/null and b/ror-demo-cluster/readonlyrest-1.67.0-pre6_es9.1.4.zip differ diff --git a/ror-demo-cluster/run.sh b/ror-demo-cluster/run.sh index 3bf2da6..8554207 100755 --- a/ror-demo-cluster/run.sh +++ b/ror-demo-cluster/run.sh @@ -1,5 +1,7 @@ #!/bin/bash -e +cd "$(dirname "$0")" || exit 1 + if ! docker version &>/dev/null; then echo "No Docker found. Docker is required to run this Sandbox. See https://docs.docker.com/engine/install/" exit 1 @@ -28,9 +30,24 @@ echo -e " ./../utils/collect-info-about-ror-es-kbn.sh +# Call the extract helper using an explicit relative path (./../utils/...) +output="$(./../utils/extract_license_edition.sh "${ROR_ACTIVATION_KEY}" 2>&1)" rc=$? +if [ $rc -ne 0 ]; then + echo "ERROR: Failed to extract the ROR license edition (exit code: $rc)." >&2 + echo "$output" >&2 + exit $rc +elif [ -z "$output" ]; then + echo "ERROR: Could not determine the ROR license edition (the extract_license_edition helper returned no result)." >&2 + exit 2 +else + export ROR_LICENSE_EDITION="$output" + echo "Auto-detected ROR_LICENSE_EDITION=$ROR_LICENSE_EDITION" +fi + echo "Starting Elasticsearch and Kibana with installed ROR plugins ..." -docker compose up -d --build --wait --remove-orphans --force-recreate +docker compose --profile "${ROR_LICENSE_EDITION}" up -d --build --wait --remove-orphans --force-recreate + docker compose logs -f > ror-cluster.log 2>&1 & echo -e " @@ -41,4 +58,13 @@ echo -e " *********************************************************************** " -echo -e "You can access ROR KBN here: https://localhost:15601 (users: 'user1:test', 'user2:test' or admin user: 'admin:admin')" +case "${ROR_LICENSE_EDITION:-}" in + ENT) + echo -e "You can access ROR KBN here: https://localhost:15601 (login via 'Keycloak' button; users: 'extUser1:extUser1', 'extUser2:extUser2').\nKeycloak admin console: http://kc.localhost:8080/admin (admin:admin)" + ;; + PRO|FREE) + echo -e "You can access ROR KBN here: https://localhost:15601" + ;; + *) + ;; +esac diff --git a/utils/extract_license_edition.sh b/utils/extract_license_edition.sh new file mode 100755 index 0000000..ab6f638 --- /dev/null +++ b/utils/extract_license_edition.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env sh +# Extract 'license.edition' from a ROR_ACTIVATION_KEY +# Usage: extract_license_edition.sh +set -eu +[ "$#" -ge 1 ] || { printf '%s\n' "Missing argument: JWT required" >&2; exit 1; } +rorActivationLicense="$1" + +function extractLicense() { + local executionVariant="$1" + local tmpf rc output edition + local cmd args + + case "$executionVariant" in + local) + cmd=(python3) + args=() + export JWT="$rorActivationLicense" + ;; + docker) + cmd=(docker run --rm -i -e JWT="$rorActivationLicense" python:3.12-alpine python3) + args=() + ;; + *) + printf '%s\n' "ERROR: unsupported execution variant: $executionVariant" >&2 + return 1 + ;; + esac + + tmpf=$(mktemp 2>/dev/null || (printf '/tmp/extract_license_edition.XXXXXX' && mktemp -t extract_license_edition)) + trap ' [ -n "${tmpf:-}" ] && [ -f "${tmpf:-}" ] && rm -f -- "${tmpf}" 2>/dev/null || true' EXIT + + # Run the Python code using here-doc piped to the command stored in cmd array + # Using printf '%s' and process substitution for portability + # Note: in docker command, can pipe here-doc via stdin + printf '%s\n' " +import os,base64,json,sys +s=os.environ.get('JWT','') +parts=s.split('.') +if len(parts) < 2: + sys.exit(1) +p=parts[1] +rem=len(p) % 4 +if rem: + p += '=' * (4 - rem) +decoded=base64.urlsafe_b64decode(p.encode('utf-8')) +try: + j=json.loads(decoded.decode('utf-8')) + print(j.get('license',{}).get('edition','')) +except Exception as e: + sys.stderr.write(str(e) + \"\n\") + sys.exit(2) +" | "${cmd[@]}" - >"$tmpf" 2>/dev/stderr + + rc=$? + output=$(cat "$tmpf" 2>/dev/null || true) + if [ "$rc" -ne 0 ]; then + printf '%s\n' "$output" >&2 + return 2 + fi + + edition=$(printf '%s' "$output" | tr -d '\r' | sed -n '1p') + if [ -z "$edition" ]; then + return 2 + fi + + printf '%s' "$edition" + return 0 +} + +function executeExtractLicense() { +if command -v python3 >/dev/null 2>&1; then + extractLicense local +else + extractLicense docker +fi +} + +# if not defined or empty, return FREE +if [ -z "${rorActivationLicense:-}" ]; then + printf 'FREE\n' + exit 0 +fi + +# Enforce JWT format strictly; fail early if not a JWT +if ! echo "$rorActivationLicense" | grep -qE '^[^\.]+\.[^\.]+\.[^\.]+$'; then + echo "ERROR: ROR_ACTIVATION_KEY is not a JWT (expected three dot-separated parts). Aborting." >&2 + exit 1 +fi + +if ! extractedEdition="$(executeExtractLicense)"; then + printf '%s\n' "ERROR: failed to extract edition" >&2 + exit 2 +fi + +case "${extractedEdition:-}" in + kbn_ent) + printf 'ENT' + exit 0 + ;; + kbn_pro) + printf 'PRO' + exit 0 + ;; + kbn_free) + printf 'FREE' + exit 0 + ;; + '') + printf "ERROR: no edition extracted" >&2 + exit 2 + ;; + *) + printf "ERROR: unknown edition: %s" "$extractedEdition" >&2 + exit 3 + ;; +esac