fix(session): correct kdbx parser path to zarya and scope flux sync

This commit is contained in:
v 2026-10-25 18:07:55 +03:00
parent 0b6d470fb9
commit 279dea6567
15 changed files with 1486 additions and 43 deletions

12
bin/fc Executable file
View file

@ -0,0 +1,12 @@
#!/bin/bash
set -euo pipefail
if [[ $# -eq 0 ]]; then
echo "Использование: fc <файл>"
exit 1
fi
if [[ -f "$1" ]]; then
wl-copy < "$1"
echo "'$1' +++"
else
echo "'$1'+++"
fi

7
bin/gg Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
set -euo pipefail
if [[ -z "${1:-}" ]]; then
echo "Тема СВО не раскрыта: gg \"сообщение\""
exit 1
fi
git add . && git commit -m "$1" && git push

9
bin/op Executable file
View file

@ -0,0 +1,9 @@
#!/bin/bash
set -euo pipefail
if [[ $# -eq 0 ]]; then
echo "Использование: op <файл...>"
exit 1
fi
for f in "$@"; do
printf "file://%s\r\n" "$(realpath "$f")"
done | wl-copy -t text/uri-list

View file

@ -7,7 +7,11 @@ SUBCMD="${1:-help}"
shift || true shift || true
case "${SUBCMD}" in case "${SUBCMD}" in
git-credential) exec "${ZARYA_DIR}/cmd/git-credential.sh" "$@" ;;
exec) exec "${ZARYA_DIR}/cmd/exec.sh" "$@" ;;
p|pod|pods) exec "${ZARYA_DIR}/cmd/pods.sh" "$@" ;; p|pod|pods) exec "${ZARYA_DIR}/cmd/pods.sh" "$@" ;;
node|nodes) exec "${ZARYA_DIR}/cmd/nodes.sh" "$@" ;;
flux) exec "${ZARYA_DIR}/cmd/flux.sh" "$@" ;;
e|err|errors) exec "${ZARYA_DIR}/cmd/errors.sh" "$@" ;; e|err|errors) exec "${ZARYA_DIR}/cmd/errors.sh" "$@" ;;
l|log|logs) exec "${ZARYA_DIR}/cmd/logs.sh" "$@" ;; l|log|logs) exec "${ZARYA_DIR}/cmd/logs.sh" "$@" ;;
n|net) exec "${ZARYA_DIR}/cmd/net.sh" "$@" ;; n|net) exec "${ZARYA_DIR}/cmd/net.sh" "$@" ;;
@ -24,14 +28,18 @@ case "${SUBCMD}" in
gc) exec "${ZARYA_DIR}/layers/gc.sh" "$@" ;; gc) exec "${ZARYA_DIR}/layers/gc.sh" "$@" ;;
help|--help|-h) help|--help|-h)
cat <<EOF cat <<EOF
Zarya C2 Operator Interface (z) ZARYA Operator Interface (z)
Команды диагностики: Диагностика и мониторинг:
z pods [-w] [-n <ns>] [-s <query>] [-A] Просмотр подов z pods [-w] [-n <ns>] [-s <query>] [-A] Просмотр подов
z nodes [-w] Статус нод, роли, зона и регион
z errors Мгновенный триаж сломанных сервисов z errors Мгновенный триаж сломанных сервисов
z logs <service> [-f] [-t <N>] Логи любого сервиса без ввода неймспейса z logs <service> [-f] [-t <N>] Логи сервиса без ввода неймспейса
z net Сетевой радар доступности узлов (1 сек) z net Сетевой радар доступности узлов (1 сек)
z disks Срез пулов astra/terra и ZVOL томов K8s z disks Срез пулов astra/terra и томов K8s
Управление и сессия: GitOps и оркестрация:
z flux [status|sync|logs] Управление GitOps-конвергенцией
z exec <команда...> Вызов бинарников внутри RAM-изоляции
Сессия и доступы:
z login [TTL] Открытие смены (YubiKey + RAM) z login [TTL] Открытие смены (YubiKey + RAM)
z logout Мгновенная очистка RAM z logout Мгновенная очистка RAM
z unseal Распечатывание OpenBao Vault z unseal Распечатывание OpenBao Vault
@ -40,8 +48,8 @@ Zarya C2 Operator Interface (z)
z run <selector> Плейбуки Ansible (01, 02) z run <selector> Плейбуки Ansible (01, 02)
z a [-auto-approve] OpenTofu apply в RAM-изоляции z a [-auto-approve] OpenTofu apply в RAM-изоляции
Телеметрия и LLM: Телеметрия и LLM:
z snap Снятие полного .md аудита в snapshots/ z snap Снятие аудита в state/snapshots/
z pack [code|state|atlas] Сборка контекста Repomix z pack [all|atlas|code|state] Сборка контекстов Repomix для LLM
EOF EOF
;; ;;
*) *)

11
cmd/exec.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/bash
set -euo pipefail
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ZARYA_DIR}/lib/common.sh"
if [[ $# -eq 0 ]]; then
log_err "Использование: z exec <команда> [аргументы...]"
exit 1
fi
run_isolated "$@"

28
cmd/flux.sh Executable file
View file

@ -0,0 +1,28 @@
#!/bin/bash
set -uo pipefail
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ZARYA_DIR}/lib/common.sh"
subcmd="${1:-status}"
shift || true
case "${subcmd}" in
sync|reconcile|s)
log_info "Принудительная конвергенция FluxCD..."
flux reconcile source git atlas-repo -n flux-system 2>/dev/null || true
flux reconcile kustomization infra-sync -n flux-system 2>/dev/null || true
flux reconcile kustomization apps-sync -n flux-system 2>/dev/null || true
log_ok "Синхронизация завершена."
;;
logs|log|l)
log_info "Стриминг логов kustomize-controller..."
exec kubectl -n flux-system logs -l app.kubernetes.io/name=kustomize-controller --tail=50 -f
;;
status|st)
echo -e "${BLUE}=== СТАТУС РЕПОЗИТОРИЕВ И KUSTOMIZATION (FLUX) ===${NC}"
kubectl -n flux-system get gitrepositories,kustomizations,helmreleases 2>/dev/null || log_err "Flux недоступен"
;;
*)
kubectl -n flux-system get kustomizations 2>/dev/null || log_err "Flux недоступен"
;;
esac

13
cmd/git-credential.sh Normal file
View file

@ -0,0 +1,13 @@
#!/bin/bash
set -euo pipefail
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ZARYA_DIR}/lib/common.sh"
if [[ -f "${RAM_CACHE}" ]]; then
token=$(grep '^export ATLAS_PUSH_TOKEN=' "${RAM_CACHE}" 2>/dev/null | cut -d= -f2- | tr -d '"'\'' ' || true)
if [[ -n "${token}" ]]; then
echo "username=atlas"
echo "password=${token}"
fi
fi
exit 0

46
cmd/nodes.sh Executable file
View file

@ -0,0 +1,46 @@
#!/bin/bash
set -u
watch_mode=false
while [[ $# -gt 0 ]]; do
case "$1" in
-w|--watch) watch_mode=true; shift ;;
*) shift ;;
esac
done
render_nodes() {
local raw
raw=$(kubectl get nodes -L topology.kubernetes.io/zone,topology.kubernetes.io/region 2>/dev/null || true)
echo "$raw" | awk '
BEGIN {
ERR = "\033[38;2;255;46;76m"
RUN = "\033[38;2;166;227;161m"
HEAD = "\033[38;2;147;154;183m"
RST = "\033[0m"
}
NR==1 { print HEAD $0 RST; next }
{
if ($2 ~ /Ready/ && $2 !~ /NotReady/) {
print RUN $0 RST
}
else {
print ERR $0 RST
}
}'
}
if [[ "$watch_mode" == true ]]; then
trap 'tput cnorm 2>/dev/null || true; echo ""; exit 0' INT TERM
tput civis 2>/dev/null || true
clear
while true; do
tput cup 0 0 2>/dev/null || true
render_nodes
tput ed 2>/dev/null || true
sleep 1
done
else
render_nodes
fi

View file

@ -1,28 +1,50 @@
#!/bin/bash #!/bin/bash
set -euo pipefail set -euo pipefail
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
mode="${1:-state}" source "${ZARYA_DIR}/lib/common.sh"
mode="${1:-all}"
pack_atlas() {
log_info "==> [1/3] Упаковка чистой архитектуры Atlas (atlas-code.xml)..."
(cd "${ATLAS_DIR}" && repomix --config "${ATLAS_DIR}/repomix.config.json")
log_ok "Файл ${ATLAS_DIR}/atlas-code.xml готов."
}
pack_zarya() {
log_info "==> [2/3] Упаковка станции оператора Zarya (zarya-code.xml)..."
(cd "${ZARYA_DIR}" && repomix --config "${ZARYA_DIR}/repomix.config.json")
log_ok "Файл ${ZARYA_DIR}/zarya-code.xml готов."
}
pack_state() {
log_info "==> [3/3] Снятие живого аудита и упаковка телеметрии (zarya-state.xml)..."
"${ZARYA_DIR}/state/collect_state.sh" all
(cd "${ZARYA_DIR}" && repomix --config "${ZARYA_DIR}/repomix.state.json")
log_ok "Файл ${ZARYA_DIR}/zarya-state.xml готов."
}
case "${mode}" in case "${mode}" in
state) all)
echo "==> Снятие свежего аудита..." pack_atlas
"${ZARYA_DIR}/state/collect_state.sh" all >/dev/null 2>&1 || true echo ""
echo "==> Упаковка среза состояния Repomix (zarya-state.xml)..." pack_zarya
repomix --config "${ZARYA_DIR}/repomix.state.json" echo ""
echo "✔ Файл zarya-state.xml готов для отправки в LLM." pack_state
;; echo ""
code) log_ok "Все три контекста Repomix собраны без ошибок."
echo "==> Упаковка кодовой базы zarya (zarya-code.xml)..."
repomix --config "${ZARYA_DIR}/repomix.config.json"
echo "✔ Файл zarya-code.xml готов."
;; ;;
atlas) atlas)
echo "==> Упаковка чистой инфраструктуры atlas (atlas-code.xml)..." pack_atlas
cd "${ATLAS_DIR}" && repomix ;;
echo "✔ Файл atlas/repomix-output.xml готов." code)
pack_zarya
;;
state)
pack_state
;; ;;
*) *)
echo "Использование: z pack [state|code|atlas]" log_err "Использование: z pack [all|atlas|code|state]"
exit 1 exit 1
;; ;;
esac esac

View file

@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
# Network routing and terminal prerequisites
ensure_prerequisites() { ensure_prerequisites() {
local target_ip="${VAULT_ADDR#*//}" local target_ip="${VAULT_ADDR#*//}"
target_ip="${target_ip%%:*}" target_ip="${target_ip%%:*}"
@ -7,19 +6,20 @@ ensure_prerequisites() {
log_info "Восстанавливаем маршрут к ${NET_PREFIX} через VyOS (${VYOS_ROUTER_IP})..." log_info "Восстанавливаем маршрут к ${NET_PREFIX} через VyOS (${VYOS_ROUTER_IP})..."
sudo ip route replace "${NET_PREFIX}" via "${VYOS_ROUTER_IP}" 2>/dev/null || true sudo ip route replace "${NET_PREFIX}" via "${VYOS_ROUTER_IP}" 2>/dev/null || true
fi fi
# Регистрация Git Credential Helper (доменный и прямой IP Tier-0)
local target_helper="!${REPO_ROOT}/deploy.sh git-credential" local target_helper="!${ZARYA_DIR}/bin/zarya git-credential"
local current_helper local current_helper
current_helper=$(git config --global --get credential."https://${GIT_HOST}".helper 2>/dev/null || true) current_helper=$(git config --global --get credential."https://${GIT_HOST}".helper 2>/dev/null || true)
if [[ "${current_helper}" != "${target_helper}" ]]; then if [[ "${current_helper}" != "${target_helper}" ]]; then
git config --global credential."https://${GIT_HOST}".helper "${target_helper}" git config --global credential."https://${GIT_HOST}".helper "${target_helper}"
fi fi
local direct_helper local direct_helper
direct_helper=$(git config --global --get credential."http://10.0.10.13:3000".helper 2>/dev/null || true) direct_helper=$(git config --global --get credential."http://10.0.10.13:3000".helper 2>/dev/null || true)
if [[ "${direct_helper}" != "${target_helper}" ]]; then if [[ "${direct_helper}" != "${target_helper}" ]]; then
git config --global credential."http://10.0.10.13:3000".helper "${target_helper}" git config --global credential."http://10.0.10.13:3000".helper "${target_helper}"
fi fi
# Нативная привязка IdentityFile для всех C2-хостов и LXC-контейнеров
local ssh_hosts="proxmox pve0 vyos vyos_router 10.0.* dns0 vault0 git0 storage0 registry0" local ssh_hosts="proxmox pve0 vyos vyos_router 10.0.* dns0 vault0 git0 storage0 registry0"
if [[ -f "${HOME}/.ssh/config" ]] && ! grep -q "IdentityFile ${RAM_KEY}" "${HOME}/.ssh/config"; then if [[ -f "${HOME}/.ssh/config" ]] && ! grep -q "IdentityFile ${RAM_KEY}" "${HOME}/.ssh/config"; then
printf "\nHost %s\n IdentityFile %s\n IdentitiesOnly yes\n" "${ssh_hosts}" "${RAM_KEY}" >> "${HOME}/.ssh/config" printf "\nHost %s\n IdentityFile %s\n IdentitiesOnly yes\n" "${ssh_hosts}" "${RAM_KEY}" >> "${HOME}/.ssh/config"

View file

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

68
state/collect_state.sh Normal file
View file

@ -0,0 +1,68 @@
#!/bin/bash
set -uo pipefail
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
STATE_DIR="${ZARYA_DIR}/state"
SNAPSHOTS_DIR="${STATE_DIR}/snapshots"
TARGET="${1:-all}"
MODULES=(
"00_workstation.sh"
"01_pve.sh"
"02_vps.sh"
"03_vyos.sh"
"04_tier0.sh"
"05_k8s.sh"
)
mkdir -p "${SNAPSHOTS_DIR}"
generate_header() {
local mod_name="$1"
local timestamp branch short_hash commit_msg
timestamp=$(date -u +"%Y-%m-%d %H:%M:%S UTC")
branch=$(git -C "${ATLAS_DIR:-$HOME/Projects/atlas}" branch --show-current 2>/dev/null || echo "unknown")
short_hash=$(git -C "${ATLAS_DIR:-$HOME/Projects/atlas}" rev-parse --short HEAD 2>/dev/null || echo "none")
commit_msg=$(git -C "${ATLAS_DIR:-$HOME/Projects/atlas}" log -1 --format='%s' 2>/dev/null || echo "none")
cat <<EOF
# Sovereign C2 Runtime: ${mod_name}
**Срез:** ${timestamp} | **Git:** ${branch}@${short_hash} ("${commit_msg}")
EOF
}
run_single_module() {
local mod="$1"
local mod_name="${mod%.sh}"
local script="${STATE_DIR}/${mod}"
local out_file="${SNAPSHOTS_DIR}/${mod_name}.md"
local tmp_file="${out_file}.tmp"
echo " -> Сбор модуля: ${mod_name}..."
generate_header "${mod_name}" > "${tmp_file}"
if [[ -x "${script}" ]]; then
"${script}" >> "${tmp_file}" 2>&1
else
bash "${script}" >> "${tmp_file}" 2>&1
fi
mv "${tmp_file}" "${out_file}"
}
if [[ "${TARGET}" == "all" ]]; then
echo "==> Сбор полного аудита Sovereign C2 в ${SNAPSHOTS_DIR}..."
for mod in "${MODULES[@]}"; do
run_single_module "${mod}"
done
echo "✔ Все модули телеметрии успешно сохранены."
else
case "${TARGET}" in
00_workstation|workstation|host) run_single_module "00_workstation.sh" ;;
01_pve|pve) run_single_module "01_pve.sh" ;;
02_vps|vps) run_single_module "02_vps.sh" ;;
03_vyos|vyos|net) run_single_module "03_vyos.sh" ;;
04_tier0|tier0) run_single_module "04_tier0.sh" ;;
05_k8s|k8s|talos) run_single_module "05_k8s.sh" ;;
*)
echo "Неизвестный модуль: ${TARGET}"
exit 1
;;
esac
fi

0
test
View file

1181
zarya-code.xml Normal file

File diff suppressed because it is too large Load diff

51
zarya-state.xml Normal file
View file

@ -0,0 +1,51 @@
This file is a merged representation of a subset of the codebase, containing specifically included files, combined into a single document by Repomix.
The content has been processed where empty lines have been removed.
<file_summary>
This section contains a summary of this file.
<purpose>
This file contains a packed representation of a subset of the repository's contents that is considered the most important context.
It is designed to be easily consumable by AI systems for analysis, code review,
or other automated processes.
</purpose>
<file_format>
The content is organized as follows:
1. This summary section
2. Repository information
3. Directory structure
4. Repository files (if enabled)
5. Multiple file entries, each consisting of:
- File path as an attribute
- Full contents of the file
</file_format>
<usage_guidelines>
- This file should be treated as read-only. Any changes should be made to the
original repository files, not this packed version.
- When processing this file, use the file path to distinguish
between different files in the repository.
- Be aware that this file may contain sensitive information. Handle it with
the same level of security as you would the original repository.
</usage_guidelines>
<notes>
- Some files may have been excluded based on .gitignore rules and Repomix's configuration
- Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files
- Only files matching these patterns are included: state/snapshots/**
- Files matching default ignore patterns are excluded
- Empty lines have been removed from all files
- Files are sorted by Git change count (files with more changes are at the bottom)
</notes>
</file_summary>
<directory_structure>
</directory_structure>
<files>
This section contains the contents of the repository's files.
</files>