✨ Add automated session logging system
Some checks failed
Build and Deploy Docs / build-and-deploy (push) Has been cancelled
Some checks failed
Build and Deploy Docs / build-and-deploy (push) Has been cancelled
- Created logs/ structure (sessions, operations, incidents) - Added session-start/log/end scripts - Installed Git hooks for auto-logging commits/pushes - Added shell integration for zsh - Created CHANGELOG.md - Documented today's session (2026-01-10)
This commit is contained in:
67
scripts/git-sync-all.sh
Executable file
67
scripts/git-sync-all.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# git-sync-all.sh - Синхронізація на всі Git репозиторії
|
||||
# ============================================================
|
||||
# Автоматично push на:
|
||||
# - GitHub (origin)
|
||||
# - Gitea (локальний, localhost:3000)
|
||||
# - GitLab (NODE3, через SSH tunnel)
|
||||
# ============================================================
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Кольори
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${GREEN}🔄 Git Sync All Remotes${NC}"
|
||||
echo "================================"
|
||||
date
|
||||
echo ""
|
||||
|
||||
# Поточна гілка
|
||||
BRANCH=$(git branch --show-current)
|
||||
echo -e "📌 Гілка: ${YELLOW}$BRANCH${NC}"
|
||||
echo ""
|
||||
|
||||
# 1. Push на GitHub (origin)
|
||||
echo -e "${GREEN}1. GitHub (origin)${NC}"
|
||||
if git push origin "$BRANCH" 2>/dev/null; then
|
||||
echo " ✅ GitHub OK"
|
||||
else
|
||||
echo -e " ${RED}❌ GitHub FAILED${NC}"
|
||||
fi
|
||||
|
||||
# 2. Push на Gitea (локальний)
|
||||
echo -e "${GREEN}2. Gitea (localhost:3000)${NC}"
|
||||
if git push gitea "$BRANCH" 2>/dev/null; then
|
||||
echo " ✅ Gitea OK"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠️ Gitea - можливо потрібен логін${NC}"
|
||||
# Спробуємо з credentials
|
||||
git push http://daarion-admin:DaarionGit2026!@localhost:3000/daarion-admin/microdao-daarion.git "$BRANCH" 2>/dev/null && echo " ✅ Gitea OK (з credentials)" || echo -e " ${RED}❌ Gitea FAILED${NC}"
|
||||
fi
|
||||
|
||||
# 3. Push на GitLab (NODE3)
|
||||
echo -e "${GREEN}3. GitLab (NODE3)${NC}"
|
||||
# Перевірка чи є SSH tunnel
|
||||
if nc -z localhost 8929 2>/dev/null; then
|
||||
if git push gitlab "$BRANCH" 2>/dev/null; then
|
||||
echo " ✅ GitLab OK"
|
||||
else
|
||||
# Спробуємо з credentials
|
||||
git push http://root:glpat-daarion-gitlab-2026@localhost:8929/root/microdao-daarion.git "$BRANCH" 2>/dev/null && echo " ✅ GitLab OK (з credentials)" || echo -e " ${RED}❌ GitLab FAILED${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " ${YELLOW}⚠️ GitLab недоступний. Запустіть SSH tunnel:${NC}"
|
||||
echo " ssh -p 33147 -L 8929:localhost:8929 zevs@80.77.35.151"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "================================"
|
||||
echo -e "${GREEN}✅ Синхронізація завершена${NC}"
|
||||
78
scripts/logging/install-hooks.sh
Executable file
78
scripts/logging/install-hooks.sh
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# install-hooks.sh — Встановлення Git hooks для автологування
|
||||
# ============================================================
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
|
||||
HOOKS_DIR="$PROJECT_DIR/.git/hooks"
|
||||
|
||||
echo "🔧 Встановлення Git hooks..."
|
||||
|
||||
# Post-commit hook — логує кожен коміт
|
||||
cat > "$HOOKS_DIR/post-commit" << 'HOOK'
|
||||
#!/bin/bash
|
||||
# Auto-log commits to session file
|
||||
|
||||
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
|
||||
SESSIONS_DIR="$PROJECT_DIR/logs/sessions"
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
TIME=$(date +%H:%M)
|
||||
SESSION_FILE="$SESSIONS_DIR/${DATE}.md"
|
||||
|
||||
# Отримати інформацію про коміт
|
||||
COMMIT_HASH=$(git rev-parse --short HEAD)
|
||||
COMMIT_MSG=$(git log -1 --pretty=%B | head -1)
|
||||
CHANGED_FILES=$(git diff-tree --no-commit-id --name-only -r HEAD | wc -l | tr -d ' ')
|
||||
|
||||
# Створити файл якщо не існує
|
||||
if [ ! -f "$SESSION_FILE" ]; then
|
||||
mkdir -p "$SESSIONS_DIR"
|
||||
cat > "$SESSION_FILE" << EOF
|
||||
# 📅 Session Log: $DATE
|
||||
|
||||
**Проєкт:** DAARION & MicroDAO
|
||||
|
||||
---
|
||||
|
||||
## 📋 Хронологія дій
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Додати запис про коміт
|
||||
echo "- **$TIME** — 📦 Commit \`$COMMIT_HASH\`: $COMMIT_MSG ($CHANGED_FILES files)" >> "$SESSION_FILE"
|
||||
HOOK
|
||||
|
||||
chmod +x "$HOOKS_DIR/post-commit"
|
||||
echo "✅ post-commit hook встановлено"
|
||||
|
||||
# Pre-push hook — логує push операції
|
||||
cat > "$HOOKS_DIR/pre-push" << 'HOOK'
|
||||
#!/bin/bash
|
||||
# Log push operations
|
||||
|
||||
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
|
||||
SESSIONS_DIR="$PROJECT_DIR/logs/sessions"
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
TIME=$(date +%H:%M)
|
||||
SESSION_FILE="$SESSIONS_DIR/${DATE}.md"
|
||||
|
||||
REMOTE_NAME=$1
|
||||
REMOTE_URL=$2
|
||||
|
||||
if [ -f "$SESSION_FILE" ]; then
|
||||
echo "- **$TIME** — 🚀 Push to \`$REMOTE_NAME\`" >> "$SESSION_FILE"
|
||||
fi
|
||||
HOOK
|
||||
|
||||
chmod +x "$HOOKS_DIR/pre-push"
|
||||
echo "✅ pre-push hook встановлено"
|
||||
|
||||
echo ""
|
||||
echo "🎉 Git hooks встановлено!"
|
||||
echo ""
|
||||
echo "Тепер автоматично логуватиметься:"
|
||||
echo " • Кожен commit"
|
||||
echo " • Кожен push"
|
||||
97
scripts/logging/session-end.sh
Executable file
97
scripts/logging/session-end.sh
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# session-end.sh — Завершення робочої сесії
|
||||
# ============================================================
|
||||
# Автоматично:
|
||||
# - Додає підсумок сесії
|
||||
# - Комітить зміни
|
||||
# - Пушить на всі репозиторії
|
||||
# ============================================================
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
|
||||
SESSIONS_DIR="$PROJECT_DIR/logs/sessions"
|
||||
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
TIME=$(date +%H:%M)
|
||||
|
||||
SESSION_FILE="${DAARION_SESSION_FILE:-$SESSIONS_DIR/${DATE}.md}"
|
||||
|
||||
# Кольори
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${GREEN}🏁 Завершення сесії${NC}"
|
||||
echo "================================"
|
||||
|
||||
# Додати підсумок
|
||||
if [ -f "$SESSION_FILE" ]; then
|
||||
cat >> "$SESSION_FILE" << EOF
|
||||
|
||||
### $TIME — Сесію завершено
|
||||
|
||||
---
|
||||
|
||||
## 📊 Підсумок
|
||||
|
||||
- **Завершено:** $TIME
|
||||
- **Git status:** $(cd "$PROJECT_DIR" && git status --short | wc -l | tr -d ' ') змінених файлів
|
||||
|
||||
EOF
|
||||
echo -e "📄 Оновлено: ${CYAN}$SESSION_FILE${NC}"
|
||||
fi
|
||||
|
||||
# Git операції
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}📦 Git операції...${NC}"
|
||||
|
||||
# Додати всі зміни
|
||||
git add -A
|
||||
|
||||
# Перевірити чи є що комітити
|
||||
if git diff --cached --quiet; then
|
||||
echo "ℹ️ Немає змін для коміту"
|
||||
else
|
||||
# Коміт
|
||||
COMMIT_MSG="📝 Session $DATE: auto-commit on session end"
|
||||
git commit -m "$COMMIT_MSG"
|
||||
echo -e "✅ Commit: ${CYAN}$COMMIT_MSG${NC}"
|
||||
|
||||
# Push на всі remote
|
||||
echo ""
|
||||
echo -e "${YELLOW}🚀 Push на всі репозиторії...${NC}"
|
||||
|
||||
# GitHub
|
||||
if git push origin 2>/dev/null; then
|
||||
echo " ✅ GitHub (origin)"
|
||||
else
|
||||
echo " ⚠️ GitHub — помилка або немає змін"
|
||||
fi
|
||||
|
||||
# Gitea
|
||||
if git push gitea 2>/dev/null; then
|
||||
echo " ✅ Gitea"
|
||||
else
|
||||
echo " ⚠️ Gitea — помилка або недоступний"
|
||||
fi
|
||||
|
||||
# GitLab (через tunnel)
|
||||
if nc -z localhost 8929 2>/dev/null; then
|
||||
if git push gitlab 2>/dev/null; then
|
||||
echo " ✅ GitLab"
|
||||
else
|
||||
echo " ⚠️ GitLab — помилка"
|
||||
fi
|
||||
else
|
||||
echo " ⚠️ GitLab — SSH tunnel не активний"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ Сесію завершено!${NC}"
|
||||
echo "До зустрічі! 👋"
|
||||
43
scripts/logging/session-log.sh
Executable file
43
scripts/logging/session-log.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# session-log.sh — Додати запис до поточної сесії
|
||||
# ============================================================
|
||||
# Використання: ./scripts/logging/session-log.sh "Опис дії"
|
||||
# Або через alias: session-log "Опис дії"
|
||||
# ============================================================
|
||||
|
||||
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
|
||||
SESSIONS_DIR="$PROJECT_DIR/logs/sessions"
|
||||
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
TIME=$(date +%H:%M)
|
||||
|
||||
SESSION_FILE="${DAARION_SESSION_FILE:-$SESSIONS_DIR/${DATE}.md}"
|
||||
MESSAGE="$*"
|
||||
|
||||
if [ -z "$MESSAGE" ]; then
|
||||
echo "❌ Вкажіть опис дії"
|
||||
echo "Використання: session-log \"Опис дії\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Якщо файл не існує — створити
|
||||
if [ ! -f "$SESSION_FILE" ]; then
|
||||
mkdir -p "$SESSIONS_DIR"
|
||||
cat > "$SESSION_FILE" << EOF
|
||||
# 📅 Session Log: $DATE
|
||||
|
||||
**Оператор:** Ivan + AI Assistant
|
||||
**Проєкт:** DAARION & MicroDAO
|
||||
|
||||
---
|
||||
|
||||
## 📋 Хронологія дій
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Додати запис
|
||||
echo "- **$TIME** — $MESSAGE" >> "$SESSION_FILE"
|
||||
|
||||
echo "✅ Записано: $MESSAGE"
|
||||
76
scripts/logging/session-start.sh
Executable file
76
scripts/logging/session-start.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# session-start.sh — Початок нової робочої сесії
|
||||
# ============================================================
|
||||
# Використання: ./scripts/logging/session-start.sh [опис]
|
||||
# Приклад: ./scripts/logging/session-start.sh "Деплой нових сервісів"
|
||||
# ============================================================
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_DIR="/Users/apple/github-projects/microdao-daarion"
|
||||
LOGS_DIR="$PROJECT_DIR/logs"
|
||||
SESSIONS_DIR="$LOGS_DIR/sessions"
|
||||
|
||||
# Дата та час
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
TIME=$(date +%H:%M)
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# Опис сесії
|
||||
DESCRIPTION="${1:-Робоча сесія}"
|
||||
|
||||
# Файл сесії
|
||||
SESSION_FILE="$SESSIONS_DIR/${DATE}.md"
|
||||
|
||||
# Кольори
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${GREEN}🚀 Початок нової сесії${NC}"
|
||||
echo "================================"
|
||||
echo -e "📅 Дата: ${CYAN}$DATE${NC}"
|
||||
echo -e "⏰ Час: ${CYAN}$TIME${NC}"
|
||||
echo -e "📝 Опис: ${YELLOW}$DESCRIPTION${NC}"
|
||||
echo ""
|
||||
|
||||
# Якщо файл не існує — створити шаблон
|
||||
if [ ! -f "$SESSION_FILE" ]; then
|
||||
cat > "$SESSION_FILE" << EOF
|
||||
# 📅 Session Log: $DATE
|
||||
|
||||
**Оператор:** Ivan + AI Assistant
|
||||
**Проєкт:** DAARION & MicroDAO
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Цілі сесії
|
||||
|
||||
- [ ] $DESCRIPTION
|
||||
|
||||
---
|
||||
|
||||
## 📋 Хронологія дій
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Додати запис про початок сесії
|
||||
cat >> "$SESSION_FILE" << EOF
|
||||
|
||||
### $TIME — Початок: $DESCRIPTION
|
||||
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}✅ Сесію розпочато!${NC}"
|
||||
echo "📄 Файл: $SESSION_FILE"
|
||||
echo ""
|
||||
echo "Команди:"
|
||||
echo " session-log \"Опис дії\" — додати запис"
|
||||
echo " session-end — завершити сесію"
|
||||
|
||||
# Експортуємо змінні для інших скриптів
|
||||
export DAARION_SESSION_FILE="$SESSION_FILE"
|
||||
export DAARION_SESSION_START="$TIMESTAMP"
|
||||
81
scripts/logging/shell-integration.sh
Executable file
81
scripts/logging/shell-integration.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# shell-integration.sh — Інтеграція логування з shell
|
||||
# ============================================================
|
||||
# Додайте до ~/.zshrc або ~/.bashrc:
|
||||
# source /Users/apple/github-projects/microdao-daarion/scripts/logging/shell-integration.sh
|
||||
# ============================================================
|
||||
|
||||
# Шляхи
|
||||
export DAARION_PROJECT="/Users/apple/github-projects/microdao-daarion"
|
||||
export DAARION_LOGS="$DAARION_PROJECT/logs"
|
||||
|
||||
# Aliases для швидкого доступу
|
||||
alias daarion="cd $DAARION_PROJECT"
|
||||
alias session-start="$DAARION_PROJECT/scripts/logging/session-start.sh"
|
||||
alias session-log="$DAARION_PROJECT/scripts/logging/session-log.sh"
|
||||
alias session-end="$DAARION_PROJECT/scripts/logging/session-end.sh"
|
||||
alias git-sync="$DAARION_PROJECT/scripts/git-sync-all.sh"
|
||||
|
||||
# Функція для логування важливих команд
|
||||
daarion-log() {
|
||||
local cmd="$*"
|
||||
local date=$(date +%Y-%m-%d)
|
||||
local time=$(date +%H:%M:%S)
|
||||
local session_file="$DAARION_LOGS/sessions/${date}.md"
|
||||
|
||||
if [ -f "$session_file" ]; then
|
||||
echo "- **$time** — \`$cmd\`" >> "$session_file"
|
||||
fi
|
||||
|
||||
# Виконати команду
|
||||
eval "$cmd"
|
||||
}
|
||||
|
||||
# Функція для швидкого запису нотатки
|
||||
daarion-note() {
|
||||
local note="$*"
|
||||
local date=$(date +%Y-%m-%d)
|
||||
local time=$(date +%H:%M)
|
||||
local session_file="$DAARION_LOGS/sessions/${date}.md"
|
||||
|
||||
if [ ! -f "$session_file" ]; then
|
||||
mkdir -p "$DAARION_LOGS/sessions"
|
||||
cat > "$session_file" << EOF
|
||||
# 📅 Session Log: $date
|
||||
|
||||
**Проєкт:** DAARION & MicroDAO
|
||||
|
||||
---
|
||||
|
||||
## 📋 Нотатки
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "- **$time** — 📝 $note" >> "$session_file"
|
||||
echo "✅ Нотатку додано"
|
||||
}
|
||||
|
||||
# Автоматичне логування при вході в директорію проєкту
|
||||
daarion-auto-session() {
|
||||
if [[ "$PWD" == "$DAARION_PROJECT"* ]]; then
|
||||
local date=$(date +%Y-%m-%d)
|
||||
local session_file="$DAARION_LOGS/sessions/${date}.md"
|
||||
|
||||
if [ ! -f "$session_file" ]; then
|
||||
echo "📝 Нова сесія для $date"
|
||||
session-start "Автоматична сесія"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Hook для zsh (опціонально)
|
||||
if [ -n "$ZSH_VERSION" ]; then
|
||||
# Додати до chpwd hook
|
||||
autoload -U add-zsh-hook
|
||||
add-zsh-hook chpwd daarion-auto-session
|
||||
fi
|
||||
|
||||
# Повідомлення при завантаженні
|
||||
echo "🔧 DAARION logging loaded. Commands: session-start, session-log, session-end, daarion-note"
|
||||
355
scripts/security/triage-postgres-compromise.sh
Executable file
355
scripts/security/triage-postgres-compromise.sh
Executable file
@@ -0,0 +1,355 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# TRIAGE SCRIPT: Verify if PostgreSQL images are compromised OR NODE1 is compromised
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
#
|
||||
# USAGE:
|
||||
# ./triage-postgres-compromise.sh [local|remote|compare]
|
||||
#
|
||||
# MODES:
|
||||
# local - Run checks on LOCAL machine (MacBook/clean host)
|
||||
# remote - Run checks on NODE1 via SSH
|
||||
# compare - Compare results between local and remote
|
||||
#
|
||||
# REQUIREMENTS:
|
||||
# - Docker installed locally
|
||||
# - SSH access to NODE1 (root@144.76.224.179)
|
||||
# - Run on CLEAN machine (not NODE1!)
|
||||
#
|
||||
# Created: 2026-01-10
|
||||
# Purpose: Incident #4 triage - determine if host or images compromised
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
NODE1_HOST="root@144.76.224.179"
|
||||
IMAGES_TO_TEST=(
|
||||
"postgres:16-alpine"
|
||||
"postgres:16"
|
||||
"postgres:15-alpine"
|
||||
"postgres:14-alpine"
|
||||
"postgres:14"
|
||||
)
|
||||
|
||||
# IOC patterns
|
||||
IOC_FILES=(
|
||||
"/tmp/httpd"
|
||||
"/tmp/.perf.c"
|
||||
"/tmp/mysql"
|
||||
"/tmp/cpioshuf"
|
||||
"/tmp/ipcalc"
|
||||
)
|
||||
|
||||
RESULTS_DIR="/tmp/triage-results-$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$RESULTS_DIR"
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Function: Check container for IOC
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
check_container_ioc() {
|
||||
local image="$1"
|
||||
local location="$2" # "local" or "remote"
|
||||
local result_file="$RESULTS_DIR/${image//[:\/]/_}_${location}.txt"
|
||||
|
||||
log_info "Testing $image on $location..."
|
||||
|
||||
local docker_cmd="docker"
|
||||
if [[ "$location" == "remote" ]]; then
|
||||
docker_cmd="ssh $NODE1_HOST docker"
|
||||
fi
|
||||
|
||||
# Pull image
|
||||
$docker_cmd pull "$image" 2>/dev/null || {
|
||||
log_error "Failed to pull $image"
|
||||
echo "PULL_FAILED" > "$result_file"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Get digest
|
||||
local digest=$($docker_cmd inspect --format='{{index .RepoDigests 0}}' "$image" 2>/dev/null || echo "NO_DIGEST")
|
||||
echo "DIGEST: $digest" > "$result_file"
|
||||
|
||||
# Run container and check /tmp
|
||||
local tmp_contents=$($docker_cmd run --rm "$image" sh -c "ls -la /tmp/ 2>/dev/null; find /tmp -type f 2>/dev/null" 2>/dev/null || echo "RUN_FAILED")
|
||||
echo "TMP_CONTENTS:" >> "$result_file"
|
||||
echo "$tmp_contents" >> "$result_file"
|
||||
|
||||
# Check for IOC
|
||||
local ioc_found=0
|
||||
for ioc in "${IOC_FILES[@]}"; do
|
||||
if echo "$tmp_contents" | grep -q "$(basename "$ioc")"; then
|
||||
log_error "IOC FOUND in $image on $location: $ioc"
|
||||
echo "IOC_FOUND: $ioc" >> "$result_file"
|
||||
ioc_found=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $ioc_found -eq 0 ]]; then
|
||||
log_success "$image on $location: CLEAN"
|
||||
echo "STATUS: CLEAN" >> "$result_file"
|
||||
else
|
||||
log_error "$image on $location: INFECTED"
|
||||
echo "STATUS: INFECTED" >> "$result_file"
|
||||
fi
|
||||
|
||||
return $ioc_found
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Function: Check NODE1 host for persistence
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
check_node1_persistence() {
|
||||
log_info "Checking NODE1 for persistence mechanisms..."
|
||||
local result_file="$RESULTS_DIR/node1_persistence.txt"
|
||||
|
||||
ssh "$NODE1_HOST" << 'REMOTE_SCRIPT' > "$result_file" 2>&1
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "NODE1 PERSISTENCE CHECK - $(date)"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
|
||||
echo ""
|
||||
echo "=== CRON JOBS ==="
|
||||
echo "--- root crontab ---"
|
||||
crontab -l 2>/dev/null || echo "(empty)"
|
||||
echo "--- /etc/crontab ---"
|
||||
cat /etc/crontab 2>/dev/null | grep -v "^#" | grep -v "^$"
|
||||
echo "--- /etc/cron.d/ ---"
|
||||
ls -la /etc/cron.d/ 2>/dev/null
|
||||
for f in /etc/cron.d/*; do
|
||||
echo "--- $f ---"
|
||||
cat "$f" 2>/dev/null | grep -v "^#" | grep -v "^$"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== SYSTEMD SERVICES (suspicious) ==="
|
||||
systemctl list-units --type=service --all 2>/dev/null | grep -iE "perf|miner|http|crypto|kdev|kinsin" || echo "(none found)"
|
||||
|
||||
echo ""
|
||||
echo "=== LD_PRELOAD ==="
|
||||
echo "--- /etc/ld.so.preload ---"
|
||||
cat /etc/ld.so.preload 2>/dev/null || echo "(not exists)"
|
||||
echo "--- LD_PRELOAD env ---"
|
||||
echo "${LD_PRELOAD:-not set}"
|
||||
|
||||
echo ""
|
||||
echo "=== SUSPICIOUS PROCESSES ==="
|
||||
ps aux | grep -E "(httpd|xmrig|kdevtmp|kinsing|perfctl|\.perf|softirq|vrarhpb)" | grep -v grep || echo "(none running)"
|
||||
|
||||
echo ""
|
||||
echo "=== HIGH CPU PROCESSES ==="
|
||||
ps aux --sort=-%cpu | head -10
|
||||
|
||||
echo ""
|
||||
echo "=== NETWORK CONNECTIONS (mining pools) ==="
|
||||
ss -anp 2>/dev/null | grep -E "(3333|4444|5555|8080|8888|14433|14444)" | head -20 || echo "(none found)"
|
||||
|
||||
echo ""
|
||||
echo "=== SSH AUTHORIZED KEYS ==="
|
||||
echo "--- /root/.ssh/authorized_keys ---"
|
||||
cat /root/.ssh/authorized_keys 2>/dev/null | head -20
|
||||
|
||||
echo ""
|
||||
echo "=== /tmp CONTENTS ==="
|
||||
ls -la /tmp/ 2>/dev/null
|
||||
find /tmp -type f -executable 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "=== /var/tmp CONTENTS ==="
|
||||
find /var/tmp -type f -executable 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "=== /dev/shm CONTENTS ==="
|
||||
ls -la /dev/shm/ 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "=== DOCKER DAEMON CONFIG ==="
|
||||
cat /etc/docker/daemon.json 2>/dev/null || echo "(default config)"
|
||||
|
||||
echo ""
|
||||
echo "=== KERNEL MODULES (first 30) ==="
|
||||
lsmod | head -30
|
||||
|
||||
echo ""
|
||||
echo "=== SYSTEM LOAD ==="
|
||||
uptime
|
||||
cat /proc/loadavg
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "CHECK COMPLETE"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
REMOTE_SCRIPT
|
||||
|
||||
log_info "Results saved to: $result_file"
|
||||
|
||||
# Quick analysis
|
||||
if grep -qE "(httpd|xmrig|perfctl|kdevtmp|kinsing)" "$result_file"; then
|
||||
log_error "SUSPICIOUS ACTIVITY DETECTED ON NODE1!"
|
||||
return 1
|
||||
else
|
||||
log_success "No obvious persistence found (manual review recommended)"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Function: Compare local vs remote results
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
compare_results() {
|
||||
log_info "Comparing local vs remote results..."
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "COMPARISON RESULTS"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
local local_infected=0
|
||||
local remote_infected=0
|
||||
|
||||
for image in "${IMAGES_TO_TEST[@]}"; do
|
||||
local safe_name="${image//[:\/]/_}"
|
||||
local local_file="$RESULTS_DIR/${safe_name}_local.txt"
|
||||
local remote_file="$RESULTS_DIR/${safe_name}_remote.txt"
|
||||
|
||||
echo "Image: $image"
|
||||
echo " Local digest: $(grep "DIGEST:" "$local_file" 2>/dev/null | cut -d' ' -f2- || echo "N/A")"
|
||||
echo " Remote digest: $(grep "DIGEST:" "$remote_file" 2>/dev/null | cut -d' ' -f2- || echo "N/A")"
|
||||
echo " Local status: $(grep "STATUS:" "$local_file" 2>/dev/null | cut -d' ' -f2 || echo "N/A")"
|
||||
echo " Remote status: $(grep "STATUS:" "$remote_file" 2>/dev/null | cut -d' ' -f2 || echo "N/A")"
|
||||
|
||||
if grep -q "STATUS: INFECTED" "$local_file" 2>/dev/null; then
|
||||
local_infected=$((local_infected + 1))
|
||||
fi
|
||||
if grep -q "STATUS: INFECTED" "$remote_file" 2>/dev/null; then
|
||||
remote_infected=$((remote_infected + 1))
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "VERDICT:"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
|
||||
if [[ $local_infected -eq 0 && $remote_infected -gt 0 ]]; then
|
||||
echo -e "${RED}🔴 NODE1 IS COMPROMISED${NC}"
|
||||
echo ""
|
||||
echo "Evidence: Same images are CLEAN locally but INFECTED on NODE1"
|
||||
echo ""
|
||||
echo "REQUIRED ACTIONS:"
|
||||
echo " 1. STOP using NODE1 immediately"
|
||||
echo " 2. Rotate ALL secrets (SSH keys, tokens, passwords)"
|
||||
echo " 3. Full OS reinstall (not cleanup!)"
|
||||
echo " 4. Deploy only verified images from clean host"
|
||||
elif [[ $local_infected -gt 0 && $remote_infected -gt 0 ]]; then
|
||||
echo -e "${RED}🔴 DOCKER HUB IMAGES MAY BE COMPROMISED${NC}"
|
||||
echo ""
|
||||
echo "Evidence: Same images are INFECTED both locally and on NODE1"
|
||||
echo ""
|
||||
echo "REQUIRED ACTIONS:"
|
||||
echo " 1. Report to Docker Security team"
|
||||
echo " 2. Use alternative registry (GHCR, Quay.io)"
|
||||
echo " 3. Build from source"
|
||||
echo " 4. Scan all images with Trivy before use"
|
||||
elif [[ $local_infected -eq 0 && $remote_infected -eq 0 ]]; then
|
||||
echo -e "${GREEN}✅ ALL IMAGES APPEAR CLEAN${NC}"
|
||||
echo ""
|
||||
echo "However, if you saw IOC earlier, the malware may be:"
|
||||
echo " - Triggered by specific conditions"
|
||||
echo " - Using time-based activation"
|
||||
echo " - Detected your testing and hiding"
|
||||
echo ""
|
||||
echo "Recommend: Still perform NODE1 persistence check"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ INCONCLUSIVE RESULTS${NC}"
|
||||
echo ""
|
||||
echo "Manual investigation required"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Full results saved in: $RESULTS_DIR"
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Main
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
main() {
|
||||
local mode="${1:-help}"
|
||||
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo "PostgreSQL Compromise Triage Script"
|
||||
echo "Results directory: $RESULTS_DIR"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
case "$mode" in
|
||||
local)
|
||||
log_info "Running LOCAL checks (this machine)..."
|
||||
for image in "${IMAGES_TO_TEST[@]}"; do
|
||||
check_container_ioc "$image" "local" || true
|
||||
done
|
||||
;;
|
||||
remote)
|
||||
log_info "Running REMOTE checks (NODE1)..."
|
||||
check_node1_persistence || true
|
||||
for image in "${IMAGES_TO_TEST[@]}"; do
|
||||
check_container_ioc "$image" "remote" || true
|
||||
done
|
||||
;;
|
||||
compare)
|
||||
log_info "Running FULL comparison..."
|
||||
log_warn "This will pull images on both local and NODE1"
|
||||
echo ""
|
||||
|
||||
# Run local checks
|
||||
for image in "${IMAGES_TO_TEST[@]}"; do
|
||||
check_container_ioc "$image" "local" || true
|
||||
done
|
||||
|
||||
# Run remote checks
|
||||
check_node1_persistence || true
|
||||
for image in "${IMAGES_TO_TEST[@]}"; do
|
||||
check_container_ioc "$image" "remote" || true
|
||||
done
|
||||
|
||||
# Compare
|
||||
compare_results
|
||||
;;
|
||||
persistence)
|
||||
check_node1_persistence
|
||||
cat "$RESULTS_DIR/node1_persistence.txt"
|
||||
;;
|
||||
help|*)
|
||||
echo "Usage: $0 [local|remote|compare|persistence]"
|
||||
echo ""
|
||||
echo "Modes:"
|
||||
echo " local - Check images on THIS machine (should be clean)"
|
||||
echo " remote - Check images on NODE1 + persistence mechanisms"
|
||||
echo " compare - Run both and compare results (RECOMMENDED)"
|
||||
echo " persistence - Only check NODE1 for persistence mechanisms"
|
||||
echo ""
|
||||
echo "⚠️ Run this script from a CLEAN machine (not NODE1!)"
|
||||
echo ""
|
||||
echo "Example workflow:"
|
||||
echo " 1. ./triage-postgres-compromise.sh compare"
|
||||
echo " 2. Review results in $RESULTS_DIR"
|
||||
echo " 3. If NODE1 compromised → full rebuild"
|
||||
echo " 4. If images compromised → report to Docker"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -41,3 +41,12 @@ echo " docker-compose -f docker-compose.city-space.yml logs -f"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -44,3 +44,12 @@ echo " ./scripts/test-phase2-e2e.sh"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -53,3 +53,12 @@ echo ""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -57,3 +57,12 @@ echo "📚 Documentation: docs/PHASE4_READY.md"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -16,3 +16,12 @@ echo "✅ Services stopped!"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,3 +19,12 @@ echo " docker-compose -f docker-compose.agents.yml down -v"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,3 +18,12 @@ echo ""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,3 +13,12 @@ echo "✅ Phase 4 services stopped"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -206,3 +206,12 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user