refactor: load ssh key from entry password and streamline session cache
This commit is contained in:
parent
8e283ad670
commit
bceb1080e5
|
|
@ -1,9 +1,6 @@
|
|||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
import base64
|
||||
import os
|
||||
import gzip
|
||||
import zlib
|
||||
|
||||
dump_file = sys.argv[1]
|
||||
cache_file = sys.argv[2]
|
||||
|
|
@ -15,9 +12,16 @@ vault_addr = sys.argv[6]
|
|||
tree = ET.parse(dump_file)
|
||||
root = tree.getroot()
|
||||
|
||||
# Исключаем чтение старых версий паролей и удаленных записей
|
||||
for h in root.findall(".//History"):
|
||||
h.clear()
|
||||
for g in root.findall(".//Group"):
|
||||
name = g.find("./Name")
|
||||
if name is not None and name.text == "Recycle Bin":
|
||||
g.clear()
|
||||
|
||||
entries = {}
|
||||
|
||||
# Чтение актуальных записей (первое вхождение отсекает старый мусор из History)
|
||||
for entry in root.findall(".//Entry"):
|
||||
title = ""
|
||||
username = ""
|
||||
|
|
@ -42,64 +46,23 @@ for entry in root.findall(".//Entry"):
|
|||
"notes": notes
|
||||
}
|
||||
|
||||
# Извлечение приватного SSH-ключа в RAM tmpfs
|
||||
# Прямое извлечение SSH-ключа из текстового поля записи Atlas Core Key
|
||||
ssh_loaded = False
|
||||
|
||||
# 1. Поиск во вложениях KeePass XML
|
||||
for b in root.findall(".//Binary"):
|
||||
raw_text = (b.text or "").strip()
|
||||
if len(raw_text) < 50:
|
||||
continue
|
||||
try:
|
||||
raw_bytes = base64.b64decode(raw_text)
|
||||
key_bytes = None
|
||||
|
||||
if raw_bytes.startswith(b"\x1f\x8b"):
|
||||
key_bytes = gzip.decompress(raw_bytes)
|
||||
elif b"-----BEGIN" in raw_bytes:
|
||||
key_bytes = raw_bytes
|
||||
elif len(raw_bytes) > 4:
|
||||
# Срез 4-байтового заголовка длины Qt (qCompress)
|
||||
try:
|
||||
key_bytes = zlib.decompress(raw_bytes[4:])
|
||||
except Exception:
|
||||
try:
|
||||
key_bytes = zlib.decompress(raw_bytes)
|
||||
except Exception:
|
||||
key_bytes = raw_bytes
|
||||
else:
|
||||
key_bytes = raw_bytes
|
||||
|
||||
if key_bytes and (b"PRIVATE KEY" in key_bytes or b"-----BEGIN" in key_bytes):
|
||||
with open(key_file, "wb") as kf:
|
||||
kf.write(key_bytes.strip() + b"\n")
|
||||
for title in ("Atlas Core Key", "AtlasCoreKey", "Atlas Core"):
|
||||
entry_data = entries.get(title, {})
|
||||
for field in ("password", "notes"):
|
||||
val = entry_data.get(field, "")
|
||||
if "-----BEGIN" in val or "PRIVATE KEY" in val:
|
||||
with open(key_file, "w") as kf:
|
||||
kf.write(val.strip() + "\n")
|
||||
os.chmod(key_file, 0o600)
|
||||
ssh_loaded = True
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
if ssh_loaded:
|
||||
break
|
||||
|
||||
# 2. Поиск в текстовых полях записей Atlas Core
|
||||
if not ssh_loaded:
|
||||
for title, data in entries.items():
|
||||
if "atlas" in title.lower() and "key" in title.lower():
|
||||
for field in ("password", "notes"):
|
||||
val = data.get(field, "")
|
||||
if "-----BEGIN" in val or "PRIVATE KEY" in val:
|
||||
with open(key_file, "w") as kf:
|
||||
kf.write(val.strip() + "\n")
|
||||
os.chmod(key_file, 0o600)
|
||||
ssh_loaded = True
|
||||
break
|
||||
if ssh_loaded:
|
||||
break
|
||||
|
||||
# Гарантия наличия файла для блокировки повторных запросов пароля
|
||||
if not ssh_loaded:
|
||||
sys.stderr.write("Внимание: приватный SSH-ключ не найден среди вложений KDBX.\n")
|
||||
with open(key_file, "wb") as kf:
|
||||
pass
|
||||
os.chmod(key_file, 0o600)
|
||||
sys.stderr.write("Внимание: приватный SSH-ключ не найден в полях Password/Notes записи Atlas Core Key.\n")
|
||||
|
||||
with open(cache_file, "w") as f:
|
||||
f.write(f"# TTL_SECONDS={ttl_sec}\n")
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ load_secrets_to_ram() {
|
|||
|
||||
ensure_prerequisites
|
||||
|
||||
# Валидация сессии строго по кэшу в RAM
|
||||
if [[ -f "${RAM_CACHE}" ]]; then
|
||||
# Валидация сессии по наличию непустых кэша секретов и 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 ))
|
||||
|
|
@ -40,6 +40,7 @@ load_secrets_to_ram() {
|
|||
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}"
|
||||
|
|
|
|||
Loading…
Reference in a new issue