Skip to content

Commit

Permalink
follow-cvelist.py hard reset on pull failure (-F) mode
Browse files Browse the repository at this point in the history
Add recovery capabilities from 'git pull' failures. Continue
on non-permanent (network) issues. Exit on permanent failures,
or try 'git reset --hard origin/main' with -F/--force.
  • Loading branch information
oh2fih committed Aug 14, 2024
1 parent 09b7e93 commit e7682b9
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Miscellaneous scripts for different purposes. Mostly unrelated to each other.
| Email | [`mail-prepender.sh`](bin/mail-prepender.sh)<br>Shell (bash) | Prepends (to stdin/stdout) email header strings given in as flags `i`, `I`, `a`, or `A`; after possible mbox `From` & `Return-Path` header lines. Intended as a limited `formail` replacement that ignores the nyanses of the flags and simply prepends the valid (RFC 5322, 2.2) non-empty headers keeping the other headers as is. Flags `x` & `X` are implemented. Any other flags are ignored. |
| Git | [`git-find-commits-by-file-hash.sh`](bin/git-find-commits-by-file-hash.sh)<br>Shell (bash) | Search Git repository history for commits with SHA-256 checksum of a file. Answers the question "Has this version of this file ever been committed as the file on this path of this Git repository?" and shows a summary (`git show --stat`) of the matching commit(s). The `path` should be relative to the repository root.<br>`git-find-commits-by-file-hash.sh sha256sum path`|
| Infosec | [`netcat-proxy.sh`](bin/netcat-proxy.sh)<br>Shell (sh) | Creates a simple persistent TCP proxy with netcat & named pipes.<br>`netcat-proxy.sh listenport targethost targetport` |
| Infosec | [`follow-cvelist.py`](bin/follow-cvelist.py)<br>Python 3 | Follow changes (commits) in CVEProject / [cvelistV5](https://github.com/CVEProject/cvelistV5). Requires git. Working directory must be the root of the cvelistV5 repository.<br>`follow-cvelist.py [-haoru4] [-vvvv] [-i s] [-c N] [-w N]`|
| Infosec | [`follow-cvelist.py`](bin/follow-cvelist.py)<br>Python 3 | Follow changes (commits) in CVEProject / [cvelistV5](https://github.com/CVEProject/cvelistV5). Requires git. Working directory must be the root of the cvelistV5 repository.<br>`follow-cvelist.py [-haForu4] [-vvvv] [-i s] [-c N] [-w N]`|
| Infosec | [`partialpassword.sh`](bin/partialpassword.sh)<br>Shell (bash) | Creates a new wordlist from a wordlist by replacing all ambiguous characters with all their possible combinations.<br>`partialpassword.sh input.txt output.txt O0 [Il1 ...]` |
| Infosec | [`duplicate-ssh-hostkeys.sh`](bin/duplicate-ssh-hostkeys.sh)<br>Shell (bash) | Find duplicate SSH host keys in a CIDR range. Examine your network for shared host keys that could potentially be dangerous.<br>`duplicate-ssh-hostkeys.sh CIDR [HostKeyAlgorithm ...]` |
| Infosec<br>Automation | [`make-mac-prefixes.py`](bin/make-mac-prefixes.py)<br>Python 3 | Processes registered MAC address prefixes from [IEEE MA-L Assignments (CSV)](https://standards.ieee.org/products-programs/regauth/) (stdin) to Nmap's [`nmap-mac-prefixes`](https://github.com/nmap/nmap/blob/master/nmap-mac-prefixes) (stdout) with a few additional unregistered OUIs.<br>`curl https://standards-oui.ieee.org/oui/oui.csv \| make-mac-prefixes.py > nmap-mac-prefixes` |
Expand Down
95 changes: 90 additions & 5 deletions bin/follow-cvelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
# ------------------------------------------------------------------------------
# Follow changes (commits) in CVEProject / cvelistV5
#
# Usage: follow-cvelist.py [-haoru4] [-vvvv] [-i s] [-c N] [-w N]
# Usage: follow-cvelist.py [-haForu4] [-vvvv] [-i s] [-c N] [-w N]
#
# -h, --help show this help message and exit
# -a, --ansi add ansi colors to the output (default: False)
# -F, --force origin/main hard reset if git pull fails (default: False)
# -o, --once only the current tail; no active follow (default: False)
# -r, --reload-only skip pulls & only follow local changes (default: False)
# -u, --url prefix cve with url to nvd nist details (default: False)
Expand Down Expand Up @@ -165,7 +166,7 @@ def monitor(self) -> None:
cursor = new_cursor

def pull(self) -> None:
"""Runs git pull. Exits if it fails."""
"""Runs git pull. Exits on permanent, unrecoverable errors"""
result = subprocess.run(
["git", "pull"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
Expand All @@ -176,12 +177,89 @@ def pull(self) -> None:
file=sys.stderr,
)
if result.returncode > 0:
if self.fetch_all():
if self.args.force:
if self.args.verbose > 1:
print(
f"{result.stderr.decode('utf-8').strip()}",
file=sys.stderr,
)
self.reset_repo()
else:
print(
f"{result.stderr.decode('utf-8').strip()}",
file=sys.stderr,
)
begin = ""
end = ""
if self.args.ansi:
begin = f"{ANSI.code('red')}"
end = f"{ANSI.code('end')}"
print(
f"{begin}Manual intervention (or -F/--force) "
f"required; 'git pull' failed permanently!{end}",
file=sys.stderr,
)
sys.exit(1)

def fetch_all(self) -> bool:
"""Try fetch; good for distinguishing connectivity issues from other failures"""
result = subprocess.run(
["git", "fetch", "--all"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
if self.args.verbose > 1:
print(f"{result.stdout.decode('utf-8').strip()}", file=sys.stderr)
if result.returncode > 0:
begin = ""
end = ""
if self.args.ansi:
begin = f"{ANSI.code('yellow')}"
end = f"{ANSI.code('end')}"
print(
f"{begin}{time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())} "
f"Fetch failed; connectivity issues?{end}",
file=sys.stderr,
)
return False # fetch failed
return True # fetch successful

def reset_repo(self) -> None:
"""Tries to recover from git pull errors by hard resetting to origin/main"""
begin = ""
end = ""
if self.args.ansi:
begin = f"{ANSI.code('yellow')}"
end = f"{ANSI.code('end')}"
print(
f"{begin}{time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())}"
f" Recovering from a failed git pull...{end}",
file=sys.stderr,
)
result = subprocess.run(
["git", "reset", "--hard", "origin/main"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
if self.args.verbose > 1:
print(f"{result.stdout.decode('utf-8').strip()}", file=sys.stderr)
if result.returncode > 0:
begin = ""
end = ""
if self.args.ansi:
begin = f"{ANSI.code('red')}"
end = f"{ANSI.code('end')}"
print(
f"\n{result.stderr.decode('utf-8').strip()}\n{ANSI.code('red')}"
f"Manual intervention required; 'git pull' failed!{ANSI.code('end')}",
f"{begin}Hard reset to origin/main failed; "
f"manual intervention required!{end}",
file=sys.stderr,
)
sys.exit(1)
begin = ""
end = ""
if self.args.ansi:
begin = f"{ANSI.code('green')}"
end = f"{ANSI.code('end')}"
print(f"{begin}Successfully recovered.{end}", file=sys.stderr)

def get_cursor(self, offset: int = 0) -> str:
"""Gets commit id at the offset from the current head"""
Expand Down Expand Up @@ -552,7 +630,7 @@ def check_positive(value: str) -> int:
if __name__ == "__main__":
argParser = argparse.ArgumentParser(
description="Follow changes (commits) in CVEProject / cvelistV5",
usage="%(prog)s [-haoru4] [-vvvv] [-i s] [-c N] [-w N]",
usage="%(prog)s [-haForu4] [-vvvv] [-i s] [-c N] [-w N]",
epilog="Requires git. "
"Working directory must be the root of the cvelistV5 repository.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
Expand All @@ -564,6 +642,13 @@ def check_positive(value: str) -> int:
help="add ansi colors to the output",
default=False,
)
argParser.add_argument(
"-F",
"--force",
action="store_true",
help="origin/main hard reset if git pull fails",
default=False,
)
argParser.add_argument(
"-o",
"--once",
Expand Down

0 comments on commit e7682b9

Please sign in to comment.