upgrade audit
This commit is contained in:
Executable
+155
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Docker system audit: collect container diagnostics and return as JSON."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
|
||||
def cmd(args, parse_json=False):
|
||||
try:
|
||||
result = subprocess.run(
|
||||
args,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
)
|
||||
out = (result.stdout + result.stderr).strip()
|
||||
|
||||
if parse_json:
|
||||
try:
|
||||
return json.loads(out) if out else None
|
||||
except json.JSONDecodeError:
|
||||
return out
|
||||
|
||||
return out
|
||||
|
||||
except Exception as e:
|
||||
return f"ERROR: {e}"
|
||||
|
||||
|
||||
def read_file(path):
|
||||
try:
|
||||
with open(path) as f:
|
||||
return f.read().strip().splitlines()
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
audit = {}
|
||||
|
||||
# Container identity
|
||||
audit["container_id"] = os.environ.get("HOSTNAME")
|
||||
audit["environment"] = dict(os.environ)
|
||||
|
||||
# OS information inside container
|
||||
audit["os_release"] = read_file("/etc/os-release")
|
||||
audit["uname"] = cmd(["uname", "-a"])
|
||||
|
||||
# Installed packages (works for Debian/Ubuntu, Alpine, etc.)
|
||||
audit["packages"] = {}
|
||||
|
||||
if os.path.exists("/etc/alpine-release"):
|
||||
audit["packages"]["manager"] = "apk"
|
||||
audit["packages"]["installed"] = cmd(
|
||||
["apk", "info", "-v"]
|
||||
).splitlines()
|
||||
audit["packages"]["upgradeable"] = cmd(
|
||||
["apk", "version", "-l", "<"]
|
||||
).splitlines()
|
||||
|
||||
elif os.path.exists("/etc/debian_version"):
|
||||
audit["packages"]["manager"] = "dpkg"
|
||||
audit["packages"]["installed"] = cmd(
|
||||
["dpkg-query", "-W", "-f=${Package}-${Version}\n"]
|
||||
).splitlines()
|
||||
|
||||
elif os.path.exists("/etc/redhat-release"):
|
||||
audit["packages"]["manager"] = "rpm"
|
||||
audit["packages"]["installed"] = cmd(
|
||||
["rpm", "-qa"]
|
||||
).splitlines()
|
||||
|
||||
# Docker engine information
|
||||
audit["docker_version"] = cmd(
|
||||
["docker", "version", "--format", "{{json .}}"],
|
||||
parse_json=True,
|
||||
)
|
||||
|
||||
audit["docker_info"] = cmd(
|
||||
["docker", "info", "--format", "{{json .}}"],
|
||||
parse_json=True,
|
||||
)
|
||||
|
||||
# Containers
|
||||
containers = cmd(
|
||||
["docker", "ps", "-a", "--format", "{{json .}}"],
|
||||
parse_json=True,
|
||||
)
|
||||
|
||||
if isinstance(containers, list):
|
||||
audit["docker_containers"] = containers
|
||||
else:
|
||||
audit["docker_containers"] = []
|
||||
|
||||
# Images
|
||||
audit["docker_images"] = cmd(
|
||||
["docker", "images", "--format", "{{json .}}"],
|
||||
parse_json=True,
|
||||
)
|
||||
|
||||
# Runtime stats
|
||||
audit["docker_stats"] = cmd(
|
||||
[
|
||||
"docker",
|
||||
"stats",
|
||||
"--no-stream",
|
||||
"--format",
|
||||
"table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}",
|
||||
]
|
||||
)
|
||||
|
||||
# Container logs
|
||||
logs = {}
|
||||
|
||||
for c in audit["docker_containers"]:
|
||||
name = c.get("Names") or c.get("ID")
|
||||
|
||||
if not name:
|
||||
continue
|
||||
|
||||
logs[name] = cmd(
|
||||
[
|
||||
"docker",
|
||||
"logs",
|
||||
"--tail",
|
||||
"100",
|
||||
name,
|
||||
]
|
||||
)
|
||||
|
||||
audit["docker_logs"] = logs
|
||||
|
||||
# SSH config if present
|
||||
audit["sshd_config"] = cmd(
|
||||
["sshd", "-T"]
|
||||
).splitlines()
|
||||
|
||||
# Users
|
||||
audit["passwd"] = read_file("/etc/passwd")
|
||||
|
||||
# Runtime info
|
||||
audit["uptime"] = cmd(["uptime"])
|
||||
|
||||
# cgroups (useful in Docker)
|
||||
audit["cgroup"] = read_file("/proc/self/cgroup")
|
||||
|
||||
# Mounted filesystems
|
||||
audit["mounts"] = cmd(["mount"]).splitlines()
|
||||
|
||||
print(json.dumps(audit, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
# Set target Alpine version here
|
||||
TARGET_VERSION="3.24"
|
||||
|
||||
echo "Current Alpine:"
|
||||
cat /etc/alpine-release
|
||||
|
||||
echo "Upgrading to Alpine ${TARGET_VERSION}..."
|
||||
|
||||
# Safety backup
|
||||
BACKUP="/etc/apk/repositories.backup.$(date +%Y%m%d-%H%M%S)"
|
||||
cp /etc/apk/repositories "$BACKUP"
|
||||
echo "Repository backup saved: $BACKUP"
|
||||
|
||||
# Update repositories
|
||||
sed -i "s/v[0-9]\+\.[0-9]\+/v${TARGET_VERSION}/g" /etc/apk/repositories
|
||||
|
||||
echo "New repositories:"
|
||||
cat /etc/apk/repositories
|
||||
|
||||
# Refresh indexes
|
||||
apk update
|
||||
|
||||
# Upgrade apk tooling first
|
||||
apk add --upgrade apk-tools
|
||||
|
||||
# Upgrade all packages to target branch
|
||||
apk upgrade --available
|
||||
|
||||
# Clean cache
|
||||
apk cache clean
|
||||
|
||||
echo
|
||||
echo "Upgrade finished."
|
||||
echo "New Alpine version:"
|
||||
cat /etc/alpine-release
|
||||
|
||||
echo
|
||||
echo "Kernel:"
|
||||
uname -r
|
||||
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
rex doas apk update
|
||||
rex doas apk fix
|
||||
rex doas apk upgrade
|
||||
rex doas reboot
|
||||
Binary file not shown.
Reference in New Issue
Block a user