Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions ror-demo-cluster/conf/es/readonlyrest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,26 @@ readonlyrest:

- name: "End users"
groups: ["EndUsers"]
indices: ["frontend_logs", "kibana_sample_data_*"]
indices: ["frontend_logs*", "kibana_sample_data_*"]
kibana:
index: .kibana_end_@{user}
access: rw
hide_apps: ["Security", "Observability"]
Comment on lines +21 to 25
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

End users still miss the heartbeat-* index pattern used by Data Streams requests.

Line 21 excludes heartbeat-*, but your repro shows EndUsers querying that pattern and hitting IDX_NOT_FOUND, which then surfaces as Kibana 500 in Index Management. If End users should use Data Streams, this needs to be allowed (or the feature hidden for this role).

Suggested config adjustment
-      indices: ["frontend_logs*", "kibana_sample_data_*"]
+      indices: ["frontend_logs*", "heartbeat-*", "kibana_sample_data_*"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
indices: ["frontend_logs*", "kibana_sample_data_*"]
kibana:
index: .kibana_end_@{user}
access: rw
hide_apps: ["Security", "Observability"]
indices: ["frontend_logs*", "heartbeat-*", "kibana_sample_data_*"]
kibana:
index: .kibana_end_@{user}
access: rw
hide_apps: ["Security", "Observability"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ror-demo-cluster/conf/es/readonlyrest.yml` around lines 21 - 25, The role's
indices list currently allows only "frontend_logs*" and "kibana_sample_data_*",
which causes queries against the Data Streams pattern "heartbeat-*" to hit
IDX_NOT_FOUND and crash Kibana; update the indices entry in the readonlyrest.yml
role to include "heartbeat-*" (or alternatively disable/hide the Index
Management/Data Streams feature for this role) so EndUsers can access Data
Streams; locate the indices: ["frontend_logs*", "kibana_sample_data_*"] line and
add "heartbeat-*" (or implement feature-hiding for the kibana: index
.kibana_end_@{user} role) accordingly.


- name: "Business users"
groups: ["BusinessUsers"]
indices: ["business_logs", "kibana_sample_data_*"]
indices: ["business_logs*", "kibana_sample_data_*"]
kibana:
index: .kibana_business_@{user}
access: rw
access: ro
hide_apps: ["Security", "Observability"]

- name: "Test users"
groups: ["TestUsers"]
indices: ["business_logs*", "kibana_sample_data_*"]
kibana:
index: .kibana_test_@{user}
access: ro_strict
hide_apps: ["Security", "Observability"]
Comment on lines +33 to 41
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Management is still exposed for read-only tenants, which can lead to broken flows.

Line 33 and Line 41 hide Security/Observability only. Read-only users can still navigate to Index Management and hit failing endpoints. Consider hiding Management for ro/ro_strict profiles until permissions/index scope fully support those pages.

Suggested config adjustment
-        hide_apps: ["Security", "Observability"]
+        hide_apps: ["Security", "Observability", "Management"]
...
-        hide_apps: ["Security", "Observability"]
+        hide_apps: ["Security", "Observability", "Management"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
hide_apps: ["Security", "Observability"]
- name: "Test users"
groups: ["TestUsers"]
indices: ["business_logs*", "kibana_sample_data_*"]
kibana:
index: .kibana_test_@{user}
access: ro_strict
hide_apps: ["Security", "Observability"]
hide_apps: ["Security", "Observability", "Management"]
- name: "Test users"
groups: ["TestUsers"]
indices: ["business_logs*", "kibana_sample_data_*"]
kibana:
index: .kibana_test_@{user}
access: ro_strict
hide_apps: ["Security", "Observability", "Management"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ror-demo-cluster/conf/es/readonlyrest.yml` around lines 33 - 41, The
read-only tenant config ("Test users" with groups "TestUsers" and kibana access
"ro_strict") currently only hides "Security" and "Observability" which leaves
"Management" exposed; update the kibana hide_apps for read-only profiles (e.g.,
the "Test users" block and any other ro/ro_strict entries) to include
"Management" so read-only users cannot access Index/Management pages until those
pages are supported by the permission/index scope.


users:
Expand All @@ -42,6 +50,8 @@ readonlyrest:
name: "End Users"
- id: "BusinessUsers"
name: "Business Users"
- id: "TestUsers"
name: "Test Users"

- username: user1
auth_key: user1:test
Expand All @@ -50,26 +60,11 @@ readonlyrest:
name: "End Users"
- id: "BusinessUsers"
name: "Business Users"
- id: "TestUsers"
name: "Test Users"

- username: user2
auth_key: user2:test
groups:
- id: "EndUsers"
name: "End Users"

- username: "*"
ror_kbn_auth:
name: "kbn1"
groups: ["*"]
groups:
- local_group:
id: "EndUsers"
name: "End Users"
external_group_ids: [ "extEndUsers" ]
- local_group:
id: "BusinessUsers"
name: "Business Users"
external_group_ids: [ "extBusinessUsers" ]
ror_kbn:
- name: kbn1
signature_key: "9yzBfnLaTYLfGPzyKW9es76RKYhUVgmuv6ZtehaScj5msGpBpa5FWpwk295uJYaaffTFnQC5tsknh2AguVDaTrqCLfM5zCTqdE4UGNL73h28Bg4dPrvTAFQyygQqv4xfgnevBED6VZYdfjXAQLc8J8ywaHQQSmprZqYCWGE6sM3vzNUEWWB3kmGrEKa4sGbXhmXZCvL6NDnEJhXPDJAzu9BMQxn8CzVLqrx6BxDgPYF8gZCxtyxMckXwCaYXrxAGbjkYH69F4wYhuAdHSWgRAQCuWwYmWCA6g39j4VPge5pv962XYvxwJpvn23Y5KvNZ5S5c6crdG4f4gTCXnU36x92fKMQzsQV9K4phcuNvMWkpqVB6xMA5aPzUeHcGytD93dG8D52P5BxsgaJJE6QqDrk3Y2vyLw9ZEbJhPRJxbuBKVCBtVx26Ldd46dq5eyyzmNEyQGLrjQ4qd978VtG8TNT5rkn4ETJQEju5HfCBbjm3urGLFVqxhGVawecT4YM9Rry4EqXWkRJGTFQWQRnweUFbKNbVTC9NxcXEp6K5rSPEy9trb5UYLYhhMJ9fWSBMuenGRjNSJxeurMRCaxPpNppBLFnp8qW5ezfHgCBpEjkSNNzP4uXMZFAXmdUfJ8XQdPTWuYfdHYc5TZWnzrdq9wcfFQRDpDB2zX5Myu96krDt9vA7wNKfYwkSczA6qUQV66jA8nV4Cs38cDAKVBXnxz22ddAVrPv8ajpu7hgBtULMURjvLt94Nc5FDKw79CTTQxffWEj9BJCDCpQnTufmT8xenywwVJvtj49yv2MP2mGECrVDRmcGUAYBKR8G6ZnFAYDVC9UhY46FGWDcyVX3HKwgtHeb45Ww7dsW8JdMnZYctaEU585GZmqTJp2LcAWRcQPH25JewnPX8pjzVpJNcy7avfA2bcU86bfASvQBDUCrhjgRmK2ECR6vzPwTsYKRgFrDqb62FeMdrKgJ9vKs435T5ACN7MNtdRXHQ4fj5pNpUMDW26Wd7tt9bkBTqEGf"
62 changes: 12 additions & 50 deletions ror-demo-cluster/conf/kbn/enterprise-ror-newplatform-kibana.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,53 +12,15 @@ 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"
saml_keycloak:
buttonName: 'Keycloak SAML'
enabled: true
type: 'saml'
issuer: 'ror-saml'
entryPoint: 'http://kc.localhost:8080/realms/ror/protocol/saml'
kibanaExternalHost: 'localhost:15601'
protocol: 'https'
usernameParameter: 'nameID'
groupsParameter: 'Role'
logoutUrl: 'http://kc.localhost:8080/realms/ror/protocol/saml'
YOU_SHOULD_READ_ME_IN_STRATEGY_CONFIGURATION_LOG: 'unknown conf params should be passed unmodified to the underlying passport-saml library'
cert: 'MIICrDCCAZQCCQDN5Tcc+Rn6rTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1rZXljbG9hay1zYW1sMB4XDTI1MTExMDA0MjQyOFoXDTM1MTEwODA0MjQyOFowGDEWMBQGA1UEAwwNa2V5Y2xvYWstc2FtbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJv0EFcTjNkpn5kV/XedCJ/AQKsPafZ7u33u3zfYgZbTh0V+CJ4bUAZyTfvGrcxR/iZy3hkYQBL7DGM6c/fYJGq1IH+/jxAk/GBY9tVnxotRsyhIMJYtZCb+DBUVX+wLowv2kZPlf/6OibjVpy+I6klQxIU8aeMkd+M/Phl97l+pRUjTuQZvEaEtkVLcsG6gEUcNo2X0MpNFwT7UgpGZLGy8zSHGNu703tb8w0oCYTEj42WqLWYNm5NMqD/clbPRj8g+1qZHpSoIH+p/cqVfU+oAZd3R2Y8SGR2OhYwyu9wHRnuqgiEgCIYbzwyh3IzX+57R8MQxHnjBFnzJKFtBWHMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAUGrj7hEEHJvm58RYTjqhcJ38MVkgEmAnGovObxvS9Xi6ZBct4irWdpyESowRJtY4nxFGs0uiArOpQDkteSeDzJs/IkSg3xTx3UwOpevf8IV5gU8Bwq68Fyh9An8NvczE5XhLZD1Tacphlz5OzoXthMsS1pcCumr5ZELwMtvLYAWkEV/cKmlis4JuMEZXc5v9KVybsmHv1hgM+fxg1neuWrPK1JebuVm4oaHUHYKCxqn9MXjnDvOq6MkYtKBfcYf6BKk29lapYuHNiRTi0hMPD1tWVaZg3H1/uMxlLXDxAZqkS4DNq/7MeIMUWemOqxQHZAi4rtplrVl/F3WES6pqWw=='
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: 'ror-oidc'
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'
xpack.encryptedSavedObjects:
encryptionKey: "min-32-byte-long-strong-encryption-key"
Comment on lines +15 to +16
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hardcoded encryption key detected.

The static analysis tool flagged this as a generic API key. Even for a demo/reproducer environment, committing secrets to version control is risky—this value could inadvertently be reused or copied into production configurations.

Consider using an environment variable or a secrets file that's excluded from version control:

xpack.encryptedSavedObjects:
  encryptionKey: ${KIBANA_ENCRYPTION_KEY}
🧰 Tools
🪛 Gitleaks (8.30.0)

[high] 16-16: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ror-demo-cluster/conf/kbn/enterprise-ror-newplatform-kibana.yml` around lines
15 - 16, The hardcoded secret in xpack.encryptedSavedObjects.encryptionKey must
be replaced with a non-committed secret reference: change the static value to
read from an environment variable (e.g. KIBANA_ENCRYPTION_KEY) or a secrets
store, update any deployment/start scripts to set that env var, and remove the
literal key from the file and repo history if possible; ensure the config now
references the env var and add instructions or a .env/secrets sample (excluded
from VCS) so developers can provide their own keys securely.


logging:
root:
level: debug
loggers:
- name: elasticsearch
level: trace

readonlyrest_kbn.logLevel: trace
readonlyrest_kbn.cookiePass: '12312313123213123213123abcdefghijklm'
37 changes: 10 additions & 27 deletions ror-demo-cluster/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,4 @@
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:
Expand Down Expand Up @@ -55,6 +32,15 @@ services:
soft: -1
hard: -1

es-ror-proxy:
image: mitmproxy/mitmproxy
command:
mitmdump --set validate_inbound_headers=false --mode reverse:https://es-ror:9200 --ssl-insecure --verbose
depends_on:
- es-ror
networks:
- es-ror-network
Comment thread
coutoPL marked this conversation as resolved.

Comment on lines +35 to +43
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add readiness gating for es-ror-proxy now that Kibana depends on it.

After Line 59 switched ELASTICSEARCH_HOSTS to es-ror-proxy, kbn-ror should also wait for proxy readiness. Right now it only waits for es-ror, which can produce startup/transient 5xx when proxy isn’t ready yet.

Suggested compose patch
   es-ror-proxy:
     image: mitmproxy/mitmproxy
     command:
       mitmdump --set validate_inbound_headers=false --mode reverse:https://es-ror:9200 --ssl-insecure --verbose
     depends_on:
       - es-ror
+    healthcheck:
+      test: ["CMD-SHELL", "curl -fksS --connect-timeout 3 --max-time 5 --retry 2 --retry-connrefused -u admin:admin https://127.0.0.1:8080/_cluster/health >/dev/null || exit 1"]
+      interval: 10s
+      timeout: 10s
+      retries: 30
+      start_period: 20s
     networks:
       - es-ror-network

   kbn-ror:
@@
     depends_on:
       es-ror:
         condition: service_healthy
+      es-ror-proxy:
+        condition: service_healthy

Also applies to: 59-59

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ror-demo-cluster/docker-compose.yml` around lines 35 - 43, kbn-ror currently
only waits on es-ror, but because ELASTICSEARCH_HOSTS now points at es-ror-proxy
you must gate kbn-ror on proxy readiness; add a healthcheck to es-ror-proxy (or
reuse an existing one) that verifies the proxy is forwarding (e.g., a simple
HTTP request to the reverse target) and update kbn-ror's startup dependency to
depend_on: es-ror-proxy with condition: service_healthy (or implement an
explicit wait-for startup step in kbn-ror that polls es-ror-proxy); reference
the es-ror-proxy service, the kbn-ror service and ELASTICSEARCH_HOSTS when
making the change.

kbn-ror:
build:
context: .
Expand All @@ -67,13 +53,10 @@ services:
depends_on:
es-ror:
condition: service_healthy
keycloak:
condition: service_healthy
required: false
ports:
- "15601:5601"
environment:
ELASTICSEARCH_HOSTS: https://es-ror:9200
ELASTICSEARCH_HOSTS: https://es-ror-proxy:8080
ROR_ACTIVATION_KEY: $ROR_ACTIVATION_KEY
healthcheck:
test: ["CMD-SHELL", "curl -fksS --connect-timeout 3 --max-time 5 --retry 2 --retry-connrefused -u admin:admin https://127.0.0.1:5601/api/features >/dev/null || exit 1"]
Expand Down
Binary file not shown.
Binary file not shown.
39 changes: 6 additions & 33 deletions shared/init-scripts/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,10 @@ cd "$(dirname "$0")"

source utils/lib.sh

function generate_log_documents() {
if [ "$#" -ne 1 ]; then
echo "ERROR: One required: 1) number of documents to generate"
return 1
fi
#createDataStream "frontend_logs_ds" && generate_log_documents 100 | putDocument "frontend_logs_ds"
#createDataStream "business_logs_ds" && generate_log_documents 50 | putDocument "business_logs_ds"
#createDataStream "system_logs_ds" && generate_log_documents 60 | putDocument "system_logs_ds"

N=$1

for ((i = 1; i <= N; i++)); do
user_id=$((RANDOM % 10000 + 1))
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
log_message="User $user_id login successful"
level="$(pick_randomly "INFO" "WARN" "ERROR" "DEBUG")"

echo "{ \"message\": \"$log_message\", \"level\": \"$level\", \"timestamp\": \"$timestamp\", \"user_id\": \"$user_id\" }"
done
}

function index_documents() {
if [ "$#" -ne 1 ]; then
echo "ERROR: One required: 1) index name"
return 1
fi

INDEX_NAME=$1

while IFS= read -r document; do
putDocument "$INDEX_NAME" "$document"
done
}

generate_log_documents 100 | index_documents "frontend_logs"
generate_log_documents 50 | index_documents "business_logs"
generate_log_documents 60 | index_documents "system_logs"
#createIndex "frontend_logs_index" && generate_log_documents 100 | putDocument "frontend_logs_index"
#createIndex "business_logs_index" && generate_log_documents 50 | putDocument "business_logs_index"
#createIndex "system_logs_index" && generate_log_documents 60 | putDocument "system_logs_index"
127 changes: 119 additions & 8 deletions shared/init-scripts/utils/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,92 @@ function pick_randomly() {
echo "${OPTIONS[$RANDOM_INDEX]}"
}

function createIndex() {
if [ "$#" -ne 1 ]; then
echo "ERROR: One parameter required: 1) index name"
return 1
fi

if ! [ -v ELASTICSEARCH_ADDRESS ] || [ -z "$ELASTICSEARCH_ADDRESS" ]; then
echo "ERROR: required variable ELASTICSEARCH_ADDRESS not set or empty"
exit 2
fi

if ! [ -v ELASTICSEARCH_USER ] || [ -z "$ELASTICSEARCH_USER" ]; then
echo "ERROR: required variable ELASTICSEARCH_USER not set or empty"
exit 3
fi

if ! [ -v ELASTICSEARCH_PASSWORD ] || [ -z "$ELASTICSEARCH_PASSWORD" ]; then
echo "ERROR: required variable ELASTICSEARCH_PASSWORD not set or empty"
exit 4
fi

INDEX_NAME=$1

response=$(curl -k -s -L -w "\n%{http_code}" -u $ELASTICSEARCH_USER:$ELASTICSEARCH_PASSWORD \
-X PUT "$ELASTICSEARCH_ADDRESS/$INDEX_NAME" \
-H "Content-Type: application/json"
Comment on lines +33 to +35
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd "lib.sh" shared/

Repository: beshu-tech/ror-sandbox

Length of output: 98


🏁 Script executed:

cat -n shared/init-scripts/utils/lib.sh | head -150

Repository: beshu-tech/ror-sandbox

Length of output: 5356


Quote the curl credentials.

Lines 33, 73, and 129 expand ELASTICSEARCH_USER/ELASTICSEARCH_PASSWORD unquoted in the curl -u flag. A password with whitespace or glob characters will be split or expanded by the shell, breaking authentication.

Suggested change
-response=$(curl -k -s -L -w "\n%{http_code}" -u $ELASTICSEARCH_USER:$ELASTICSEARCH_PASSWORD \
+response=$(curl -k -s -L -w "\n%{http_code}" -u "${ELASTICSEARCH_USER}:${ELASTICSEARCH_PASSWORD}" \

Apply the same quoting in createDataStream (line 73) and putSingleDocument (line 129).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
response=$(curl -k -s -L -w "\n%{http_code}" -u $ELASTICSEARCH_USER:$ELASTICSEARCH_PASSWORD \
-X PUT "$ELASTICSEARCH_ADDRESS/$INDEX_NAME" \
-H "Content-Type: application/json"
response=$(curl -k -s -L -w "\n%{http_code}" -u "${ELASTICSEARCH_USER}:${ELASTICSEARCH_PASSWORD}" \
-X PUT "$ELASTICSEARCH_ADDRESS/$INDEX_NAME" \
-H "Content-Type: application/json"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shared/init-scripts/utils/lib.sh` around lines 33 - 35, The curl invocations
are expanding ELASTICSEARCH_USER and ELASTICSEARCH_PASSWORD unquoted (seen in
the PUT call and similar calls in createDataStream and putSingleDocument), which
breaks when passwords contain spaces or glob chars; update the -u argument to
quote the credentials as a single shell word (e.g., wrap the combined
user:password value in double quotes) for every curl call that uses -u
$ELASTICSEARCH_USER:$ELASTICSEARCH_PASSWORD so the shell does not split or glob
the values.

)

http_status=$(echo "$response" | tail -n 1)
response_body=$(echo "$response" | sed \$d)

if [[ "$http_status" != 2* ]]; then
echo "ERROR: Cannot create index [$INDEX_NAME]. HTTP status: $http_status, response body: $response_body"
return 5
fi

return 0
}

function createDataStream() {
if [ "$#" -ne 1 ]; then
echo "ERROR: One parameter required: 1) data stream name"
return 1
fi

if ! [ -v ELASTICSEARCH_ADDRESS ] || [ -z "$ELASTICSEARCH_ADDRESS" ]; then
echo "ERROR: required variable ELASTICSEARCH_ADDRESS not set or empty"
exit 2
fi

if ! [ -v ELASTICSEARCH_USER ] || [ -z "$ELASTICSEARCH_USER" ]; then
echo "ERROR: required variable ELASTICSEARCH_USER not set or empty"
exit 3
fi

if ! [ -v ELASTICSEARCH_PASSWORD ] || [ -z "$ELASTICSEARCH_PASSWORD" ]; then
echo "ERROR: required variable ELASTICSEARCH_PASSWORD not set or empty"
exit 4
fi

STREAM_NAME=$1
TEMPLATE_NAME="${STREAM_NAME}-template"

response=$(curl -k -s -L -w "\n%{http_code}" -u $ELASTICSEARCH_USER:$ELASTICSEARCH_PASSWORD \
-X PUT "$ELASTICSEARCH_ADDRESS/_index_template/$TEMPLATE_NAME" \
-H "Content-Type: application/json" -d "{
\"index_patterns\": [\"$STREAM_NAME\"],
\"data_stream\": {},
\"priority\": 500
}"
)

http_status=$(echo "$response" | tail -n 1)
response_body=$(echo "$response" | sed \$d)

if [[ "$http_status" != 2* ]]; then
echo "ERROR: Cannot create index template for data stream [$STREAM_NAME]. HTTP status: $http_status, response body: $response_body"
return 5
fi

return 0
}

function putDocument() {
if [ "$#" -ne 2 ]; then
echo "ERROR: Three parameters required: 1) index name, 2) document JSON string"
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo "ERROR: Required: 1) index name, optionally 2) document JSON string (or via stdin)"
return 1
fi

Expand All @@ -29,22 +112,50 @@ function putDocument() {
fi

INDEX_NAME=$1
DOCUMENT_CONTENT=$2

set -x
if [ "$#" -eq 2 ]; then
putSingleDocument "$INDEX_NAME" "$2"
else
while IFS= read -r DOCUMENT_CONTENT; do
putSingleDocument "$INDEX_NAME" "$DOCUMENT_CONTENT"
done
fi
Comment on lines +116 to +122
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n shared/init-scripts/utils/lib.sh | sed -n '110,130p'

Repository: beshu-tech/ror-sandbox

Length of output: 738


🏁 Script executed:

ls -la shared/init-scripts/utils/lib.sh
wc -l shared/init-scripts/utils/lib.sh

Repository: beshu-tech/ror-sandbox

Length of output: 184


🏁 Script executed:

rg -n "putSingleDocument" shared/init-scripts/utils/lib.sh -B 2 -A 5

Repository: beshu-tech/ror-sandbox

Length of output: 546


🏁 Script executed:

cat -n shared/init-scripts/utils/lib.sh | sed -n '100,160p'

Repository: beshu-tech/ror-sandbox

Length of output: 2237


🏁 Script executed:

cat -n shared/init-scripts/utils/lib.sh | sed -n '90,125p'

Repository: beshu-tech/ror-sandbox

Length of output: 1254


🏁 Script executed:

rg -n "putDocument" shared/init-scripts/ -B 2 -A 2

Repository: beshu-tech/ror-sandbox

Length of output: 1300


🏁 Script executed:

rg -n "set -e" shared/init-scripts/

Repository: beshu-tech/ror-sandbox

Length of output: 48


Stop the stdin ingestion loop on the first failed write.

The while loop at lines 119-121 continues consuming input after a failed putSingleDocument call. Since putSingleDocument returns 5 on HTTP errors (line 139), but the loop doesn't check the return status, a partial ingestion failure will be silently hidden. If a later document succeeds, the function returns 0, reporting false success to the caller. Additionally, line 117's direct call also lacks error checking for the non-stdin case.

   else
     while IFS= read -r DOCUMENT_CONTENT; do
-      putSingleDocument "$INDEX_NAME" "$DOCUMENT_CONTENT"
+      putSingleDocument "$INDEX_NAME" "$DOCUMENT_CONTENT" || return $?
     done
   fi

Also apply error checking to line 117:

   if [ "$#" -eq 2 ]; then
-    putSingleDocument "$INDEX_NAME" "$2"
+    putSingleDocument "$INDEX_NAME" "$2" || return $?
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ "$#" -eq 2 ]; then
putSingleDocument "$INDEX_NAME" "$2"
else
while IFS= read -r DOCUMENT_CONTENT; do
putSingleDocument "$INDEX_NAME" "$DOCUMENT_CONTENT"
done
fi
if [ "$#" -eq 2 ]; then
putSingleDocument "$INDEX_NAME" "$2" || return $?
else
while IFS= read -r DOCUMENT_CONTENT; do
putSingleDocument "$INDEX_NAME" "$DOCUMENT_CONTENT" || return $?
done
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shared/init-scripts/utils/lib.sh` around lines 116 - 122, The stdin ingestion
loop and the single-document branch do not check the exit status of
putSingleDocument, allowing later successes to mask earlier failures; update
both the direct call (when "$#" -eq 2) and the while-read loop to capture the
exit code from putSingleDocument (called with "$INDEX_NAME" and the document
content) and if it is non-zero immediately break/return/exit with that code so
the function returns a failure on the first write error instead of continuing to
consume input.

}

respone=$(curl -k -s -L -w "\n%{http_code}" -u $ELASTICSEARCH_USER:$ELASTICSEARCH_PASSWORD \
function putSingleDocument() {
INDEX_NAME=$1
DOCUMENT_CONTENT=$2

response=$(curl -k -s -L -w "\n%{http_code}" -u $ELASTICSEARCH_USER:$ELASTICSEARCH_PASSWORD \
-X POST "$ELASTICSEARCH_ADDRESS/$INDEX_NAME/_doc/" \
-H "Content-Type: application/json" -d "$DOCUMENT_CONTENT"
)

http_status=$(echo "$respone" | tail -n 1)
response_body=$(echo "$respone" | sed \$d)
http_status=$(echo "$response" | tail -n 1)
response_body=$(echo "$response" | sed \$d)

if [[ "$http_status" != 2* ]] ; then
echo "ERROR: Cannot add document [$DOCUMENT_CONTENT] to index=[$INDEX_NAME].\nHTTP status: $HTTP_STATUS, response body: $RESPONSE_BODY"
echo "ERROR: Cannot add document [$DOCUMENT_CONTENT] to index=[$INDEX_NAME].\nHTTP status: $http_status, response body: $response_body"
return 5
fi

return 0
}

function generate_log_documents() {
if [ "$#" -ne 1 ]; then
echo "ERROR: One required: 1) number of documents to generate"
return 1
fi

N=$1

for ((i = 1; i <= N; i++)); do
user_id=$((RANDOM % 10000 + 1))
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
log_message="User $user_id login successful"
level="$(pick_randomly "INFO" "WARN" "ERROR" "DEBUG")"

echo "{ \"message\": \"$log_message\", \"level\": \"$level\", \"@timestamp\": \"$timestamp\", \"user_id\": \"$user_id\" }"
done
}
Loading