redact.sh 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. # net-ops :: _lib/redact.sh
  2. # Shared opsec redaction for diagnostic output. Source from any bash script:
  3. #
  4. # source "$(dirname "$0")/../_lib/redact.sh"
  5. # parse_redact_flag "$@"
  6. # maybe_redact_self "$@" # re-invokes self without --redact if flag set
  7. #
  8. # Public IPs (1.1.1.1, 8.8.8.8, Tailscale 100.100.100.100 anchor) are
  9. # preserved — they're diagnostic landmarks. Private/CGNAT/link-local
  10. # ranges, MACs, and *.ts.net tailnet names are masked.
  11. REDACT="${REDACT:-0}"
  12. parse_redact_flag() {
  13. for a in "$@"; do
  14. [[ "$a" == "--redact" ]] && REDACT=1
  15. done
  16. }
  17. redact_filter() {
  18. if [[ "${REDACT:-0}" -eq 0 ]]; then cat; return; fi
  19. perl -pe '
  20. # Preserve well-known anchors first
  21. s/100\.100\.100\.100/__TS_MAGIC__/g;
  22. # Redact private / CGNAT / link-local IPv4
  23. s/\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/10.X.X.X/g;
  24. s/\b172\.(1[6-9]|2[0-9]|3[01])\.\d{1,3}\.\d{1,3}\b/172.X.X.X/g;
  25. s/\b192\.168\.\d{1,3}\.\d{1,3}\b/192.168.X.X/g;
  26. s/\b100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.\d{1,3}\.\d{1,3}\b/100.X.X.X/g;
  27. s/\b169\.254\.\d{1,3}\.\d{1,3}\b/169.254.X.X/g;
  28. # MAC addresses (both : and - separators)
  29. s/\b[0-9a-fA-F]{2}([:-])[0-9a-fA-F]{2}\1[0-9a-fA-F]{2}\1[0-9a-fA-F]{2}\1[0-9a-fA-F]{2}\1[0-9a-fA-F]{2}\b/XX:XX:XX:XX:XX:XX/g;
  30. # Tailscale tailnet names
  31. s/\b[a-z0-9-]+\.ts\.net\b/REDACTED.ts.net/g;
  32. # Restore anchors
  33. s/__TS_MAGIC__/100.100.100.100/g;
  34. '
  35. }
  36. # Helper: self-reinvoke and pipe through post-processing filters when needed.
  37. # Handles both --redact (mask private addrs) and --json (drop non-JSON chatter).
  38. # Avoids bash 3.2 exec-redirect quirks via single-level subprocess.
  39. maybe_redact_self() {
  40. # Only reinvoke if at least one filter is active
  41. [[ "${REDACT:-0}" -eq 1 ]] || [[ "${JSON_MODE:-0}" -eq 1 ]] || return 0
  42. # Prevent infinite recursion
  43. [[ "${_NETOPS_POSTPROCESSED:-0}" -eq 1 ]] && return 0
  44. export _NETOPS_POSTPROCESSED=1
  45. # Strip --redact from args (child runs without it to avoid double-recursion).
  46. # --json is preserved so JSON_MODE stays set in the child for any code that
  47. # changes behavior in JSON mode (e.g. info() suppression in output.sh).
  48. local cleaned_args=()
  49. for a in "$@"; do [[ "$a" != "--redact" ]] && cleaned_args+=("$a"); done
  50. if [[ "${JSON_MODE:-0}" -eq 1 ]] && [[ "${REDACT:-0}" -eq 1 ]]; then
  51. "$0" ${cleaned_args[@]+"${cleaned_args[@]}"} | grep '^{' | redact_filter
  52. elif [[ "${JSON_MODE:-0}" -eq 1 ]]; then
  53. "$0" ${cleaned_args[@]+"${cleaned_args[@]}"} | grep '^{'
  54. else
  55. "$0" ${cleaned_args[@]+"${cleaned_args[@]}"} | redact_filter
  56. fi
  57. exit "${PIPESTATUS[0]}"
  58. }