Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ KAFKA_PORT=9092
CONNECT_PORT=8083
KAFKA_BOOTSTRAP_SERVERS=localhost:9092

# ─── Kafka Secure Mode (optional SASL_SSL overlay) ──────────────────────────
KAFKA_SECURITY_PROTOCOL=PLAINTEXT
KAFKA_SASL_MECHANISM=SCRAM-SHA-512
KAFKA_BROKER_USERNAME=broker-user
KAFKA_BROKER_PASSWORD=
KAFKA_BACKEND_USERNAME=backend-user
KAFKA_BACKEND_PASSWORD=
KAFKA_CONNECT_USERNAME=connect-user
KAFKA_CONNECT_PASSWORD=
KAFKA_CONNECT_TRUSTSTORE_PASSWORD=changeit
KAFKA_BACKEND_TRUSTSTORE_PASSWORD=changeit
KAFKA_KEYSTORE_PASSWORD=changeit
KAFKA_TRUSTSTORE_PASSWORD=changeit

# ─── Database App User (init.sql) ───────────────────────────────────────────
MONITOR_APP_USER=monitor_app
MONITOR_APP_PASSWORD=
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,18 @@ docker-compose.override.yml
*.p12
*.pfx
*.jks
*.keystore
*.crt
*.cert
secrets/
.vault-token
.vault/
!docker/
!docker/kafka/
!docker/kafka/secrets/
docker/kafka/secrets/*
!docker/kafka/secrets/.gitkeep
!docker/kafka/secrets/README.md

# Security tooling
# dependency-check-report.html (ignored below in Reports section)
62 changes: 62 additions & 0 deletions docker-compose.secure.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
services:
kafka:
ports:
- "${KAFKA_BIND_HOST:-127.0.0.1}:${KAFKA_PORT:-9092}:9092"
volumes:
- ./docker/kafka/secrets:/etc/kafka/secrets:ro
environment:
KAFKA_LISTENERS: SASL_SSL://0.0.0.0:29092,SASL_SSL_HOST://0.0.0.0:9092
KAFKA_ADVERTISED_LISTENERS: SASL_SSL://kafka:29092,SASL_SSL_HOST://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: SASL_SSL:SASL_SSL,SASL_SSL_HOST:SASL_SSL
KAFKA_INTER_BROKER_LISTENER_NAME: SASL_SSL
KAFKA_SASL_ENABLED_MECHANISMS: SCRAM-SHA-512
Comment on lines +7 to +12

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

The base docker-compose.yml Kafka healthcheck uses kafka-topics --bootstrap-server localhost:9092 --list (PLAINTEXT). With this overlay, 9092 becomes SASL_SSL, so the inherited healthcheck will likely fail and keep kafka unhealthy (blocking kafka-connect which depends on service_healthy). Consider overriding the healthcheck here with a TLS/SASL-aware check (or a simple port-open check) for secure mode.

Copilot uses AI. Check for mistakes.
KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: SCRAM-SHA-512
ZOOKEEPER_SASL_ENABLED: "false"
KAFKA_OPTS: -Djava.security.auth.login.config=/etc/kafka/secrets/kafka_server_jaas.conf -Dzookeeper.sasl.client=false
KAFKA_SSL_CLIENT_AUTH: required

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

In the secure overlay the broker sets KAFKA_SSL_CLIENT_AUTH: required, but neither kafka-connect nor backend are configured with client keystores/certs (only truststores). With required, TLS handshakes will fail unless you also provision and configure client keystores, or change this to none/requested for SASL/SCRAM-only auth.

Suggested change
KAFKA_SSL_CLIENT_AUTH: required
KAFKA_SSL_CLIENT_AUTH: none

Copilot uses AI. Check for mistakes.
KAFKA_SSL_KEYSTORE_FILENAME: ${KAFKA_SSL_KEYSTORE_FILENAME:-kafka.keystore.jks}
KAFKA_SSL_KEYSTORE_CREDENTIALS: ${KAFKA_SSL_KEYSTORE_CREDENTIALS:-kafka_keystore_creds}
KAFKA_SSL_KEY_CREDENTIALS: ${KAFKA_SSL_KEY_CREDENTIALS:-kafka_sslkey_creds}
KAFKA_SSL_TRUSTSTORE_FILENAME: ${KAFKA_SSL_TRUSTSTORE_FILENAME:-kafka.truststore.jks}
KAFKA_SSL_TRUSTSTORE_CREDENTIALS: ${KAFKA_SSL_TRUSTSTORE_CREDENTIALS:-kafka_truststore_creds}
healthcheck:
test: ["CMD-SHELL", "kafka-topics --bootstrap-server localhost:9092 --command-config /etc/kafka/secrets/kafka_admin_client.properties --list > /dev/null 2>&1 || exit 1"]
interval: 30s
timeout: 10s
retries: 5

kafka-connect:
environment:
BOOTSTRAP_SERVERS: kafka:29092
CONNECT_SECURITY_PROTOCOL: SASL_SSL
CONNECT_SASL_MECHANISM: SCRAM-SHA-512
CONNECT_SASL_JAAS_CONFIG: org.apache.kafka.common.security.scram.ScramLoginModule required username="${KAFKA_CONNECT_USERNAME}" password="${KAFKA_CONNECT_PASSWORD}";
CONNECT_SSL_TRUSTSTORE_LOCATION: /etc/kafka/secrets/connect.truststore.jks
CONNECT_SSL_TRUSTSTORE_PASSWORD: ${KAFKA_CONNECT_TRUSTSTORE_PASSWORD}
CONNECT_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM:
CONNECT_PRODUCER_SECURITY_PROTOCOL: SASL_SSL
CONNECT_PRODUCER_SASL_MECHANISM: SCRAM-SHA-512
CONNECT_PRODUCER_SASL_JAAS_CONFIG: org.apache.kafka.common.security.scram.ScramLoginModule required username="${KAFKA_CONNECT_USERNAME}" password="${KAFKA_CONNECT_PASSWORD}";
CONNECT_PRODUCER_SSL_TRUSTSTORE_LOCATION: /etc/kafka/secrets/connect.truststore.jks
CONNECT_PRODUCER_SSL_TRUSTSTORE_PASSWORD: ${KAFKA_CONNECT_TRUSTSTORE_PASSWORD}
CONNECT_PRODUCER_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM:
CONNECT_CONSUMER_SECURITY_PROTOCOL: SASL_SSL
CONNECT_CONSUMER_SASL_MECHANISM: SCRAM-SHA-512
CONNECT_CONSUMER_SASL_JAAS_CONFIG: org.apache.kafka.common.security.scram.ScramLoginModule required username="${KAFKA_CONNECT_USERNAME}" password="${KAFKA_CONNECT_PASSWORD}";
CONNECT_CONSUMER_SSL_TRUSTSTORE_LOCATION: /etc/kafka/secrets/connect.truststore.jks
CONNECT_CONSUMER_SSL_TRUSTSTORE_PASSWORD: ${KAFKA_CONNECT_TRUSTSTORE_PASSWORD}
CONNECT_CONSUMER_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM:
volumes:
- ./docker/kafka/secrets:/etc/kafka/secrets:ro

backend:
environment:
KAFKA_BOOTSTRAP_SERVERS: kafka:29092
KAFKA_SECURITY_PROTOCOL: SASL_SSL
KAFKA_SASL_MECHANISM: SCRAM-SHA-512
KAFKA_SASL_JAAS_CONFIG: org.apache.kafka.common.security.scram.ScramLoginModule required username="${KAFKA_BACKEND_USERNAME}" password="${KAFKA_BACKEND_PASSWORD}";
KAFKA_SSL_TRUSTSTORE_LOCATION: /etc/kafka/secrets/backend.truststore.jks
KAFKA_SSL_TRUSTSTORE_PASSWORD: ${KAFKA_BACKEND_TRUSTSTORE_PASSWORD}
KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM:
volumes:
- ./docker/kafka/secrets:/etc/kafka/secrets:ro
14 changes: 7 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ services:
MONITOR_APP_USER: ${MONITOR_APP_USER:-monitor_app}
MONITOR_APP_PASS: ${MONITOR_APP_PASSWORD}
ports:
- "${ORACLE_PORT:-1521}:1521"
- "${ORACLE_BIND_HOST:-127.0.0.1}:${ORACLE_PORT:-1521}:1521"
volumes:
- oracle-data:/opt/oracle/oradata
- ./docker/oracle/init.sql:/container-entrypoint-initdb.d/01-init.sql:ro
Expand Down Expand Up @@ -50,7 +50,7 @@ services:
depends_on:
- zookeeper
ports:
- "${KAFKA_PORT:-9092}:9092"
- "${KAFKA_BIND_HOST:-127.0.0.1}:${KAFKA_PORT:-9092}:9092"
networks:
- monitor-net
environment:
Expand Down Expand Up @@ -90,7 +90,7 @@ services:
CONNECT_KEY_CONVERTER_SCHEMAS_ENABLE: "false"
CONNECT_VALUE_CONVERTER_SCHEMAS_ENABLE: "false"
ports:
- "${CONNECT_PORT:-8083}:8083"
- "${CONNECT_BIND_HOST:-127.0.0.1}:${CONNECT_PORT:-8083}:8083"
networks:
- monitor-net
healthcheck:
Expand All @@ -106,8 +106,8 @@ services:
container_name: monitor-mailhog
restart: unless-stopped
ports:
- "1025:1025"
- "8025:8025"
- "${MAILHOG_BIND_HOST:-127.0.0.1}:${MAILHOG_SMTP_PORT:-1025}:1025"
- "${MAILHOG_BIND_HOST:-127.0.0.1}:${MAILHOG_UI_PORT:-8025}:8025"
networks:
- monitor-net

Expand All @@ -119,7 +119,7 @@ services:
container_name: monitor-backend
restart: unless-stopped
ports:
- "8080:8080"
- "${BACKEND_BIND_HOST:-127.0.0.1}:${BACKEND_PORT:-8080}:8080"
environment:
SPRING_PROFILES_ACTIVE: prod
KAFKA_BOOTSTRAP_SERVERS: kafka:29092
Expand Down Expand Up @@ -157,7 +157,7 @@ services:
container_name: monitor-frontend
restart: unless-stopped
ports:
- "3000:3000"
- "${FRONTEND_BIND_HOST:-127.0.0.1}:${FRONTEND_PORT:-3000}:3000"
depends_on:
backend:
condition: service_healthy
Expand Down
Empty file added docker/kafka/secrets/.gitkeep
Empty file.
16 changes: 16 additions & 0 deletions docker/kafka/secrets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Kafka Security Secrets (Local)

This directory stores local TLS/SASL materials used by `docker-compose.secure.yml`.

Do not commit private keys, truststores, or credentials.

Expected files:
- kafka.keystore.jks
- kafka.truststore.jks
- connect.truststore.jks
- backend.truststore.jks
- kafka_keystore_creds
- kafka_sslkey_creds
- kafka_truststore_creds

These files are ignored by `.gitignore` (except this README and `.gitkeep`).
22 changes: 11 additions & 11 deletions docker/oracle/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ GRANT CREATE SESSION TO "&MONITOR_APP_USER";
GRANT SELECT ON SYS.V_$DATABASE TO "&MONITOR_APP_USER";
GRANT SELECT ON SYS.V_$LOG TO "&MONITOR_APP_USER";
GRANT SELECT ON SYS.V_$LOGFILE TO "&MONITOR_APP_USER";
GRANT SELECT ON SYS.V_$LOGMNR_CONTENTS TO monitor_app;
GRANT SELECT ON SYS.V_$ARCHIVED_LOG TO monitor_app;
GRANT SELECT ON SYS.V_$TRANSACTION TO monitor_app;
GRANT SELECT ON SYS.V_$LOGMNR_CONTENTS TO "&MONITOR_APP_USER";
GRANT SELECT ON SYS.V_$ARCHIVED_LOG TO "&MONITOR_APP_USER";
GRANT SELECT ON SYS.V_$TRANSACTION TO "&MONITOR_APP_USER";

-- Switch to the application schema
ALTER SESSION SET CURRENT_SCHEMA = monitor_app;
ALTER SESSION SET CURRENT_SCHEMA = "&MONITOR_APP_USER";

-- =============================================================================
-- Table: LOG_TRAZA
-- =============================================================================
CREATE TABLE monitor_app.log_traza (
CREATE TABLE log_traza (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
error_code VARCHAR2(50) NOT NULL,
error_msg VARCHAR2(4000) NOT NULL,
Expand All @@ -51,7 +51,7 @@ CREATE TABLE monitor_app.log_traza (
-- =============================================================================
-- Table: CRITICAL_OUTBOX
-- =============================================================================
CREATE TABLE monitor_app.critical_outbox (
CREATE TABLE critical_outbox (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
attempts NUMBER DEFAULT 0 NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
Expand All @@ -70,17 +70,17 @@ CREATE TABLE monitor_app.critical_outbox (
);

-- Enable row-level supplemental logging
ALTER TABLE monitor_app.log_traza ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
ALTER TABLE monitor_app.critical_outbox ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
ALTER TABLE log_traza ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
ALTER TABLE critical_outbox ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

-- Seed data
INSERT INTO monitor_app.log_traza (error_code, error_msg, severity, source_app)
INSERT INTO log_traza (error_code, error_msg, severity, source_app)
VALUES ('APP-001', 'Scheduled job completed successfully', 'INFO', 'batch-processor');

INSERT INTO monitor_app.log_traza (error_code, error_msg, severity, source_app)
INSERT INTO log_traza (error_code, error_msg, severity, source_app)
VALUES ('APP-002', 'Connection pool near capacity (85%)', 'WARNING', 'api-gateway');

INSERT INTO monitor_app.log_traza (error_code, error_msg, severity, source_app)
INSERT INTO log_traza (error_code, error_msg, severity, source_app)
VALUES ('APP-003', 'Unable to reach secondary Oracle node', 'CRITICAL', 'data-sync-daemon');

COMMIT;
10 changes: 10 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ It is designed to serve three audiences:
- `docs/operations/README.md` - operations index
- `docs/operations/monitor-operations-runbook.md` - operational runbook

#### Security Reports

- `docs/reports/SECURITY-AUDIT.md` - baseline security assessment and findings catalog
- `docs/reports/SECURITY-HARDENING-READINESS.md` - current closure/readiness status for findings #8-#14

### Recommended Reading Paths

#### For executives or architects
Expand Down Expand Up @@ -134,6 +139,11 @@ Esta dise�ado para tres audiencias:
- `docs/operations/README.md` - indice operativo
- `docs/operations/monitor-operations-runbook.md` - runbook operativo

#### Reportes de Seguridad

- `docs/reports/SECURITY-AUDIT.md` - evaluacion base de seguridad y catalogo de hallazgos
- `docs/reports/SECURITY-HARDENING-READINESS.md` - estado actual de cierre/readiness para hallazgos #8-#14

Comment on lines +142 to +146

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

The Spanish bullets added here are missing accents (evaluacion, catalogo) and mix English (readiness) into Spanish. Please correct accents and consider a consistent Spanish term (e.g., preparación/alistamiento) so this section reads cleanly.

Copilot uses AI. Check for mistakes.
### Rutas de Lectura Recomendadas

#### Para ejecutivos o arquitectos
Expand Down
8 changes: 7 additions & 1 deletion docs/operations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ It is intended for developers, operators, and support engineers who need repeata
### Index

- `monitor-operations-runbook.md` - day-to-day operational procedures, smoke checks, and incident-oriented troubleshooting
- `kafka-sasl-ssl-quickstart.md` - secure Kafka enablement (TLS/SASL) with bootstrap scripts
- `kafka-sasl-ssl-troubleshooting.md` - failure patterns and diagnostics for Kafka secure mode
- `kafka-sasl-ssl-acceptance-checklist.md` - release checklist to close secure Kafka rollout

### Scope

Expand All @@ -42,7 +45,7 @@ The operations set covers:
### Resumen Ejecutivo

Esta carpeta es el punto de entrada operativo para validar y diagnosticar `Monitor`.
Esta pensada para responder rapidamente una pregunta: **¿la plataforma esta sana, observable y conectada de extremo a extremo?**
Esta pensada para responder rapidamente una pregunta: **�la plataforma esta sana, observable y conectada de extremo a extremo?**

Comment on lines 45 to 49

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

The Spanish text contains mojibake/encoding artifacts (e.g., **�la plataforma...** should use ¿), and is missing accents (e.g., está). Since this line was modified, please correct the punctuation/accents so the bilingual doc renders correctly.

Copilot uses AI. Check for mistakes.
### Proposito

Expand All @@ -52,6 +55,9 @@ Esta pensada para desarrolladores, operadores y personal de soporte que necesite
### Indice

- `monitor-operations-runbook.md` - procedimientos operativos diarios, smoke checks y troubleshooting orientado a incidentes
- `kafka-sasl-ssl-quickstart.md` - habilitacion de Kafka seguro (TLS/SASL) con scripts de bootstrap
- `kafka-sasl-ssl-troubleshooting.md` - guia de diagnostico para fallas de Kafka en modo seguro
- `kafka-sasl-ssl-acceptance-checklist.md` - checklist de aceptacion para cierre operativo de Kafka seguro
Comment on lines +58 to +60

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

The newly added Spanish index entries are missing accents (habilitacion, guia, aceptacion). Please update to proper Spanish spelling (habilitación, guía, aceptación) for consistency with bilingual docs.

Suggested change
- `kafka-sasl-ssl-quickstart.md` - habilitacion de Kafka seguro (TLS/SASL) con scripts de bootstrap
- `kafka-sasl-ssl-troubleshooting.md` - guia de diagnostico para fallas de Kafka en modo seguro
- `kafka-sasl-ssl-acceptance-checklist.md` - checklist de aceptacion para cierre operativo de Kafka seguro
- `kafka-sasl-ssl-quickstart.md` - habilitación de Kafka seguro (TLS/SASL) con scripts de bootstrap
- `kafka-sasl-ssl-troubleshooting.md` - guía de diagnostico para fallas de Kafka en modo seguro
- `kafka-sasl-ssl-acceptance-checklist.md` - checklist de aceptación para cierre operativo de Kafka seguro

Copilot uses AI. Check for mistakes.

### Alcance

Expand Down
34 changes: 34 additions & 0 deletions docs/operations/kafka-sasl-ssl-acceptance-checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Kafka SASL/SSL Acceptance Checklist

Use this checklist to declare Hallazgo #12 operationally closed.

## Preconditions
- [ ] `.env` contains secure Kafka credentials
- [ ] TLS artifacts exist under `docker/kafka/secrets/`
- [ ] Preflight passes: `./scripts/kafka-secure-preflight.sh`

## Activation
- [ ] Secure mode applied: `./scripts/kafka-enable-secure-mode.sh`
- [ ] Overlay is active: `docker compose -f docker-compose.yml -f docker-compose.secure.yml ps`

## Smoke validation
- [ ] `./scripts/kafka-secure-smoke.sh` exits with code 0
- [ ] `kafka`, `kafka-connect`, `backend` are running
- [ ] Backend env has `KAFKA_SECURITY_PROTOCOL=SASL_SSL`
- [ ] Connect env has `CONNECT_SECURITY_PROTOCOL=SASL_SSL`
- [ ] Recent logs have no TLS/SASL handshake/auth failures

## Functional validation
- [ ] Debezium connector stays healthy
- [ ] CDC events still arrive to backend pipeline
- [ ] No regression on SSE event delivery

## Rollback validated
- [ ] Plaintext fallback works: `docker compose -f docker-compose.yml up -d`
- [ ] Services recover after rollback

## Evidence to attach in PR/issue
- [ ] `docker compose ps` output (secure mode)
- [ ] `./scripts/kafka-secure-preflight.sh` output
- [ ] `./scripts/kafka-secure-smoke.sh` output
- [ ] relevant logs for kafka/connect/backend
73 changes: 73 additions & 0 deletions docs/operations/kafka-sasl-ssl-quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Kafka SASL/SSL Quickstart

## Purpose
Enable encrypted and authenticated Kafka traffic using `docker-compose.secure.yml` on top of the default stack.

## 1) Prepare secrets
Generate truststores/keystores and credential files automatically:

```bash
./scripts/kafka-generate-secrets.sh
```

Artifacts are written under:
- `docker/kafka/secrets/`

See required filenames in:
- `docker/kafka/secrets/README.md`

## 2) Export required environment variables
Example:

```bash
export KAFKA_CONNECT_USERNAME=connect-user
export KAFKA_CONNECT_PASSWORD=connect-password
export KAFKA_CONNECT_TRUSTSTORE_PASSWORD=changeit

export KAFKA_BACKEND_USERNAME=backend-user
export KAFKA_BACKEND_PASSWORD=backend-password
export KAFKA_BACKEND_TRUSTSTORE_PASSWORD=changeit
```

## 3) Start secure stack

```bash
docker compose up -d kafka zookeeper
./scripts/kafka-bootstrap-scram-users.sh
docker compose -f docker-compose.yml -f docker-compose.secure.yml up -d
```

Or run the full flow in one command:

```bash
./scripts/kafka-enable-secure-mode.sh
```

## Troubleshooting preflight

Run explicit prerequisite checks before secure activation:

```bash
./scripts/kafka-secure-preflight.sh
```

If preflight fails, fix missing env vars/files and rerun.

## 4) Verify secure mode
- Kafka broker listener map includes `SASL_SSL`
- Backend starts with `KAFKA_SECURITY_PROTOCOL=SASL_SSL`
- Debezium connect worker starts with SASL settings

Comment on lines +56 to +60

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

The quickstart doesn’t mention hostname verification constraints. With the current secret generation (self-signed cert without SANs) and ssl.endpoint.identification.algorithm=HTTPS default, secure mode may fail with hostname/handshake errors unless cert SANs are added or endpoint identification is overridden. Please add a note here (or adjust the scripts) so the documented flow works end-to-end.

Copilot uses AI. Check for mistakes.
Run automated smoke check:

```bash
./scripts/kafka-secure-smoke.sh
```

## 5) Rollback to plaintext

```bash
docker compose -f docker-compose.yml up -d
```

This removes secure override and returns to base plaintext mode.
Loading
Loading