Compare commits
2 commits
3c61779a4b
...
279dea6567
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
279dea6567 | ||
|
|
0b6d470fb9 |
221
bin/dep
221
bin/dep
|
|
@ -1,221 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
||||||
source "${ZARYA_DIR}/lib/common.sh"
|
|
||||||
COMMAND="${1:-help}"
|
|
||||||
|
|
||||||
parse_run_targets() {
|
|
||||||
local raw_input="$*"
|
|
||||||
local normalized
|
|
||||||
normalized=$(echo "${raw_input}" | tr ',' ' ')
|
|
||||||
local targets=()
|
|
||||||
for item in ${normalized}; do
|
|
||||||
if [[ "${item}" =~ ^([0-9]+)-([0-9]+)$ ]]; then
|
|
||||||
local start="${BASH_REMATCH[1]}"
|
|
||||||
local end="${BASH_REMATCH[2]}"
|
|
||||||
for ((i=10#$start; i<=10#$end; i++)); do
|
|
||||||
targets+=($(printf "%02d" "${i}"))
|
|
||||||
done
|
|
||||||
elif [[ "${item}" =~ ^[0-9]+$ ]]; then
|
|
||||||
targets+=($(printf "%02d" "$((10#$item))"))
|
|
||||||
else
|
|
||||||
log_err "Некорректный идентификатор плейбука: '${item}'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
printf "%s\n" "${targets[@]}" | sort -u -n
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_playbook() {
|
|
||||||
local id="$1"
|
|
||||||
local found
|
|
||||||
found=$(find "${REPO_ROOT}/ansible/playbooks" -maxdepth 1 -name "${id}_*.yml" | head -n1)
|
|
||||||
if [[ -z "${found}" ]]; then
|
|
||||||
log_err "Плейбук с префиксом [${id}] не найден в ansible/playbooks/"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "${found}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_playbooks_catalog() {
|
|
||||||
echo -e "${BLUE}=== Каталог доступных плейбуков (ansible/playbooks/) ===${NC}"
|
|
||||||
printf "%-4s %-28s %-12s %s\n" "ID" "PLAYBOOK" "HOSTS" "DESCRIPTION"
|
|
||||||
echo "----------------------------------------------------------------------------------"
|
|
||||||
for pb in $(ls -1 "${REPO_ROOT}/ansible/playbooks"/[0-9][0-9]_*.yml 2>/dev/null | sort); do
|
|
||||||
local file_name
|
|
||||||
file_name=$(basename "${pb}")
|
|
||||||
local id="${file_name:0:2}"
|
|
||||||
local hosts
|
|
||||||
hosts=$(awk '/hosts:/ {print $2; exit}' "${pb}" | tr -d '"'"'")
|
|
||||||
local desc
|
|
||||||
desc=$(awk '/- name:/ {print substr($0, index($0,$3)); exit}' "${pb}")
|
|
||||||
printf "%-4s %-28s %-12s %s\n" "${id}" "${file_name%.yml}" "${hosts}" "${desc}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
case "${COMMAND}" in
|
|
||||||
git-credential)
|
|
||||||
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
|
|
||||||
;;
|
|
||||||
start|login)
|
|
||||||
shift || true
|
|
||||||
hours="${1:-1}"
|
|
||||||
if ! [[ "${hours}" =~ ^[0-9]+$ ]] || (( hours < 0 || hours > 24 )); then
|
|
||||||
log_err "Недопустимый TTL сессии: '${hours}'. Допустимо: 0 (бессрочно) или 1-24 (часы)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
ensure_prerequisites
|
|
||||||
load_secrets_to_ram "${hours}"
|
|
||||||
unseal_vault
|
|
||||||
if [[ "${hours}" -eq 0 ]]; then
|
|
||||||
log_ok "Рабочая сессия Sovereign C2 открыта (Бессрочно)."
|
|
||||||
else
|
|
||||||
log_ok "Рабочая сессия Sovereign C2 открыта (TTL: ${hours} ч)."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
clean|logout)
|
|
||||||
rm -f "${RAM_CACHE}" /dev/shm/.atlas_core
|
|
||||||
log_ok "Секреты и SSH-ключи безопасно удалены из RAM."
|
|
||||||
;;
|
|
||||||
unseal)
|
|
||||||
ensure_prerequisites
|
|
||||||
unseal_vault
|
|
||||||
;;
|
|
||||||
up)
|
|
||||||
shift || true
|
|
||||||
target="${1:-all}"
|
|
||||||
case "${target}" in
|
|
||||||
host) run_isolated "${ZARYA_DIR}/layers/00_host.sh" ;;
|
|
||||||
net) run_isolated "${ZARYA_DIR}/layers/01_net.sh" ;;
|
|
||||||
tier0) run_isolated "${ZARYA_DIR}/layers/02_tier0.sh" ;;
|
|
||||||
talos) run_isolated "${ZARYA_DIR}/layers/03_talos.sh" ;;
|
|
||||||
apps) "${ZARYA_DIR}/layers/04_apps.sh" ;;
|
|
||||||
all)
|
|
||||||
run_isolated "${ZARYA_DIR}/layers/00_host.sh"
|
|
||||||
run_isolated "${ZARYA_DIR}/layers/01_net.sh"
|
|
||||||
run_isolated "${ZARYA_DIR}/layers/02_tier0.sh"
|
|
||||||
run_isolated "${ZARYA_DIR}/layers/03_talos.sh"
|
|
||||||
"${ZARYA_DIR}/layers/04_apps.sh"
|
|
||||||
log_ok "Вся инфраструктура полностью развернута."
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_err "Неизвестный слой: ${target}. Доступны: host, net, tier0, talos, apps, all"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
run)
|
|
||||||
shift || true
|
|
||||||
if [[ $# -eq 0 ]] || [[ "${1:-}" == "list" ]]; then
|
|
||||||
print_playbooks_catalog
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
targets=$(parse_run_targets "$*")
|
|
||||||
log_info "Очередь выполнения плейбуков: $(echo ${targets} | tr '\n' ' ')"
|
|
||||||
for id in ${targets}; do
|
|
||||||
pb_path=$(resolve_playbook "${id}")
|
|
||||||
log_info "==> [RUN ${id}] Исполнение: $(basename "${pb_path}")..."
|
|
||||||
run_isolated ansible-playbook -i "${REPO_ROOT}/ansible/inventory.yml" "${pb_path}"
|
|
||||||
done
|
|
||||||
log_ok "Все выбранные плейбуки успешно выполнены."
|
|
||||||
;;
|
|
||||||
exec)
|
|
||||||
shift || true
|
|
||||||
if [[ $# -eq 0 ]]; then
|
|
||||||
log_err "Использование: dep exec <команда> [аргументы...]"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
run_isolated "$@"
|
|
||||||
;;
|
|
||||||
a|apply)
|
|
||||||
unseal_vault
|
|
||||||
shift || true
|
|
||||||
run_isolated bash -c "cd '${REPO_ROOT}/tofu' && tofu apply $*"
|
|
||||||
;;
|
|
||||||
plan)
|
|
||||||
shift || true
|
|
||||||
run_isolated bash -c "cd '${REPO_ROOT}/tofu' && tofu plan $*"
|
|
||||||
;;
|
|
||||||
tf)
|
|
||||||
shift || true
|
|
||||||
run_isolated bash -c "cd '${REPO_ROOT}/tofu' && tofu $*"
|
|
||||||
;;
|
|
||||||
pods)
|
|
||||||
shift || true
|
|
||||||
kpods "$@"
|
|
||||||
;;
|
|
||||||
sync)
|
|
||||||
log_info "Принудительная конвергенция FluxCD..."
|
|
||||||
flux reconcile source git atlas-repo
|
|
||||||
flux reconcile kustomization infra-sync
|
|
||||||
flux reconcile kustomization apps-sync
|
|
||||||
log_ok "Синхронизация завершена."
|
|
||||||
;;
|
|
||||||
gc)
|
|
||||||
"${ZARYA_DIR}/layers/gc.sh"
|
|
||||||
;;
|
|
||||||
state)
|
|
||||||
shift || true
|
|
||||||
target="${1:-all}"
|
|
||||||
if [[ "${target}" == "--snapshot" ]]; then
|
|
||||||
shift || true
|
|
||||||
"${ZARYA_DIR}/state/collect_state.sh" "$@"
|
|
||||||
else
|
|
||||||
case "${target}" in
|
|
||||||
host|pve) bash "${ZARYA_DIR}/state/01_pve.sh" ;;
|
|
||||||
net|vyos) bash "${ZARYA_DIR}/state/03_vyos.sh" ;;
|
|
||||||
vps|edge) bash "${ZARYA_DIR}/state/02_vps.sh" ;;
|
|
||||||
tier0) bash "${ZARYA_DIR}/state/04_tier0.sh" ;;
|
|
||||||
k8s|talos) bash "${ZARYA_DIR}/state/05_k8s.sh" ;;
|
|
||||||
workstation) bash "${ZARYA_DIR}/state/00_workstation.sh" ;;
|
|
||||||
all)
|
|
||||||
for mod in 00_workstation 01_pve 02_vps 03_vyos 04_tier0 05_k8s; do
|
|
||||||
bash "${ZARYA_DIR}/state/${mod}.sh"
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_err "Неизвестный таргет: ${target}. Доступны: host, net, vps, tier0, k8s, workstation, all"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
reset|nuke)
|
|
||||||
"${ZARYA_DIR}/layers/reset.sh"
|
|
||||||
;;
|
|
||||||
help|--help|-h)
|
|
||||||
cat <<EOF
|
|
||||||
Sovereign C2 Orchestrator (dep)
|
|
||||||
Управление сессией:
|
|
||||||
dep start [0-24] Открытие смены (TTL в часах, по дефолту 1ч, 0 = бессрочно)
|
|
||||||
dep clean Закрытие смены (уничтожение RAM-кэша и ключа SSH)
|
|
||||||
dep unseal Ручной ансил OpenBao + синк токена в K8s
|
|
||||||
Исполнение и деплой:
|
|
||||||
dep up [layer] Сквозной макро-деплой: host, net, tier0, talos, apps, all
|
|
||||||
dep run <selector> Точечный запуск плейбуков: 06 | 01-03 | 01,03,06
|
|
||||||
dep run list Каталог всех плейбуков с описанием
|
|
||||||
dep exec <команда...> Вызов любого бинарника строго внутри RAM-изоляции run_isolated
|
|
||||||
Инфраструктура (IaC):
|
|
||||||
dep a [-auto-approve] OpenTofu apply с авто-ансилом Vault
|
|
||||||
dep plan OpenTofu plan
|
|
||||||
dep tf <args...> Прямой вызов OpenTofu в изолированном контексте
|
|
||||||
Кластер и состояние:
|
|
||||||
dep pods [args...] Просмотр подов через kpods (включая kpods -w)
|
|
||||||
dep sync Принудительный синк FluxCD
|
|
||||||
dep gc Сборка мусора и сброс бэкоффа подов
|
|
||||||
dep state [target] Живой вывод статуса в терминал (host, net, vps, tier0, k8s, all)
|
|
||||||
dep reset Полное уничтожение инфраструктуры (MFA через YubiKey)
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_err "Неизвестная команда: ${COMMAND}. Используйте 'dep help' для справки."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
12
bin/fc
Executable file
12
bin/fc
Executable 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
7
bin/gg
Executable 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
|
||||||
67
bin/kpods
67
bin/kpods
|
|
@ -1,67 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -u
|
|
||||||
|
|
||||||
watch_mode=false
|
|
||||||
args=()
|
|
||||||
for arg in "$@"; do
|
|
||||||
if [[ "$arg" == "-w" || "$arg" == "--watch" ]]; then
|
|
||||||
watch_mode=true
|
|
||||||
else
|
|
||||||
args+=("$arg")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
render_pods() {
|
|
||||||
local q="${1:-}"
|
|
||||||
local raw
|
|
||||||
if [[ "$q" == "all" || "$q" == "-A" || "$q" == "-a" ]]; then
|
|
||||||
raw=$(kubectl get pods -A 2>/dev/null || true)
|
|
||||||
else
|
|
||||||
if [[ -n "$q" ]]; then
|
|
||||||
raw=$(kubectl get pods -A 2>/dev/null | awk -v q="$q" 'NR==1 || tolower($1) ~ tolower(q) || tolower($2) ~ tolower(q)' || true)
|
|
||||||
else
|
|
||||||
raw=$(kubectl get pods -A 2>/dev/null | awk 'NR==1 || ($1 !~ /^(kube-system|flux-system|cert-manager|external-secrets)$/ && $4 != "Completed")' || true)
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$raw" | awk '
|
|
||||||
BEGIN {
|
|
||||||
ERR = "\033[38;2;255;46;76m"
|
|
||||||
RUN = "\033[38;2;180;190;254m"
|
|
||||||
WARN = "\033[38;2;250;179;135m"
|
|
||||||
HEAD = "\033[38;2;147;154;183m"
|
|
||||||
RST = "\033[0m"
|
|
||||||
}
|
|
||||||
NR==1 {
|
|
||||||
print HEAD $0 RST
|
|
||||||
next
|
|
||||||
}
|
|
||||||
{
|
|
||||||
if ($0 ~ /CrashLoopBackOff|Error|OOMKilled|ImagePullBackOff/) {
|
|
||||||
print ERR $0 RST
|
|
||||||
}
|
|
||||||
else if ($0 ~ /ContainerCreating|Pending|Terminating|Init:/ || ($0 ~ /Running/ && $2 ~ /^0\//)) {
|
|
||||||
print WARN $0 RST
|
|
||||||
}
|
|
||||||
else if ($0 ~ /Running/) {
|
|
||||||
print RUN $0 RST
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print $0
|
|
||||||
}
|
|
||||||
}'
|
|
||||||
}
|
|
||||||
|
|
||||||
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_pods "${args[@]:-}"
|
|
||||||
tput ed 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
else
|
|
||||||
render_pods "${args[@]:-}"
|
|
||||||
fi
|
|
||||||
9
bin/op
Executable file
9
bin/op
Executable 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
|
||||||
|
|
@ -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
11
cmd/exec.sh
Executable 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
28
cmd/flux.sh
Executable 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
13
cmd/git-credential.sh
Normal 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
46
cmd/nodes.sh
Executable 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
|
||||||
56
cmd/pack.sh
56
cmd/pack.sh
|
|
@ -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
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
68
state/collect_state.sh
Normal 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
|
||||||
1181
zarya-code.xml
Normal file
1181
zarya-code.xml
Normal file
File diff suppressed because it is too large
Load diff
51
zarya-state.xml
Normal file
51
zarya-state.xml
Normal 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>
|
||||||
Loading…
Reference in a new issue