Utoljára aktív 1 month ago

nuno gist felülvizsgálása 1 month ago. Revízióhoz ugrás

1 file changed, 411 insertions

gistfile1.txt(fájl létrehozva)

@@ -0,0 +1,411 @@
1 + #!/usr/bin/env bash
2 +
3 + FW_EVENTS_LOG="$(ctx::fw_events_log)"
4 + WG_EVENTS_LOG="$(ctx::events_log)"
5 +
6 + function cmd::logs::on_load() {
7 + flag::register --name
8 + flag::register --type
9 + flag::register --since
10 + flag::register --limit
11 + flag::register --fw
12 + flag::register --wg
13 + flag::register --follow
14 + flag::register --merged
15 + flag::register --all
16 + flag::register --before
17 + flag::register --force
18 + flag::register --days
19 + flag::register --raw
20 + flag::register --detailed
21 + }
22 +
23 + function cmd::logs::help() {
24 + cat <<EOF
25 + Usage: wgctl logs [subcommand] [options]
26 +
27 + Show or manage WireGuard and firewall activity logs.
28 +
29 + Subcommands:
30 + show (default) Show activity logs
31 + remove, rm Remove log entries
32 + rotate Remove entries older than N days
33 +
34 + Options for show:
35 + --name <name> Filter by client name
36 + --type <type> Filter by device type
37 + --limit <n> Max results per source (default: 50)
38 + --fw Show only firewall drops
39 + --wg Show only WireGuard events
40 + --merged Show all events chronologically interleaved
41 + --follow, -f Follow logs in real time (alias: wgctl watch)
42 + --raw Show raw IPs without service annotation
43 +
44 + Options for remove:
45 + --name <name> Remove entries for specific peer
46 + --all Remove all log entries
47 + --fw Remove only firewall events
48 + --wg Remove only WireGuard events
49 + --before <days> Remove entries older than N days
50 + --force Skip confirmation
51 +
52 + Options for rotate:
53 + --days <n> Days to keep (default: 7)
54 + --force Skip confirmation
55 +
56 + Examples:
57 + wgctl logs
58 + wgctl logs --name phone-nuno
59 + wgctl logs --fw --limit 100
60 + wgctl logs --merged
61 + wgctl logs --follow
62 + wgctl logs remove --name phone-nuno
63 + wgctl logs rotate --days 30
64 + EOF
65 + }
66 +
67 + function cmd::logs::run() {
68 + local subcmd="${1:-show}"
69 + if [[ "$subcmd" == --* ]]; then
70 + subcmd="show"
71 + else
72 + shift || true
73 + fi
74 +
75 + case "$subcmd" in
76 + show) cmd::logs::show "$@" ;;
77 + remove|rm|del) cmd::logs::remove "$@" ;;
78 + rotate) cmd::logs::rotate "$@" ;;
79 + help) cmd::logs::help ;;
80 + *)
81 + log::error "Unknown subcommand: '${subcmd}'"
82 + cmd::logs::help
83 + return 1
84 + ;;
85 + esac
86 + }
87 +
88 + function cmd::logs::show() {
89 + local name="" type="" limit=50
90 + local fw_only=false wg_only=false follow=false merged=false raw=false detailed=false
91 +
92 +
93 + while [[ $# -gt 0 ]]; do
94 + case "$1" in
95 + --name) name="$2"; shift 2 ;;
96 + --type) type="$2"; shift 2 ;;
97 + --limit) limit="$2"; shift 2 ;;
98 + --fw) fw_only=true; shift ;;
99 + --wg) wg_only=true; shift ;;
100 + --merged) merged=true; shift ;;
101 + --follow|-f) follow=true; shift ;;
102 + --raw) raw=true; shift ;;
103 + --detailed) detailed=true shift ;;
104 + --help) cmd::logs::help; return ;;
105 + *)
106 + log::error "Unknown flag: $1"
107 + return 1
108 + ;;
109 + esac
110 + done
111 +
112 + local collapse=1
113 + $detailed && collapse=0
114 +
115 +
116 + if [[ -n "$name" && -n "$type" ]]; then
117 + name=$(peers::resolve_and_require "$name" "$type") || return 1
118 + fi
119 +
120 + local filter_ip=""
121 + if [[ -n "$name" ]]; then
122 + filter_ip=$(peers::get_ip "$name")
123 + [[ -z "$filter_ip" ]] && log::error "Could not find IP for: $name" && return 1
124 + fi
125 +
126 + if $follow; then
127 + cmd::logs::follow "$filter_ip" "$name" "$type" "$fw_only" "$wg_only"
128 + return
129 + fi
130 +
131 + local net_file=""
132 + $raw || net_file="$(ctx::net)"
133 +
134 + log::section "WireGuard Activity Log"
135 + printf "\n"
136 +
137 + if $merged; then
138 + cmd::logs::show_merged "$filter_ip" "$name" "$type" "$limit" "$net_file"
139 + return
140 + fi
141 +
142 + $wg_only || cmd::logs::show_fw_events "$filter_ip" "$name" "$type" "$limit" "$net_file" "$collapse"
143 + $fw_only || cmd::logs::show_wg_events "$filter_ip" "$name" "$type" "$limit" "$collapse"
144 + }
145 +
146 + function cmd::logs::show_fw_events() {
147 + local filter_ip="${1:-}" filter_name="${2:-}" filter_type="${3:-}" \
148 + limit="${4:-50}" net_file="${5:-}" collapse="${6:-1}"
149 +
150 + [[ ! -f "$FW_EVENTS_LOG" ]] && return 0
151 +
152 + local data
153 + data=$(json::fw_events "$FW_EVENTS_LOG" "$filter_ip" "$filter_type" \
154 + "$(ctx::clients)" "${net_file:-}" "$limit" "$collapse" 2>/dev/null)
155 +
156 + [[ -z "$data" ]] && return 0
157 +
158 + # Measure column widths
159 + local w_client=16 w_dest=20
160 + while IFS='|' read -r ts client dest_ip dest_port proto svc count; do
161 + [[ -z "$ts" ]] && continue
162 + (( ${#client} > w_client )) && w_client=${#client}
163 + local dest_display
164 + local host_name
165 + host_name=$(hosts::resolve_ip "$dest_ip")
166 + if [[ -n "$host_name" ]]; then
167 + dest_display="$host_name"
168 + elif [[ -n "$svc" ]]; then
169 + [[ -n "$dest_port" ]] && dest_display="${svc}/${proto}" || dest_display="${svc} (${proto})"
170 + else
171 + [[ -n "$dest_port" ]] && dest_display="${dest_ip}:${dest_port}/${proto}" || dest_display="${dest_ip} (${proto})"
172 + fi
173 + (( ${#dest_display} > w_dest )) && w_dest=${#dest_display}
174 + done <<< "$data"
175 + (( w_client += 2 ))
176 + (( w_dest += 2 ))
177 +
178 + ui::logs::fw_section_header
179 + while IFS='|' read -r ts client dest_ip dest_port proto svc count; do
180 + [[ -z "$ts" ]] && continue
181 + ui::logs::fw_row "$ts" "$client" "$dest_ip" "$dest_port" \
182 + "$proto" "$svc" "$count" "$w_client" "$w_dest"
183 + done <<< "$data"
184 + printf "\n"
185 + }
186 +
187 + function cmd::logs::show_wg_events() {
188 + local filter_ip="${1:-}" filter_name="${2:-}" filter_type="${3:-}" \
189 + limit="${4:-50}" collapse="${5:-1}"
190 +
191 + [[ ! -f "$WG_EVENTS_LOG" ]] && return 0
192 +
193 + local data
194 + data=$(json::wg_events "$WG_EVENTS_LOG" "$filter_name" "$filter_type" "$limit" "$collapse" 2>/dev/null)
195 +
196 + [[ -z "$data" ]] && return 0
197 +
198 + # Resolve endpoints and measure column widths
199 + local w_client=16 w_endpoint=16
200 + local resolved_data=""
201 + while IFS='|' read -r ts client endpoint event count; do
202 + [[ -z "$ts" ]] && continue
203 + local endpoint_display
204 + endpoint_display=$(resolve::ip "$endpoint")
205 + [[ -z "$endpoint_display" ]] && endpoint_display="$endpoint"
206 + resolved_data+="${ts}|${client}|${endpoint_display}|${event}|${count}"$'\n'
207 + (( ${#client} > w_client )) && w_client=${#client}
208 + (( ${#endpoint_display} > w_endpoint )) && w_endpoint=${#endpoint_display}
209 + done <<< "$data"
210 + (( w_client += 2 ))
211 + (( w_endpoint += 2 ))
212 +
213 + ui::logs::wg_section_header
214 + while IFS='|' read -r ts client endpoint event count; do
215 + [[ -z "$ts" ]] && continue
216 + ui::logs::wg_row "$ts" "$client" "$endpoint" "$event" \
217 + "$count" "$w_client" "$w_endpoint"
218 + done <<< "$resolved_data"
219 + printf "\n"
220 + }
221 +
222 +
223 + function cmd::logs::show_merged() {
224 + local filter_ip="${1:-}" filter_name="${2:-}" filter_type="${3:-}" \
225 + limit="${4:-50}" net_file="${5:-}"
226 +
227 + local fw_data wg_data
228 + fw_data=$(json::fw_events "$FW_EVENTS_LOG" "$filter_ip" "$filter_type" \
229 + "$(ctx::clients)" "${net_file:-}" "$limit" 2>/dev/null)
230 + wg_data=$(json::wg_events "$WG_EVENTS_LOG" "$filter_name" "$filter_type" \
231 + "$limit" 2>/dev/null)
232 +
233 + # Measure widths across both sources
234 + local w_client=16 w_dest=20
235 + while IFS='|' read -r ts client rest; do
236 + [[ -z "$ts" ]] && continue
237 + (( ${#client} > w_client )) && w_client=${#client}
238 + done < <(echo "$fw_data"; echo "$wg_data")
239 + (( w_client += 2 ))
240 +
241 + # Tag and merge: prefix fw lines with "fw|", wg lines with "wg|"
242 + local merged_data
243 + merged_data=$(
244 + while IFS='|' read -r ts client dest_ip dest_port proto svc count; do
245 + [[ -z "$ts" ]] && continue
246 + echo "fw|${ts}|${client}|${dest_ip}|${dest_port}|${proto}|${svc}|${count}"
247 + done <<< "$fw_data"
248 + while IFS='|' read -r ts client endpoint event count; do
249 + [[ -z "$ts" ]] && continue
250 + echo "wg|${ts}|${client}|${endpoint}|${event}|${count}"
251 + done <<< "$wg_data"
252 + )
253 +
254 + # Sort by timestamp field 2
255 + while IFS='|' read -r source ts rest; do
256 + [[ -z "$source" ]] && continue
257 + case "$source" in
258 + fw)
259 + IFS='|' read -r client dest_ip dest_port proto svc count <<< "$rest"
260 + local dest_display
261 + if [[ -n "$svc" ]]; then
262 + [[ -n "$dest_port" ]] && dest_display="${svc}/${proto}" || dest_display="${svc} (${proto})"
263 + else
264 + [[ -n "$dest_port" ]] && dest_display="${dest_ip}:${dest_port}/${proto}" || dest_display="${dest_ip} (${proto})"
265 + fi
266 + (( ${#dest_display} > w_dest )) && w_dest=${#dest_display}
267 + ;;
268 + esac
269 + done <<< "$merged_data"
270 + (( w_dest += 2 ))
271 +
272 + while IFS='|' read -r source ts rest; do
273 + [[ -z "$source" ]] && continue
274 + case "$source" in
275 + fw)
276 + IFS='|' read -r client dest_ip dest_port proto svc count <<< "$rest"
277 + ui::watch::fw_row "$ts" "$client" \
278 + "$(ui::logs::build_dest "$dest_ip" "$dest_port" "$proto" "$svc")" \
279 + "$w_client" "$w_dest"
280 + ;;
281 + wg)
282 + IFS='|' read -r client endpoint event count <<< "$rest"
283 + ui::watch::wg_row "$ts" "$client" "$endpoint" "$event" \
284 + "$w_client" "$w_dest"
285 + ;;
286 + esac
287 + done < <(echo "$merged_data" | sort -t'|' -k2,2)
288 +
289 + printf "\n"
290 + }
291 +
292 + function cmd::logs::follow() {
293 + local filter_ip="${1:-}" filter_name="${2:-}" filter_type="${3:-}"
294 + local fw_only="${4:-false}" wg_only="${5:-false}"
295 +
296 + log::section "WireGuard Live Log (Ctrl+C to stop)"
297 + printf "\n"
298 +
299 + # Delegate to watch command
300 + local watch_args=()
301 + [[ -n "$filter_name" ]] && watch_args+=(--name "$filter_name")
302 + [[ -n "$filter_type" ]] && watch_args+=(--type "$filter_type")
303 + $fw_only && watch_args+=(--restricted)
304 + $wg_only && watch_args+=(--blocked)
305 +
306 + cmd::watch::run "${watch_args[@]}"
307 + }
308 +
309 + function cmd::logs::remove() {
310 + local name="" type="" before="" force=false
311 + local fw_only=false wg_only=false all=false
312 +
313 + while [[ $# -gt 0 ]]; do
314 + case "$1" in
315 + --name) name="$2"; shift 2 ;;
316 + --type) type="$2"; shift 2 ;;
317 + --before) before="$2"; shift 2 ;;
318 + --fw) fw_only=true; shift ;;
319 + --wg) wg_only=true; shift ;;
320 + --all) all=true; shift ;;
321 + --force) force=true; shift ;;
322 + --help) cmd::logs::help; return ;;
323 + *)
324 + log::error "Unknown flag: $1"
325 + return 1
326 + ;;
327 + esac
328 + done
329 +
330 + if ! $all && [[ -z "$name" && -z "$before" ]]; then
331 + log::error "Specify --name, --before, or --all"
332 + cmd::logs::help
333 + return 1
334 + fi
335 +
336 + local filter_ip=""
337 + if [[ -n "$name" ]]; then
338 + name=$(peers::resolve_and_require "$name" "$type") || return 1
339 + filter_ip=$(peers::get_ip "$name")
340 + fi
341 +
342 + local desc=""
343 + $all && desc="all entries"
344 + [[ -n "$name" ]] && desc="entries for '${name}'"
345 + [[ -n "$before" ]] && desc="${desc:+$desc, }entries older than ${before} days"
346 + $fw_only && desc="${desc} (fw only)"
347 + $wg_only && desc="${desc} (wg only)"
348 +
349 + if ! $force; then
350 + read -r -p "Remove ${desc}? [y/N] " confirm
351 + case "$confirm" in
352 + [yY]*) ;;
353 + *) log::info "Aborted"; return 0 ;;
354 + esac
355 + fi
356 +
357 + local result
358 + result=$(json::remove_events_filtered \
359 + "$WG_EVENTS_LOG" "$FW_EVENTS_LOG" \
360 + "${name:-}" "${filter_ip:-}" \
361 + "$fw_only" "$wg_only" \
362 + "${before:-}")
363 +
364 + local removed_wg removed_fw
365 + IFS="|" read -r removed_wg removed_fw <<< "$result"
366 + local total=$(( removed_wg + removed_fw ))
367 +
368 + if [[ "$total" -eq 0 ]]; then
369 + log::wg_warning "No log entries found matching the criteria"
370 + return 0
371 + fi
372 +
373 + log::wg_success "Removed ${total} log entries (wg: ${removed_wg}, fw: ${removed_fw})"
374 + }
375 +
376 + function cmd::logs::rotate() {
377 + local days=7 force=false
378 +
379 + while [[ $# -gt 0 ]]; do
380 + case "$1" in
381 + --days) days="$2"; shift 2 ;;
382 + --force) force=true; shift ;;
383 + --help) cmd::logs::help; return ;;
384 + *) log::error "Unknown flag: $1"; return 1 ;;
385 + esac
386 + done
387 +
388 + $force || {
389 + read -r -p "Remove log entries older than ${days} days? [y/N] " confirm
390 + case "$confirm" in
391 + [yY]*) ;;
392 + *) log::info "Aborted"; return 0 ;;
393 + esac
394 + }
395 +
396 + local result
397 + result=$(json::remove_events_filtered \
398 + "$WG_EVENTS_LOG" "$FW_EVENTS_LOG" \
399 + "" "" "false" "false" "$days")
400 +
401 + local removed_wg removed_fw
402 + IFS="|" read -r removed_wg removed_fw <<< "$result"
403 + local total=$(( removed_wg + removed_fw ))
404 +
405 + if [[ "$total" -eq 0 ]]; then
406 + log::wg_warning "No log entries older than ${days} days"
407 + return 0
408 + fi
409 +
410 + log::wg_success "Rotated ${total} entries older than ${days} days (wg: ${removed_wg}, fw: ${removed_fw})"
411 + }
Újabb Régebbi