#!/bin/bash # Session state in RAM tmpfs and YubiKey integration load_secrets_to_ram() { local hours="${1:-$DEFAULT_SESSION_TTL}" local now now=$(date +%s) ensure_prerequisites # Валидация сессии по наличию непустых кэша секретов и SSH-ключа if [[ -f "${RAM_CACHE}" ]] && [[ -f "${RAM_KEY}" ]] && [[ -s "${RAM_KEY}" ]]; then local created age cached_ttl created=$(stat -c %Y "${RAM_CACHE}" 2>/dev/null || echo 0) age=$(( now - created )) cached_ttl=$(grep '^# TTL_SECONDS=' "${RAM_CACHE}" 2>/dev/null | cut -d= -f2 || echo 3600) if [[ "${cached_ttl}" -ne 0 ]] && (( age >= cached_ttl )); then log_warn "Время сессии истекло ($(( age / 60 )) мин >= $(( cached_ttl / 60 )) мин). Инвалидация кэша..." rm -f "${RAM_CACHE}" "${RAM_KEY}" else return 0 fi fi local ttl_seconds if [[ "${hours}" -eq 0 ]]; then ttl_seconds=0 else ttl_seconds=$(( hours * 3600 )) fi log_info "🔐 Вход в защищенный контур C2..." read -s -p "Master Password: " KP_PASS echo "" local yk_args=() if ykman info >/dev/null 2>&1; then yk_args=("-y" "2") log_info "YubiKey обнаружен. Приготовьтесь к аппаратному подтверждению (1 касание)..." fi # Атомарный 1-Touch экспорт всей базы KDBX в RAM (ровно 1 касание YubiKey на всю сессию) local tmp_dump="/dev/shm/.kdbx_dump_${now}_$$.xml" rm -f "${tmp_dump}" touch "${tmp_dump}" chmod 600 "${tmp_dump}" if ! echo "${KP_PASS}" | keepassxc-cli export "${yk_args[@]}" "${KDBX_PATH}" -f xml > "${tmp_dump}" 2>/dev/null; then log_err "Ошибка расшифровки базы KDBX (неверный пароль или таймаут касания YubiKey)" rm -f "${tmp_dump}" unset KP_PASS return 1 fi unset KP_PASS python3 "${REPO_ROOT}/scripts/lib/kdbx_parser.py" "${tmp_dump}" "${RAM_CACHE}" "${RAM_KEY}" "${ttl_seconds}" "${PVE_ENDPOINT}" "${VAULT_ADDR}" rm -f "${tmp_dump}" log_ok "База расшифрована за 1 касание. Ключ и секреты в RAM (TTL: ${hours}ч)" } run_isolated() { ensure_prerequisites load_secrets_to_ram ( set -a source "${RAM_CACHE}" set +a "$@" ) }