#!/bin/bash # Ubuntu uBlue apt-layer Advanced Package Management # Provides enterprise-grade package management with multi-user support, security features, # and advanced dependency resolution for production deployments # ============================================================================= # ADVANCED PACKAGE MANAGEMENT FUNCTIONS # ============================================================================= # Advanced package management configuration (with fallbacks for when particle-config.sh is not loaded) ADVANCED_PKG_CONFIG_DIR="${UBLUE_CONFIG_DIR:-/etc/ubuntu-ublue}/package-management" ADVANCED_PKG_STATE_DIR="${UBLUE_ROOT:-/var/lib/particle-os}/package-management" ADVANCED_PKG_CACHE_DIR="$ADVANCED_PKG_STATE_DIR/cache" ADVANCED_PKG_DEPENDENCIES_DIR="$ADVANCED_PKG_STATE_DIR/dependencies" ADVANCED_PKG_SECURITY_DIR="$ADVANCED_PKG_STATE_DIR/security" ADVANCED_PKG_USERS_DIR="$ADVANCED_PKG_STATE_DIR/users" ADVANCED_PKG_POLICIES_DIR="$ADVANCED_PKG_STATE_DIR/policies" # Initialize advanced package management system init_advanced_package_management() { log_info "Initializing advanced package management system" "apt-layer" # Create advanced package management directories mkdir -p "$ADVANCED_PKG_CONFIG_DIR" "$ADVANCED_PKG_STATE_DIR" "$ADVANCED_PKG_CACHE_DIR" mkdir -p "$ADVANCED_PKG_DEPENDENCIES_DIR" "$ADVANCED_PKG_SECURITY_DIR" "$ADVANCED_PKG_USERS_DIR" mkdir -p "$ADVANCED_PKG_POLICIES_DIR" # Set proper permissions chmod 755 "$ADVANCED_PKG_CONFIG_DIR" "$ADVANCED_PKG_STATE_DIR" chmod 700 "$ADVANCED_PKG_CACHE_DIR" "$ADVANCED_PKG_DEPENDENCIES_DIR" "$ADVANCED_PKG_SECURITY_DIR" chmod 750 "$ADVANCED_PKG_USERS_DIR" "$ADVANCED_PKG_POLICIES_DIR" # Initialize user management database init_user_management_db # Initialize security policies init_security_policies # Initialize dependency resolution cache init_dependency_cache log_success "Advanced package management system initialized" "apt-layer" } # Initialize user management database init_user_management_db() { local user_db="$ADVANCED_PKG_USERS_DIR/users.json" if [[ ! -f "$user_db" ]]; then cat > "$user_db" << EOF { "users": {}, "groups": {}, "permissions": {}, "roles": { "admin": { "description": "Full system administration", "permissions": ["all"] }, "package_manager": { "description": "Package installation and management", "permissions": ["install", "remove", "update", "list"] }, "viewer": { "description": "Read-only access to package information", "permissions": ["list", "info", "status"] } } } EOF chmod 600 "$user_db" fi } # Initialize security policies init_security_policies() { local security_policy="$ADVANCED_PKG_SECURITY_DIR/security-policy.json" if [[ ! -f "$security_policy" ]]; then cat > "$security_policy" << EOF { "package_verification": { "enabled": true, "gpg_check": true, "hash_verification": true, "source_verification": true }, "installation_policies": { "allow_unsigned_packages": false, "allow_external_sources": false, "require_approval": false, "max_package_size_mb": 1000 }, "security_scanning": { "enabled": true, "scan_installed_packages": true, "scan_dependencies": true, "vulnerability_check": true }, "audit_logging": { "enabled": true, "log_level": "INFO", "retention_days": 90 } } EOF chmod 600 "$security_policy" fi } # Initialize dependency cache init_dependency_cache() { local dep_cache="$ADVANCED_PKG_DEPENDENCIES_DIR/dependency-cache.json" if [[ ! -f "$dep_cache" ]]; then cat > "$dep_cache" << EOF { "package_dependencies": {}, "reverse_dependencies": {}, "conflict_resolution": {}, "last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)" } EOF chmod 644 "$dep_cache" fi } # Check user permissions check_user_permissions() { local user="$1" local required_permission="$2" log_debug "Checking permission '$required_permission' for user '$user'" "apt-layer" # Root user has all permissions if [[ "$user" == "root" ]] || [[ $EUID -eq 0 ]]; then return 0 fi local user_db="$ADVANCED_PKG_USERS_DIR/users.json" if [[ ! -f "$user_db" ]]; then log_error "User management database not found" "apt-layer" return 1 fi # Get user role local user_role user_role=$(jq -r ".users[\"$user\"].role // \"viewer\"" "$user_db" 2>/dev/null || echo "viewer") # Get role permissions local role_permissions role_permissions=$(jq -r ".roles[\"$user_role\"].permissions[]?" "$user_db" 2>/dev/null || echo "") # Check if user has required permission if echo "$role_permissions" | grep -q "^$required_permission$" || echo "$role_permissions" | grep -q "^all$"; then return 0 fi log_error "User '$user' does not have permission '$required_permission'" "apt-layer" return 1 } # Add user to package management system add_package_user() { local username="$1" local role="${2:-viewer}" if [[ -z "$username" ]]; then log_error "Username required" "apt-layer" return 1 fi log_info "Adding user '$username' with role '$role'" "apt-layer" # Check if user exists in system if ! id "$username" &>/dev/null; then log_error "User '$username' does not exist in system" "apt-layer" return 1 fi local user_db="$ADVANCED_PKG_USERS_DIR/users.json" # Check if role exists if ! jq -e ".roles[\"$role\"]" "$user_db" >/dev/null 2>&1; then log_error "Role '$role' does not exist" "apt-layer" return 1 fi # Add user to database jq --arg user "$username" --arg role "$role" '.users[$user] = {"role": $role, "added": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' "$user_db" > "$user_db.tmp" && \ mv "$user_db.tmp" "$user_db" log_success "User '$username' added with role '$role'" "apt-layer" return 0 } # Remove user from package management system remove_package_user() { local username="$1" if [[ -z "$username" ]]; then log_error "Username required" "apt-layer" return 1 fi log_info "Removing user '$username'" "apt-layer" local user_db="$ADVANCED_PKG_USERS_DIR/users.json" # Remove user from database jq --arg user "$username" 'del(.users[$user])' "$user_db" > "$user_db.tmp" && \ mv "$user_db.tmp" "$user_db" log_success "User '$username' removed" "apt-layer" return 0 } # List package management users list_package_users() { log_info "Listing package management users" "apt-layer" local user_db="$ADVANCED_PKG_USERS_DIR/users.json" if [[ ! -f "$user_db" ]]; then log_error "User management database not found" "apt-layer" return 1 fi echo "=== Package Management Users ===" local users users=$(jq -r '.users | to_entries[] | "\(.key): \(.value.role)"' "$user_db" 2>/dev/null || echo "") if [[ -n "$users" ]]; then echo "$users" | while read -r user_info; do echo " $user_info" done else log_info "No users found" "apt-layer" fi echo "" echo "=== Available Roles ===" local roles roles=$(jq -r '.roles | to_entries[] | "\(.key): \(.value.description)"' "$user_db" 2>/dev/null || echo "") if [[ -n "$roles" ]]; then echo "$roles" | while read -r role_info; do echo " $role_info" done else log_info "No roles found" "apt-layer" fi echo "" } # Advanced dependency resolution resolve_package_dependencies() { local packages=("$@") if [[ ${#packages[@]} -eq 0 ]]; then log_error "No packages specified for dependency resolution" "apt-layer" return 1 fi log_info "Resolving dependencies for packages: ${packages[*]}" "apt-layer" # Create temporary file for dependency resolution local temp_deps="$ADVANCED_PKG_CACHE_DIR/temp-deps-$$.txt" local resolved_deps="$ADVANCED_PKG_CACHE_DIR/resolved-deps-$$.txt" # Get package dependencies using apt-cache for package in "${packages[@]}"; do log_debug "Resolving dependencies for package: $package" "apt-layer" # Get direct dependencies apt-cache depends "$package" 2>/dev/null | grep -E "^(Depends|Recommends|Suggests)" | cut -d: -f2 | tr -d ' ' | grep -v "^$" >> "$temp_deps" || true # Get reverse dependencies (what depends on this package) apt-cache rdepends "$package" 2>/dev/null | grep -v "^Reverse Depends" | grep -v "^$" >> "$temp_deps" || true done # Remove duplicates and sort sort -u "$temp_deps" > "$resolved_deps" # Check for conflicts local conflicts=() while read -r dep; do if [[ -n "$dep" ]]; then # Check if package conflicts with any existing packages if check_package_conflicts "$dep"; then conflicts+=("$dep") fi fi done < "$resolved_deps" # Report conflicts if [[ ${#conflicts[@]} -gt 0 ]]; then log_warning "Package conflicts detected: ${conflicts[*]}" "apt-layer" log_info "Manual resolution may be required" "apt-layer" fi # Clean up temporary files rm -f "$temp_deps" "$resolved_deps" log_success "Dependency resolution completed" "apt-layer" return 0 } # Check for package conflicts check_package_conflicts() { local package="$1" if [[ -z "$package" ]]; then return 1 fi # Check if package conflicts with any installed packages local conflicts conflicts=$(apt-cache policy "$package" 2>/dev/null | grep -A1 "Installed" | grep -E "(Conflicts|Breaks)" || echo "") if [[ -n "$conflicts" ]]; then log_warning "Package '$package' has conflicts: $conflicts" "apt-layer" return 0 fi return 1 } # Advanced package installation with security checks advanced_install_packages() { local packages=("$@") local user="${SUDO_USER:-$USER}" if [[ ${#packages[@]} -eq 0 ]]; then log_error "No packages specified for installation" "apt-layer" return 1 fi log_info "Advanced package installation for packages: ${packages[*]}" "apt-layer" # Check user permissions if ! check_user_permissions "$user" "install"; then return 1 fi # Check security policies if ! check_security_policies "${packages[@]}"; then return 1 fi # Resolve dependencies if ! resolve_package_dependencies "${packages[@]}"; then log_error "Dependency resolution failed" "apt-layer" return 1 fi # Start transaction start_transaction "advanced_install_${packages[0]}" # Update package lists update_transaction_phase "updating_package_lists" log_info "Updating package lists" "apt-layer" if ! apt-get update; then log_error "Failed to update package lists" "apt-layer" rollback_transaction return 1 fi # Install packages update_transaction_phase "installing_packages" log_info "Installing packages: ${packages[*]}" "apt-layer" if ! apt-get install -y "${packages[@]}"; then log_error "Failed to install packages: ${packages[*]}" "apt-layer" rollback_transaction return 1 fi # Clean up apt-get clean apt-get autoremove -y # Log installation log_package_installation "$user" "${packages[@]}" commit_transaction log_success "Advanced package installation completed: ${packages[*]}" "apt-layer" return 0 } # Check security policies check_security_policies() { local packages=("$@") log_info "Checking security policies for packages: ${packages[*]}" "apt-layer" local security_policy="$ADVANCED_PKG_SECURITY_DIR/security-policy.json" if [[ ! -f "$security_policy" ]]; then log_warning "Security policy not found, using default policies" "apt-layer" return 0 fi # Check package verification settings local gpg_check gpg_check=$(jq -r '.package_verification.gpg_check' "$security_policy" 2>/dev/null || echo "true") if [[ "$gpg_check" == "true" ]]; then log_info "GPG verification enabled" "apt-layer" # Perform comprehensive GPG verification for package in "${packages[@]}"; do if ! check_package_gpg_signature "$package"; then log_error "Package '$package' failed GPG signature verification" "apt-layer" return 1 fi done fi # Check installation policies local allow_unsigned allow_unsigned=$(jq -r '.installation_policies.allow_unsigned_packages' "$security_policy" 2>/dev/null || echo "false") if [[ "$allow_unsigned" == "false" ]]; then log_info "Unsigned packages not allowed" "apt-layer" # Check for unsigned packages using enhanced signing verification for package in "${packages[@]}"; do if ! check_package_signing "$package"; then log_error "Package '$package' is not properly signed" "apt-layer" return 1 fi done fi # Check package size limits local max_size max_size=$(jq -r '.installation_policies.max_package_size_mb' "$security_policy" 2>/dev/null || echo "1000") for package in "${packages[@]}"; do if ! check_package_size "$package" "$max_size"; then log_error "Package '$package' exceeds size limit of ${max_size}MB" "apt-layer" return 1 fi done log_success "Security policy checks passed" "apt-layer" return 0 } # Check package signature check_package_signature() { local package="$1" if [[ -z "$package" ]]; then return 1 fi # Check if package is signed (simplified check) local package_info package_info=$(apt-cache policy "$package" 2>/dev/null || echo "") if echo "$package_info" | grep -q "Signed-By"; then return 0 fi return 1 } # Check package GPG signature (comprehensive verification) check_package_gpg_signature() { local package="$1" if [[ -z "$package" ]]; then return 1 fi log_debug "Verifying GPG signature for package: $package" "apt-layer" # Check if GPG is available if ! command -v gpg &>/dev/null; then log_warning "GPG not available, skipping signature verification for: $package" "apt-layer" return 0 fi # Get package source and key information local package_info package_info=$(apt-cache policy "$package" 2>/dev/null || echo "") # Check if package has a signed-by field local signed_by signed_by=$(echo "$package_info" | grep "Signed-By:" | cut -d: -f2 | tr -d ' ' || echo "") if [[ -z "$signed_by" ]]; then log_warning "Package '$package' has no Signed-By field" "apt-layer" return 1 fi # Verify the GPG key exists and is trusted if ! gpg --list-keys "$signed_by" &>/dev/null; then log_warning "GPG key '$signed_by' for package '$package' not found in keyring" "apt-layer" return 1 fi # Additional verification: check if the key is trusted local trust_level trust_level=$(gpg --list-keys --with-colons "$signed_by" 2>/dev/null | grep "^pub:" | cut -d: -f2 || echo "") if [[ "$trust_level" != "u" ]] && [[ "$trust_level" != "f" ]]; then log_warning "GPG key '$signed_by' for package '$package' is not fully trusted (trust level: $trust_level)" "apt-layer" return 1 fi log_debug "GPG signature verification passed for package: $package" "apt-layer" return 0 } # Check package signing (enhanced verification) check_package_signing() { local package="$1" if [[ -z "$package" ]]; then return 1 fi log_debug "Checking package signing for: $package" "apt-layer" # Check if debsig-verify is available for Debian package signing verification if command -v debsig-verify &>/dev/null; then # Get package file path (this would require downloading or finding the .deb file) local package_file package_file=$(find /var/cache/apt/archives -name "${package}*.deb" 2>/dev/null | head -1 || echo "") if [[ -n "$package_file" ]] && [[ -f "$package_file" ]]; then if debsig-verify "$package_file" &>/dev/null; then log_debug "Package signing verification passed for: $package" "apt-layer" return 0 else log_warning "Package signing verification failed for: $package" "apt-layer" return 1 fi fi fi # Fallback to basic signature check if check_package_signature "$package"; then log_debug "Basic package signature check passed for: $package" "apt-layer" return 0 fi log_warning "Package signing verification failed for: $package" "apt-layer" return 1 } # Check package size check_package_size() { local package="$1" local max_size_mb="$2" if [[ -z "$package" ]] || [[ -z "$max_size_mb" ]]; then return 1 fi # Get package size (simplified check) local package_size package_size=$(apt-cache show "$package" 2>/dev/null | grep "^Size:" | cut -d: -f2 | tr -d ' ' || echo "0") if [[ "$package_size" -gt $((max_size_mb * 1024 * 1024)) ]]; then return 1 fi return 0 } # Log package installation log_package_installation() { local user="$1" shift local packages=("$@") local audit_log="$ADVANCED_PKG_SECURITY_DIR/audit.log" for package in "${packages[@]}"; do echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - INSTALL - User: $user - Package: $package" >> "$audit_log" done } # Advanced package removal with dependency checking advanced_remove_packages() { local packages=("$@") local user="${SUDO_USER:-$USER}" if [[ ${#packages[@]} -eq 0 ]]; then log_error "No packages specified for removal" "apt-layer" return 1 fi log_info "Advanced package removal for packages: ${packages[*]}" "apt-layer" # Check user permissions if ! check_user_permissions "$user" "remove"; then return 1 fi # Check for critical dependencies for package in "${packages[@]}"; do if check_critical_dependency "$package"; then log_warning "Package '$package' may be a critical dependency" "apt-layer" log_info "Manual verification recommended" "apt-layer" fi done # Start transaction start_transaction "advanced_remove_${packages[0]}" # Remove packages update_transaction_phase "removing_packages" log_info "Removing packages: ${packages[*]}" "apt-layer" if ! apt-get remove -y "${packages[@]}"; then log_error "Failed to remove packages: ${packages[*]}" "apt-layer" rollback_transaction return 1 fi # Clean up apt-get autoremove -y apt-get clean # Log removal log_package_removal "$user" "${packages[@]}" commit_transaction log_success "Advanced package removal completed: ${packages[*]}" "apt-layer" return 0 } # Check if package is a critical dependency check_critical_dependency() { local package="$1" if [[ -z "$package" ]]; then return 1 fi # List of critical system packages (simplified) local critical_packages=("systemd" "bash" "coreutils" "apt" "dpkg" "base-files" "ubuntu-minimal") for critical in "${critical_packages[@]}"; do if [[ "$package" == "$critical" ]]; then return 0 fi done return 1 } # Log package removal log_package_removal() { local user="$1" shift local packages=("$@") local audit_log="$ADVANCED_PKG_SECURITY_DIR/audit.log" for package in "${packages[@]}"; do echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - REMOVE - User: $user - Package: $package" >> "$audit_log" done } # Advanced package update with rollback capability advanced_update_packages() { local packages=("$@") local user="${SUDO_USER:-$USER}" log_info "Advanced package update for packages: ${packages[*]}" "apt-layer" # Check user permissions if ! check_user_permissions "$user" "update"; then return 1 fi # Create backup of current state local backup_id backup_id=$(create_package_backup "${packages[@]}") if [[ -z "$backup_id" ]]; then log_error "Failed to create package backup" "apt-layer" return 1 fi log_info "Created backup: $backup_id" "apt-layer" # Start transaction start_transaction "advanced_update_${packages[0]}" # Update package lists update_transaction_phase "updating_package_lists" log_info "Updating package lists" "apt-layer" if ! apt-get update; then log_error "Failed to update package lists" "apt-layer" rollback_transaction return 1 fi # Update packages update_transaction_phase "updating_packages" log_info "Updating packages: ${packages[*]}" "apt-layer" if ! apt-get upgrade -y "${packages[@]}"; then log_error "Failed to update packages: ${packages[*]}" "apt-layer" log_info "Rolling back to backup: $backup_id" "apt-layer" restore_package_backup "$backup_id" rollback_transaction return 1 fi # Log update log_package_update "$user" "${packages[@]}" commit_transaction log_success "Advanced package update completed: ${packages[*]}" "apt-layer" return 0 } # Create package backup create_package_backup() { local packages=("$@") local backup_id="backup-$(date +%Y%m%d-%H%M%S)-$$" local backup_dir="$ADVANCED_PKG_STATE_DIR/backups/$backup_id" mkdir -p "$backup_dir" log_info "Creating comprehensive package backup: $backup_id" "apt-layer" # Save package states for package in "${packages[@]}"; do dpkg -l "$package" > "$backup_dir/${package}.state" 2>/dev/null || true done # Save complete package list dpkg -l | grep -E "^ii" > "$backup_dir/installed-packages.list" 2>/dev/null || true # Save package configuration dpkg --get-selections > "$backup_dir/package-selections.list" 2>/dev/null || true # Save repository information cp /etc/apt/sources.list "$backup_dir/sources.list" 2>/dev/null || true cp -r /etc/apt/sources.list.d "$backup_dir/" 2>/dev/null || true # Save GPG key information apt-key list > "$backup_dir/apt-keys.list" 2>/dev/null || true # Create backup metadata cat > "$backup_dir/backup-metadata.json" << EOF { "backup_id": "$backup_id", "created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", "created_by": "$(whoami)", "packages": $(printf '%s\n' "${packages[@]}" | jq -R . | jq -s .), "system_info": { "hostname": "$(hostname)", "distribution": "$(lsb_release -d | cut -f2 2>/dev/null || echo 'unknown')", "kernel": "$(uname -r)" } } EOF # Compress backup for storage efficiency tar -czf "$backup_dir.tar.gz" -C "$ADVANCED_PKG_STATE_DIR/backups" "$backup_id" 2>/dev/null || true log_success "Package backup created: $backup_id" "apt-layer" echo "$backup_id" } # Restore package backup restore_package_backup() { local backup_id="$1" local backup_dir="$ADVANCED_PKG_STATE_DIR/backups/$backup_id" local backup_archive="$backup_dir.tar.gz" # Check if backup exists (try both directory and compressed archive) if [[ ! -d "$backup_dir" ]] && [[ ! -f "$backup_archive" ]]; then log_error "Backup not found: $backup_id" "apt-layer" return 1 fi log_info "Restoring from backup: $backup_id" "apt-layer" # Extract compressed backup if needed if [[ -f "$backup_archive" ]] && [[ ! -d "$backup_dir" ]]; then log_info "Extracting compressed backup..." "apt-layer" tar -xzf "$backup_archive" -C "$ADVANCED_PKG_STATE_DIR/backups/" 2>/dev/null || { log_error "Failed to extract backup archive: $backup_archive" "apt-layer" return 1 } fi # Verify backup integrity if [[ ! -f "$backup_dir/backup-metadata.json" ]]; then log_error "Backup metadata not found, backup may be corrupted: $backup_id" "apt-layer" return 1 fi # Read backup metadata local backup_metadata backup_metadata=$(cat "$backup_dir/backup-metadata.json" 2>/dev/null || echo "{}") local backup_packages backup_packages=$(echo "$backup_metadata" | jq -r '.packages[]?' 2>/dev/null || echo "") log_info "Backup contains $(echo "$backup_packages" | wc -l) packages" "apt-layer" # Restore package selections if available if [[ -f "$backup_dir/package-selections.list" ]]; then log_info "Restoring package selections..." "apt-layer" dpkg --set-selections < "$backup_dir/package-selections.list" 2>/dev/null || { log_warning "Failed to restore package selections" "apt-layer" } fi # Restore repository information if available if [[ -f "$backup_dir/sources.list" ]]; then log_info "Restoring repository configuration..." "apt-layer" cp "$backup_dir/sources.list" /etc/apt/sources.list 2>/dev/null || { log_warning "Failed to restore sources.list" "apt-layer" } fi if [[ -d "$backup_dir/sources.list.d" ]]; then cp -r "$backup_dir/sources.list.d"/* /etc/apt/sources.list.d/ 2>/dev/null || { log_warning "Failed to restore sources.list.d" "apt-layer" } fi # Update package lists after repository restoration apt-get update 2>/dev/null || { log_warning "Failed to update package lists after repository restoration" "apt-layer" } log_success "Backup restoration completed: $backup_id" "apt-layer" log_audit "BACKUP_RESTORE" "Restored from backup: $backup_id" return 0 } # Log package update log_package_update() { local user="$1" shift local packages=("$@") local audit_log="$ADVANCED_PKG_SECURITY_DIR/audit.log" for package in "${packages[@]}"; do echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - UPDATE - User: $user - Package: $package" >> "$audit_log" done } # List package backups list_package_backups() { log_info "Listing package backups" "apt-layer" local backups_dir="$ADVANCED_PKG_STATE_DIR/backups" if [[ ! -d "$backups_dir" ]]; then log_info "No backups directory found" "apt-layer" return 0 fi echo "=== Package Backups ===" local backups backups=$(find "$backups_dir" -name "backup-*" -type d 2>/dev/null | sort -r || echo "") if [[ -n "$backups" ]]; then for backup_dir in $backups; do local backup_id backup_id=$(basename "$backup_dir") local metadata_file="$backup_dir/backup-metadata.json" if [[ -f "$metadata_file" ]]; then local created_at created_at=$(jq -r '.created_at // "unknown"' "$metadata_file" 2>/dev/null || echo "unknown") local created_by created_by=$(jq -r '.created_by // "unknown"' "$metadata_file" 2>/dev/null || echo "unknown") local package_count package_count=$(jq -r '.packages | length // 0' "$metadata_file" 2>/dev/null || echo "0") echo " $backup_id: $package_count packages, created by $created_by at $created_at" else echo " $backup_id: (metadata not available)" fi done else log_info "No backups found" "apt-layer" fi echo "" } # Clean up old backups cleanup_old_backups() { local max_age_days="${1:-30}" log_info "Cleaning up backups older than $max_age_days days" "apt-layer" local backups_dir="$ADVANCED_PKG_STATE_DIR/backups" if [[ ! -d "$backups_dir" ]]; then log_info "No backups directory found" "apt-layer" return 0 fi local removed_count=0 # Find and remove old backup directories while IFS= read -r -d '' backup_dir; do local backup_id backup_id=$(basename "$backup_dir") local metadata_file="$backup_dir/backup-metadata.json" if [[ -f "$metadata_file" ]]; then local created_at created_at=$(jq -r '.created_at // ""' "$metadata_file" 2>/dev/null || echo "") if [[ -n "$created_at" ]]; then local created_timestamp created_timestamp=$(date -d "$created_at" +%s 2>/dev/null || echo "0") local current_timestamp current_timestamp=$(date +%s) local age_days age_days=$(( (current_timestamp - created_timestamp) / 86400 )) if [[ $age_days -gt $max_age_days ]]; then log_info "Removing old backup: $backup_id (age: ${age_days} days)" "apt-layer" rm -rf "$backup_dir" 2>/dev/null || true rm -f "$backup_dir.tar.gz" 2>/dev/null || true ((removed_count++)) fi fi fi done < <(find "$backups_dir" -name "backup-*" -type d -print0 2>/dev/null) log_success "Cleaned up $removed_count old backups" "apt-layer" return 0 } # Get advanced package information get_advanced_package_info() { local package="$1" if [[ -z "$package" ]]; then log_error "Package name required" "apt-layer" return 1 fi log_info "Getting advanced information for package: $package" "apt-layer" echo "=== Advanced Package Information: $package ===" # Basic package information echo "Basic Information:" apt-cache show "$package" 2>/dev/null | grep -E "^(Package|Version|Architecture|Maintainer|Description)" | head -10 # Dependencies echo "" echo "Dependencies:" apt-cache depends "$package" 2>/dev/null | grep -E "^(Depends|Recommends|Suggests)" | head -5 # Reverse dependencies echo "" echo "Reverse Dependencies:" apt-cache rdepends "$package" 2>/dev/null | grep -v "^Reverse Depends" | head -5 # Security information echo "" echo "Security Information:" if check_package_signature "$package"; then echo " â Package is signed" else echo " â Package is not signed" fi # Size information local package_size package_size=$(apt-cache show "$package" 2>/dev/null | grep "^Size:" | cut -d: -f2 | tr -d ' ' || echo "unknown") echo " Size: $package_size bytes" echo "" } # List advanced package management status list_advanced_package_status() { log_info "Listing advanced package management status" "apt-layer" echo "=== Advanced Package Management Status ===" # User management status echo "User Management:" local user_count user_count=$(jq '.users | length' "$ADVANCED_PKG_USERS_DIR/users.json" 2>/dev/null || echo "0") echo " Active users: $user_count" # Security policy status echo "" echo "Security Policies:" local security_policy="$ADVANCED_PKG_SECURITY_DIR/security-policy.json" if [[ -f "$security_policy" ]]; then local gpg_check gpg_check=$(jq -r '.package_verification.gpg_check' "$security_policy" 2>/dev/null || echo "unknown") echo " GPG verification: $gpg_check" local audit_logging audit_logging=$(jq -r '.audit_logging.enabled' "$security_policy" 2>/dev/null || echo "unknown") echo " Audit logging: $audit_logging" else echo " Security policies: not configured" fi # Dependency cache status echo "" echo "Dependency Cache:" local dep_cache="$ADVANCED_PKG_DEPENDENCIES_DIR/dependency-cache.json" if [[ -f "$dep_cache" ]]; then local last_updated last_updated=$(jq -r '.last_updated' "$dep_cache" 2>/dev/null || echo "unknown") echo " Last updated: $last_updated" else echo " Dependency cache: not initialized" fi # Audit log status echo "" echo "Audit Log:" local audit_log="$ADVANCED_PKG_SECURITY_DIR/audit.log" if [[ -f "$audit_log" ]]; then local log_entries log_entries=$(wc -l < "$audit_log" 2>/dev/null || echo "0") echo " Total entries: $log_entries" local recent_entries recent_entries=$(tail -10 "$audit_log" 2>/dev/null | wc -l || echo "0") echo " Recent entries: $recent_entries" else echo " Audit log: not available" fi echo "" } # ============================================================================= # INTEGRATION FUNCTIONS # ============================================================================= # Initialize advanced package management on script startup init_advanced_package_management_on_startup() { # Only initialize if not already done if [[ ! -d "$ADVANCED_PKG_STATE_DIR" ]]; then init_advanced_package_management fi } # Cleanup advanced package management on script exit cleanup_advanced_package_management_on_exit() { # Clean up temporary files rm -f "$ADVANCED_PKG_CACHE_DIR"/temp-* 2>/dev/null || true rm -f "$ADVANCED_PKG_CACHE_DIR"/resolved-* 2>/dev/null || true } # Register cleanup function trap cleanup_advanced_package_management_on_exit EXIT