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