-
Notifications
You must be signed in to change notification settings - Fork 0
feat(security): add kafka secure-mode smoke test and acceptance checklist #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,72 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" | ||||||||||||||||||||||||||||||||||||||||||||||||
| cd "$ROOT_DIR" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| services=(kafka kafka-connect backend) | ||||||||||||||||||||||||||||||||||||||||||||||||
| failed=0 | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| echo "[1/4] Checking container status" | ||||||||||||||||||||||||||||||||||||||||||||||||
| for svc in "${services[@]}"; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| if ! docker compose ps "$svc" >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo " [FAIL] service not found: $svc" | ||||||||||||||||||||||||||||||||||||||||||||||||
| failed=1 | ||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| status="$(docker compose ps --format json "$svc" | tr -d '\n' | sed 's/}\s*{/}\n{/g' | grep -m1 '"Service":"'"$svc"'"' || true)" | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ -z "$status" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo " [FAIL] unable to read status: $svc" | ||||||||||||||||||||||||||||||||||||||||||||||||
| failed=1 | ||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if echo "$status" | grep -q '"State":"running"'; then | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+18
to
+25
|
||||||||||||||||||||||||||||||||||||||||||||||||
| status="$(docker compose ps --format json "$svc" | tr -d '\n' | sed 's/}\s*{/}\n{/g' | grep -m1 '"Service":"'"$svc"'"' || true)" | |
| if [[ -z "$status" ]]; then | |
| echo " [FAIL] unable to read status: $svc" | |
| failed=1 | |
| continue | |
| fi | |
| if echo "$status" | grep -q '"State":"running"'; then | |
| states="$(docker compose ps --format '{{.State}}' "$svc" || true)" | |
| if [[ -z "$states" ]]; then | |
| echo " [FAIL] unable to read status: $svc" | |
| failed=1 | |
| continue | |
| fi | |
| all_running=1 | |
| while IFS= read -r state; do | |
| if [[ "$state" != "running" ]]; then | |
| all_running=0 | |
| fi | |
| done <<< "$states" | |
| if [[ "$all_running" -eq 1 ]]; then |
Copilot
AI
Apr 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block prints [WARN] but still sets failed=1, which makes the script exit non-zero. Either treat these matches as [FAIL] (and keep failing), or keep [WARN] but don’t flip failed so operators can distinguish a warning-only run from a hard failure.
| failed=1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The checklist says ".env contains secure Kafka credentials", but the referenced preflight script (
./scripts/kafka-secure-preflight.sh) only checks the current process environment and does not source.env. This can confuse operators who rely on.envalone. Consider updating the checklist to explicitly say the vars must be exported in the shell (or that.envmust be sourced before running preflight/smoke scripts).