Fix clippy warnings: remove unused imports/variables/functions, derive Default, fix comparisons
Some checks failed
CI/CD Pipeline / Code Format (push) Failing after 12s
CI/CD Pipeline / Clippy Lints (push) Failing after 5m34s
CI/CD Pipeline / Unit Tests (push) Failing after 10m51s
CI/CD Pipeline / Build Debian Package (push) Failing after 1s
CI/CD Pipeline / Build RPM Package (push) Failing after 1s
CI/CD Pipeline / Build Alpine Package (push) Failing after 2s
CI/CD Pipeline / Build Arch Package (push) Failing after 2s
CI/CD Pipeline / Create Release (push) Has been skipped
CI/CD Pipeline / Security Audit (push) Failing after 15m40s
Some checks failed
CI/CD Pipeline / Code Format (push) Failing after 12s
CI/CD Pipeline / Clippy Lints (push) Failing after 5m34s
CI/CD Pipeline / Unit Tests (push) Failing after 10m51s
CI/CD Pipeline / Build Debian Package (push) Failing after 1s
CI/CD Pipeline / Build RPM Package (push) Failing after 1s
CI/CD Pipeline / Build Alpine Package (push) Failing after 2s
CI/CD Pipeline / Build Arch Package (push) Failing after 2s
CI/CD Pipeline / Create Release (push) Has been skipped
CI/CD Pipeline / Security Audit (push) Failing after 15m40s
This commit is contained in:
Binary file not shown.
@ -1 +1 @@
|
|||||||
83b25f5ec0339f647903ab0d4a7eb3411db8e448b1048431e8c63d6897709cbd
|
7ca8faef2728fcd4a384eed9dcf826a8989f7573d24e35bd83bfae86d8875818
|
||||||
Binary file not shown.
11
debian/.debhelper/generated/linux-patch-api/dh_installchangelogs.dch.trimmed
vendored
Normal file
11
debian/.debhelper/generated/linux-patch-api/dh_installchangelogs.dch.trimmed
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
linux-patch-api (1.0.0-1) stable; urgency=medium
|
||||||
|
|
||||||
|
* Initial production release
|
||||||
|
* Secure mTLS-authenticated REST API for remote package management
|
||||||
|
* 15 API endpoints for package install/remove, patch application, system management
|
||||||
|
* Asynchronous job processing with WebSocket status streaming
|
||||||
|
* IP whitelist enforcement and comprehensive audit logging
|
||||||
|
* Systemd integration with security hardening
|
||||||
|
* Supports Debian 11/12, Ubuntu 20.04/22.04/24.04
|
||||||
|
|
||||||
|
-- Echo <echo@moon-dragon.us> Thu, 09 Apr 2026 18:57:12 -0500
|
||||||
4
debian/.debhelper/generated/linux-patch-api/installed-by-dh_install
vendored
Normal file
4
debian/.debhelper/generated/linux-patch-api/installed-by-dh_install
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
debian/tmp/usr/bin/linux-patch-api
|
||||||
|
debian/tmp/lib/systemd/system/linux-patch-api.service
|
||||||
|
debian/tmp/etc/linux_patch_api/config.yaml
|
||||||
|
debian/tmp/etc/linux_patch_api/whitelist.yaml
|
||||||
0
debian/.debhelper/generated/linux-patch-api/installed-by-dh_installdocs
vendored
Normal file
0
debian/.debhelper/generated/linux-patch-api/installed-by-dh_installdocs
vendored
Normal file
30
debian/.debhelper/generated/linux-patch-api/postinst.service
vendored
Normal file
30
debian/.debhelper/generated/linux-patch-api/postinst.service
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Automatically added by dh_installsystemd/13.31
|
||||||
|
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
|
||||||
|
# The following line should be removed in trixie or trixie+1
|
||||||
|
deb-systemd-helper unmask 'linux-patch-api.service' >/dev/null || true
|
||||||
|
|
||||||
|
# was-enabled defaults to true, so new installations run enable.
|
||||||
|
if deb-systemd-helper --quiet was-enabled 'linux-patch-api.service'; then
|
||||||
|
# Enables the unit on first installation, creates new
|
||||||
|
# symlinks on upgrades if the unit file has changed.
|
||||||
|
deb-systemd-helper enable 'linux-patch-api.service' >/dev/null || true
|
||||||
|
else
|
||||||
|
# Update the statefile to add new symlinks (if any), which need to be
|
||||||
|
# cleaned up on purge. Also remove old symlinks.
|
||||||
|
deb-systemd-helper update-state 'linux-patch-api.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# End automatically added section
|
||||||
|
# Automatically added by dh_installsystemd/13.31
|
||||||
|
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
|
||||||
|
if [ -d /run/systemd/system ]; then
|
||||||
|
systemctl --system daemon-reload >/dev/null || true
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
_dh_action=restart
|
||||||
|
else
|
||||||
|
_dh_action=start
|
||||||
|
fi
|
||||||
|
deb-systemd-invoke $_dh_action 'linux-patch-api.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# End automatically added section
|
||||||
5
debian/.debhelper/generated/linux-patch-api/prerm.service
vendored
Normal file
5
debian/.debhelper/generated/linux-patch-api/prerm.service
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Automatically added by dh_installsystemd/13.31
|
||||||
|
if [ -z "$DPKG_ROOT" ] && [ "$1" = remove ] && [ -d /run/systemd/system ] ; then
|
||||||
|
deb-systemd-invoke stop 'linux-patch-api.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
# End automatically added section
|
||||||
1
debian/debhelper-build-stamp
vendored
Normal file
1
debian/debhelper-build-stamp
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
linux-patch-api
|
||||||
2
debian/files
vendored
Normal file
2
debian/files
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
linux-patch-api_1.0.0-1_amd64.buildinfo admin optional
|
||||||
|
linux-patch-api_1.0.0-1_amd64.deb admin optional
|
||||||
1
debian/linux-patch-api.debhelper.log
vendored
Normal file
1
debian/linux-patch-api.debhelper.log
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
dh_auto_install
|
||||||
12
debian/linux-patch-api.postrm.debhelper
vendored
Normal file
12
debian/linux-patch-api.postrm.debhelper
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Automatically added by dh_installsystemd/13.31
|
||||||
|
if [ "$1" = remove ] && [ -d /run/systemd/system ] ; then
|
||||||
|
systemctl --system daemon-reload >/dev/null || true
|
||||||
|
fi
|
||||||
|
# End automatically added section
|
||||||
|
# Automatically added by dh_installsystemd/13.31
|
||||||
|
if [ "$1" = "purge" ]; then
|
||||||
|
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||||
|
deb-systemd-helper purge 'linux-patch-api.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# End automatically added section
|
||||||
3
debian/linux-patch-api.substvars
vendored
Normal file
3
debian/linux-patch-api.substvars
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
shlibs:Depends=libc6 (>= 2.39), libgcc-s1 (>= 4.2)
|
||||||
|
misc:Depends=
|
||||||
|
misc:Pre-Depends=
|
||||||
4
debian/linux-patch-api/DEBIAN/conffiles
vendored
Normal file
4
debian/linux-patch-api/DEBIAN/conffiles
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/etc/linux_patch_api/config.yaml
|
||||||
|
/etc/linux_patch_api/whitelist.yaml
|
||||||
|
/etc/linux_patch_api/config.yaml
|
||||||
|
/etc/linux_patch_api/whitelist.yaml
|
||||||
23
debian/linux-patch-api/DEBIAN/control
vendored
Normal file
23
debian/linux-patch-api/DEBIAN/control
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Package: linux-patch-api
|
||||||
|
Version: 1.0.0-1
|
||||||
|
Architecture: amd64
|
||||||
|
Maintainer: Echo <echo@moon-dragon.us>
|
||||||
|
Installed-Size: 8897
|
||||||
|
Depends: systemd, libsystemd0, libc6 (>= 2.39), libgcc-s1 (>= 4.2)
|
||||||
|
Section: admin
|
||||||
|
Priority: optional
|
||||||
|
Homepage: https://gitea.moon-dragon.us/echo/linux_patch_api
|
||||||
|
Description: Secure remote package management API for Linux systems
|
||||||
|
Linux Patch API provides a secure, mTLS-authenticated REST API for
|
||||||
|
remote package management operations including:
|
||||||
|
- Package installation and removal
|
||||||
|
- Security patch application
|
||||||
|
- System health monitoring
|
||||||
|
- Job queue management with WebSocket status streaming
|
||||||
|
.
|
||||||
|
Features:
|
||||||
|
- Mutual TLS (mTLS) authentication
|
||||||
|
- IP whitelist enforcement
|
||||||
|
- Asynchronous job processing
|
||||||
|
- Comprehensive audit logging
|
||||||
|
- Systemd integration with security hardening
|
||||||
5
debian/linux-patch-api/DEBIAN/md5sums
vendored
Normal file
5
debian/linux-patch-api/DEBIAN/md5sums
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
23b89eecc51f46c6813658dd615d13a9 lib/systemd/system/linux-patch-api.service
|
||||||
|
d64a80e2a796561c39c6941c6b9e268c usr/bin/linux-patch-api
|
||||||
|
154c7ae7e01ae22cdc8ceea1fd0956e2 usr/share/doc/linux-patch-api/changelog.Debian.gz
|
||||||
|
978478c6c7f1e9dcb38eb1f2454535c0 usr/share/doc/linux-patch-api/changelog.gz
|
||||||
|
c2fab316c94aa61adb70d79365cfe08f usr/share/doc/linux-patch-api/copyright
|
||||||
49
debian/linux-patch-api/DEBIAN/postinst
vendored
Executable file
49
debian/linux-patch-api/DEBIAN/postinst
vendored
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# postinst script for linux-patch-api
|
||||||
|
# Created by package build system
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configure with debhelper
|
||||||
|
if [ "$1" = "configure" ]; then
|
||||||
|
echo "Configuring linux-patch-api..."
|
||||||
|
|
||||||
|
# Copy example configs if they don't exist
|
||||||
|
if [ ! -f "/etc/linux_patch_api/config.yaml" ]; then
|
||||||
|
echo "Creating default config.yaml..."
|
||||||
|
cp /etc/linux_patch_api/config.yaml.example /etc/linux_patch_api/config.yaml
|
||||||
|
chmod 640 /etc/linux_patch_api/config.yaml
|
||||||
|
chown linux-patch-api:linux-patch-api /etc/linux_patch_api/config.yaml
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "/etc/linux_patch_api/whitelist.yaml" ]; then
|
||||||
|
echo "Creating default whitelist.yaml..."
|
||||||
|
cp /etc/linux_patch_api/whitelist.yaml.example /etc/linux_patch_api/whitelist.yaml
|
||||||
|
chmod 640 /etc/linux_patch_api/whitelist.yaml
|
||||||
|
chown linux-patch-api:linux-patch-api /etc/linux_patch_api/whitelist.yaml
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reload systemd daemon to pick up new service file
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# Enable the service (but don't start automatically - admin should configure first)
|
||||||
|
systemctl enable linux-patch-api.service
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "linux-patch-api installed successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Configure /etc/linux_patch_api/config.yaml with your settings"
|
||||||
|
echo " 2. Place TLS certificates in /etc/linux_patch_api/certs/"
|
||||||
|
echo " 3. Configure IP whitelist in /etc/linux_patch_api/whitelist.yaml"
|
||||||
|
echo " 4. Start the service: systemctl start linux-patch-api"
|
||||||
|
echo " 5. Check status: systemctl status linux-patch-api"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle upgrade
|
||||||
|
if [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-remove" ] || [ "$1" = "abort-deconfigure" ]; then
|
||||||
|
echo "Installation aborted - service remains in previous state"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
64
debian/linux-patch-api/DEBIAN/postrm
vendored
Executable file
64
debian/linux-patch-api/DEBIAN/postrm
vendored
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# postrm script for linux-patch-api
|
||||||
|
# Created by package build system
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Handle purge - remove all configuration and data
|
||||||
|
if [ "$1" = "purge" ]; then
|
||||||
|
echo "Purging linux-patch-api configuration and data..."
|
||||||
|
|
||||||
|
# Stop service if still running
|
||||||
|
if systemctl is-active --quiet linux-patch-api.service 2>/dev/null; then
|
||||||
|
systemctl stop linux-patch-api.service
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Disable service
|
||||||
|
if systemctl is-enabled --quiet linux-patch-api.service 2>/dev/null; then
|
||||||
|
systemctl disable linux-patch-api.service
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reload systemd to remove service file
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# Remove configuration directory (preserved by conffiles during normal remove)
|
||||||
|
if [ -d "/etc/linux_patch_api" ]; then
|
||||||
|
echo "Removing /etc/linux_patch_api..."
|
||||||
|
rm -rf /etc/linux_patch_api
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove data directory
|
||||||
|
if [ -d "/var/lib/linux_patch_api" ]; then
|
||||||
|
echo "Removing /var/lib/linux_patch_api..."
|
||||||
|
rm -rf /var/lib/linux_patch_api
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove log directory
|
||||||
|
if [ -d "/var/log/linux_patch_api" ]; then
|
||||||
|
echo "Removing /var/log/linux_patch_api..."
|
||||||
|
rm -rf /var/log/linux_patch_api
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove system user
|
||||||
|
if getent passwd linux-patch-api > /dev/null 2>&1; then
|
||||||
|
echo "Removing user linux-patch-api..."
|
||||||
|
userdel linux-patch-api 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove system group
|
||||||
|
if getent group linux-patch-api > /dev/null 2>&1; then
|
||||||
|
echo "Removing group linux-patch-api..."
|
||||||
|
groupdel linux-patch-api 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "linux-patch-api purged successfully"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle upgrade/remove - just ensure service is disabled
|
||||||
|
if [ "$1" = "remove" ] || [ "$1" = "upgrade" ]; then
|
||||||
|
# Service should already be stopped by prerm
|
||||||
|
# Just reload systemd to remove the service file
|
||||||
|
systemctl daemon-reload 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
46
debian/linux-patch-api/DEBIAN/preinst
vendored
Executable file
46
debian/linux-patch-api/DEBIAN/preinst
vendored
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# preinst script for linux-patch-api
|
||||||
|
# Created by package build system
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check if this is an upgrade
|
||||||
|
if [ -d "/etc/linux_patch_api" ]; then
|
||||||
|
echo "Detected existing installation - performing upgrade"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create system user if it doesn't exist
|
||||||
|
if ! getent group linux-patch-api > /dev/null 2>&1; then
|
||||||
|
echo "Creating group linux-patch-api..."
|
||||||
|
groupadd --system linux-patch-api
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! getent passwd linux-patch-api > /dev/null 2>&1; then
|
||||||
|
echo "Creating user linux-patch-api..."
|
||||||
|
useradd --system \
|
||||||
|
--gid linux-patch-api \
|
||||||
|
--home-dir /var/lib/linux_patch_api \
|
||||||
|
--no-create-home \
|
||||||
|
--shell /usr/sbin/nologin \
|
||||||
|
--comment "Linux Patch API Service" \
|
||||||
|
linux-patch-api
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create required directories
|
||||||
|
mkdir -p /etc/linux_patch_api/certs
|
||||||
|
mkdir -p /var/lib/linux_patch_api
|
||||||
|
mkdir -p /var/log/linux_patch_api
|
||||||
|
|
||||||
|
# Set proper ownership
|
||||||
|
chown -R linux-patch-api:linux-patch-api /var/lib/linux_patch_api
|
||||||
|
chown -R linux-patch-api:linux-patch-api /var/log/linux_patch_api
|
||||||
|
|
||||||
|
# Set secure permissions
|
||||||
|
chmod 750 /etc/linux_patch_api
|
||||||
|
chmod 750 /etc/linux_patch_api/certs
|
||||||
|
chmod 755 /var/lib/linux_patch_api
|
||||||
|
chmod 755 /var/log/linux_patch_api
|
||||||
|
|
||||||
|
echo "Pre-installation checks completed successfully"
|
||||||
|
|
||||||
|
exit 0
|
||||||
33
debian/linux-patch-api/DEBIAN/prerm
vendored
Executable file
33
debian/linux-patch-api/DEBIAN/prerm
vendored
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# prerm script for linux-patch-api
|
||||||
|
# Created by package build system
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Stop the service before removal/upgrade
|
||||||
|
if [ "$1" = "remove" ] || [ "$1" = "upgrade" ]; then
|
||||||
|
echo "Stopping linux-patch-api service..."
|
||||||
|
|
||||||
|
if systemctl is-active --quiet linux-patch-api.service; then
|
||||||
|
systemctl stop linux-patch-api.service
|
||||||
|
echo "Service stopped successfully"
|
||||||
|
else
|
||||||
|
echo "Service was not running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Disable the service
|
||||||
|
if systemctl is-enabled --quiet linux-patch-api.service 2>/dev/null; then
|
||||||
|
systemctl disable linux-patch-api.service
|
||||||
|
echo "Service disabled"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle failed upgrade
|
||||||
|
if [ "$1" = "failed-upgrade" ]; then
|
||||||
|
echo "Upgrade failed - attempting to restore previous state"
|
||||||
|
# Previous version should handle restoration
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Pre-removal script completed"
|
||||||
|
|
||||||
|
exit 0
|
||||||
46
debian/linux-patch-api/etc/linux_patch_api/config.yaml
vendored
Normal file
46
debian/linux-patch-api/etc/linux_patch_api/config.yaml
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Linux Patch API Configuration
|
||||||
|
# Example configuration file - copy to /etc/linux_patch_api/config.yaml
|
||||||
|
|
||||||
|
# Server Configuration
|
||||||
|
server:
|
||||||
|
port: 12443
|
||||||
|
bind: "0.0.0.0"
|
||||||
|
timeout_seconds: 30
|
||||||
|
|
||||||
|
# TLS/mTLS Configuration
|
||||||
|
tls:
|
||||||
|
enabled: true
|
||||||
|
port: 12443
|
||||||
|
ca_cert: "/etc/linux_patch_api/certs/ca.pem"
|
||||||
|
server_cert: "/etc/linux_patch_api/certs/server.pem"
|
||||||
|
server_key: "/etc/linux_patch_api/certs/server.key"
|
||||||
|
min_tls_version: "1.3"
|
||||||
|
|
||||||
|
# Job Configuration
|
||||||
|
jobs:
|
||||||
|
max_concurrent: 5
|
||||||
|
timeout_minutes: 30
|
||||||
|
storage_path: "/var/lib/linux_patch_api/jobs"
|
||||||
|
|
||||||
|
# Logging Configuration
|
||||||
|
logging:
|
||||||
|
level: "info"
|
||||||
|
journal_enabled: true
|
||||||
|
syslog_enabled: false
|
||||||
|
# syslog_server: "udp://localhost:514"
|
||||||
|
file_path: "/var/log/linux_patch_api/audit.log"
|
||||||
|
retention_days: 30
|
||||||
|
|
||||||
|
# IP Whitelist Configuration
|
||||||
|
whitelist:
|
||||||
|
path: "/etc/linux_patch_api/whitelist.yaml"
|
||||||
|
# Entries can be:
|
||||||
|
# - Individual IPs: "192.168.1.100"
|
||||||
|
# - CIDR subnets: "192.168.1.0/24"
|
||||||
|
# - Hostnames: "admin-server.internal"
|
||||||
|
|
||||||
|
# Package Manager Backend
|
||||||
|
package_manager:
|
||||||
|
# Primary backend (auto-detected if not specified)
|
||||||
|
# Options: apt, dnf, yum, apk, pacman
|
||||||
|
backend: "auto"
|
||||||
14
debian/linux-patch-api/etc/linux_patch_api/whitelist.yaml
vendored
Normal file
14
debian/linux-patch-api/etc/linux_patch_api/whitelist.yaml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Linux Patch API - IP Whitelist Configuration
|
||||||
|
# Copy to /etc/linux_patch_api/whitelist.yaml
|
||||||
|
# Block all by default - only listed IPs can access the API
|
||||||
|
|
||||||
|
# Supported entry types:
|
||||||
|
# - Individual IPs: "192.168.1.100"
|
||||||
|
# - CIDR subnets: "192.168.1.0/24"
|
||||||
|
# - Hostnames: "admin-server.internal" (resolved at startup)
|
||||||
|
|
||||||
|
# Example entries:
|
||||||
|
entries:
|
||||||
|
- "192.168.1.0/24" # Management network
|
||||||
|
- "10.0.0.50" # Specific admin workstation
|
||||||
|
# - "admin-server.internal" # Hostname example (uncomment to use)
|
||||||
57
debian/linux-patch-api/lib/systemd/system/linux-patch-api.service
vendored
Normal file
57
debian/linux-patch-api/lib/systemd/system/linux-patch-api.service
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Linux Patch API - Secure Remote Package Management
|
||||||
|
Documentation=man:linux-patch-api(8)
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
ExecStart=/usr/bin/linux-patch-api --config /etc/linux_patch_api/config.yaml
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5s
|
||||||
|
TimeoutStopSec=30s
|
||||||
|
|
||||||
|
# Process management
|
||||||
|
RuntimeDirectory=linux-patch-api
|
||||||
|
RuntimeDirectoryMode=0755
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ReadWritePaths=/var/lib/linux_patch_api /var/log/linux_patch_api
|
||||||
|
PrivateTmp=true
|
||||||
|
PrivateDevices=true
|
||||||
|
ProtectHostname=true
|
||||||
|
ProtectClock=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
RestrictNamespaces=true
|
||||||
|
LockPersonality=true
|
||||||
|
MemoryDenyWriteExecute=false
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
RemoveIPC=true
|
||||||
|
|
||||||
|
# System call filtering (whitelist approach)
|
||||||
|
SystemCallFilter=@system-service
|
||||||
|
SystemCallErrorNumber=EPERM
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
Environment="RUST_BACKTRACE=1"
|
||||||
|
Environment="RUST_LOG=info"
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier=linux-patch-api
|
||||||
|
SyslogFacility=daemon
|
||||||
|
SyslogLevel=info
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
LimitNOFILE=65536
|
||||||
|
LimitNPROC=4096
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
BIN
debian/linux-patch-api/usr/bin/linux-patch-api
vendored
Executable file
BIN
debian/linux-patch-api/usr/bin/linux-patch-api
vendored
Executable file
Binary file not shown.
BIN
debian/linux-patch-api/usr/share/doc/linux-patch-api/changelog.Debian.gz
vendored
Normal file
BIN
debian/linux-patch-api/usr/share/doc/linux-patch-api/changelog.Debian.gz
vendored
Normal file
Binary file not shown.
BIN
debian/linux-patch-api/usr/share/doc/linux-patch-api/changelog.gz
vendored
Normal file
BIN
debian/linux-patch-api/usr/share/doc/linux-patch-api/changelog.gz
vendored
Normal file
Binary file not shown.
31
debian/linux-patch-api/usr/share/doc/linux-patch-api/copyright
vendored
Normal file
31
debian/linux-patch-api/usr/share/doc/linux-patch-api/copyright
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: linux-patch-api
|
||||||
|
Upstream-Contact: Echo <echo@moon-dragon.us>
|
||||||
|
Source: https://gitea.moon-dragon.us/echo/linux_patch_api
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2024-2026 Echo <echo@moon-dragon.us>
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2024-2026 Echo <echo@moon-dragon.us>
|
||||||
|
License: MIT
|
||||||
46
debian/tmp/etc/linux_patch_api/config.yaml
vendored
Normal file
46
debian/tmp/etc/linux_patch_api/config.yaml
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Linux Patch API Configuration
|
||||||
|
# Example configuration file - copy to /etc/linux_patch_api/config.yaml
|
||||||
|
|
||||||
|
# Server Configuration
|
||||||
|
server:
|
||||||
|
port: 12443
|
||||||
|
bind: "0.0.0.0"
|
||||||
|
timeout_seconds: 30
|
||||||
|
|
||||||
|
# TLS/mTLS Configuration
|
||||||
|
tls:
|
||||||
|
enabled: true
|
||||||
|
port: 12443
|
||||||
|
ca_cert: "/etc/linux_patch_api/certs/ca.pem"
|
||||||
|
server_cert: "/etc/linux_patch_api/certs/server.pem"
|
||||||
|
server_key: "/etc/linux_patch_api/certs/server.key"
|
||||||
|
min_tls_version: "1.3"
|
||||||
|
|
||||||
|
# Job Configuration
|
||||||
|
jobs:
|
||||||
|
max_concurrent: 5
|
||||||
|
timeout_minutes: 30
|
||||||
|
storage_path: "/var/lib/linux_patch_api/jobs"
|
||||||
|
|
||||||
|
# Logging Configuration
|
||||||
|
logging:
|
||||||
|
level: "info"
|
||||||
|
journal_enabled: true
|
||||||
|
syslog_enabled: false
|
||||||
|
# syslog_server: "udp://localhost:514"
|
||||||
|
file_path: "/var/log/linux_patch_api/audit.log"
|
||||||
|
retention_days: 30
|
||||||
|
|
||||||
|
# IP Whitelist Configuration
|
||||||
|
whitelist:
|
||||||
|
path: "/etc/linux_patch_api/whitelist.yaml"
|
||||||
|
# Entries can be:
|
||||||
|
# - Individual IPs: "192.168.1.100"
|
||||||
|
# - CIDR subnets: "192.168.1.0/24"
|
||||||
|
# - Hostnames: "admin-server.internal"
|
||||||
|
|
||||||
|
# Package Manager Backend
|
||||||
|
package_manager:
|
||||||
|
# Primary backend (auto-detected if not specified)
|
||||||
|
# Options: apt, dnf, yum, apk, pacman
|
||||||
|
backend: "auto"
|
||||||
14
debian/tmp/etc/linux_patch_api/whitelist.yaml
vendored
Normal file
14
debian/tmp/etc/linux_patch_api/whitelist.yaml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Linux Patch API - IP Whitelist Configuration
|
||||||
|
# Copy to /etc/linux_patch_api/whitelist.yaml
|
||||||
|
# Block all by default - only listed IPs can access the API
|
||||||
|
|
||||||
|
# Supported entry types:
|
||||||
|
# - Individual IPs: "192.168.1.100"
|
||||||
|
# - CIDR subnets: "192.168.1.0/24"
|
||||||
|
# - Hostnames: "admin-server.internal" (resolved at startup)
|
||||||
|
|
||||||
|
# Example entries:
|
||||||
|
entries:
|
||||||
|
- "192.168.1.0/24" # Management network
|
||||||
|
- "10.0.0.50" # Specific admin workstation
|
||||||
|
# - "admin-server.internal" # Hostname example (uncomment to use)
|
||||||
57
debian/tmp/lib/systemd/system/linux-patch-api.service
vendored
Normal file
57
debian/tmp/lib/systemd/system/linux-patch-api.service
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Linux Patch API - Secure Remote Package Management
|
||||||
|
Documentation=man:linux-patch-api(8)
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
ExecStart=/usr/bin/linux-patch-api --config /etc/linux_patch_api/config.yaml
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5s
|
||||||
|
TimeoutStopSec=30s
|
||||||
|
|
||||||
|
# Process management
|
||||||
|
RuntimeDirectory=linux-patch-api
|
||||||
|
RuntimeDirectoryMode=0755
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ReadWritePaths=/var/lib/linux_patch_api /var/log/linux_patch_api
|
||||||
|
PrivateTmp=true
|
||||||
|
PrivateDevices=true
|
||||||
|
ProtectHostname=true
|
||||||
|
ProtectClock=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
RestrictNamespaces=true
|
||||||
|
LockPersonality=true
|
||||||
|
MemoryDenyWriteExecute=false
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
RemoveIPC=true
|
||||||
|
|
||||||
|
# System call filtering (whitelist approach)
|
||||||
|
SystemCallFilter=@system-service
|
||||||
|
SystemCallErrorNumber=EPERM
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
Environment="RUST_BACKTRACE=1"
|
||||||
|
Environment="RUST_LOG=info"
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier=linux-patch-api
|
||||||
|
SyslogFacility=daemon
|
||||||
|
SyslogLevel=info
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
LimitNOFILE=65536
|
||||||
|
LimitNPROC=4096
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
BIN
debian/tmp/usr/bin/linux-patch-api
vendored
Executable file
BIN
debian/tmp/usr/bin/linux-patch-api
vendored
Executable file
Binary file not shown.
@ -12,9 +12,9 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::jobs::manager::{Job, JobManager, JobOperation, JobStatus};
|
use crate::jobs::manager::{Job, JobManager, JobStatus};
|
||||||
|
|
||||||
use super::packages::{ApiResponse, JobResponseData};
|
use super::packages::ApiResponse;
|
||||||
|
|
||||||
/// Job list response data
|
/// Job list response data
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -110,7 +110,7 @@ pub async fn list_jobs(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
|
|
||||||
let status_filter = query.status.as_ref().and_then(|s| parse_job_status(s));
|
let status_filter = query.status.as_ref().and_then(|s| parse_job_status(s));
|
||||||
let limit = query.limit.unwrap_or(50);
|
let limit = query.limit.unwrap_or(50);
|
||||||
@ -141,7 +141,7 @@ pub async fn get_job(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
let job_id_str = path.into_inner();
|
let job_id_str = path.into_inner();
|
||||||
|
|
||||||
info!(request_id = %request_id, job_id = %job_id_str, "Getting job details");
|
info!(request_id = %request_id, job_id = %job_id_str, "Getting job details");
|
||||||
@ -185,7 +185,7 @@ pub async fn rollback_job(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
let job_id_str = path.into_inner();
|
let job_id_str = path.into_inner();
|
||||||
|
|
||||||
info!(request_id = %request_id, job_id = %job_id_str, "Initiating job rollback");
|
info!(request_id = %request_id, job_id = %job_id_str, "Initiating job rollback");
|
||||||
@ -253,7 +253,7 @@ pub async fn delete_job(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
let job_id_str = path.into_inner();
|
let job_id_str = path.into_inner();
|
||||||
|
|
||||||
info!(request_id = %request_id, job_id = %job_id_str, "Deleting job from history");
|
info!(request_id = %request_id, job_id = %job_id_str, "Deleting job from history");
|
||||||
|
|||||||
@ -7,13 +7,13 @@
|
|||||||
use actix_web::{web, HttpRequest, HttpResponse, Responder};
|
use actix_web::{web, HttpRequest, HttpResponse, Responder};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::jobs::manager::{JobManager, JobOperation, JobStatus};
|
use crate::jobs::manager::{JobManager, JobOperation, JobStatus};
|
||||||
use crate::packages::PackageManagerBackend;
|
use crate::packages::PackageManagerBackend;
|
||||||
|
|
||||||
use super::packages::{ApiError, ApiResponse, JobResponseData};
|
use super::packages::{ApiResponse, JobResponseData};
|
||||||
|
|
||||||
/// Patch list response data
|
/// Patch list response data
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -41,7 +41,7 @@ pub async fn list_patches(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
|
|
||||||
info!(request_id = %request_id, "Listing available patches");
|
info!(request_id = %request_id, "Listing available patches");
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ pub async fn apply_patches(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
let packages_count = body.packages.as_ref().map(|p| p.len()).unwrap_or(0);
|
let packages_count = body.packages.as_ref().map(|p| p.len()).unwrap_or(0);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
|
|||||||
@ -8,40 +8,15 @@
|
|||||||
use actix_web::{web, HttpRequest, HttpResponse, Responder};
|
use actix_web::{web, HttpRequest, HttpResponse, Responder};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::packages::{ApiResponse, JobResponseData};
|
use super::packages::ApiResponse;
|
||||||
use crate::jobs::manager::{JobManager, JobOperation, JobStatus};
|
use crate::jobs::manager::{JobManager, JobOperation, JobStatus};
|
||||||
use crate::packages::PackageManagerBackend;
|
use crate::packages::PackageManagerBackend;
|
||||||
|
|
||||||
/// Normalize and validate file paths to prevent path traversal attacks (VULN-002)
|
/// Normalize and validate file paths to prevent path traversal attacks (VULN-002)
|
||||||
/// Returns None if path contains traversal patterns
|
/// Returns None if path contains traversal patterns
|
||||||
fn normalize_path(path: &str) -> Option<String> {
|
|
||||||
// Reject obvious traversal patterns
|
|
||||||
if path.contains("..") || path.contains("//") {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode common URL-encoded traversal attempts
|
|
||||||
let decoded = path
|
|
||||||
.replace("%2e", ".")
|
|
||||||
.replace("%2E", ".")
|
|
||||||
.replace("%2f", "/")
|
|
||||||
.replace("%2F", "/")
|
|
||||||
.replace("%5c", "\\")
|
|
||||||
.replace("%5C", "\\");
|
|
||||||
|
|
||||||
// Check decoded path for traversal
|
|
||||||
if decoded.contains("..") || decoded.contains("//") || decoded.contains("\\") {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure path starts with expected prefix or is relative
|
|
||||||
Some(path.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validate path input for traversal attacks
|
|
||||||
fn validate_path_no_traversal(path: &str) -> bool {
|
fn validate_path_no_traversal(path: &str) -> bool {
|
||||||
normalize_path(path).is_some()
|
normalize_path(path).is_some()
|
||||||
}
|
}
|
||||||
@ -82,7 +57,7 @@ pub async fn get_system_info(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
|
|
||||||
info!(request_id = %request_id, "Getting system information");
|
info!(request_id = %request_id, "Getting system information");
|
||||||
|
|
||||||
@ -116,8 +91,8 @@ pub async fn get_system_info(
|
|||||||
|
|
||||||
/// Health check endpoint
|
/// Health check endpoint
|
||||||
pub async fn health_check(_req: HttpRequest) -> impl Responder {
|
pub async fn health_check(_req: HttpRequest) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let _request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
|
|
||||||
// Calculate uptime from /proc/uptime
|
// Calculate uptime from /proc/uptime
|
||||||
let uptime_seconds = std::fs::read_to_string("/proc/uptime")
|
let uptime_seconds = std::fs::read_to_string("/proc/uptime")
|
||||||
@ -150,7 +125,7 @@ pub async fn reboot_system(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let request_id = Uuid::new_v4().to_string();
|
let request_id = Uuid::new_v4().to_string();
|
||||||
let timestamp = Utc::now().to_rfc3339();
|
let _timestamp = Utc::now().to_rfc3339();
|
||||||
let delay = body.delay_seconds;
|
let delay = body.delay_seconds;
|
||||||
let force = body.force;
|
let force = body.force;
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,10 @@
|
|||||||
//!
|
//!
|
||||||
//! Aggregates all endpoint routes and configures the Actix-web application.
|
//! Aggregates all endpoint routes and configures the Actix-web application.
|
||||||
|
|
||||||
use actix_web::{http::Method, web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::jobs::manager::JobManager;
|
use crate::jobs::manager::JobManager;
|
||||||
use crate::packages::create_backend;
|
|
||||||
|
|
||||||
use super::handlers::{jobs, packages, patches, system, websocket};
|
use super::handlers::{jobs, packages, patches, system, websocket};
|
||||||
|
|
||||||
|
|||||||
@ -3,12 +3,11 @@
|
|||||||
//! Provides mutual TLS authentication middleware for Actix-web.
|
//! Provides mutual TLS authentication middleware for Actix-web.
|
||||||
//! Non-mTLS connections are silently dropped (no response).
|
//! Non-mTLS connections are silently dropped (no response).
|
||||||
|
|
||||||
use actix_web::http::header;
|
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
|
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
|
||||||
Error, HttpMessage,
|
Error, HttpMessage,
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Duration, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use futures_util::future::LocalBoxFuture;
|
use futures_util::future::LocalBoxFuture;
|
||||||
use rustls::{
|
use rustls::{
|
||||||
server::{ServerConfig, WebPkiClientVerifier},
|
server::{ServerConfig, WebPkiClientVerifier},
|
||||||
@ -19,9 +18,8 @@ use std::{
|
|||||||
fs::File,
|
fs::File,
|
||||||
io::BufReader,
|
io::BufReader,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
task::{Context, Poll},
|
|
||||||
};
|
};
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
/// Check for duplicate critical headers (VULN-006)
|
/// Check for duplicate critical headers (VULN-006)
|
||||||
/// Returns true if duplicate headers are detected
|
/// Returns true if duplicate headers are detected
|
||||||
@ -275,7 +273,7 @@ where
|
|||||||
|
|
||||||
// All checks passed - call the service
|
// All checks passed - call the service
|
||||||
let fut = self.service.call(req);
|
let fut = self.service.call(req);
|
||||||
Box::pin(async move { fut.await })
|
Box::pin(fut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
/// Whitelist entry types
|
/// Whitelist entry types
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
@ -193,7 +193,7 @@ impl WhitelistManager {
|
|||||||
/// Set up file watcher for auto-reload
|
/// Set up file watcher for auto-reload
|
||||||
fn setup_watcher(&mut self) -> Result<()> {
|
fn setup_watcher(&mut self) -> Result<()> {
|
||||||
let config_path = self.config_path.clone();
|
let config_path = self.config_path.clone();
|
||||||
let entries = self.entries.clone();
|
let _entries = self.entries.clone();
|
||||||
|
|
||||||
let watcher = RecommendedWatcher::new(
|
let watcher = RecommendedWatcher::new(
|
||||||
move |res: Result<Event, notify::Error>| {
|
move |res: Result<Event, notify::Error>| {
|
||||||
|
|||||||
@ -203,7 +203,7 @@ mod tests {
|
|||||||
let result = AppConfig::load("tests/fixtures/valid_config.yaml");
|
let result = AppConfig::load("tests/fixtures/valid_config.yaml");
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let config = result.unwrap();
|
let config = result.unwrap();
|
||||||
assert!(config.server.port >= 1 && config.server.port <= 65535);
|
assert!(config.server.port >= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
/// Package status
|
/// Package status
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
@ -33,20 +33,12 @@ pub struct Package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Package installation options
|
/// Package installation options
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
pub struct InstallOptions {
|
pub struct InstallOptions {
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
pub no_recommends: bool,
|
pub no_recommends: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for InstallOptions {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
force: false,
|
|
||||||
no_recommends: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Patch information
|
/// Patch information
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -191,7 +183,7 @@ impl PackageManagerBackend for AptBackend {
|
|||||||
// Check if installed
|
// Check if installed
|
||||||
let dpkg_output = self.run_dpkg(&["-s", name]);
|
let dpkg_output = self.run_dpkg(&["-s", name]);
|
||||||
|
|
||||||
if let Err(_) = dpkg_output {
|
if dpkg_output.is_err() {
|
||||||
// Package not installed, check if available
|
// Package not installed, check if available
|
||||||
let list_output = self.run_apt(&["list", name])?;
|
let list_output = self.run_apt(&["list", name])?;
|
||||||
if list_output.contains(name) {
|
if list_output.contains(name) {
|
||||||
@ -227,7 +219,7 @@ impl PackageManagerBackend for AptBackend {
|
|||||||
let mut status = PackageStatus::Installed;
|
let mut status = PackageStatus::Installed;
|
||||||
let mut description = String::new();
|
let mut description = String::new();
|
||||||
let mut dependencies = Vec::new();
|
let mut dependencies = Vec::new();
|
||||||
let mut install_date = None;
|
let install_date = None;
|
||||||
let mut size_installed = None;
|
let mut size_installed = None;
|
||||||
|
|
||||||
for line in dpkg_info.lines() {
|
for line in dpkg_info.lines() {
|
||||||
@ -244,7 +236,7 @@ impl PackageManagerBackend for AptBackend {
|
|||||||
.trim_start_matches("Depends:")
|
.trim_start_matches("Depends:")
|
||||||
.trim()
|
.trim()
|
||||||
.split(',')
|
.split(',')
|
||||||
.map(|s| s.trim().split_whitespace().next().unwrap_or("").to_string())
|
.map(|s| s.split_whitespace().next().unwrap_or("").to_string())
|
||||||
.collect();
|
.collect();
|
||||||
} else if line.starts_with("Installed-Size:") {
|
} else if line.starts_with("Installed-Size:") {
|
||||||
size_installed = Some(format!(
|
size_installed = Some(format!(
|
||||||
@ -507,8 +499,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_apt_backend_creation() {
|
fn test_apt_backend_creation() {
|
||||||
let backend = AptBackend::new();
|
let _backend = AptBackend::new();
|
||||||
assert!(std::path::Path::new("/usr/bin/apt").exists() || true); // Test passes regardless
|
assert!(true); // Test passes regardless
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user