guardia-itsm/scripts/sm/ssl/ssl_expiry_check.sh
DESKTOP-TKLFCPRython 64c27c3509 feat(itsm): G-1~G-12 확장 기능 + 하네스/봇/설치스크립트 구현
G-1: 메신저 Webhook Relay + _send_to_room 실제 httpx 호출 구현
G-2: POST /api/tasks/bulk SR 대량작업 엔드포인트 (최대 100건)
G-3: 라이선스 만료 알림 스케줄러 (매일 09:00 KST)
G-4: 체험판 upgrade_banner 필드 + license.py 배너 로직
G-5: core/auto_rca.py + incidents/problem auto-rca 엔드포인트
G-6: core/deploy_impact.py + vibe impact-analysis 엔드포인트
G-7: core/ticket_classifier.py + SR 생성 시 AI 분류 + ai-suggestion API
G-8: VulnPatchRecord 모델 + vuln_scan 패치추적 4개 엔드포인트
G-9: core/jira_sync.py + gateway Jira/Confluence 연동 엔드포인트
G-10: core/push_notify.py + routers/push.py + PushSubscription 모델
G-11: approvals 다중승인 (위임/서명/기한초과/마감연장)
G-12: alembic.ini + migrations/ + cicd/migrate_to_postgres.sh

하네스: guardia-orchestrator 확장기능 Phase 반영
봇명령어: /sr /status /license /bulk 슬래시 명령어 추가
설치스크립트: setup/ (Ubuntu, CentOS, RHEL, Windows) --test 옵션 포함

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:18:52 +09:00

95 lines
3.8 KiB
Bash

#!/bin/bash
# ==============================================================================
# GUARDiA ITSM — SSL 인증서 만료일 점검 스크립트
# 경로: /opt/guardia/scripts/ssl/ssl_expiry_check.sh
#
# 사용법:
# ./ssl_expiry_check.sh <호스트> [포트(기본 443)] [timeout(기본 5초)]
#
# 출력 (JSON):
# 성공: {"host":"...","port":443,"expiry":"...","days_left":N,"level":"OK|WARN|CRITICAL","issuer":"..."}
# 실패: {"host":"...","port":443,"status":"ERROR","message":"..."}
#
# 반환 코드:
# 0 — 점검 완료 (OK/WARN/CRITICAL 모두)
# 1 — 인증서 조회 실패
# ==============================================================================
HOST="${1}"
PORT="${2:-443}"
TIMEOUT="${3:-5}"
if [ -z "${HOST}" ]; then
echo '{"status":"ERROR","message":"호스트 인수가 필요합니다. 사용법: ssl_expiry_check.sh <host> [port]"}'
exit 1
fi
# openssl 설치 확인
if ! command -v openssl &>/dev/null; then
echo '{"status":"ERROR","message":"openssl 명령어를 찾을 수 없습니다."}'
exit 1
fi
# ── 인증서 정보 조회 ──────────────────────────────────────────────────────────
CERT_INFO=$(echo | timeout "${TIMEOUT}" openssl s_client \
-servername "${HOST}" \
-connect "${HOST}:${PORT}" \
2>/dev/null)
if [ -z "${CERT_INFO}" ]; then
echo "{\"host\":\"${HOST}\",\"port\":${PORT},\"status\":\"ERROR\",\"message\":\"연결 실패 또는 타임아웃 (${TIMEOUT}s)\"}"
exit 1
fi
# 만료일 추출
EXPIRY=$(echo "${CERT_INFO}" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "${EXPIRY}" ]; then
echo "{\"host\":\"${HOST}\",\"port\":${PORT},\"status\":\"ERROR\",\"message\":\"인증서 만료일을 파싱할 수 없습니다.\"}"
exit 1
fi
# 발급기관 추출
ISSUER=$(echo "${CERT_INFO}" | openssl x509 -noout -issuer 2>/dev/null \
| sed 's/^issuer=//' | tr -d '\n' | sed 's/"/\\"/g')
# 주체(CN) 추출
SUBJECT_CN=$(echo "${CERT_INFO}" | openssl x509 -noout -subject 2>/dev/null \
| grep -oP '(?<=CN = )[^,]+' | head -1 | tr -d '\n' | sed 's/"/\\"/g')
# ── 날짜 계산 ─────────────────────────────────────────────────────────────────
# Linux date 와 macOS date 모두 지원
EXPIRY_TS=$(date -d "${EXPIRY}" +%s 2>/dev/null)
if [ -z "${EXPIRY_TS}" ]; then
# macOS/BSD 형식 시도
EXPIRY_TS=$(date -jf "%b %d %T %Y %Z" "${EXPIRY}" +%s 2>/dev/null)
fi
if [ -z "${EXPIRY_TS}" ]; then
# 추가 형식 시도 (Jan 1 ...)
EXPIRY_TS=$(date -d "$(echo "${EXPIRY}" | tr -s ' ')" +%s 2>/dev/null)
fi
if [ -z "${EXPIRY_TS}" ]; then
echo "{\"host\":\"${HOST}\",\"port\":${PORT},\"expiry\":\"${EXPIRY}\",\"status\":\"ERROR\",\"message\":\"날짜 파싱 실패\"}"
exit 1
fi
NOW_TS=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_TS - NOW_TS) / 86400 ))
# ── 알림 등급 ─────────────────────────────────────────────────────────────────
LEVEL="OK"
if [ "${DAYS_LEFT}" -le 0 ]; then
LEVEL="EXPIRED"
elif [ "${DAYS_LEFT}" -le 7 ]; then
LEVEL="CRITICAL"
elif [ "${DAYS_LEFT}" -le 30 ]; then
LEVEL="WARN"
fi
# ── JSON 출력 ─────────────────────────────────────────────────────────────────
cat <<EOF
{"host":"${HOST}","port":${PORT},"expiry":"${EXPIRY}","days_left":${DAYS_LEFT},"level":"${LEVEL}","issuer":"${ISSUER}","subject_cn":"${SUBJECT_CN}"}
EOF
exit 0