Cleanup and archived things not in scope

This commit is contained in:
robojerk 2025-07-14 01:48:14 -07:00
parent eb473b1f37
commit 5ac26d0800
39 changed files with 1433 additions and 27827 deletions

View file

@ -7,6 +7,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### [2025-07-14 UTC] - SCOPE REDUCTION: FOCUS ON CORE RPM-OSTREE FEATURES ONLY
- **Scope reduction completed**: Archived all advanced, enterprise, cloud, multi-tenant, admin, compliance, and security features.
- **Now focused on core rpm-ostree-like features for apt/Debian systems only:**
- Atomic deployment, rollback, status, diff, cleanup
- Live overlay and container-based layering
- Bootloader and kargs management
- OCI/ComposeFS integration
- Direct dpkg install for apt/deb systems
- All core rpm-ostree-like features for apt/Debian
- **compile.sh updated**: Only includes core scriptlets; all advanced/enterprise scriptlets removed from build.
- **TODO updated**: All advanced/enterprise/cloud/multi-tenant/admin/compliance/security items removed or marked as archived; TODO now only tracks core atomic/OSTree/overlay/bootloader/compatibility features.
- **Documentation updated**: All documentation and script inventory reflect the new, reduced scope.
- **Advanced features archived**: All advanced/enterprise scriptlets are safely archived and can be restored later if needed.
- **Result**: Codebase is now a true rpm-ostree equivalent for apt/Debian systems, with no extra enterprise/cloud/advanced features.
### [2025-01-27 23:58 UTC] - DOCUMENTATION UPDATES AND WORKSPACE CLEANUP COMPLETED
- **Comprehensive documentation updates completed**: Updated all major documentation files to reflect current Particle-OS capabilities and recent improvements.
- **Main documentation files updated**: Updated multiple documentation files to reflect new apt-layer atomic OSTree workflow and official ComposeFS tool integration:
- `tools.md` - Updated to reflect atomic OSTree workflow, official ComposeFS integration, and overlay/dpkg improvements
- `TODO.md` - Updated completion status and added new priorities for compilation system enhancements
- `TESTING_GUIDE.md` - Updated to include OSTree/atomic testing procedures and overlay workflow validation
- `SCRIPT_INVENTORY.md` - Updated to reflect current script organization and archiving of alternative implementations
- `Readme.md` - Updated main project README with current capabilities and recent improvements
- `comparisons.md` - Updated feature comparisons to reflect current Particle-OS capabilities
- **Workspace cleanup completed**: Moved old test and fix scripts to `archive/` directory for better organization:
- Archived 30+ test scripts, fix scripts, and development utilities
- Maintained clean workspace with only current, production-ready scripts
- Preserved historical development artifacts for reference
- **Alternative ComposeFS implementation archived**: Moved `composefs-alternative.sh` and related files to archive:
- Official ComposeFS package now ready for Debian/Ubuntu sponsorship
- Alternative implementation preserved for reference and potential future use
- Updated documentation to reflect official tool integration approach
- **Overlay and dpkg install improvements documented**: Updated documentation to reflect recent workflow improvements:
- Robust overlay/dpkg install workflow with DNS fixes for WSL environments
- Support for offline `.deb` package installation via dpkg in overlay
- Conditional DNS server injection to resolve network connectivity issues
- Clean overlay commit and rollback procedures
- **OSTree atomic workflow documentation**: Updated all documentation to reflect new atomic package management:
- `apt-layer ostree compose install/remove/update` commands for atomic, versioned package management
- `apt-layer ostree log/diff/status/rollback/cleanup` commands for commit history and management
- Integration with live overlay and dpkg install workflows
- Rollback functionality with proper deployment management
- **Git ignore updates**: Added `.scratchpad` and `scratchpad/` directories to `.gitignore`:
- `.scratchpad` already properly ignored
- `scratchpad/` directory added to ignore list for development artifacts
- **Documentation consistency**: Ensured all documentation files reflect current system state:
- Consistent terminology and feature descriptions across all files
- Updated completion status and roadmap information
- Current capabilities and testing procedures documented
- **Note**: Documentation is now fully up-to-date and workspace is clean and organized. All recent improvements including OSTree atomic workflow, official ComposeFS integration, and overlay/dpkg improvements are properly documented across all project files.
### [2025-01-27 23:55 UTC] - DKMS TESTING INFRASTRUCTURE COMPLETED
- **DKMS testing infrastructure implemented**: Created comprehensive DKMS testing system to validate all DKMS functionality in Particle-OS.
- **Comprehensive test suite created**: Created `test-dkms-functionality.sh` with 12 comprehensive test cases covering all DKMS functionality:

View file

@ -340,70 +340,28 @@ add_scriptlet "03-traditional.sh" "Traditional Layer Creation"
update_progress "Adding: Container-based Layer Creation" 31
add_scriptlet "04-container.sh" "Container-based Layer Creation (Apx-style)"
update_progress "Adding: OCI Integration" 36
add_scriptlet "06-oci-integration.sh" "OCI Export/Import Integration"
update_progress "Adding: Atomic Deployment System" 41
add_scriptlet "09-atomic-deployment.sh" "Atomic Deployment System"
update_progress "Adding: rpm-ostree Compatibility" 46
add_scriptlet "10-rpm-ostree-compat.sh" "rpm-ostree Compatibility Layer"
update_progress "Adding: Live Overlay System" 51
update_progress "Adding: Live Overlay System" 36
add_scriptlet "05-live-overlay.sh" "Live Overlay System (rpm-ostree style)"
update_progress "Adding: Bootloader Integration" 56
update_progress "Adding: OCI Integration" 41
add_scriptlet "06-oci-integration.sh" "OCI Export/Import Integration"
update_progress "Adding: Bootloader Integration" 46
add_scriptlet "07-bootloader.sh" "Bootloader Integration (UEFI/GRUB/systemd-boot)"
update_progress "Adding: Advanced Package Management" 61
add_scriptlet "08-advanced-package-management.sh" "Advanced Package Management (Enterprise Features)"
update_progress "Adding: Atomic Deployment System" 51
add_scriptlet "09-atomic-deployment.sh" "Atomic Deployment System"
update_progress "Adding: Layer Signing & Verification" 66
add_scriptlet "11-layer-signing.sh" "Layer Signing & Verification (Enterprise Security)"
update_progress "Adding: rpm-ostree Compatibility" 56
add_scriptlet "10-rpm-ostree-compat.sh" "rpm-ostree Compatibility Layer"
update_progress "Adding: Centralized Audit & Reporting" 71
add_scriptlet "12-audit-reporting.sh" "Centralized Audit & Reporting (Enterprise Compliance)"
update_progress "Adding: Automated Security Scanning" 76
add_scriptlet "13-security-scanning.sh" "Automated Security Scanning (Enterprise Security)"
update_progress "Adding: Admin Utilities" 81
add_scriptlet "14-admin-utilities.sh" "Admin Utilities (Health Monitoring, Analytics, Maintenance)"
update_progress "Adding: Multi-Tenant Support" 86
add_scriptlet "15-multi-tenant.sh" "Multi-Tenant Support (Enterprise Features)"
update_progress "Adding: OSTree Atomic Package Management" 87
update_progress "Adding: OSTree Atomic Package Management" 61
add_scriptlet "15-ostree-atomic.sh" "OSTree Atomic Package Management"
update_progress "Adding: Advanced Compliance Frameworks" 88
add_scriptlet "16-compliance-frameworks.sh" "Advanced Compliance Frameworks (Enterprise Features)"
update_progress "Adding: Enterprise Integration" 89
add_scriptlet "17-enterprise-integration.sh" "Enterprise Integration (Enterprise Features)"
update_progress "Adding: Advanced Monitoring & Alerting" 90
add_scriptlet "18-monitoring-alerting.sh" "Advanced Monitoring & Alerting (Enterprise Features)"
update_progress "Adding: Cloud Integration" 91
add_scriptlet "19-cloud-integration.sh" "Cloud Integration (AWS, Azure, GCP)"
update_progress "Adding: Kubernetes Integration" 92
add_scriptlet "20-kubernetes-integration.sh" "Kubernetes Integration (EKS, AKS, GKE, OpenShift)"
update_progress "Adding: Container Orchestration" 93
add_scriptlet "21-container-orchestration.sh" "Container Orchestration (Multi-cluster, Service Mesh, GitOps)"
update_progress "Adding: Multi-Cloud Deployment" 94
add_scriptlet "22-multicloud-deployment.sh" "Multi-Cloud Deployment (AWS, Azure, GCP, Migration, Policies)"
update_progress "Adding: Cloud-Native Security" 95
add_scriptlet "23-cloud-security.sh" "Cloud-Native Security (Workload Scanning, Policy Enforcement, Compliance)"
update_progress "Adding: Direct dpkg Installation" 96
update_progress "Adding: Direct dpkg Installation" 66
add_scriptlet "24-dpkg-direct-install.sh" "Direct dpkg Installation (Performance Optimization)"
update_progress "Adding: Main Dispatch" 97
update_progress "Adding: Main Dispatch" 71
add_scriptlet "99-main.sh" "Main Dispatch and Help" "true"
# Add embedded configuration files if they exist
@ -533,28 +491,22 @@ print_status "Lines of code: $(wc -l < "$OUTPUT_FILE")"
print_status ""
print_status "The compiled apt-layer.sh is now self-contained and includes:"
print_status "<22> Particle-OS configuration integration"
print_status "<22> Transactional operations with automatic rollback"
print_status "<22> Traditional chroot-based layer creation"
print_status "<22> Container-based layer creation (Apx-style)"
print_status "<22> OCI export/import integration"
print_status "<22> Live overlay system (rpm-ostree style)"
print_status "<22> Bootloader integration (UEFI/GRUB/systemd-boot)"
print_status "<22> Advanced package management (Enterprise features)"
print_status "<22> Layer signing & verification (Enterprise security)"
print_status "<22> Centralized audit & reporting (Enterprise compliance)"
print_status "<22> Automated security scanning (Enterprise security)"
print_status "<22> Admin utilities (Health monitoring, performance analytics, maintenance)"
print_status "<22> Multi-tenant support (Enterprise features)"
print_status "<22> Atomic deployment system with rollback"
print_status "<22> rpm-ostree compatibility layer (1:1 command mapping)"
print_status "<22> ComposeFS backend integration"
print_status "<22> Dependency validation and error handling"
print_status "<22> Comprehensive JSON configuration system"
print_status "<22> Direct dpkg installation (Performance optimization)"
print_status "<22> All dependencies merged into a single file"
print_status "- Particle-OS configuration integration"
print_status "- Transactional operations with automatic rollback"
print_status "- Traditional chroot-based layer creation"
print_status "- Container-based layer creation (Apx-style)"
print_status "- OCI export/import integration"
print_status "- Live overlay system (rpm-ostree style)"
print_status "- Bootloader integration (UEFI/GRUB/systemd-boot)"
print_status "- Atomic deployment system with rollback"
print_status "- rpm-ostree compatibility layer (1:1 command mapping)"
print_status "- ComposeFS backend integration"
print_status "- Dependency validation and error handling"
print_status "- Comprehensive JSON configuration system"
print_status "- Direct dpkg installation (Performance optimization)"
print_status "- All dependencies merged into a single file"
print_status ""
print_status "<EFBFBD> Particle-OS apt-layer compilation complete with all features!"
print_status "Particle-OS apt-layer compilation complete with all core rpm-ostree-like features!"
print_status ""
print_status "Usage:"

File diff suppressed because it is too large Load diff

View file

@ -1,847 +0,0 @@
#!/bin/bash
# Ubuntu uBlue apt-layer Layer Signing & Verification
# Provides enterprise-grade layer signing and verification for immutable deployments
# Supports Sigstore (cosign) for modern OCI-compatible signing and GPG for traditional workflows
# =============================================================================
# LAYER SIGNING & VERIFICATION FUNCTIONS
# =============================================================================
# Layer signing configuration (with fallbacks for when particle-config.sh is not loaded)
LAYER_SIGNING_CONFIG_DIR="${UBLUE_CONFIG_DIR:-/etc/ubuntu-ublue}/layer-signing"
LAYER_SIGNING_STATE_DIR="${UBLUE_ROOT:-/var/lib/particle-os}/layer-signing"
LAYER_SIGNING_KEYS_DIR="$LAYER_SIGNING_STATE_DIR/keys"
LAYER_SIGNING_SIGNATURES_DIR="$LAYER_SIGNING_STATE_DIR/signatures"
LAYER_SIGNING_VERIFICATION_DIR="$LAYER_SIGNING_STATE_DIR/verification"
LAYER_SIGNING_REVOCATION_DIR="$LAYER_SIGNING_STATE_DIR/revocation"
# Signing configuration
LAYER_SIGNING_ENABLED="${LAYER_SIGNING_ENABLED:-true}"
LAYER_SIGNING_METHOD="${LAYER_SIGNING_METHOD:-sigstore}" # sigstore, gpg, both
LAYER_SIGNING_VERIFY_ON_IMPORT="${LAYER_SIGNING_VERIFY_ON_IMPORT:-true}"
LAYER_SIGNING_VERIFY_ON_MOUNT="${LAYER_SIGNING_VERIFY_ON_MOUNT:-true}"
LAYER_SIGNING_VERIFY_ON_ACTIVATE="${LAYER_SIGNING_VERIFY_ON_ACTIVATE:-true}"
LAYER_SIGNING_FAIL_ON_VERIFY="${LAYER_SIGNING_FAIL_ON_VERIFY:-true}"
# Initialize layer signing system
init_layer_signing() {
log_info "Initializing layer signing and verification system" "apt-layer"
# Create layer signing directories
mkdir -p "$LAYER_SIGNING_CONFIG_DIR" "$LAYER_SIGNING_STATE_DIR" "$LAYER_SIGNING_KEYS_DIR"
mkdir -p "$LAYER_SIGNING_SIGNATURES_DIR" "$LAYER_SIGNING_VERIFICATION_DIR" "$LAYER_SIGNING_REVOCATION_DIR"
# Set proper permissions
chmod 755 "$LAYER_SIGNING_CONFIG_DIR" "$LAYER_SIGNING_STATE_DIR"
chmod 700 "$LAYER_SIGNING_KEYS_DIR" "$LAYER_SIGNING_SIGNATURES_DIR"
chmod 750 "$LAYER_SIGNING_VERIFICATION_DIR" "$LAYER_SIGNING_REVOCATION_DIR"
# Initialize signing configuration
init_signing_config
# Initialize key management
init_key_management
# Initialize revocation system
init_revocation_system
# Check signing tools availability
check_signing_tools
log_success "Layer signing and verification system initialized" "apt-layer"
}
# Initialize signing configuration
init_signing_config() {
local config_file="$LAYER_SIGNING_CONFIG_DIR/signing-config.json"
if [[ ! -f "$config_file" ]]; then
cat > "$config_file" << EOF
{
"signing": {
"enabled": true,
"method": "sigstore",
"verify_on_import": true,
"verify_on_mount": true,
"verify_on_activate": true,
"fail_on_verify": true
},
"sigstore": {
"enabled": true,
"keyless": false,
"fulcio_url": "https://fulcio.sigstore.dev",
"rekor_url": "https://rekor.sigstore.dev",
"tuf_url": "https://tuf.sigstore.dev"
},
"gpg": {
"enabled": true,
"keyring": "/etc/apt/trusted.gpg",
"signing_key": "",
"verification_keys": []
},
"key_management": {
"local_keys": true,
"hsm_support": false,
"remote_key_service": false,
"key_rotation_days": 365
},
"revocation": {
"enabled": true,
"check_revocation": true,
"revocation_list_url": "",
"local_revocation_list": true
}
}
EOF
chmod 600 "$config_file"
fi
}
# Initialize key management
init_key_management() {
local key_db="$LAYER_SIGNING_KEYS_DIR/keys.json"
if [[ ! -f "$key_db" ]]; then
cat > "$key_db" << EOF
{
"keys": {},
"key_pairs": {},
"public_keys": {},
"key_metadata": {},
"last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
chmod 600 "$key_db"
fi
}
# Initialize revocation system
init_revocation_system() {
local revocation_list="$LAYER_SIGNING_REVOCATION_DIR/revocation-list.json"
if [[ ! -f "$revocation_list" ]]; then
cat > "$revocation_list" << EOF
{
"revoked_keys": {},
"revoked_signatures": {},
"revoked_layers": {},
"revocation_reasons": {},
"last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
chmod 600 "$revocation_list"
fi
}
# Check signing tools availability
check_signing_tools() {
log_info "Checking signing tools availability" "apt-layer"
local tools_available=true
# Check for cosign (Sigstore)
if ! command -v cosign &>/dev/null; then
log_warning "cosign (Sigstore) not found - Sigstore signing will be disabled" "apt-layer"
LAYER_SIGNING_METHOD="gpg"
else
log_info "cosign (Sigstore) found: $(cosign version 2>/dev/null | head -1 || echo 'version unknown')" "apt-layer"
fi
# Check for GPG
if ! command -v gpg &>/dev/null; then
log_warning "GPG not found - GPG signing will be disabled" "apt-layer"
if [[ "$LAYER_SIGNING_METHOD" == "gpg" ]]; then
LAYER_SIGNING_METHOD="sigstore"
fi
else
log_info "GPG found: $(gpg --version | head -1)" "apt-layer"
fi
# Check if any signing method is available
if [[ "$LAYER_SIGNING_METHOD" == "both" ]] && ! command -v cosign &>/dev/null && ! command -v gpg &>/dev/null; then
log_error "No signing tools available - layer signing will be disabled" "apt-layer"
LAYER_SIGNING_ENABLED=false
return 1
fi
return 0
}
# Generate signing key pair
generate_signing_key_pair() {
local key_name="$1"
local key_type="${2:-sigstore}"
if [[ -z "$key_name" ]]; then
log_error "Key name required for key pair generation" "apt-layer"
return 1
fi
log_info "Generating signing key pair: $key_name (type: $key_type)" "apt-layer"
case "$key_type" in
"sigstore")
generate_sigstore_key_pair "$key_name"
;;
"gpg")
generate_gpg_key_pair "$key_name"
;;
*)
log_error "Unsupported key type: $key_type" "apt-layer"
return 1
;;
esac
}
# Generate Sigstore key pair
generate_sigstore_key_pair() {
local key_name="$1"
local key_dir="$LAYER_SIGNING_KEYS_DIR/sigstore/$key_name"
mkdir -p "$key_dir"
log_info "Generating Sigstore key pair for: $key_name" "apt-layer"
# Generate cosign key pair
if cosign generate-key-pair --output-key-prefix "$key_dir/key" 2>/dev/null; then
# Store key metadata
local key_db="$LAYER_SIGNING_KEYS_DIR/keys.json"
local key_id
key_id=$(cosign public-key --key "$key_dir/key.key" 2>/dev/null | sha256sum | cut -d' ' -f1 || echo "unknown")
jq --arg name "$key_name" \
--arg type "sigstore" \
--arg public_key "$key_dir/key.pub" \
--arg private_key "$key_dir/key.key" \
--arg key_id "$key_id" \
--arg created "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.key_pairs[$name] = {
"type": $type,
"public_key": $public_key,
"private_key": $private_key,
"key_id": $key_id,
"created": $created,
"status": "active"
}' "$key_db" > "$key_db.tmp" && mv "$key_db.tmp" "$key_db"
chmod 600 "$key_dir/key.key"
chmod 644 "$key_dir/key.pub"
log_success "Sigstore key pair generated: $key_name" "apt-layer"
return 0
else
log_error "Failed to generate Sigstore key pair: $key_name" "apt-layer"
return 1
fi
}
# Generate GPG key pair
generate_gpg_key_pair() {
local key_name="$1"
local key_dir="$LAYER_SIGNING_KEYS_DIR/gpg/$key_name"
mkdir -p "$key_dir"
log_info "Generating GPG key pair for: $key_name" "apt-layer"
# Create GPG key configuration
cat > "$key_dir/key-config" << EOF
Key-Type: RSA
Key-Length: 4096
Name-Real: apt-layer signing key
Name-Email: apt-layer@$(hostname)
Name-Comment: $key_name
Expire-Date: 2y
%commit
EOF
# Generate GPG key
if gpg --batch --gen-key "$key_dir/key-config" 2>/dev/null; then
# Export public key
gpg --armor --export apt-layer@$(hostname) > "$key_dir/public.key" 2>/dev/null
# Get key fingerprint
local key_fingerprint
key_fingerprint=$(gpg --fingerprint apt-layer@$(hostname) 2>/dev/null | grep "Key fingerprint" | sed 's/.*= //' | tr -d ' ')
# Store key metadata
local key_db="$LAYER_SIGNING_KEYS_DIR/keys.json"
jq --arg name "$key_name" \
--arg type "gpg" \
--arg public_key "$key_dir/public.key" \
--arg key_id "$key_fingerprint" \
--arg email "apt-layer@$(hostname)" \
--arg created "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.key_pairs[$name] = {
"type": $type,
"public_key": $public_key,
"key_id": $key_id,
"email": $email,
"created": $created,
"status": "active"
}' "$key_db" > "$key_db.tmp" && mv "$key_db.tmp" "$key_db"
chmod 600 "$key_dir/key-config"
chmod 644 "$key_dir/public.key"
log_success "GPG key pair generated: $key_name" "apt-layer"
return 0
else
log_error "Failed to generate GPG key pair: $key_name" "apt-layer"
return 1
fi
}
# Sign layer with specified method
sign_layer() {
local layer_path="$1"
local key_name="$2"
local signing_method="${3:-$LAYER_SIGNING_METHOD}"
if [[ -z "$layer_path" ]] || [[ -z "$key_name" ]]; then
log_error "Layer path and key name required for signing" "apt-layer"
return 1
fi
if [[ ! -f "$layer_path" ]]; then
log_error "Layer file not found: $layer_path" "apt-layer"
return 1
fi
log_info "Signing layer: $layer_path with key: $key_name (method: $signing_method)" "apt-layer"
case "$signing_method" in
"sigstore")
sign_layer_sigstore "$layer_path" "$key_name"
;;
"gpg")
sign_layer_gpg "$layer_path" "$key_name"
;;
"both")
sign_layer_sigstore "$layer_path" "$key_name" && \
sign_layer_gpg "$layer_path" "$key_name"
;;
*)
log_error "Unsupported signing method: $signing_method" "apt-layer"
return 1
;;
esac
}
# Sign layer with Sigstore
sign_layer_sigstore() {
local layer_path="$1"
local key_name="$2"
local key_dir="$LAYER_SIGNING_KEYS_DIR/sigstore/$key_name"
local signature_path="$layer_path.sig"
if [[ ! -f "$key_dir/key.key" ]]; then
log_error "Sigstore private key not found: $key_dir/key.key" "apt-layer"
return 1
fi
log_info "Signing layer with Sigstore: $layer_path" "apt-layer"
# Sign the layer
if cosign sign-blob --key "$key_dir/key.key" --output-signature "$signature_path" "$layer_path" 2>/dev/null; then
# Store signature metadata
local signature_db="$LAYER_SIGNING_SIGNATURES_DIR/signatures.json"
if [[ ! -f "$signature_db" ]]; then
cat > "$signature_db" << EOF
{
"signatures": {},
"last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
fi
local layer_hash
layer_hash=$(sha256sum "$layer_path" | cut -d' ' -f1)
jq --arg layer "$layer_path" \
--arg signature "$signature_path" \
--arg method "sigstore" \
--arg key_name "$key_name" \
--arg layer_hash "$layer_hash" \
--arg signed_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.signatures[$layer] = {
"signature_file": $signature,
"method": $method,
"key_name": $key_name,
"layer_hash": $layer_hash,
"signed_at": $signed_at,
"status": "valid"
}' "$signature_db" > "$signature_db.tmp" && mv "$signature_db.tmp" "$signature_db"
log_success "Layer signed with Sigstore: $layer_path" "apt-layer"
return 0
else
log_error "Failed to sign layer with Sigstore: $layer_path" "apt-layer"
return 1
fi
}
# Sign layer with GPG
sign_layer_gpg() {
local layer_path="$1"
local key_name="$2"
local signature_path="$layer_path.sig"
log_info "Signing layer with GPG: $layer_path" "apt-layer"
# Sign the layer
if gpg --detach-sign --armor --output "$signature_path" "$layer_path" 2>/dev/null; then
# Store signature metadata
local signature_db="$LAYER_SIGNING_SIGNATURES_DIR/signatures.json"
if [[ ! -f "$signature_db" ]]; then
cat > "$signature_db" << EOF
{
"signatures": {},
"last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
fi
local layer_hash
layer_hash=$(sha256sum "$layer_path" | cut -d' ' -f1)
jq --arg layer "$layer_path" \
--arg signature "$signature_path" \
--arg method "gpg" \
--arg key_name "$key_name" \
--arg layer_hash "$layer_hash" \
--arg signed_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.signatures[$layer] = {
"signature_file": $signature,
"method": $method,
"key_name": $key_name,
"layer_hash": $layer_hash,
"signed_at": $signed_at,
"status": "valid"
}' "$signature_db" > "$signature_db.tmp" && mv "$signature_db.tmp" "$signature_db"
log_success "Layer signed with GPG: $layer_path" "apt-layer"
return 0
else
log_error "Failed to sign layer with GPG: $layer_path" "apt-layer"
return 1
fi
}
# Verify layer signature
verify_layer_signature() {
local layer_path="$1"
local signature_path="$2"
local verification_method="${3:-auto}"
if [[ -z "$layer_path" ]] || [[ -z "$signature_path" ]]; then
log_error "Layer path and signature path required for verification" "apt-layer"
return 1
fi
if [[ ! -f "$layer_path" ]]; then
log_error "Layer file not found: $layer_path" "apt-layer"
return 1
fi
if [[ ! -f "$signature_path" ]]; then
log_error "Signature file not found: $signature_path" "apt-layer"
return 1
fi
log_info "Verifying layer signature: $layer_path" "apt-layer"
# Auto-detect verification method
if [[ "$verification_method" == "auto" ]]; then
if [[ "$signature_path" == *.sig ]] && head -1 "$signature_path" | grep -q "-----BEGIN PGP SIGNATURE-----"; then
verification_method="gpg"
else
verification_method="sigstore"
fi
fi
case "$verification_method" in
"sigstore")
verify_layer_sigstore "$layer_path" "$signature_path"
;;
"gpg")
verify_layer_gpg "$layer_path" "$signature_path"
;;
*)
log_error "Unsupported verification method: $verification_method" "apt-layer"
return 1
;;
esac
}
# Verify layer with Sigstore
verify_layer_sigstore() {
local layer_path="$1"
local signature_path="$2"
local key_dir="$LAYER_SIGNING_KEYS_DIR/sigstore"
log_info "Verifying layer with Sigstore: $layer_path" "apt-layer"
# Find the public key
local public_key=""
for key_name in "$key_dir"/*/key.pub; do
if [[ -f "$key_name" ]]; then
public_key="$key_name"
break
fi
done
if [[ -z "$public_key" ]]; then
log_error "No Sigstore public key found for verification" "apt-layer"
return 1
fi
# Verify the signature
if cosign verify-blob --key "$public_key" --signature "$signature_path" "$layer_path" 2>/dev/null; then
log_success "Layer signature verified with Sigstore: $layer_path" "apt-layer"
return 0
else
log_error "Layer signature verification failed with Sigstore: $layer_path" "apt-layer"
return 1
fi
}
# Verify layer with GPG
verify_layer_gpg() {
local layer_path="$1"
local signature_path="$2"
log_info "Verifying layer with GPG: $layer_path" "apt-layer"
# Verify the signature
if gpg --verify "$signature_path" "$layer_path" 2>/dev/null; then
log_success "Layer signature verified with GPG: $layer_path" "apt-layer"
return 0
else
log_error "Layer signature verification failed with GPG: $layer_path" "apt-layer"
return 1
fi
}
# Check if layer is revoked
check_layer_revocation() {
local layer_path="$1"
if [[ -z "$layer_path" ]]; then
return 1
fi
local revocation_list="$LAYER_SIGNING_REVOCATION_DIR/revocation-list.json"
if [[ ! -f "$revocation_list" ]]; then
return 1
fi
local layer_hash
layer_hash=$(sha256sum "$layer_path" 2>/dev/null | cut -d' ' -f1 || echo "")
if [[ -n "$layer_hash" ]]; then
if jq -e ".revoked_layers[\"$layer_hash\"]" "$revocation_list" >/dev/null 2>&1; then
log_warning "Layer is revoked: $layer_path" "apt-layer"
return 0
fi
fi
return 1
}
# Revoke layer
revoke_layer() {
local layer_path="$1"
local reason="${2:-Manual revocation}"
if [[ -z "$layer_path" ]]; then
log_error "Layer path required for revocation" "apt-layer"
return 1
fi
if [[ ! -f "$layer_path" ]]; then
log_error "Layer file not found: $layer_path" "apt-layer"
return 1
fi
log_info "Revoking layer: $layer_path" "apt-layer"
local revocation_list="$LAYER_SIGNING_REVOCATION_DIR/revocation-list.json"
local layer_hash
layer_hash=$(sha256sum "$layer_path" | cut -d' ' -f1)
jq --arg layer_hash "$layer_hash" \
--arg reason "$reason" \
--arg revoked_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.revoked_layers[$layer_hash] = {
"reason": $reason,
"revoked_at": $revoked_at,
"revoked_by": "'$(whoami)'"
}' "$revocation_list" > "$revocation_list.tmp" && mv "$revocation_list.tmp" "$revocation_list"
log_success "Layer revoked: $layer_path" "apt-layer"
return 0
}
# List signing keys
list_signing_keys() {
log_info "Listing signing keys" "apt-layer"
local key_db="$LAYER_SIGNING_KEYS_DIR/keys.json"
if [[ ! -f "$key_db" ]]; then
log_error "Key database not found" "apt-layer"
return 1
fi
echo "=== Signing Keys ==="
local keys
keys=$(jq -r '.key_pairs | to_entries[] | "\(.key): \(.value.type) - \(.value.key_id) (\(.value.status))"' "$key_db" 2>/dev/null || echo "")
if [[ -n "$keys" ]]; then
echo "$keys" | while read -r key_info; do
echo " $key_info"
done
else
log_info "No signing keys found" "apt-layer"
fi
echo ""
}
# List layer signatures
list_layer_signatures() {
log_info "Listing layer signatures" "apt-layer"
local signature_db="$LAYER_SIGNING_SIGNATURES_DIR/signatures.json"
if [[ ! -f "$signature_db" ]]; then
log_error "Signature database not found" "apt-layer"
return 1
fi
echo "=== Layer Signatures ==="
local signatures
signatures=$(jq -r '.signatures | to_entries[] | "\(.key): \(.value.method) - \(.value.key_name) (\(.value.status))"' "$signature_db" 2>/dev/null || echo "")
if [[ -n "$signatures" ]]; then
echo "$signatures" | while read -r sig_info; do
echo " $sig_info"
done
else
log_info "No layer signatures found" "apt-layer"
fi
echo ""
}
# Get layer signing status
get_layer_signing_status() {
local layer_path="$1"
if [[ -z "$layer_path" ]]; then
log_error "Layer path required for status check" "apt-layer"
return 1
fi
log_info "Getting signing status for layer: $layer_path" "apt-layer"
echo "=== Layer Signing Status: $layer_path ==="
# Check if layer exists
if [[ ! -f "$layer_path" ]]; then
echo " â Layer file not found"
return 1
fi
echo " â Layer file exists"
# Check for signatures
local signature_db="$LAYER_SIGNING_SIGNATURES_DIR/signatures.json"
if [[ -f "$signature_db" ]]; then
local signature_info
signature_info=$(jq -r ".signatures[\"$layer_path\"] // empty" "$signature_db" 2>/dev/null)
if [[ -n "$signature_info" ]]; then
local method
method=$(echo "$signature_info" | jq -r '.method // "unknown"')
local key_name
key_name=$(echo "$signature_info" | jq -r '.key_name // "unknown"')
local status
status=$(echo "$signature_info" | jq -r '.status // "unknown"')
local signed_at
signed_at=$(echo "$signature_info" | jq -r '.signed_at // "unknown"')
echo " â Signed with $method using key: $key_name"
echo " â Signature status: $status"
echo " â Signed at: $signed_at"
else
echo " â No signature found"
fi
else
echo " â Signature database not found"
fi
# Check for revocation
if check_layer_revocation "$layer_path"; then
echo " â  Layer is revoked"
else
echo " â Layer is not revoked"
fi
echo ""
}
# =============================================================================
# INTEGRATION FUNCTIONS
# =============================================================================
# Initialize layer signing on script startup
init_layer_signing_on_startup() {
# Only initialize if not already done and signing is enabled
if [[ "$LAYER_SIGNING_ENABLED" == "true" ]] && [[ ! -d "$LAYER_SIGNING_STATE_DIR" ]]; then
init_layer_signing
fi
}
# Verify layer before import
verify_layer_before_import() {
local layer_path="$1"
if [[ "$LAYER_SIGNING_VERIFY_ON_IMPORT" != "true" ]]; then
return 0
fi
if [[ -z "$layer_path" ]]; then
return 1
fi
log_info "Verifying layer before import: $layer_path" "apt-layer"
# Check for revocation first
if check_layer_revocation "$layer_path"; then
if [[ "$LAYER_SIGNING_FAIL_ON_VERIFY" == "true" ]]; then
log_error "Layer is revoked, import blocked: $layer_path" "apt-layer"
return 1
else
log_warning "Layer is revoked but import allowed: $layer_path" "apt-layer"
fi
fi
# Check for signature
local signature_path="$layer_path.sig"
if [[ -f "$signature_path" ]]; then
if ! verify_layer_signature "$layer_path" "$signature_path"; then
if [[ "$LAYER_SIGNING_FAIL_ON_VERIFY" == "true" ]]; then
log_error "Layer signature verification failed, import blocked: $layer_path" "apt-layer"
return 1
else
log_warning "Layer signature verification failed but import allowed: $layer_path" "apt-layer"
fi
fi
else
log_warning "No signature found for layer: $layer_path" "apt-layer"
fi
return 0
}
# Verify layer before mount
verify_layer_before_mount() {
local layer_path="$1"
if [[ "$LAYER_SIGNING_VERIFY_ON_MOUNT" != "true" ]]; then
return 0
fi
if [[ -z "$layer_path" ]]; then
return 1
fi
log_info "Verifying layer before mount: $layer_path" "apt-layer"
# Check for revocation
if check_layer_revocation "$layer_path"; then
if [[ "$LAYER_SIGNING_FAIL_ON_VERIFY" == "true" ]]; then
log_error "Layer is revoked, mount blocked: $layer_path" "apt-layer"
return 1
else
log_warning "Layer is revoked but mount allowed: $layer_path" "apt-layer"
fi
fi
# Check for signature
local signature_path="$layer_path.sig"
if [[ -f "$signature_path" ]]; then
if ! verify_layer_signature "$layer_path" "$signature_path"; then
if [[ "$LAYER_SIGNING_FAIL_ON_VERIFY" == "true" ]]; then
log_error "Layer signature verification failed, mount blocked: $layer_path" "apt-layer"
return 1
else
log_warning "Layer signature verification failed but mount allowed: $layer_path" "apt-layer"
fi
fi
else
log_warning "No signature found for layer: $layer_path" "apt-layer"
fi
return 0
}
# Verify layer before activation
verify_layer_before_activation() {
local layer_path="$1"
if [[ "$LAYER_SIGNING_VERIFY_ON_ACTIVATE" != "true" ]]; then
return 0
fi
if [[ -z "$layer_path" ]]; then
return 1
fi
log_info "Verifying layer before activation: $layer_path" "apt-layer"
# Check for revocation
if check_layer_revocation "$layer_path"; then
if [[ "$LAYER_SIGNING_FAIL_ON_VERIFY" == "true" ]]; then
log_error "Layer is revoked, activation blocked: $layer_path" "apt-layer"
return 1
else
log_warning "Layer is revoked but activation allowed: $layer_path" "apt-layer"
fi
fi
# Check for signature
local signature_path="$layer_path.sig"
if [[ -f "$signature_path" ]]; then
if ! verify_layer_signature "$layer_path" "$signature_path"; then
if [[ "$LAYER_SIGNING_FAIL_ON_VERIFY" == "true" ]]; then
log_error "Layer signature verification failed, activation blocked: $layer_path" "apt-layer"
return 1
else
log_warning "Layer signature verification failed but activation allowed: $layer_path" "apt-layer"
fi
fi
else
log_warning "No signature found for layer: $layer_path" "apt-layer"
fi
return 0
}
# Cleanup layer signing on script exit
cleanup_layer_signing_on_exit() {
# Clean up temporary files
rm -f "$LAYER_SIGNING_VERIFICATION_DIR"/temp-* 2>/dev/null || true
}
# Register cleanup function
trap cleanup_layer_signing_on_exit EXIT

View file

@ -1,769 +0,0 @@
#!/bin/bash
# Ubuntu uBlue apt-layer Centralized Audit & Reporting
# Provides enterprise-grade audit logging, reporting, and compliance features
# for comprehensive security monitoring and regulatory compliance
# =============================================================================
# AUDIT & REPORTING FUNCTIONS
# =============================================================================
# Audit and reporting configuration (with fallbacks for when particle-config.sh is not loaded)
AUDIT_CONFIG_DIR="${UBLUE_CONFIG_DIR:-/etc/ubuntu-ublue}/audit"
AUDIT_STATE_DIR="${UBLUE_ROOT:-/var/lib/particle-os}/audit"
AUDIT_LOGS_DIR="$AUDIT_STATE_DIR/logs"
AUDIT_REPORTS_DIR="$AUDIT_STATE_DIR/reports"
AUDIT_EXPORTS_DIR="$AUDIT_STATE_DIR/exports"
AUDIT_QUERIES_DIR="$AUDIT_STATE_DIR/queries"
AUDIT_COMPLIANCE_DIR="$AUDIT_STATE_DIR/compliance"
# Audit configuration
AUDIT_ENABLED="${AUDIT_ENABLED:-true}"
AUDIT_LOG_LEVEL="${AUDIT_LOG_LEVEL:-INFO}"
AUDIT_RETENTION_DAYS="${AUDIT_RETENTION_DAYS:-90}"
AUDIT_ROTATION_SIZE_MB="${AUDIT_ROTATION_SIZE_MB:-100}"
AUDIT_REMOTE_SHIPPING="${AUDIT_REMOTE_SHIPPING:-false}"
AUDIT_SYSLOG_ENABLED="${AUDIT_SYSLOG_ENABLED:-false}"
AUDIT_HTTP_ENDPOINT="${AUDIT_HTTP_ENDPOINT:-}"
AUDIT_HTTP_API_KEY="${AUDIT_HTTP_API_KEY:-}"
# Initialize audit and reporting system
init_audit_reporting() {
log_info "Initializing centralized audit and reporting system" "apt-layer"
# Create audit and reporting directories
mkdir -p "$AUDIT_CONFIG_DIR" "$AUDIT_STATE_DIR" "$AUDIT_LOGS_DIR"
mkdir -p "$AUDIT_REPORTS_DIR" "$AUDIT_EXPORTS_DIR" "$AUDIT_QUERIES_DIR"
mkdir -p "$AUDIT_COMPLIANCE_DIR"
# Set proper permissions
chmod 755 "$AUDIT_CONFIG_DIR" "$AUDIT_STATE_DIR"
chmod 750 "$AUDIT_LOGS_DIR" "$AUDIT_REPORTS_DIR" "$AUDIT_EXPORTS_DIR"
chmod 700 "$AUDIT_QUERIES_DIR" "$AUDIT_COMPLIANCE_DIR"
# Initialize audit configuration
init_audit_config
# Initialize audit log rotation
init_audit_log_rotation
# Initialize compliance templates
init_compliance_templates
# Initialize query cache
init_query_cache
log_success "Centralized audit and reporting system initialized" "apt-layer"
}
# Initialize audit configuration
init_audit_config() {
local config_file="$AUDIT_CONFIG_DIR/audit-config.json"
if [[ ! -f "$config_file" ]]; then
cat > "$config_file" << 'EOF'
{
"audit": {
"enabled": true,
"log_level": "INFO",
"retention_days": 90,
"rotation_size_mb": 100,
"compression_enabled": true
},
"remote_shipping": {
"enabled": false,
"syslog_enabled": false,
"syslog_facility": "local0",
"http_endpoint": "",
"http_api_key": "",
"http_timeout": 30,
"retry_attempts": 3
},
"compliance": {
"sox_enabled": false,
"pci_dss_enabled": false,
"hipaa_enabled": false,
"gdpr_enabled": false,
"custom_frameworks": []
},
"reporting": {
"auto_generate_reports": false,
"report_schedule": "weekly",
"export_formats": ["json", "csv", "html"],
"include_sensitive_data": false
},
"alerts": {
"enabled": false,
"critical_events": ["SECURITY_VIOLATION", "POLICY_VIOLATION"],
"notification_methods": ["email", "webhook"],
"email_recipients": [],
"webhook_url": ""
}
}
EOF
chmod 600 "$config_file"
fi
}
# Initialize audit log rotation
init_audit_log_rotation() {
local logrotate_config="$AUDIT_CONFIG_DIR/logrotate.conf"
if [[ ! -f "$logrotate_config" ]]; then
cat > "$logrotate_config" << 'EOF'
$AUDIT_LOGS_DIR/*.log {
daily
rotate 90
compress
delaycompress
missingok
notifempty
create 640 root root
postrotate
systemctl reload rsyslog > /dev/null 2>&1 || true
endscript
}
EOF
chmod 644 "$logrotate_config"
fi
}
# Initialize compliance templates
init_compliance_templates() {
# SOX compliance template
local sox_template="$AUDIT_COMPLIANCE_DIR/sox-template.json"
if [[ ! -f "$sox_template" ]]; then
cat > "$sox_template" << 'EOF'
{
"framework": "SOX",
"version": "2002",
"requirements": {
"access_control": {
"user_management": true,
"role_based_access": true,
"privilege_escalation": true
},
"change_management": {
"package_installation": true,
"system_modifications": true,
"deployment_approval": true
},
"audit_trail": {
"comprehensive_logging": true,
"log_integrity": true,
"log_retention": true
}
},
"reporting_periods": ["daily", "weekly", "monthly", "quarterly"]
}
EOF
fi
# PCI DSS compliance template
local pci_template="$AUDIT_COMPLIANCE_DIR/pci-dss-template.json"
if [[ ! -f "$pci_template" ]]; then
cat > "$pci_template" << 'EOF'
{
"framework": "PCI-DSS",
"version": "4.0",
"requirements": {
"access_control": {
"unique_user_ids": true,
"role_based_access": true,
"privilege_minimization": true
},
"security_monitoring": {
"audit_logging": true,
"intrusion_detection": true,
"vulnerability_scanning": true
},
"change_management": {
"change_approval": true,
"testing_procedures": true,
"rollback_capabilities": true
}
},
"reporting_periods": ["daily", "weekly", "monthly"]
}
EOF
fi
}
# Initialize query cache
init_query_cache() {
local query_cache="$AUDIT_QUERIES_DIR/query-cache.json"
if [[ ! -f "$query_cache" ]]; then
cat > "$query_cache" << 'EOF'
{
"queries": {},
"cached_results": {},
"last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
chmod 600 "$query_cache"
fi
}
# Enhanced audit logging function
log_audit_event() {
local event_type="$1"
local event_data="$2"
local severity="${3:-INFO}"
local user="${4:-$(whoami)}"
local session_id="${5:-$(echo $$)}"
if [[ "$AUDIT_ENABLED" != "true" ]]; then
return 0
fi
# Create structured audit event
local audit_event
audit_event=$(cat << 'EOF'
{
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"event_type": "$event_type",
"severity": "$severity",
"user": "$user",
"session_id": "$session_id",
"hostname": "$(hostname)",
"data": $event_data
}
EOF
)
# Write to local audit log
local audit_log="$AUDIT_LOGS_DIR/audit.log"
echo "$audit_event" >> "$audit_log"
# Ship to remote destinations if enabled
ship_audit_event "$audit_event"
# Log to syslog if enabled
if [[ "$AUDIT_SYSLOG_ENABLED" == "true" ]]; then
logger -t "apt-layer-audit" -p "local0.info" "$audit_event"
fi
}
# Ship audit event to remote destinations
ship_audit_event() {
local audit_event="$1"
# Ship to HTTP endpoint if configured
if [[ -n "$AUDIT_HTTP_ENDPOINT" ]] && [[ -n "$AUDIT_HTTP_API_KEY" ]]; then
ship_to_http_endpoint "$audit_event" &
fi
# Ship to syslog if enabled
if [[ "$AUDIT_SYSLOG_ENABLED" == "true" ]]; then
ship_to_syslog "$audit_event" &
fi
}
# Ship audit event to HTTP endpoint
ship_to_http_endpoint() {
local audit_event="$1"
local config_file="$AUDIT_CONFIG_DIR/audit-config.json"
local endpoint
endpoint=$(jq -r '.remote_shipping.http_endpoint' "$config_file" 2>/dev/null || echo "$AUDIT_HTTP_ENDPOINT")
local api_key
api_key=$(jq -r '.remote_shipping.http_api_key' "$config_file" 2>/dev/null || echo "$AUDIT_HTTP_API_KEY")
local timeout
timeout=$(jq -r '.remote_shipping.http_timeout // 30' "$config_file" 2>/dev/null || echo "30")
local retry_attempts
retry_attempts=$(jq -r '.remote_shipping.retry_attempts // 3' "$config_file" 2>/dev/null || echo "3")
if [[ -z "$endpoint" ]] || [[ -z "$api_key" ]]; then
return 1
fi
local attempt=0
while [[ $attempt -lt $retry_attempts ]]; do
if curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $api_key" \
-H "User-Agent: apt-layer-audit/1.0" \
--data "$audit_event" \
--connect-timeout "$timeout" \
"$endpoint" >/dev/null 2>&1; then
return 0
fi
((attempt++))
if [[ $attempt -lt $retry_attempts ]]; then
sleep $((attempt * 2)) # Exponential backoff
fi
done
log_warning "Failed to ship audit event to HTTP endpoint after $retry_attempts attempts" "apt-layer"
return 1
}
# Ship audit event to syslog
ship_to_syslog() {
local audit_event="$1"
local config_file="$AUDIT_CONFIG_DIR/audit-config.json"
local facility
facility=$(jq -r '.remote_shipping.syslog_facility // "local0"' "$config_file" 2>/dev/null || echo "local0")
logger -t "apt-layer-audit" -p "$facility.info" "$audit_event"
}
# Query audit logs
query_audit_logs() {
local query_params=("$@")
local output_format="${query_params[0]:-json}"
local filters=("${query_params[@]:1}")
log_info "Querying audit logs with format: $output_format" "apt-layer"
local audit_log="$AUDIT_LOGS_DIR/audit.log"
if [[ ! -f "$audit_log" ]]; then
log_error "Audit log not found" "apt-layer"
return 1
fi
# Build jq filter from parameters
local jq_filter="."
for filter in "${filters[@]}"; do
case "$filter" in
--user=*)
local user="${filter#--user=}"
jq_filter="$jq_filter | select(.user == \"$user\")"
;;
--event-type=*)
local event_type="${filter#--event-type=}"
jq_filter="$jq_filter | select(.event_type == \"$event_type\")"
;;
--severity=*)
local severity="${filter#--severity=}"
jq_filter="$jq_filter | select(.severity == \"$severity\")"
;;
--since=*)
local since="${filter#--since=}"
jq_filter="$jq_filter | select(.timestamp >= \"$since\")"
;;
--until=*)
local until="${filter#--until=}"
jq_filter="$jq_filter | select(.timestamp <= \"$until\")"
;;
--limit=*)
local limit="${filter#--limit=}"
jq_filter="$jq_filter | head -n $limit"
;;
esac
done
# Execute query
case "$output_format" in
"json")
jq -s "$jq_filter" "$audit_log" 2>/dev/null || echo "[]"
;;
"csv")
echo "timestamp,event_type,severity,user,session_id,hostname,data"
jq -r "$jq_filter | .[] | [.timestamp, .event_type, .severity, .user, .session_id, .hostname, .data] | @csv" "$audit_log" 2>/dev/null || true
;;
"table")
echo "Timestamp | Event Type | Severity | User | Session ID | Hostname"
echo "----------|------------|----------|------|------------|----------"
jq -r "$jq_filter | .[] | \"\(.timestamp) | \(.event_type) | \(.severity) | \(.user) | \(.session_id) | \(.hostname)\"" "$audit_log" 2>/dev/null || true
;;
*)
log_error "Unsupported output format: $output_format" "apt-layer"
return 1
;;
esac
}
# Export audit logs
export_audit_logs() {
local export_format="$1"
local output_file="$2"
local filters=("${@:3}")
if [[ -z "$export_format" ]]; then
log_error "Export format required" "apt-layer"
return 1
fi
if [[ -z "$output_file" ]]; then
output_file="$AUDIT_EXPORTS_DIR/audit-export-$(date +%Y%m%d-%H%M%S).$export_format"
fi
log_info "Exporting audit logs to: $output_file" "apt-layer"
# Create exports directory if it doesn't exist
mkdir -p "$(dirname "$output_file")"
# Export with filters
if query_audit_logs "$export_format" "${filters[@]}" > "$output_file"; then
log_success "Audit logs exported to: $output_file" "apt-layer"
log_audit_event "EXPORT_AUDIT_LOGS" "{\"format\": \"$export_format\", \"file\": \"$output_file\", \"filters\": $(printf '%s\n' "${filters[@]}" | jq -R . | jq -s .)}"
return 0
else
log_error "Failed to export audit logs" "apt-layer"
return 1
fi
}
# Generate compliance report
generate_compliance_report() {
local framework="$1"
local report_period="${2:-monthly}"
local output_format="${3:-html}"
if [[ -z "$framework" ]]; then
log_error "Compliance framework required" "apt-layer"
return 1
fi
log_info "Generating $framework compliance report for period: $report_period" "apt-layer"
local template_file="$AUDIT_COMPLIANCE_DIR/${framework,,}-template.json"
if [[ ! -f "$template_file" ]]; then
log_error "Compliance template not found: $template_file" "apt-layer"
return 1
fi
local report_file="$AUDIT_REPORTS_DIR/${framework,,}-compliance-$(date +%Y%m%d-%H%M%S).$output_format"
# Generate report based on framework
case "$framework" in
"SOX"|"sox")
generate_sox_report "$template_file" "$report_period" "$output_format" "$report_file"
;;
"PCI-DSS"|"pci_dss")
generate_pci_dss_report "$template_file" "$report_period" "$output_format" "$report_file"
;;
*)
log_error "Unsupported compliance framework: $framework" "apt-layer"
return 1
;;
esac
log_success "Compliance report generated: $report_file" "apt-layer"
log_audit_event "GENERATE_COMPLIANCE_REPORT" "{\"framework\": \"$framework\", \"period\": \"$report_period\", \"format\": \"$output_format\", \"file\": \"$report_file\"}"
return 0
}
# Generate SOX compliance report
generate_sox_report() {
local template_file="$1"
local report_period="$2"
local output_format="$3"
local report_file="$4"
# Query relevant audit events
local access_control_events
access_control_events=$(query_audit_logs json --event-type=USER_ADD --event-type=USER_REMOVE --event-type=PERMISSION_CHECK)
local change_management_events
change_management_events=$(query_audit_logs json --event-type=INSTALL_SUCCESS --event-type=REMOVE_SUCCESS --event-type=UPDATE_SUCCESS)
local audit_trail_events
audit_trail_events=$(query_audit_logs json --event-type=EXPORT_AUDIT_LOGS --event-type=GENERATE_COMPLIANCE_REPORT)
# Generate report content
case "$output_format" in
"html")
generate_sox_html_report "$template_file" "$report_period" "$access_control_events" "$change_management_events" "$audit_trail_events" "$report_file"
;;
"json")
generate_sox_json_report "$template_file" "$report_period" "$access_control_events" "$change_management_events" "$audit_trail_events" "$report_file"
;;
*)
log_error "Unsupported output format for SOX report: $output_format" "apt-layer"
return 1
;;
esac
}
# Generate SOX HTML report
generate_sox_html_report() {
local template_file="$1"
local report_period="$2"
local access_control_events="$3"
local change_management_events="$4"
local audit_trail_events="$5"
local report_file="$6"
cat > "$report_file" << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>SOX Compliance Report - $report_period</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
.requirement { margin: 10px 0; padding: 10px; background-color: #f9f9f9; }
.compliant { border-left: 5px solid #4CAF50; }
.non-compliant { border-left: 5px solid #f44336; }
.warning { border-left: 5px solid #ff9800; }
table { width: 100%; border-collapse: collapse; margin: 10px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="header">
<h1>SOX Compliance Report</h1>
<p><strong>Period:</strong> $report_period</p>
<p><strong>Generated:</strong> $(date -u +%Y-%m-%dT%H:%M:%SZ)</p>
<p><strong>System:</strong> $(hostname)</p>
</div>
<div class="section">
<h2>Access Control (Section 404)</h2>
<div class="requirement compliant">
<h3>User Management</h3>
<p>Status: Compliant</p>
<p>User management events tracked and logged.</p>
</div>
<div class="requirement compliant">
<h3>Role-Based Access Control</h3>
<p>Status: Compliant</p>
<p>RBAC implemented with proper permission validation.</p>
</div>
</div>
<div class="section">
<h2>Change Management (Section 404)</h2>
<div class="requirement compliant">
<h3>Package Installation Tracking</h3>
<p>Status: Compliant</p>
<p>All package installations are logged and tracked.</p>
</div>
<div class="requirement compliant">
<h3>System Modifications</h3>
<p>Status: Compliant</p>
<p>System modifications are tracked through audit logs.</p>
</div>
</div>
<div class="section">
<h2>Audit Trail (Section 404)</h2>
<div class="requirement compliant">
<h3>Comprehensive Logging</h3>
<p>Status: Compliant</p>
<p>All critical operations are logged with timestamps and user information.</p>
</div>
<div class="requirement compliant">
<h3>Log Integrity</h3>
<p>Status: Compliant</p>
<p>Audit logs are protected and tamper-evident.</p>
</div>
</div>
</body>
</html>
EOF
}
# Generate SOX JSON report
generate_sox_json_report() {
local template_file="$1"
local report_period="$2"
local access_control_events="$3"
local change_management_events="$4"
local audit_trail_events="$5"
local report_file="$6"
cat > "$report_file" << 'EOF'
{
"framework": "SOX",
"version": "2002",
"report_period": "$report_period",
"generated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"system": "$(hostname)",
"compliance_status": "compliant",
"requirements": {
"access_control": {
"status": "compliant",
"user_management": {
"status": "compliant",
"description": "User management events tracked and logged"
},
"role_based_access": {
"status": "compliant",
"description": "RBAC implemented with proper permission validation"
}
},
"change_management": {
"status": "compliant",
"package_installation": {
"status": "compliant",
"description": "All package installations are logged and tracked"
},
"system_modifications": {
"status": "compliant",
"description": "System modifications are tracked through audit logs"
}
},
"audit_trail": {
"status": "compliant",
"comprehensive_logging": {
"status": "compliant",
"description": "All critical operations are logged with timestamps and user information"
},
"log_integrity": {
"status": "compliant",
"description": "Audit logs are protected and tamper-evident"
}
}
}
}
EOF
}
# Generate PCI DSS compliance report
generate_pci_dss_report() {
local template_file="$1"
local report_period="$2"
local output_format="$3"
local report_file="$4"
# Similar implementation to SOX but with PCI DSS specific requirements
log_info "PCI DSS report generation not yet implemented" "apt-layer"
return 1
}
# List audit reports
list_audit_reports() {
log_info "Listing audit reports" "apt-layer"
echo "=== Audit Reports ==="
local reports
reports=$(find "$AUDIT_REPORTS_DIR" -name "*.html" -o -name "*.json" -o -name "*.csv" 2>/dev/null | sort -r || echo "")
if [[ -n "$reports" ]]; then
for report in $reports; do
local report_name
report_name=$(basename "$report")
local report_size
report_size=$(du -h "$report" | cut -f1)
local report_date
report_date=$(stat -c %y "$report" 2>/dev/null || echo "unknown")
echo " $report_name ($report_size) - $report_date"
done
else
log_info "No audit reports found" "apt-layer"
fi
echo ""
}
# Clean up old audit logs
cleanup_old_audit_logs() {
local max_age_days="${1:-90}"
log_info "Cleaning up audit logs older than $max_age_days days" "apt-layer"
local removed_count=0
# Clean up old log files
while IFS= read -r -d '' log_file; do
local file_age
file_age=$(find "$log_file" -mtime +$max_age_days 2>/dev/null | wc -l)
if [[ $file_age -gt 0 ]]; then
log_info "Removing old audit log: $(basename "$log_file")" "apt-layer"
rm -f "$log_file"
((removed_count++))
fi
done < <(find "$AUDIT_LOGS_DIR" -name "*.log*" -print0 2>/dev/null)
# Clean up old exports
while IFS= read -r -d '' export_file; do
local file_age
file_age=$(find "$export_file" -mtime +$max_age_days 2>/dev/null | wc -l)
if [[ $file_age -gt 0 ]]; then
log_info "Removing old export: $(basename "$export_file")" "apt-layer"
rm -f "$export_file"
((removed_count++))
fi
done < <(find "$AUDIT_EXPORTS_DIR" -name "*" -print0 2>/dev/null)
log_success "Cleaned up $removed_count old audit files" "apt-layer"
return 0
}
# Get audit system status
get_audit_status() {
log_info "Getting audit system status" "apt-layer"
echo "=== Audit System Status ==="
# General status
echo "General:"
echo " Enabled: $AUDIT_ENABLED"
echo " Log Level: $AUDIT_LOG_LEVEL"
echo " Retention Days: $AUDIT_RETENTION_DAYS"
echo " Rotation Size: ${AUDIT_ROTATION_SIZE_MB}MB"
# Remote shipping status
echo ""
echo "Remote Shipping:"
echo " Enabled: $AUDIT_REMOTE_SHIPPING"
echo " Syslog: $AUDIT_SYSLOG_ENABLED"
echo " HTTP Endpoint: ${AUDIT_HTTP_ENDPOINT:-not configured}"
# Log statistics
echo ""
echo "Log Statistics:"
local audit_log="$AUDIT_LOGS_DIR/audit.log"
if [[ -f "$audit_log" ]]; then
local total_entries
total_entries=$(wc -l < "$audit_log" 2>/dev/null || echo "0")
echo " Total Entries: $total_entries"
local recent_entries
recent_entries=$(tail -100 "$audit_log" 2>/dev/null | wc -l || echo "0")
echo " Recent Entries (last 100): $recent_entries"
local log_size
log_size=$(du -h "$audit_log" | cut -f1 2>/dev/null || echo "unknown")
echo " Log Size: $log_size"
else
echo " Audit log: not available"
fi
# Report statistics
echo ""
echo "Report Statistics:"
local report_count
report_count=$(find "$AUDIT_REPORTS_DIR" -name "*.html" -o -name "*.json" -o -name "*.csv" 2>/dev/null | wc -l || echo "0")
echo " Total Reports: $report_count"
local export_count
export_count=$(find "$AUDIT_EXPORTS_DIR" -name "*" 2>/dev/null | wc -l || echo "0")
echo " Total Exports: $export_count"
echo ""
}
# =============================================================================
# INTEGRATION FUNCTIONS
# =============================================================================
# Initialize audit reporting on script startup
init_audit_reporting_on_startup() {
# Only initialize if not already done
if [[ ! -d "$AUDIT_STATE_DIR" ]]; then
init_audit_reporting
fi
}
# Cleanup audit reporting on script exit
cleanup_audit_reporting_on_exit() {
# Clean up temporary files
rm -f "$AUDIT_QUERIES_DIR"/temp-* 2>/dev/null || true
rm -f "$AUDIT_EXPORTS_DIR"/temp-* 2>/dev/null || true
}
# Register cleanup function
trap cleanup_audit_reporting_on_exit EXIT

View file

@ -1,878 +0,0 @@
#!/bin/bash
# Ubuntu uBlue apt-layer Automated Security Scanning
# Provides enterprise-grade security scanning, CVE checking, and policy enforcement
# for comprehensive security monitoring and vulnerability management
# =============================================================================
# SECURITY SCANNING FUNCTIONS
# =============================================================================
# Security scanning configuration (with fallbacks for when particle-config.sh is not loaded)
SECURITY_CONFIG_DIR="${UBLUE_CONFIG_DIR:-/etc/ubuntu-ublue}/security"
SECURITY_STATE_DIR="${UBLUE_ROOT:-/var/lib/particle-os}/security"
SECURITY_SCANS_DIR="$SECURITY_STATE_DIR/scans"
SECURITY_REPORTS_DIR="$SECURITY_STATE_DIR/reports"
SECURITY_CACHE_DIR="$SECURITY_STATE_DIR/cache"
SECURITY_POLICIES_DIR="$SECURITY_STATE_DIR/policies"
SECURITY_CVE_DB_DIR="$SECURITY_STATE_DIR/cve-db"
# Security configuration
SECURITY_ENABLED="${SECURITY_ENABLED:-true}"
SECURITY_SCAN_LEVEL="${SECURITY_SCAN_LEVEL:-standard}"
SECURITY_AUTO_SCAN="${SECURITY_AUTO_SCAN:-false}"
SECURITY_CVE_CHECKING="${SECURITY_CVE_CHECKING:-true}"
SECURITY_POLICY_ENFORCEMENT="${SECURITY_POLICY_ENFORCEMENT:-true}"
SECURITY_SCAN_INTERVAL_HOURS="${SECURITY_SCAN_INTERVAL_HOURS:-24}"
SECURITY_REPORT_RETENTION_DAYS="${SECURITY_REPORT_RETENTION_DAYS:-90}"
# Initialize security scanning system
init_security_scanning() {
log_info "Initializing automated security scanning system" "apt-layer"
# Create security scanning directories
mkdir -p "$SECURITY_CONFIG_DIR" "$SECURITY_STATE_DIR" "$SECURITY_SCANS_DIR"
mkdir -p "$SECURITY_REPORTS_DIR" "$SECURITY_CACHE_DIR" "$SECURITY_POLICIES_DIR"
mkdir -p "$SECURITY_CVE_DB_DIR"
# Set proper permissions
chmod 755 "$SECURITY_CONFIG_DIR" "$SECURITY_STATE_DIR"
chmod 750 "$SECURITY_SCANS_DIR" "$SECURITY_REPORTS_DIR" "$SECURITY_CACHE_DIR"
chmod 700 "$SECURITY_POLICIES_DIR" "$SECURITY_CVE_DB_DIR"
# Initialize security configuration
init_security_config
# Initialize CVE database
init_cve_database
# Initialize security policies
init_security_policies
# Initialize scan cache
init_scan_cache
log_success "Automated security scanning system initialized" "apt-layer"
}
# Initialize security configuration
init_security_config() {
local config_file="$SECURITY_CONFIG_DIR/security-config.json"
if [[ ! -f "$config_file" ]]; then
cat > "$config_file" << EOF
{
"security": {
"enabled": true,
"scan_level": "standard",
"auto_scan": false,
"cve_checking": true,
"policy_enforcement": true,
"scan_interval_hours": 24,
"report_retention_days": 90
},
"scanning": {
"package_scanning": true,
"layer_scanning": true,
"system_scanning": true,
"dependency_scanning": true,
"vulnerability_scanning": true
},
"cve": {
"database_url": "https://nvd.nist.gov/vuln/data-feeds",
"update_interval_hours": 6,
"severity_threshold": "MEDIUM",
"auto_update": true
},
"policies": {
"critical_vulnerabilities": "BLOCK",
"high_vulnerabilities": "WARN",
"medium_vulnerabilities": "LOG",
"low_vulnerabilities": "LOG",
"unknown_severity": "WARN"
},
"reporting": {
"auto_generate_reports": false,
"report_format": "html",
"include_recommendations": true,
"include_remediation": true
}
}
EOF
chmod 600 "$config_file"
fi
}
# Initialize CVE database
init_cve_database() {
local cve_db_file="$SECURITY_CVE_DB_DIR/cve-database.json"
if [[ ! -f "$cve_db_file" ]]; then
cat > "$cve_db_file" << EOF
{
"metadata": {
"version": "1.0",
"last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"source": "NVD",
"total_cves": 0
},
"cves": {},
"packages": {},
"severity_levels": {
"CRITICAL": 4,
"HIGH": 3,
"MEDIUM": 2,
"LOW": 1,
"UNKNOWN": 0
}
}
EOF
chmod 600 "$cve_db_file"
fi
}
# Initialize security policies
init_security_policies() {
# Default security policy
local default_policy="$SECURITY_POLICIES_DIR/default-policy.json"
if [[ ! -f "$default_policy" ]]; then
cat > "$default_policy" << EOF
{
"policy_name": "default",
"version": "1.0",
"description": "Default security policy for Ubuntu uBlue apt-layer",
"rules": {
"critical_vulnerabilities": {
"action": "BLOCK",
"description": "Block installation of packages with critical vulnerabilities"
},
"high_vulnerabilities": {
"action": "WARN",
"description": "Warn about packages with high vulnerabilities"
},
"medium_vulnerabilities": {
"action": "LOG",
"description": "Log packages with medium vulnerabilities"
},
"low_vulnerabilities": {
"action": "LOG",
"description": "Log packages with low vulnerabilities"
},
"unknown_severity": {
"action": "WARN",
"description": "Warn about packages with unknown vulnerability status"
}
},
"exceptions": [],
"enabled": true
}
EOF
chmod 600 "$default_policy"
fi
}
# Initialize scan cache
init_scan_cache() {
local cache_file="$SECURITY_CACHE_DIR/scan-cache.json"
if [[ ! -f "$cache_file" ]]; then
cat > "$cache_file" << EOF
{
"cache_metadata": {
"version": "1.0",
"created": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"last_cleaned": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
},
"package_scans": {},
"layer_scans": {},
"system_scans": {},
"cve_checks": {}
}
EOF
chmod 600 "$cache_file"
fi
}
# Scan package for vulnerabilities
scan_package() {
local package_name="$1"
local package_version="${2:-}"
local scan_level="${3:-standard}"
log_info "Scanning package: $package_name" "apt-layer"
# Check cache first
local cache_key="${package_name}_${package_version}_${scan_level}"
local cached_result
cached_result=$(get_cached_scan_result "package_scans" "$cache_key")
if [[ -n "$cached_result" ]]; then
log_info "Using cached scan result for $package_name" "apt-layer"
echo "$cached_result"
return 0
fi
# Perform package scan
local scan_result
scan_result=$(perform_package_scan "$package_name" "$package_version" "$scan_level")
# Cache the result
cache_scan_result "package_scans" "$cache_key" "$scan_result"
# Apply security policy
apply_security_policy "$package_name" "$scan_result"
echo "$scan_result"
}
# Perform package vulnerability scan
perform_package_scan() {
local package_name="$1"
local package_version="$2"
local scan_level="$3"
# Create scan result structure
local scan_result
scan_result=$(cat << 'EOF'
{
"package": "$package_name",
"version": "$package_version",
"scan_level": "$scan_level",
"scan_timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"vulnerabilities": [],
"security_score": 100,
"recommendations": [],
"status": "clean"
}
EOF
)
# Check for known vulnerabilities
local vulnerabilities
vulnerabilities=$(check_package_vulnerabilities "$package_name" "$package_version")
if [[ -n "$vulnerabilities" ]]; then
# Update scan result with vulnerabilities
scan_result=$(echo "$scan_result" | jq --argjson vulns "$vulnerabilities" '.vulnerabilities = $vulns')
# Calculate security score
local security_score
security_score=$(calculate_security_score "$vulnerabilities")
scan_result=$(echo "$scan_result" | jq --arg score "$security_score" '.security_score = ($score | tonumber)')
# Update status
scan_result=$(echo "$scan_result" | jq '.status = "vulnerable"')
# Generate recommendations
local recommendations
recommendations=$(generate_security_recommendations "$vulnerabilities")
scan_result=$(echo "$scan_result" | jq --argjson recs "$recommendations" '.recommendations = $recs')
fi
echo "$scan_result"
}
# Check package for known vulnerabilities
check_package_vulnerabilities() {
local package_name="$1"
local package_version="$2"
local cve_db_file="$SECURITY_CVE_DB_DIR/cve-database.json"
if [[ ! -f "$cve_db_file" ]]; then
log_warning "CVE database not found, skipping vulnerability check" "apt-layer"
return 0
fi
# Search for package in CVE database
local vulnerabilities
vulnerabilities=$(jq -r --arg pkg "$package_name" '.packages[$pkg] // []' "$cve_db_file" 2>/dev/null || echo "[]")
if [[ "$vulnerabilities" == "[]" ]]; then
# Try alternative package name formats
local alt_names=("${package_name}-dev" "${package_name}-common" "lib${package_name}")
for alt_name in "${alt_names[@]}"; do
local alt_vulns
alt_vulns=$(jq -r --arg pkg "$alt_name" '.packages[$pkg] // []' "$cve_db_file" 2>/dev/null || echo "[]")
if [[ "$alt_vulns" != "[]" ]]; then
vulnerabilities="$alt_vulns"
break
fi
done
fi
echo "$vulnerabilities"
}
# Calculate security score based on vulnerabilities
calculate_security_score() {
local vulnerabilities="$1"
local score=100
local critical_count=0
local high_count=0
local medium_count=0
local low_count=0
# Count vulnerabilities by severity
critical_count=$(echo "$vulnerabilities" | jq -r '[.[] | select(.severity == "CRITICAL")] | length' 2>/dev/null || echo "0")
high_count=$(echo "$vulnerabilities" | jq -r '[.[] | select(.severity == "HIGH")] | length' 2>/dev/null || echo "0")
medium_count=$(echo "$vulnerabilities" | jq -r '[.[] | select(.severity == "MEDIUM")] | length' 2>/dev/null || echo "0")
low_count=$(echo "$vulnerabilities" | jq -r '[.[] | select(.severity == "LOW")] | length' 2>/dev/null || echo "0")
# Calculate score (critical: -20, high: -10, medium: -5, low: -1)
score=$((score - (critical_count * 20) - (high_count * 10) - (medium_count * 5) - low_count))
# Ensure score doesn't go below 0
if [[ $score -lt 0 ]]; then
score=0
fi
echo "$score"
}
# Generate security recommendations
generate_security_recommendations() {
local vulnerabilities="$1"
local recommendations="[]"
# Check for critical vulnerabilities
local critical_count
critical_count=$(echo "$vulnerabilities" | jq -r '[.[] | select(.severity == "CRITICAL")] | length' 2>/dev/null || echo "0")
if [[ $critical_count -gt 0 ]]; then
recommendations=$(echo "$recommendations" | jq '. += ["Do not install packages with critical vulnerabilities"]')
fi
# Check for high vulnerabilities
local high_count
high_count=$(echo "$vulnerabilities" | jq -r '[.[] | select(.severity == "HIGH")] | length' 2>/dev/null || echo "0")
if [[ $high_count -gt 0 ]]; then
recommendations=$(echo "$recommendations" | jq '. += ["Consider alternative packages or wait for security updates"]')
fi
# Check for outdated packages
local outdated_count
outdated_count=$(echo "$vulnerabilities" | jq -r '[.[] | select(.type == "outdated")] | length' 2>/dev/null || echo "0")
if [[ $outdated_count -gt 0 ]]; then
recommendations=$(echo "$recommendations" | jq '. += ["Update to latest version when available"]')
fi
echo "$recommendations"
}
# Apply security policy to scan result
apply_security_policy() {
local package_name="$1"
local scan_result="$2"
local policy_file="$SECURITY_POLICIES_DIR/default-policy.json"
if [[ ! -f "$policy_file" ]]; then
log_warning "Security policy not found, skipping policy enforcement" "apt-layer"
return 0
fi
# Get highest severity vulnerability
local highest_severity
highest_severity=$(echo "$scan_result" | jq -r '.vulnerabilities | map(.severity) | sort | reverse | .[0] // "UNKNOWN"' 2>/dev/null || echo "UNKNOWN")
# Get policy action for this severity
local policy_action
policy_action=$(jq -r --arg sev "$highest_severity" '.rules[$sev + "_vulnerabilities"].action // "LOG"' "$policy_file" 2>/dev/null || echo "LOG")
case "$policy_action" in
"BLOCK")
log_error "Security policy BLOCKED installation of $package_name (severity: $highest_severity)" "apt-layer"
log_audit_event "SECURITY_POLICY_BLOCK" "{\"package\": \"$package_name\", \"severity\": \"$highest_severity\", \"policy_action\": \"$policy_action\"}" "WARNING"
return 1
;;
"WARN")
log_warning "Security policy WARNING for $package_name (severity: $highest_severity)" "apt-layer"
log_audit_event "SECURITY_POLICY_WARN" "{\"package\": \"$package_name\", \"severity\": \"$highest_severity\", \"policy_action\": \"$policy_action\"}" "WARNING"
;;
"LOG")
log_info "Security policy LOGGED $package_name (severity: $highest_severity)" "apt-layer"
log_audit_event "SECURITY_POLICY_LOG" "{\"package\": \"$package_name\", \"severity\": \"$highest_severity\", \"policy_action\": \"$policy_action\"}" "INFO"
;;
*)
log_info "Security policy action $policy_action for $package_name (severity: $highest_severity)" "apt-layer"
;;
esac
return 0
}
# Scan layer for vulnerabilities
scan_layer() {
local layer_path="$1"
local scan_level="${2:-standard}"
log_info "Scanning layer: $layer_path" "apt-layer"
# Check cache first
local cache_key="${layer_path}_${scan_level}"
local cached_result
cached_result=$(get_cached_scan_result "layer_scans" "$cache_key")
if [[ -n "$cached_result" ]]; then
log_info "Using cached scan result for layer" "apt-layer"
echo "$cached_result"
return 0
fi
# Extract packages from layer
local packages
packages=$(extract_packages_from_layer "$layer_path")
# Scan each package
local layer_scan_result
layer_scan_result=$(cat << 'EOF'
{
"layer": "$layer_path",
"scan_level": "$scan_level",
"scan_timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"packages": [],
"total_vulnerabilities": 0,
"security_score": 100,
"status": "clean"
}
EOF
)
local total_vulnerabilities=0
local total_score=0
local package_count=0
while IFS= read -r package; do
if [[ -n "$package" ]]; then
local package_scan
package_scan=$(scan_package "$package" "" "$scan_level")
# Add package to layer scan result
layer_scan_result=$(echo "$layer_scan_result" | jq --argjson pkg_scan "$package_scan" '.packages += [$pkg_scan]')
# Count vulnerabilities
local vuln_count
vuln_count=$(echo "$package_scan" | jq -r '.vulnerabilities | length' 2>/dev/null || echo "0")
total_vulnerabilities=$((total_vulnerabilities + vuln_count))
# Accumulate score
local pkg_score
pkg_score=$(echo "$package_scan" | jq -r '.security_score' 2>/dev/null || echo "100")
total_score=$((total_score + pkg_score))
package_count=$((package_count + 1))
fi
done <<< "$packages"
# Calculate average security score
if [[ $package_count -gt 0 ]]; then
local avg_score=$((total_score / package_count))
layer_scan_result=$(echo "$layer_scan_result" | jq --arg score "$avg_score" '.security_score = ($score | tonumber)')
fi
# Update total vulnerabilities
layer_scan_result=$(echo "$layer_scan_result" | jq --arg vulns "$total_vulnerabilities" '.total_vulnerabilities = ($vulns | tonumber)')
# Update status
if [[ $total_vulnerabilities -gt 0 ]]; then
layer_scan_result=$(echo "$layer_scan_result" | jq '.status = "vulnerable"')
fi
# Cache the result
cache_scan_result "layer_scans" "$cache_key" "$layer_scan_result"
echo "$layer_scan_result"
}
# Extract packages from layer
extract_packages_from_layer() {
local layer_path="$1"
# This is a simplified implementation
# In a real implementation, you would extract the actual package list from the layer
local temp_dir
temp_dir=$(mktemp -d)
# Mount layer and extract package information
if mount_layer "$layer_path" "$temp_dir"; then
# Extract package list (simplified)
local packages
packages=$(find "$temp_dir" -name "*.deb" -exec basename {} \; 2>/dev/null | sed 's/_.*$//' || echo "")
# Cleanup
umount_layer "$temp_dir"
rmdir "$temp_dir" 2>/dev/null || true
echo "$packages"
else
log_warning "Failed to mount layer for package extraction" "apt-layer"
echo ""
fi
}
# Mount layer for scanning
mount_layer() {
local layer_path="$1"
local mount_point="$2"
# Simplified mount implementation
# In a real implementation, you would use appropriate mounting for the layer format
if [[ -f "$layer_path" ]]; then
# For squashfs layers
mount -t squashfs "$layer_path" "$mount_point" 2>/dev/null || return 1
elif [[ -d "$layer_path" ]]; then
# For directory layers
mount --bind "$layer_path" "$mount_point" 2>/dev/null || return 1
else
return 1
fi
return 0
}
# Unmount layer
umount_layer() {
local mount_point="$1"
umount "$mount_point" 2>/dev/null || true
}
# Get cached scan result
get_cached_scan_result() {
local cache_type="$1"
local cache_key="$2"
local cache_file="$SECURITY_CACHE_DIR/scan-cache.json"
if [[ ! -f "$cache_file" ]]; then
return 1
fi
# Check if cache entry exists and is not expired
local cached_result
cached_result=$(jq -r --arg type "$cache_type" --arg key "$cache_key" '.[$type][$key] // empty' "$cache_file" 2>/dev/null)
if [[ -n "$cached_result" ]]; then
# Check if cache is still valid (24 hours)
local cache_timestamp
cache_timestamp=$(echo "$cached_result" | jq -r '.cache_timestamp' 2>/dev/null || echo "")
if [[ -n "$cache_timestamp" ]]; then
local cache_age
cache_age=$(($(date +%s) - $(date -d "$cache_timestamp" +%s)))
if [[ $cache_age -lt 86400 ]]; then # 24 hours
echo "$cached_result"
return 0
fi
fi
fi
return 1
}
# Cache scan result
cache_scan_result() {
local cache_type="$1"
local cache_key="$2"
local scan_result="$3"
local cache_file="$SECURITY_CACHE_DIR/scan-cache.json"
# Add cache timestamp
local cached_result
cached_result=$(echo "$scan_result" | jq --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '.cache_timestamp = $timestamp')
# Update cache file
jq --arg type "$cache_type" --arg key "$cache_key" --argjson result "$cached_result" '.[$type][$key] = $result' "$cache_file" > "$cache_file.tmp" && mv "$cache_file.tmp" "$cache_file" 2>/dev/null || true
}
# Update CVE database
update_cve_database() {
log_info "Updating CVE database" "apt-layer"
local cve_db_file="$SECURITY_CVE_DB_DIR/cve-database.json"
local config_file="$SECURITY_CONFIG_DIR/security-config.json"
# Get database URL from config
local db_url
db_url=$(jq -r '.cve.database_url // "https://nvd.nist.gov/vuln/data-feeds"' "$config_file" 2>/dev/null || echo "https://nvd.nist.gov/vuln/data-feeds")
# Download latest CVE data (simplified implementation)
local temp_file
temp_file=$(mktemp)
if curl -s -L "$db_url" > "$temp_file" 2>/dev/null; then
# Process and update database (simplified)
log_success "CVE database updated successfully" "apt-layer"
log_audit_event "CVE_DATABASE_UPDATE" "{\"status\": \"success\", \"source\": \"$db_url\"}" "INFO"
else
log_error "Failed to update CVE database" "apt-layer"
log_audit_event "CVE_DATABASE_UPDATE" "{\"status\": \"failed\", \"source\": \"$db_url\"}" "ERROR"
return 1
fi
rm -f "$temp_file"
return 0
}
# Generate security report
generate_security_report() {
local report_type="$1"
local output_format="${2:-html}"
local scan_level="${3:-standard}"
log_info "Generating security report: $report_type" "apt-layer"
local report_file="$SECURITY_REPORTS_DIR/security-report-$(date +%Y%m%d-%H%M%S).$output_format"
case "$report_type" in
"package")
generate_package_security_report "$output_format" "$scan_level" "$report_file"
;;
"layer")
generate_layer_security_report "$output_format" "$scan_level" "$report_file"
;;
"system")
generate_system_security_report "$output_format" "$scan_level" "$report_file"
;;
*)
log_error "Unknown report type: $report_type" "apt-layer"
return 1
;;
esac
log_success "Security report generated: $report_file" "apt-layer"
log_audit_event "GENERATE_SECURITY_REPORT" "{\"type\": \"$report_type\", \"format\": \"$output_format\", \"file\": \"$report_file\"}"
return 0
}
# Generate package security report
generate_package_security_report() {
local output_format="$1"
local scan_level="$2"
local report_file="$3"
case "$output_format" in
"html")
generate_package_html_report "$scan_level" "$report_file"
;;
"json")
generate_package_json_report "$scan_level" "$report_file"
;;
*)
log_error "Unsupported output format for package report: $output_format" "apt-layer"
return 1
;;
esac
}
# Generate package HTML report
generate_package_html_report() {
local scan_level="$1"
local report_file="$2"
cat > "$report_file" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Package Security Report - $scan_level</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
.vulnerability { margin: 10px 0; padding: 10px; background-color: #f9f9f9; }
.critical { border-left: 5px solid #f44336; }
.high { border-left: 5px solid #ff9800; }
.medium { border-left: 5px solid #ffc107; }
.low { border-left: 5px solid #4CAF50; }
table { width: 100%; border-collapse: collapse; margin: 10px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="header">
<h1>Package Security Report</h1>
<p><strong>Scan Level:</strong> $scan_level</p>
<p><strong>Generated:</strong> $(date -u +%Y-%m-%dT%H:%M:%SZ)</p>
<p><strong>System:</strong> $(hostname)</p>
</div>
<div class="section">
<h2>Security Summary</h2>
<p>This report provides a comprehensive security analysis of scanned packages.</p>
<p>Scan level: $scan_level</p>
</div>
<div class="section">
<h2>Recommendations</h2>
<ul>
<li>Review all critical and high severity vulnerabilities</li>
<li>Update packages to latest secure versions</li>
<li>Consider alternative packages for persistent vulnerabilities</li>
<li>Implement security policies to prevent vulnerable package installation</li>
</ul>
</div>
</body>
</html>
EOF
}
# Generate package JSON report
generate_package_json_report() {
local scan_level="$1"
local report_file="$2"
cat > "$report_file" << EOF
{
"report_type": "package_security",
"scan_level": "$scan_level",
"generated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"system": "$(hostname)",
"summary": {
"total_packages_scanned": 0,
"vulnerable_packages": 0,
"critical_vulnerabilities": 0,
"high_vulnerabilities": 0,
"medium_vulnerabilities": 0,
"low_vulnerabilities": 0
},
"packages": [],
"recommendations": [
"Review all critical and high severity vulnerabilities",
"Update packages to latest secure versions",
"Consider alternative packages for persistent vulnerabilities",
"Implement security policies to prevent vulnerable package installation"
]
}
EOF
}
# Generate layer security report
generate_layer_security_report() {
local output_format="$1"
local scan_level="$2"
local report_file="$3"
# Similar implementation to package report but for layers
log_info "Layer security report generation not yet implemented" "apt-layer"
return 1
}
# Generate system security report
generate_system_security_report() {
local output_format="$1"
local scan_level="$2"
local report_file="$3"
# Similar implementation to package report but for system-wide analysis
log_info "System security report generation not yet implemented" "apt-layer"
return 1
}
# Get security scanning status
get_security_status() {
log_info "Getting security scanning system status" "apt-layer"
echo "=== Security Scanning System Status ==="
# General status
echo "General:"
echo " Enabled: $SECURITY_ENABLED"
echo " Scan Level: $SECURITY_SCAN_LEVEL"
echo " Auto Scan: $SECURITY_AUTO_SCAN"
echo " CVE Checking: $SECURITY_CVE_CHECKING"
echo " Policy Enforcement: $SECURITY_POLICY_ENFORCEMENT"
# CVE database status
echo ""
echo "CVE Database:"
local cve_db_file="$SECURITY_CVE_DB_DIR/cve-database.json"
if [[ -f "$cve_db_file" ]]; then
local last_updated
last_updated=$(jq -r '.metadata.last_updated' "$cve_db_file" 2>/dev/null || echo "unknown")
local total_cves
total_cves=$(jq -r '.metadata.total_cves' "$cve_db_file" 2>/dev/null || echo "0")
echo " Last Updated: $last_updated"
echo " Total CVEs: $total_cves"
else
echo " Status: Not initialized"
fi
# Scan statistics
echo ""
echo "Scan Statistics:"
local cache_file="$SECURITY_CACHE_DIR/scan-cache.json"
if [[ -f "$cache_file" ]]; then
local package_scans
package_scans=$(jq -r '.package_scans | keys | length' "$cache_file" 2>/dev/null || echo "0")
local layer_scans
layer_scans=$(jq -r '.layer_scans | keys | length' "$cache_file" 2>/dev/null || echo "0")
echo " Cached Package Scans: $package_scans"
echo " Cached Layer Scans: $layer_scans"
else
echo " Cache: Not initialized"
fi
# Report statistics
echo ""
echo "Report Statistics:"
local report_count
report_count=$(find "$SECURITY_REPORTS_DIR" -name "*.html" -o -name "*.json" 2>/dev/null | wc -l || echo "0")
echo " Total Reports: $report_count"
echo ""
}
# Clean up old security reports
cleanup_old_security_reports() {
local max_age_days="${1:-90}"
log_info "Cleaning up security reports older than $max_age_days days" "apt-layer"
local removed_count=0
# Clean up old reports
while IFS= read -r report_file; do
local file_age
file_age=$(find "$report_file" -mtime +$max_age_days 2>/dev/null | wc -l)
if [[ $file_age -gt 0 ]]; then
log_info "Removing old security report: $(basename "$report_file")" "apt-layer"
rm -f "$report_file"
((removed_count++))
fi
done < <(find "$SECURITY_REPORTS_DIR" -name "*.html" -o -name "*.json" 2>/dev/null)
log_success "Cleaned up $removed_count old security reports" "apt-layer"
return 0
}
# =============================================================================
# INTEGRATION FUNCTIONS
# =============================================================================
# Initialize security scanning on script startup
init_security_scanning_on_startup() {
# Only initialize if not already done
if [[ ! -d "$SECURITY_STATE_DIR" ]]; then
init_security_scanning
fi
}
# Cleanup security scanning on script exit
cleanup_security_scanning_on_exit() {
# Clean up temporary files
rm -f "$SECURITY_CACHE_DIR"/temp-* 2>/dev/null || true
rm -f "$SECURITY_SCANS_DIR"/temp-* 2>/dev/null || true
}
# Register cleanup function
trap cleanup_security_scanning_on_exit EXIT

View file

@ -1,307 +0,0 @@
#!/bin/bash
# 14-admin-utilities.sh - Admin Utilities for Particle-OS apt-layer
# Provides system health monitoring, performance analytics, and admin tools
# --- Color and Symbols ---
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
CYAN='\033[0;36m'
NC='\033[0m'
CHECK="â"
WARN="â ï¸ "
CROSS="â"
INFO="â¹ï¸ "
# --- Helper: Check for WSL ---
is_wsl() {
grep -qi microsoft /proc/version 2>/dev/null
}
get_wsl_version() {
if is_wsl; then
if grep -q WSL2 /proc/version 2>/dev/null; then
echo "WSL2"
else
echo "WSL1"
fi
fi
}
# --- System Health Monitoring ---
health_check() {
local health_status=0
echo -e "${CYAN}================= System Health Check =================${NC}"
echo -e "${INFO} Hostname: $(hostname 2>/dev/null || echo N/A)"
echo -e "${INFO} Uptime: $(uptime -p 2>/dev/null || echo N/A)"
echo -e "${INFO} Kernel: $(uname -r 2>/dev/null || echo N/A)"
if is_wsl; then
echo -e "${INFO} WSL: $(get_wsl_version)"
fi
echo -e "${INFO} Load Avg: $(awk '{print $1, $2, $3}' /proc/loadavg 2>/dev/null || echo N/A)"
# CPU Info
if command -v lscpu &>/dev/null; then
cpu_model=$(lscpu | grep 'Model name' | awk -F: '{print $2}' | xargs)
cpu_cores=$(lscpu | grep '^CPU(s):' | awk '{print $2}')
echo -e "${INFO} CPU: $cpu_model ($cpu_cores cores)"
else
echo -e "${WARN} CPU: lscpu not available"
health_status=1
fi
# Memory
if command -v free &>/dev/null; then
mem_line=$(free -m | grep Mem)
mem_total=$(echo $mem_line | awk '{print $2}')
mem_used=$(echo $mem_line | awk '{print $3}')
mem_free=$(echo $mem_line | awk '{print $4}')
mem_perc=$((100 * mem_used / mem_total))
echo -e "${INFO} Memory: ${mem_total}MiB total, ${mem_used}MiB used (${mem_perc}%)"
else
echo -e "${WARN} Memory: free not available"
health_status=1
fi
# Disk
if command -v df &>/dev/null; then
disk_root=$(df -h / | tail -1)
disk_total=$(echo $disk_root | awk '{print $2}')
disk_used=$(echo $disk_root | awk '{print $3}')
disk_avail=$(echo $disk_root | awk '{print $4}')
disk_perc=$(echo $disk_root | awk '{print $5}')
echo -e "${INFO} Disk /: $disk_total total, $disk_used used, $disk_avail free ($disk_perc)"
if [ -d /var/lib/particle-os ]; then
disk_ublue=$(df -h /var/lib/particle-os 2>/dev/null | tail -1)
if [ -n "$disk_ublue" ]; then
ublue_total=$(echo $disk_ublue | awk '{print $2}')
ublue_used=$(echo $disk_ublue | awk '{print $3}')
ublue_avail=$(echo $disk_ublue | awk '{print $4}')
ublue_perc=$(echo $disk_ublue | awk '{print $5}')
echo -e "${INFO} Disk /var/lib/particle-os: $ublue_total total, $ublue_used used, $ublue_avail free ($ublue_perc)"
fi
fi
else
echo -e "${WARN} Disk: df not available"
health_status=1
fi
# OverlayFS/ComposeFS
overlays=$(mount | grep overlay | wc -l)
composefs=$(mount | grep composefs | wc -l)
echo -e "${INFO} OverlayFS: $overlays overlays mounted"
echo -e "${INFO} ComposeFS: $composefs composefs mounted"
# Bootloader
if command -v bootctl &>/dev/null; then
boot_status=$(bootctl status 2>/dev/null | grep 'System:' | xargs)
echo -e "${INFO} Bootloader: ${boot_status:-N/A}"
else
echo -e "${WARN} Bootloader: bootctl not available"
fi
# Security
if command -v apparmor_status &>/dev/null; then
sec_status=$(apparmor_status | grep 'profiles are in enforce mode' || echo 'N/A')
echo -e "${INFO} Security: $sec_status"
else
echo -e "${WARN} Security: apparmor_status not available"
fi
# Layer Integrity/Deployment
echo -e "${CYAN}-----------------------------------------------------${NC}"
echo -e "${INFO} Layer Integrity: [Coming soon] (future: check layer hashes)"
echo -e "${INFO} Deployment Status: [Coming soon] (future: show active deployments)"
# Top processes
echo -e "${CYAN}---------------- Top 3 Processes ---------------------${NC}"
if command -v ps &>/dev/null; then
echo -e "${INFO} By CPU:"
ps -eo pid,comm,%cpu --sort=-%cpu | head -n 4 | tail -n 3 | awk '{printf " PID: %-6s %-20s CPU: %s%%\n", $1, $2, $3}'
echo -e "${INFO} By MEM:"
ps -eo pid,comm,%mem --sort=-%mem | head -n 4 | tail -n 3 | awk '{printf " PID: %-6s %-20s MEM: %s%%\n", $1, $2, $3}'
else
echo -e "${WARN} ps not available for process listing"
fi
echo -e "${CYAN}-----------------------------------------------------${NC}"
# Summary
if [ $health_status -eq 0 ]; then
echo -e "${GREEN}${CHECK} System health: OK${NC}"
else
echo -e "${YELLOW}${WARN} System health: WARNING (see above)${NC}"
fi
echo -e "${CYAN}=====================================================${NC}"
}
# --- Performance Analytics ---
performance_report() {
echo -e "${CYAN}=============== Performance Analytics ===============${NC}"
echo -e "${INFO} Layer creation time (last 5): [Coming soon] (future: show timing logs)"
echo -e "${INFO} Resource usage (CPU/mem): [Coming soon] (future: show resource stats)"
if command -v iostat &>/dev/null; then
echo -e "${INFO} Disk I/O stats:"
iostat | grep -A1 Device | tail -n +2
else
echo -e "${WARN} Disk I/O stats: iostat not available"
fi
echo -e "${INFO} Historical trends: [Coming soon] (future: show trends if data available)"
echo -e "${CYAN}=====================================================${NC}"
}
# --- Automated Maintenance ---
admin_cleanup() {
# Defaults
local days=30
local dry_run=false
local keep_recent=2
local DEPLOYMENTS_DIR="/var/lib/particle-os/deployments"
local LOGS_DIR="/var/log/apt-layer"
local BACKUPS_DIR="/var/lib/particle-os/backups"
# Load config from JSON if available
local config_file="$(dirname "${BASH_SOURCE[0]}")/../config/maintenance.json"
if [ -f "$config_file" ] && command -v jq &>/dev/null; then
days=$(jq -r '.retention_days // 30' "$config_file")
keep_recent=$(jq -r '.keep_recent // 2' "$config_file")
DEPLOYMENTS_DIR=$(jq -r '.deployments_dir // "/var/lib/particle-os/deployments"' "$config_file")
LOGS_DIR=$(jq -r '.logs_dir // "/var/log/apt-layer"' "$config_file")
BACKUPS_DIR=$(jq -r '.backups_dir // "/var/lib/particle-os/backups"' "$config_file")
fi
# Parse arguments (override config)
while [[ $# -gt 0 ]]; do
case $1 in
--days|-d)
days="$2"; shift 2;;
--dry-run)
dry_run=true; shift;;
--keep-recent)
keep_recent="$2"; shift 2;;
--deployments-dir)
DEPLOYMENTS_DIR="$2"; shift 2;;
--logs-dir)
LOGS_DIR="$2"; shift 2;;
--backups-dir)
BACKUPS_DIR="$2"; shift 2;;
--schedule)
echo -e "${YELLOW}${WARN} Scheduled cleanup: Not yet implemented (will use systemd/cron)${NC}"; return;;
*)
shift;;
esac
done
echo -e "${CYAN}--- Automated Maintenance Cleanup ---${NC}"
echo -e "${INFO} Retention: $days days"
echo -e "${INFO} Keep recent: $keep_recent items"
echo -e "${INFO} Deployments dir: $DEPLOYMENTS_DIR"
echo -e "${INFO} Logs dir: $LOGS_DIR"
echo -e "${INFO} Backups dir: $BACKUPS_DIR"
if [ "$dry_run" = true ]; then
echo -e "${YELLOW}${WARN} DRY RUN MODE - No files will be deleted${NC}"
fi
local total_deleted=0
# Helper function to cleanup directory
cleanup_directory() {
local dir="$1"
local description="$2"
local deleted_count=0
if [ ! -d "$dir" ]; then
echo -e "${INFO} $description: Directory does not exist, skipping"
return
fi
echo -e "${INFO} $description: Scanning $dir"
# Get list of files/directories older than retention period
local old_items=()
if command -v find &>/dev/null; then
while IFS= read -r -d '' item; do
old_items+=("$item")
done < <(find "$dir" -maxdepth 1 -type f -o -type d -mtime +$days -print0 2>/dev/null)
fi
# Remove the most recent items from deletion list
if [ ${#old_items[@]} -gt 0 ] && [ $keep_recent -gt 0 ]; then
# Sort by modification time (newest first) and keep the most recent
local sorted_items=($(printf '%s\n' "${old_items[@]}" | xargs -I {} stat -c '%Y %n' {} 2>/dev/null | sort -nr | tail -n +$((keep_recent + 1)) | awk '{print $2}'))
old_items=("${sorted_items[@]}")
fi
if [ ${#old_items[@]} -eq 0 ]; then
echo -e "${INFO} $description: No items to delete"
return
fi
echo -e "${INFO} $description: Found ${#old_items[@]} items to delete"
for item in "${old_items[@]}"; do
if [ "$dry_run" = true ]; then
echo -e " ${YELLOW}Would delete: $item${NC}"
else
if rm -rf "$item" 2>/dev/null; then
echo -e " ${GREEN}Deleted: $item${NC}"
((deleted_count++))
else
echo -e " ${RED}Failed to delete: $item${NC}"
fi
fi
done
if [ "$dry_run" = false ]; then
total_deleted=$((total_deleted + deleted_count))
fi
}
# Cleanup each directory
cleanup_directory "$DEPLOYMENTS_DIR" "Deployments"
cleanup_directory "$LOGS_DIR" "Logs"
cleanup_directory "$BACKUPS_DIR" "Backups"
# Summary
if [ "$dry_run" = true ]; then
echo -e "${YELLOW}${WARN} Dry run completed - no files were deleted${NC}"
else
echo -e "${GREEN}${CHECK} Cleanup complete - $total_deleted items deleted${NC}"
fi
echo -e "${CYAN}-------------------------------------${NC}"
}
# --- Backup/Restore (Stub) ---
admin_backup() {
echo -e "${YELLOW}${WARN} Backup: Not yet implemented${NC}"
}
admin_restore() {
echo -e "${YELLOW}${WARN} Restore: Not yet implemented${NC}"
}
# --- Command Dispatch ---
admin_utilities_main() {
case "${1:-}" in
health|health-check)
health_check
;;
perf|performance|analytics)
performance_report
;;
cleanup)
shift
admin_cleanup "$@"
;;
backup)
admin_backup
;;
restore)
admin_restore
;;
help|--help|-h|"")
echo -e "${CYAN}Admin Utilities Commands:${NC}"
echo -e " ${GREEN}health${NC} - System health check"
echo -e " ${GREEN}perf${NC} - Performance analytics"
echo -e " ${GREEN}cleanup${NC} - Maintenance cleanup (--days N, --dry-run, --keep-recent N)"
echo -e " ${GREEN}backup${NC} - Backup configs/layers (stub)"
echo -e " ${GREEN}restore${NC} - Restore from backup (stub)"
echo -e " ${GREEN}help${NC} - Show this help message"
;;
*)
echo -e "${RED}${CROSS} Unknown admin command: $1${NC}"
admin_utilities_main help
;;
esac
}

View file

@ -1,641 +0,0 @@
#!/bin/bash
# Multi-Tenant Support for apt-layer
# Enables enterprise deployments with multiple organizations, departments, or environments
# Provides tenant isolation, resource quotas, and cross-tenant management
# Multi-tenant configuration
MULTI_TENANT_ENABLED="${MULTI_TENANT_ENABLED:-false}"
TENANT_ISOLATION_LEVEL="${TENANT_ISOLATION_LEVEL:-strict}" # strict, moderate, permissive
TENANT_RESOURCE_QUOTAS="${TENANT_RESOURCE_QUOTAS:-true}"
TENANT_CROSS_ACCESS="${TENANT_CROSS_ACCESS:-false}"
# Tenant management functions
init_multi_tenant_system() {
log_info "Initializing multi-tenant system..." "multi-tenant"
# Create tenant directories
local tenant_base="${WORKSPACE}/tenants"
mkdir -p "$tenant_base"
mkdir -p "$tenant_base/shared"
mkdir -p "$tenant_base/templates"
# Initialize tenant database
local tenant_db="$tenant_base/tenants.json"
if [[ ! -f "$tenant_db" ]]; then
cat > "$tenant_db" << 'EOF'
{
"tenants": [],
"policies": {
"default_isolation": "strict",
"default_quotas": {
"max_layers": 100,
"max_storage_gb": 50,
"max_users": 10
},
"cross_tenant_access": false
},
"metadata": {
"created": "",
"version": "1.0"
}
}
EOF
# Set creation timestamp
jq --arg created "$(date -Iseconds)" '.metadata.created = $created' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
fi
log_success "Multi-tenant system initialized" "multi-tenant"
}
# Tenant creation and management
create_tenant() {
local tenant_name="$1"
local tenant_config="$2"
if [[ -z "$tenant_name" ]]; then
log_error "Tenant name is required" "multi-tenant"
return 1
fi
# Validate tenant name
if [[ ! "$tenant_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
log_error "Invalid tenant name: $tenant_name (use alphanumeric, underscore, hyphen only)" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
local tenant_dir="$tenant_base/$tenant_name"
# Check if tenant already exists
if jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
log_error "Tenant '$tenant_name' already exists" "multi-tenant"
return 1
fi
# Create tenant directory structure
mkdir -p "$tenant_dir"
mkdir -p "$tenant_dir/layers"
mkdir -p "$tenant_dir/deployments"
mkdir -p "$tenant_dir/users"
mkdir -p "$tenant_dir/audit"
mkdir -p "$tenant_dir/backups"
mkdir -p "$tenant_dir/config"
# Create tenant configuration
local tenant_config_file="$tenant_dir/config/tenant.json"
cat > "$tenant_config_file" << EOF
{
"name": "$tenant_name",
"created": "$(date -Iseconds)",
"status": "active",
"isolation_level": "$TENANT_ISOLATION_LEVEL",
"quotas": {
"max_layers": 100,
"max_storage_gb": 50,
"max_users": 10,
"used_layers": 0,
"used_storage_gb": 0,
"used_users": 0
},
"policies": {
"allowed_packages": [],
"blocked_packages": [],
"security_level": "standard",
"audit_retention_days": 90
},
"integrations": {
"oci_registries": [],
"external_audit": null,
"monitoring": null
}
}
EOF
# Merge custom configuration if provided
if [[ -n "$tenant_config" && -f "$tenant_config" ]]; then
if jq empty "$tenant_config" 2>/dev/null; then
jq -s '.[0] * .[1]' "$tenant_config_file" "$tenant_config" > "$tenant_config_file.tmp" && mv "$tenant_config_file.tmp" "$tenant_config_file"
else
log_warning "Invalid JSON in tenant configuration, using defaults" "multi-tenant"
fi
fi
# Add tenant to database
local tenant_info
tenant_info=$(jq -r '.' "$tenant_config_file")
jq --arg name "$tenant_name" --argjson info "$tenant_info" '.tenants += [$info]' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
log_success "Tenant '$tenant_name' created successfully" "multi-tenant"
log_info "Tenant directory: $tenant_dir" "multi-tenant"
}
# Tenant deletion
delete_tenant() {
local tenant_name="$1"
local force="${2:-false}"
if [[ -z "$tenant_name" ]]; then
log_error "Tenant name is required" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
local tenant_dir="$tenant_base/$tenant_name"
# Check if tenant exists
if ! jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
log_error "Tenant '$tenant_name' does not exist" "multi-tenant"
return 1
fi
# Check for active resources
local active_layers=0
local active_deployments=0
if [[ -d "$tenant_dir/layers" ]]; then
active_layers=$(find "$tenant_dir/layers" -name "*.squashfs" 2>/dev/null | wc -l)
fi
if [[ -d "$tenant_dir/deployments" ]]; then
active_deployments=$(find "$tenant_dir/deployments" -name "*.json" 2>/dev/null | wc -l)
fi
if [[ $active_layers -gt 0 || $active_deployments -gt 0 ]]; then
if [[ "$force" != "true" ]]; then
log_error "Tenant '$tenant_name' has active resources ($active_layers layers, $active_deployments deployments)" "multi-tenant"
log_error "Use --force to delete anyway" "multi-tenant"
return 1
else
log_warning "Force deleting tenant with active resources" "multi-tenant"
fi
fi
# Remove from database
jq --arg name "$tenant_name" 'del(.tenants[] | select(.name == $name))' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
# Remove tenant directory
if [[ -d "$tenant_dir" ]]; then
rm -rf "$tenant_dir"
fi
log_success "Tenant '$tenant_name' deleted successfully" "multi-tenant"
}
# Tenant listing and information
list_tenants() {
local format="${1:-table}"
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
if [[ ! -f "$tenant_db" ]]; then
log_error "Tenant database not found" "multi-tenant"
return 1
fi
case "$format" in
"json")
jq -r '.' "$tenant_db"
;;
"csv")
echo "name,status,created,layers,storage_gb,users"
jq -r '.tenants[] | [.name, .status, .created, .quotas.used_layers, .quotas.used_storage_gb, .quotas.used_users] | @csv' "$tenant_db"
;;
"table"|*)
echo "Tenants:"
echo "========"
jq -r '.tenants[] | "\(.name) (\(.status)) - Layers: \(.quotas.used_layers)/\(.quotas.max_layers), Storage: \(.quotas.used_storage_gb)GB/\(.quotas.max_storage_gb)GB"' "$tenant_db"
;;
esac
}
# Tenant information
get_tenant_info() {
local tenant_name="$1"
local format="${2:-json}"
if [[ -z "$tenant_name" ]]; then
log_error "Tenant name is required" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
local tenant_info
tenant_info=$(jq -r ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" 2>/dev/null)
if [[ -z "$tenant_info" ]]; then
log_error "Tenant '$tenant_name' not found" "multi-tenant"
return 1
fi
case "$format" in
"json")
echo "$tenant_info"
;;
"yaml")
echo "$tenant_info" | jq -r '.' | sed 's/^/ /'
;;
"summary")
local name status created layers storage users
name=$(echo "$tenant_info" | jq -r '.name')
status=$(echo "$tenant_info" | jq -r '.status')
created=$(echo "$tenant_info" | jq -r '.created')
layers=$(echo "$tenant_info" | jq -r '.quotas.used_layers')
storage=$(echo "$tenant_info" | jq -r '.quotas.used_storage_gb')
users=$(echo "$tenant_info" | jq -r '.quotas.used_users')
echo "Tenant: $name"
echo "Status: $status"
echo "Created: $created"
echo "Resources: $layers layers, ${storage}GB storage, $users users"
;;
esac
}
# Tenant quota management
update_tenant_quotas() {
local tenant_name="$1"
local quota_type="$2"
local value="$3"
if [[ -z "$tenant_name" || -z "$quota_type" || -z "$value" ]]; then
log_error "Usage: update_tenant_quotas <tenant> <quota_type> <value>" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
# Validate quota type
case "$quota_type" in
"max_layers"|"max_storage_gb"|"max_users")
;;
*)
log_error "Invalid quota type: $quota_type" "multi-tenant"
log_error "Valid types: max_layers, max_storage_gb, max_users" "multi-tenant"
return 1
;;
esac
# Update quota
jq --arg name "$tenant_name" --arg type "$quota_type" --arg value "$value" \
'.tenants[] | select(.name == $name) | .quotas[$type] = ($value | tonumber)' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
log_success "Updated quota for tenant '$tenant_name': $quota_type = $value" "multi-tenant"
}
# Tenant isolation and access control
check_tenant_access() {
local tenant_name="$1"
local user="$2"
local operation="$3"
if [[ -z "$tenant_name" || -z "$user" || -z "$operation" ]]; then
log_error "Usage: check_tenant_access <tenant> <user> <operation>" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
# Check if tenant exists
if ! jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
log_error "Tenant '$tenant_name' not found" "multi-tenant"
return 1
fi
# Get tenant isolation level
local isolation_level
isolation_level=$(jq -r ".tenants[] | select(.name == \"$tenant_name\") | .isolation_level" "$tenant_db")
# Check user access (simplified - in real implementation, this would check user roles)
local user_file="$tenant_base/$tenant_name/users/$user.json"
if [[ ! -f "$user_file" ]]; then
log_error "User '$user' not found in tenant '$tenant_name'" "multi-tenant"
return 1
fi
# Check operation permissions
local user_role
user_role=$(jq -r '.role' "$user_file" 2>/dev/null)
case "$operation" in
"read")
[[ "$user_role" =~ ^(admin|package_manager|viewer)$ ]] && return 0
;;
"write")
[[ "$user_role" =~ ^(admin|package_manager)$ ]] && return 0
;;
"admin")
[[ "$user_role" == "admin" ]] && return 0
;;
*)
log_error "Unknown operation: $operation" "multi-tenant"
return 1
;;
esac
log_error "Access denied: User '$user' with role '$user_role' cannot perform '$operation' operation" "multi-tenant"
return 1
}
# Tenant resource usage tracking
update_tenant_usage() {
local tenant_name="$1"
local resource_type="$2"
local amount="$3"
if [[ -z "$tenant_name" || -z "$resource_type" || -z "$amount" ]]; then
log_error "Usage: update_tenant_usage <tenant> <resource_type> <amount>" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
# Update usage
jq --arg name "$tenant_name" --arg type "$resource_type" --arg amount "$amount" \
'.tenants[] | select(.name == $name) | .quotas["used_" + $type] = (.quotas["used_" + $type] + ($amount | tonumber))' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
log_debug "Updated usage for tenant '$tenant_name': $resource_type += $amount" "multi-tenant"
}
# Tenant quota enforcement
enforce_tenant_quotas() {
local tenant_name="$1"
local resource_type="$2"
local requested_amount="$3"
if [[ -z "$tenant_name" || -z "$resource_type" || -z "$requested_amount" ]]; then
log_error "Usage: enforce_tenant_quotas <tenant> <resource_type> <amount>" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_db="$tenant_base/tenants.json"
# Get current usage and quota
local current_usage max_quota
current_usage=$(jq -r ".tenants[] | select(.name == \"$tenant_name\") | .quotas.used_$resource_type" "$tenant_db")
max_quota=$(jq -r ".tenants[] | select(.name == \"$tenant_name\") | .quotas.max_$resource_type" "$tenant_db")
# Check if request would exceed quota
local new_total=$((current_usage + requested_amount))
if [[ $new_total -gt $max_quota ]]; then
log_error "Quota exceeded for tenant '$tenant_name': $resource_type" "multi-tenant"
log_error "Current: $current_usage, Requested: $requested_amount, Max: $max_quota" "multi-tenant"
return 1
fi
return 0
}
# Cross-tenant operations (when enabled)
cross_tenant_operation() {
local source_tenant="$1"
local target_tenant="$2"
local operation="$3"
local user="$4"
if [[ "$TENANT_CROSS_ACCESS" != "true" ]]; then
log_error "Cross-tenant operations are disabled" "multi-tenant"
return 1
fi
if [[ -z "$source_tenant" || -z "$target_tenant" || -z "$operation" || -z "$user" ]]; then
log_error "Usage: cross_tenant_operation <source> <target> <operation> <user>" "multi-tenant"
return 1
fi
# Check user has admin access to both tenants
if ! check_tenant_access "$source_tenant" "$user" "admin"; then
log_error "User '$user' lacks admin access to source tenant '$source_tenant'" "multi-tenant"
return 1
fi
if ! check_tenant_access "$target_tenant" "$user" "admin"; then
log_error "User '$user' lacks admin access to target tenant '$target_tenant'" "multi-tenant"
return 1
fi
log_info "Cross-tenant operation: $operation from '$source_tenant' to '$target_tenant' by '$user'" "multi-tenant"
# Implement specific cross-tenant operations here
case "$operation" in
"copy_layer")
# Copy layer from source to target tenant
log_info "Copying layer between tenants..." "multi-tenant"
;;
"sync_config")
# Sync configuration between tenants
log_info "Syncing configuration between tenants..." "multi-tenant"
;;
*)
log_error "Unknown cross-tenant operation: $operation" "multi-tenant"
return 1
;;
esac
}
# Tenant backup and restore
backup_tenant() {
local tenant_name="$1"
local backup_path="$2"
if [[ -z "$tenant_name" ]]; then
log_error "Tenant name is required" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_dir="$tenant_base/$tenant_name"
if [[ ! -d "$tenant_dir" ]]; then
log_error "Tenant directory not found: $tenant_dir" "multi-tenant"
return 1
fi
# Create backup
local backup_file
if [[ -n "$backup_path" ]]; then
backup_file="$backup_path"
else
backup_file="$tenant_dir/backups/tenant-${tenant_name}-$(date +%Y%m%d-%H%M%S).tar.gz"
fi
mkdir -p "$(dirname "$backup_file")"
tar -czf "$backup_file" -C "$tenant_base" "$tenant_name"
log_success "Tenant '$tenant_name' backed up to: $backup_file" "multi-tenant"
}
restore_tenant() {
local backup_file="$1"
local tenant_name="$2"
if [[ -z "$backup_file" || -z "$tenant_name" ]]; then
log_error "Usage: restore_tenant <backup_file> <tenant_name>" "multi-tenant"
return 1
fi
if [[ ! -f "$backup_file" ]]; then
log_error "Backup file not found: $backup_file" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_dir="$tenant_base/$tenant_name"
# Check if tenant already exists
if [[ -d "$tenant_dir" ]]; then
log_error "Tenant '$tenant_name' already exists. Delete it first or use a different name." "multi-tenant"
return 1
fi
# Restore tenant
tar -xzf "$backup_file" -C "$tenant_base"
log_success "Tenant '$tenant_name' restored from: $backup_file" "multi-tenant"
}
# Tenant health check
check_tenant_health() {
local tenant_name="$1"
if [[ -z "$tenant_name" ]]; then
log_error "Tenant name is required" "multi-tenant"
return 1
fi
local tenant_base="${WORKSPACE}/tenants"
local tenant_dir="$tenant_base/$tenant_name"
local tenant_db="$tenant_base/tenants.json"
echo "Tenant Health Check: $tenant_name"
echo "================================"
# Check tenant exists
if [[ ! -d "$tenant_dir" ]]; then
echo "â Tenant directory not found"
return 1
fi
if ! jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
echo "â Tenant not found in database"
return 1
fi
echo "â Tenant exists"
# Check directory structure
local missing_dirs=()
for dir in layers deployments users audit backups config; do
if [[ ! -d "$tenant_dir/$dir" ]]; then
missing_dirs+=("$dir")
fi
done
if [[ ${#missing_dirs[@]} -gt 0 ]]; then
echo "â ï¸ Missing directories: ${missing_dirs[*]}"
else
echo "â Directory structure complete"
fi
# Check quota usage
local tenant_info
tenant_info=$(jq -r ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db")
local layers_used layers_max storage_used storage_max
layers_used=$(echo "$tenant_info" | jq -r '.quotas.used_layers')
layers_max=$(echo "$tenant_info" | jq -r '.quotas.max_layers')
storage_used=$(echo "$tenant_info" | jq -r '.quotas.used_storage_gb')
storage_max=$(echo "$tenant_info" | jq -r '.quotas.max_storage_gb')
echo "ð Resource Usage:"
echo " Layers: $layers_used/$layers_max"
echo " Storage: ${storage_used}GB/${storage_max}GB"
# Check for quota warnings
local layer_percent=$((layers_used * 100 / layers_max))
local storage_percent=$((storage_used * 100 / storage_max))
if [[ $layer_percent -gt 80 ]]; then
echo "â ï¸ Layer quota usage high: ${layer_percent}%"
fi
if [[ $storage_percent -gt 80 ]]; then
echo "â ï¸ Storage quota usage high: ${storage_percent}%"
fi
echo "â Tenant health check complete"
}
# Multi-tenant command handler
handle_multi_tenant_command() {
local command="$1"
shift
case "$command" in
"init")
init_multi_tenant_system
;;
"create")
local tenant_name="$1"
local config_file="$2"
create_tenant "$tenant_name" "$config_file"
;;
"delete")
local tenant_name="$1"
local force="$2"
delete_tenant "$tenant_name" "$force"
;;
"list")
local format="$1"
list_tenants "$format"
;;
"info")
local tenant_name="$1"
local format="$2"
get_tenant_info "$tenant_name" "$format"
;;
"quota")
local tenant_name="$1"
local quota_type="$2"
local value="$3"
update_tenant_quotas "$tenant_name" "$quota_type" "$value"
;;
"backup")
local tenant_name="$1"
local backup_path="$2"
backup_tenant "$tenant_name" "$backup_path"
;;
"restore")
local backup_file="$1"
local tenant_name="$2"
restore_tenant "$backup_file" "$tenant_name"
;;
"health")
local tenant_name="$1"
check_tenant_health "$tenant_name"
;;
"help"|*)
echo "Multi-Tenant Commands:"
echo "====================="
echo " init - Initialize multi-tenant system"
echo " create <tenant> [config_file] - Create new tenant"
echo " delete <tenant> [--force] - Delete tenant"
echo " list [format] - List tenants (json|csv|table)"
echo " info <tenant> [format] - Get tenant info (json|yaml|summary)"
echo " quota <tenant> <type> <value> - Update tenant quota"
echo " backup <tenant> [path] - Backup tenant"
echo " restore <backup_file> <tenant> - Restore tenant"
echo " health <tenant> - Check tenant health"
echo " help - Show this help"
;;
esac
}

View file

@ -1,887 +0,0 @@
#!/bin/bash
# Advanced Compliance Frameworks for apt-layer
# Provides comprehensive compliance capabilities for enterprise deployments
# Supports multiple compliance standards with automated reporting and validation
# Compliance framework configuration
COMPLIANCE_ENABLED="${COMPLIANCE_ENABLED:-true}"
COMPLIANCE_LEVEL="${COMPLIANCE_LEVEL:-enterprise}" # basic, enterprise, strict
COMPLIANCE_AUTO_SCAN="${COMPLIANCE_AUTO_SCAN:-true}"
COMPLIANCE_REPORTING="${COMPLIANCE_REPORTING:-true}"
# Supported compliance frameworks
SUPPORTED_FRAMEWORKS=(
"SOX" # Sarbanes-Oxley Act
"PCI-DSS" # Payment Card Industry Data Security Standard
"HIPAA" # Health Insurance Portability and Accountability Act
"GDPR" # General Data Protection Regulation
"ISO-27001" # Information Security Management
"NIST-CSF" # NIST Cybersecurity Framework
"CIS" # Center for Internet Security Controls
"FEDRAMP" # Federal Risk and Authorization Management Program
"SOC-2" # Service Organization Control 2
"CMMC" # Cybersecurity Maturity Model Certification
)
# Compliance framework initialization
init_compliance_frameworks() {
log_info "Initializing advanced compliance frameworks..." "compliance"
# Create compliance directories
local compliance_base="${WORKSPACE}/compliance"
mkdir -p "$compliance_base"
mkdir -p "$compliance_base/frameworks"
mkdir -p "$compliance_base/reports"
mkdir -p "$compliance_base/templates"
mkdir -p "$compliance_base/evidence"
mkdir -p "$compliance_base/controls"
# Initialize compliance database
local compliance_db="$compliance_base/compliance.json"
if [[ ! -f "$compliance_db" ]]; then
cat > "$compliance_db" << 'EOF'
{
"frameworks": {},
"controls": {},
"evidence": {},
"reports": {},
"metadata": {
"created": "",
"version": "1.0",
"last_scan": null
}
}
EOF
# Set creation timestamp
jq --arg created "$(date -Iseconds)" '.metadata.created = $created' "$compliance_db" > "$compliance_db.tmp" && mv "$compliance_db.tmp" "$compliance_db"
fi
# Initialize framework templates
init_framework_templates
log_success "Advanced compliance frameworks initialized" "compliance"
}
# Initialize framework templates
init_framework_templates() {
local templates_dir="${WORKSPACE}/compliance/templates"
# SOX Template
cat > "$templates_dir/sox.json" << 'EOF'
{
"name": "SOX",
"version": "2024",
"description": "Sarbanes-Oxley Act Compliance",
"controls": {
"SOX-001": {
"title": "Access Control",
"description": "Ensure proper access controls are in place",
"category": "Access Management",
"severity": "high",
"requirements": [
"User authentication and authorization",
"Role-based access control",
"Access logging and monitoring"
]
},
"SOX-002": {
"title": "Change Management",
"description": "Implement proper change management procedures",
"category": "Change Management",
"severity": "high",
"requirements": [
"Change approval process",
"Change documentation",
"Change testing and validation"
]
},
"SOX-003": {
"title": "Data Integrity",
"description": "Ensure data integrity and accuracy",
"category": "Data Management",
"severity": "critical",
"requirements": [
"Data validation",
"Backup and recovery",
"Audit trails"
]
}
}
}
EOF
# PCI-DSS Template
cat > "$templates_dir/pci-dss.json" << 'EOF'
{
"name": "PCI-DSS",
"version": "4.0",
"description": "Payment Card Industry Data Security Standard",
"controls": {
"PCI-001": {
"title": "Build and Maintain a Secure Network",
"description": "Install and maintain a firewall configuration",
"category": "Network Security",
"severity": "critical",
"requirements": [
"Firewall configuration",
"Network segmentation",
"Security testing"
]
},
"PCI-002": {
"title": "Protect Cardholder Data",
"description": "Protect stored cardholder data",
"category": "Data Protection",
"severity": "critical",
"requirements": [
"Data encryption",
"Key management",
"Data retention policies"
]
},
"PCI-003": {
"title": "Maintain Vulnerability Management",
"description": "Use and regularly update anti-virus software",
"category": "Vulnerability Management",
"severity": "high",
"requirements": [
"Anti-virus software",
"Vulnerability scanning",
"Patch management"
]
}
}
}
EOF
# HIPAA Template
cat > "$templates_dir/hipaa.json" << 'EOF'
{
"name": "HIPAA",
"version": "2024",
"description": "Health Insurance Portability and Accountability Act",
"controls": {
"HIPAA-001": {
"title": "Administrative Safeguards",
"description": "Implement administrative safeguards for PHI",
"category": "Administrative",
"severity": "critical",
"requirements": [
"Security officer designation",
"Workforce training",
"Incident response procedures"
]
},
"HIPAA-002": {
"title": "Physical Safeguards",
"description": "Implement physical safeguards for PHI",
"category": "Physical",
"severity": "high",
"requirements": [
"Facility access controls",
"Workstation security",
"Device and media controls"
]
},
"HIPAA-003": {
"title": "Technical Safeguards",
"description": "Implement technical safeguards for PHI",
"category": "Technical",
"severity": "critical",
"requirements": [
"Access control",
"Audit controls",
"Transmission security"
]
}
}
}
EOF
# GDPR Template
cat > "$templates_dir/gdpr.json" << 'EOF'
{
"name": "GDPR",
"version": "2018",
"description": "General Data Protection Regulation",
"controls": {
"GDPR-001": {
"title": "Data Protection by Design",
"description": "Implement data protection by design and by default",
"category": "Privacy by Design",
"severity": "high",
"requirements": [
"Privacy impact assessments",
"Data minimization",
"Default privacy settings"
]
},
"GDPR-002": {
"title": "Data Subject Rights",
"description": "Ensure data subject rights are protected",
"category": "Data Subject Rights",
"severity": "critical",
"requirements": [
"Right to access",
"Right to rectification",
"Right to erasure"
]
},
"GDPR-003": {
"title": "Data Breach Notification",
"description": "Implement data breach notification procedures",
"category": "Incident Response",
"severity": "high",
"requirements": [
"Breach detection",
"Notification procedures",
"Documentation requirements"
]
}
}
}
EOF
# ISO-27001 Template
cat > "$templates_dir/iso-27001.json" << 'EOF'
{
"name": "ISO-27001",
"version": "2022",
"description": "Information Security Management System",
"controls": {
"ISO-001": {
"title": "Information Security Policies",
"description": "Define information security policies",
"category": "Policies",
"severity": "high",
"requirements": [
"Policy framework",
"Policy review",
"Policy communication"
]
},
"ISO-002": {
"title": "Organization of Information Security",
"description": "Establish information security organization",
"category": "Organization",
"severity": "high",
"requirements": [
"Security roles",
"Segregation of duties",
"Contact with authorities"
]
},
"ISO-003": {
"title": "Human Resource Security",
"description": "Ensure security in human resources",
"category": "Human Resources",
"severity": "medium",
"requirements": [
"Screening",
"Terms and conditions",
"Security awareness"
]
}
}
}
EOF
log_info "Framework templates initialized" "compliance"
}
# Framework management functions
enable_framework() {
local framework_name="$1"
local config_file="$2"
if [[ -z "$framework_name" ]]; then
log_error "Framework name is required" "compliance"
return 1
fi
# Validate framework name
local valid_framework=false
for framework in "${SUPPORTED_FRAMEWORKS[@]}"; do
if [[ "$framework" == "$framework_name" ]]; then
valid_framework=true
break
fi
done
if [[ "$valid_framework" != "true" ]]; then
log_error "Unsupported framework: $framework_name" "compliance"
log_info "Supported frameworks: ${SUPPORTED_FRAMEWORKS[*]}" "compliance"
return 1
fi
local compliance_base="${WORKSPACE}/compliance"
local compliance_db="$compliance_base/compliance.json"
local template_file="$compliance_base/templates/${framework_name,,}.json"
# Check if framework template exists
if [[ ! -f "$template_file" ]]; then
log_error "Framework template not found: $template_file" "compliance"
return 1
fi
# Load template
local template_data
template_data=$(jq -r '.' "$template_file")
# Merge custom configuration if provided
if [[ -n "$config_file" && -f "$config_file" ]]; then
if jq empty "$config_file" 2>/dev/null; then
template_data=$(jq -s '.[0] * .[1]' <(echo "$template_data") "$config_file")
else
log_warning "Invalid JSON in framework configuration, using template defaults" "compliance"
fi
fi
# Add framework to database
jq --arg name "$framework_name" --argjson data "$template_data" \
'.frameworks[$name] = $data' "$compliance_db" > "$compliance_db.tmp" && mv "$compliance_db.tmp" "$compliance_db"
log_success "Framework '$framework_name' enabled successfully" "compliance"
}
disable_framework() {
local framework_name="$1"
if [[ -z "$framework_name" ]]; then
log_error "Framework name is required" "compliance"
return 1
fi
local compliance_base="${WORKSPACE}/compliance"
local compliance_db="$compliance_base/compliance.json"
# Remove framework from database
jq --arg name "$framework_name" 'del(.frameworks[$name])' "$compliance_db" > "$compliance_db.tmp" && mv "$compliance_db.tmp" "$compliance_db"
log_success "Framework '$framework_name' disabled successfully" "compliance"
}
list_frameworks() {
local format="${1:-table}"
local compliance_base="${WORKSPACE}/compliance"
local compliance_db="$compliance_base/compliance.json"
if [[ ! -f "$compliance_db" ]]; then
log_error "Compliance database not found" "compliance"
return 1
fi
case "$format" in
"json")
jq -r '.frameworks' "$compliance_db"
;;
"csv")
echo "framework,version,description,controls_count"
jq -r '.frameworks | to_entries[] | [.key, .value.version, .value.description, (.value.controls | length)] | @csv' "$compliance_db"
;;
"table"|*)
echo "Enabled Compliance Frameworks:"
echo "=============================="
jq -r '.frameworks | to_entries[] | "\(.key) (\(.value.version)) - \(.value.description)"' "$compliance_db"
;;
esac
}
# Compliance scanning and assessment
run_compliance_scan() {
local framework_name="$1"
local scan_level="${2:-standard}" # quick, standard, thorough
if [[ -z "$framework_name" ]]; then
log_error "Framework name is required" "compliance"
return 1
fi
local compliance_base="${WORKSPACE}/compliance"
local compliance_db="$compliance_base/compliance.json"
# Check if framework is enabled
if ! jq -e ".frameworks[\"$framework_name\"]" "$compliance_db" > /dev/null 2>&1; then
log_error "Framework '$framework_name' is not enabled" "compliance"
return 1
fi
log_info "Running compliance scan for framework: $framework_name (level: $scan_level)" "compliance"
# Create scan report
local scan_id="scan-$(date +%Y%m%d-%H%M%S)"
local report_file="$compliance_base/reports/${framework_name}-${scan_id}.json"
# Initialize report structure
local report_data
report_data=$(cat << 'EOF'
{
"scan_id": "$scan_id",
"framework": "$framework_name",
"scan_level": "$scan_level",
"timestamp": "$(date -Iseconds)",
"results": {},
"summary": {
"total_controls": 0,
"passed": 0,
"failed": 0,
"warnings": 0,
"not_applicable": 0
}
}
EOF
)
# Get framework controls
local controls
controls=$(jq -r ".frameworks[\"$framework_name\"].controls" "$compliance_db")
# Scan each control
local total_controls=0
local passed_controls=0
local failed_controls=0
local warning_controls=0
local na_controls=0
while IFS= read -r control_id; do
if [[ -n "$control_id" ]]; then
total_controls=$((total_controls + 1))
# Assess control compliance
local control_result
control_result=$(assess_control_compliance "$framework_name" "$control_id" "$scan_level")
# Parse result
local status
status=$(echo "$control_result" | jq -r '.status')
case "$status" in
"PASS")
passed_controls=$((passed_controls + 1))
;;
"FAIL")
failed_controls=$((failed_controls + 1))
;;
"WARNING")
warning_controls=$((warning_controls + 1))
;;
"N/A")
na_controls=$((na_controls + 1))
;;
esac
# Add to report
report_data=$(echo "$report_data" | jq --arg id "$control_id" --argjson result "$control_result" '.results[$id] = $result')
fi
done < <(echo "$controls" | jq -r 'keys[]')
# Update summary
report_data=$(echo "$report_data" | jq --argjson total $total_controls --argjson passed $passed_controls --argjson failed $failed_controls --argjson warnings $warning_controls --argjson na $na_controls \
'.summary.total_controls = $total | .summary.passed = $passed | .summary.failed = $failed | .summary.warnings = $warnings | .summary.not_applicable = $na')
# Save report
echo "$report_data" > "$report_file"
# Update compliance database
jq --arg framework "$framework_name" --arg scan_id "$scan_id" --arg report_file "$report_file" \
'.reports[$framework] = {"last_scan": $scan_id, "report_file": $report_file}' "$compliance_db" > "$compliance_db.tmp" && mv "$compliance_db.tmp" "$compliance_db"
log_success "Compliance scan completed: $scan_id" "compliance"
log_info "Report saved to: $report_file" "compliance"
# Print summary
echo "Compliance Scan Summary:"
echo "========================"
echo "Framework: $framework_name"
echo "Scan Level: $scan_level"
echo "Total Controls: $total_controls"
echo "Passed: $passed_controls"
echo "Failed: $failed_controls"
echo "Warnings: $warning_controls"
echo "Not Applicable: $na_controls"
return 0
}
# Control assessment
assess_control_compliance() {
local framework_name="$1"
local control_id="$2"
local scan_level="$3"
local compliance_base="${WORKSPACE}/compliance"
local compliance_db="$compliance_base/compliance.json"
# Get control details
local control_info
control_info=$(jq -r ".frameworks[\"$framework_name\"].controls[\"$control_id\"]" "$compliance_db")
local control_title
control_title=$(echo "$control_info" | jq -r '.title')
local control_category
control_category=$(echo "$control_info" | jq -r '.category')
local control_severity
control_severity=$(echo "$control_info" | jq -r '.severity')
# Perform control-specific assessment
local status="PASS"
local evidence=""
local findings=""
case "$control_id" in
"SOX-001"|"PCI-001"|"HIPAA-003"|"ISO-002")
# Access Control assessment
if check_access_controls; then
status="PASS"
evidence="Access controls properly configured"
else
status="FAIL"
evidence="Access controls not properly configured"
findings="Missing role-based access control implementation"
fi
;;
"SOX-002"|"PCI-003"|"ISO-001")
# Change Management assessment
if check_change_management; then
status="PASS"
evidence="Change management procedures in place"
else
status="WARNING"
evidence="Change management procedures need improvement"
findings="Documentation of change procedures incomplete"
fi
;;
"SOX-003"|"PCI-002"|"HIPAA-002")
# Data Protection assessment
if check_data_protection; then
status="PASS"
evidence="Data protection measures implemented"
else
status="FAIL"
evidence="Data protection measures insufficient"
findings="Encryption not properly configured"
fi
;;
"GDPR-001"|"GDPR-002"|"GDPR-003")
# Privacy assessment
if check_privacy_controls; then
status="PASS"
evidence="Privacy controls implemented"
else
status="WARNING"
evidence="Privacy controls need enhancement"
findings="Data minimization not fully implemented"
fi
;;
"HIPAA-001")
# Administrative safeguards
if check_administrative_safeguards; then
status="PASS"
evidence="Administrative safeguards in place"
else
status="FAIL"
evidence="Administrative safeguards missing"
findings="Security officer not designated"
fi
;;
*)
# Default assessment
status="N/A"
evidence="Control not implemented in assessment engine"
findings="Manual assessment required"
;;
esac
# Create result JSON
cat << 'EOF'
{
"control_id": "$control_id",
"title": "$control_title",
"category": "$control_category",
"severity": "$control_severity",
"status": "$status",
"evidence": "$evidence",
"findings": "$findings",
"assessment_time": "$(date -Iseconds)"
}
EOF
}
# Control check functions (stubs for now)
check_access_controls() {
# Check if access controls are properly configured
# This would check user management, role assignments, etc.
local user_count
user_count=$(jq -r '.users | length' "${WORKSPACE}/users.json" 2>/dev/null || echo "0")
if [[ $user_count -gt 0 ]]; then
return 0 # Pass
else
return 1 # Fail
fi
}
check_change_management() {
# Check if change management procedures are in place
# This would check for change logs, approval processes, etc.
local audit_logs
audit_logs=$(find "${WORKSPACE}/audit" -name "*.log" 2>/dev/null | wc -l)
if [[ $audit_logs -gt 0 ]]; then
return 0 # Pass
else
return 1 # Fail
fi
}
check_data_protection() {
# Check if data protection measures are implemented
# This would check encryption, backup procedures, etc.
local backup_count
backup_count=$(find "${WORKSPACE}/backups" -name "*.tar.gz" 2>/dev/null | wc -l)
if [[ $backup_count -gt 0 ]]; then
return 0 # Pass
else
return 1 # Fail
fi
}
check_privacy_controls() {
# Check if privacy controls are implemented
# This would check data minimization, consent management, etc.
# For now, return pass if audit system is enabled
if [[ "$COMPLIANCE_ENABLED" == "true" ]]; then
return 0 # Pass
else
return 1 # Fail
fi
}
check_administrative_safeguards() {
# Check if administrative safeguards are in place
# This would check security officer designation, training, etc.
# For now, return pass if compliance system is initialized
local compliance_db="${WORKSPACE}/compliance/compliance.json"
if [[ -f "$compliance_db" ]]; then
return 0 # Pass
else
return 1 # Fail
fi
}
# Compliance reporting
generate_compliance_report() {
local framework_name="$1"
local report_format="${2:-html}"
local report_period="${3:-monthly}"
if [[ -z "$framework_name" ]]; then
log_error "Framework name is required" "compliance"
return 1
fi
local compliance_base="${WORKSPACE}/compliance"
local compliance_db="$compliance_base/compliance.json"
# Check if framework is enabled
if ! jq -e ".frameworks[\"$framework_name\"]" "$compliance_db" > /dev/null 2>&1; then
log_error "Framework '$framework_name' is not enabled" "compliance"
return 1
fi
# Get latest scan report
local report_file
report_file=$(jq -r ".reports[\"$framework_name\"].report_file" "$compliance_db" 2>/dev/null)
if [[ -z "$report_file" || "$report_file" == "null" ]]; then
log_error "No scan report found for framework '$framework_name'" "compliance"
log_info "Run a compliance scan first: compliance scan $framework_name" "compliance"
return 1
fi
if [[ ! -f "$report_file" ]]; then
log_error "Report file not found: $report_file" "compliance"
return 1
fi
# Generate report based on format
case "$report_format" in
"html")
generate_html_compliance_report "$framework_name" "$report_file"
;;
"json")
generate_json_compliance_report "$framework_name" "$report_file"
;;
"pdf")
generate_pdf_compliance_report "$framework_name" "$report_file"
;;
*)
log_error "Unsupported report format: $report_format" "compliance"
return 1
;;
esac
}
generate_html_compliance_report() {
local framework_name="$1"
local report_file="$2"
local report_data
report_data=$(jq -r '.' "$report_file")
local output_file="${WORKSPACE}/compliance/reports/${framework_name}-report-$(date +%Y%m%d).html"
# Generate HTML report
cat > "$output_file" << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Compliance Report - $framework_name</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.summary { margin: 20px 0; }
.control { margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 3px; }
.pass { background-color: #d4edda; border-color: #c3e6cb; }
.fail { background-color: #f8d7da; border-color: #f5c6cb; }
.warning { background-color: #fff3cd; border-color: #ffeaa7; }
.na { background-color: #e2e3e5; border-color: #d6d8db; }
</style>
</head>
<body>
<div class="header">
<h1>Compliance Report - $framework_name</h1>
<p>Generated: $(date)</p>
<p>Scan ID: $(echo "$report_data" | jq -r '.scan_id')</p>
</div>
<div class="summary">
<h2>Summary</h2>
<p>Total Controls: $(echo "$report_data" | jq -r '.summary.total_controls')</p>
<p>Passed: $(echo "$report_data" | jq -r '.summary.passed')</p>
<p>Failed: $(echo "$report_data" | jq -r '.summary.failed')</p>
<p>Warnings: $(echo "$report_data" | jq -r '.summary.warnings')</p>
<p>Not Applicable: $(echo "$report_data" | jq -r '.summary.not_applicable')</p>
</div>
<div class="controls">
<h2>Control Results</h2>
EOF
# Add control results
echo "$report_data" | jq -r '.results | to_entries[] | "\(.key): \(.value.status)"' | while IFS=':' read -r control_id status; do
local control_data
control_data=$(echo "$report_data" | jq -r ".results[\"$control_id\"]")
local title
title=$(echo "$control_data" | jq -r '.title')
local evidence
evidence=$(echo "$control_data" | jq -r '.evidence')
local findings
findings=$(echo "$control_data" | jq -r '.findings')
cat >> "$output_file" << 'EOF'
<div class="control $status">
<h3>$control_id - $title</h3>
<p><strong>Status:</strong> $status</p>
<p><strong>Evidence:</strong> $evidence</p>
EOF
if [[ -n "$findings" && "$findings" != "null" ]]; then
cat >> "$output_file" << 'EOF'
<p><strong>Findings:</strong> $findings</p>
EOF
fi
cat >> "$output_file" << 'EOF'
</div>
EOF
done
cat >> "$output_file" << 'EOF'
</div>
</body>
</html>
EOF
log_success "HTML compliance report generated: $output_file" "compliance"
}
generate_json_compliance_report() {
local framework_name="$1"
local report_file="$2"
local output_file="${WORKSPACE}/compliance/reports/${framework_name}-report-$(date +%Y%m%d).json"
# Copy and enhance the report
jq --arg framework "$framework_name" --arg generated "$(date -Iseconds)" \
'. + {"framework": $framework, "report_generated": $generated}' "$report_file" > "$output_file"
log_success "JSON compliance report generated: $output_file" "compliance"
}
generate_pdf_compliance_report() {
local framework_name="$1"
local report_file="$2"
local output_file="${WORKSPACE}/compliance/reports/${framework_name}-report-$(date +%Y%m%d).pdf"
# For now, generate HTML and suggest conversion
local html_file="${WORKSPACE}/compliance/reports/${framework_name}-report-$(date +%Y%m%d).html"
generate_html_compliance_report "$framework_name" "$report_file"
log_warning "PDF generation not implemented" "compliance"
log_info "HTML report generated: $html_file" "compliance"
log_info "Convert to PDF manually or use tools like wkhtmltopdf" "compliance"
}
# Compliance command handler
handle_compliance_command() {
local command="$1"
shift
case "$command" in
"init")
init_compliance_frameworks
;;
"enable")
local framework_name="$1"
local config_file="$2"
enable_framework "$framework_name" "$config_file"
;;
"disable")
local framework_name="$1"
disable_framework "$framework_name"
;;
"list")
local format="$1"
list_frameworks "$format"
;;
"scan")
local framework_name="$1"
local scan_level="$2"
run_compliance_scan "$framework_name" "$scan_level"
;;
"report")
local framework_name="$1"
local format="$2"
local period="$3"
generate_compliance_report "$framework_name" "$format" "$period"
;;
"help"|*)
echo "Advanced Compliance Framework Commands:"
echo "======================================"
echo " init - Initialize compliance frameworks"
echo " enable <framework> [config_file] - Enable compliance framework"
echo " disable <framework> - Disable compliance framework"
echo " list [format] - List enabled frameworks (json|csv|table)"
echo " scan <framework> [level] - Run compliance scan (quick|standard|thorough)"
echo " report <framework> [format] [period] - Generate compliance report (html|json|pdf)"
echo " help - Show this help"
echo ""
echo "Supported Frameworks:"
echo " SOX, PCI-DSS, HIPAA, GDPR, ISO-27001, NIST-CSF, CIS, FEDRAMP, SOC-2, CMMC"
;;
esac
}

View file

@ -1,752 +0,0 @@
#!/bin/bash
# Enterprise Integration for apt-layer
# Provides hooks and integrations with enterprise tools and systems
# Supports SIEM, ticketing, monitoring, and other enterprise integrations
# Enterprise integration configuration
ENTERPRISE_INTEGRATION_ENABLED="${ENTERPRISE_INTEGRATION_ENABLED:-true}"
ENTERPRISE_INTEGRATION_LEVEL="${ENTERPRISE_INTEGRATION_LEVEL:-basic}" # basic, standard, advanced
ENTERPRISE_INTEGRATION_TIMEOUT="${ENTERPRISE_INTEGRATION_TIMEOUT:-30}"
ENTERPRISE_INTEGRATION_RETRY="${ENTERPRISE_INTEGRATION_RETRY:-3}"
# Supported enterprise integrations
SUPPORTED_INTEGRATIONS=(
"SIEM" # Security Information and Event Management
"TICKETING" # IT Service Management / Ticketing
"MONITORING" # System monitoring and alerting
"CMDB" # Configuration Management Database
"BACKUP" # Enterprise backup systems
"SECURITY" # Security tools and platforms
"COMPLIANCE" # Compliance and governance tools
"DEVOPS" # DevOps and CI/CD tools
"CLOUD" # Cloud platform integrations
"CUSTOM" # Custom enterprise integrations
)
# Enterprise integration initialization
init_enterprise_integration() {
log_info "Initializing enterprise integration system..." "enterprise"
# Create enterprise integration directories
local enterprise_base="${WORKSPACE}/enterprise"
mkdir -p "$enterprise_base"
mkdir -p "$enterprise_base/integrations"
mkdir -p "$enterprise_base/hooks"
mkdir -p "$enterprise_base/configs"
mkdir -p "$enterprise_base/logs"
mkdir -p "$enterprise_base/templates"
# Initialize enterprise integration database
local enterprise_db="$enterprise_base/integrations.json"
if [[ ! -f "$enterprise_db" ]]; then
cat > "$enterprise_db" << 'EOF'
{
"integrations": {},
"hooks": {},
"configs": {},
"metadata": {
"created": "",
"version": "1.0",
"last_sync": null
}
}
EOF
# Set creation timestamp
jq --arg created "$(date -Iseconds)" '.metadata.created = $created' "$enterprise_db" > "$enterprise_db.tmp" && mv "$enterprise_db.tmp" "$enterprise_db"
fi
# Initialize integration templates
init_integration_templates
log_success "Enterprise integration system initialized" "enterprise"
}
# Initialize integration templates
init_integration_templates() {
local templates_dir="${WORKSPACE}/enterprise/templates"
# SIEM Integration Template
cat > "$templates_dir/siem.json" << 'EOF'
{
"name": "SIEM",
"type": "security",
"description": "Security Information and Event Management Integration",
"endpoints": {
"events": "https://siem.example.com/api/v1/events",
"alerts": "https://siem.example.com/api/v1/alerts",
"incidents": "https://siem.example.com/api/v1/incidents"
},
"authentication": {
"type": "api_key",
"header": "X-API-Key"
},
"events": {
"layer_created": true,
"layer_deleted": true,
"security_scan": true,
"compliance_scan": true,
"user_action": true,
"system_event": true
},
"format": "json",
"retry_policy": {
"max_retries": 3,
"backoff_multiplier": 2,
"timeout": 30
}
}
EOF
# Ticketing Integration Template
cat > "$templates_dir/ticketing.json" << 'EOF'
{
"name": "TICKETING",
"type": "service_management",
"description": "IT Service Management / Ticketing System Integration",
"endpoints": {
"tickets": "https://ticketing.example.com/api/v2/tickets",
"incidents": "https://ticketing.example.com/api/v2/incidents",
"changes": "https://ticketing.example.com/api/v2/changes"
},
"authentication": {
"type": "basic_auth",
"username": "service_account",
"password": "encrypted_password"
},
"triggers": {
"security_incident": true,
"compliance_violation": true,
"system_failure": true,
"maintenance_required": true,
"user_request": true
},
"format": "json",
"priority_mapping": {
"critical": "P1",
"high": "P2",
"medium": "P3",
"low": "P4"
}
}
EOF
# Monitoring Integration Template
cat > "$templates_dir/monitoring.json" << 'EOF'
{
"name": "MONITORING",
"type": "monitoring",
"description": "System Monitoring and Alerting Integration",
"endpoints": {
"metrics": "https://monitoring.example.com/api/v1/metrics",
"alerts": "https://monitoring.example.com/api/v1/alerts",
"health": "https://monitoring.example.com/api/v1/health"
},
"authentication": {
"type": "bearer_token",
"token": "encrypted_token"
},
"metrics": {
"layer_count": true,
"storage_usage": true,
"security_status": true,
"compliance_status": true,
"user_activity": true,
"system_performance": true
},
"format": "json",
"collection_interval": 300
}
EOF
# CMDB Integration Template
cat > "$templates_dir/cmdb.json" << 'EOF'
{
"name": "CMDB",
"type": "configuration_management",
"description": "Configuration Management Database Integration",
"endpoints": {
"assets": "https://cmdb.example.com/api/v1/assets",
"configurations": "https://cmdb.example.com/api/v1/configurations",
"relationships": "https://cmdb.example.com/api/v1/relationships"
},
"authentication": {
"type": "oauth2",
"client_id": "apt_layer_client",
"client_secret": "encrypted_secret"
},
"assets": {
"layers": true,
"deployments": true,
"users": true,
"configurations": true,
"dependencies": true
},
"format": "json",
"sync_interval": 3600
}
EOF
# DevOps Integration Template
cat > "$templates_dir/devops.json" << 'EOF'
{
"name": "DEVOPS",
"type": "devops",
"description": "DevOps and CI/CD Tools Integration",
"endpoints": {
"pipelines": "https://devops.example.com/api/v1/pipelines",
"deployments": "https://devops.example.com/api/v1/deployments",
"artifacts": "https://devops.example.com/api/v1/artifacts"
},
"authentication": {
"type": "service_account",
"token": "encrypted_token"
},
"triggers": {
"layer_ready": true,
"deployment_complete": true,
"security_approved": true,
"compliance_verified": true
},
"format": "json",
"webhook_url": "https://devops.example.com/webhooks/apt-layer"
}
EOF
log_info "Integration templates initialized" "enterprise"
}
# Integration management functions
enable_integration() {
local integration_name="$1"
local config_file="$2"
if [[ -z "$integration_name" ]]; then
log_error "Integration name is required" "enterprise"
return 1
fi
# Validate integration name
local valid_integration=false
for integration in "${SUPPORTED_INTEGRATIONS[@]}"; do
if [[ "$integration" == "$integration_name" ]]; then
valid_integration=true
break
fi
done
if [[ "$valid_integration" != "true" ]]; then
log_error "Unsupported integration: $integration_name" "enterprise"
log_info "Supported integrations: ${SUPPORTED_INTEGRATIONS[*]}" "enterprise"
return 1
fi
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
local template_file="$enterprise_base/templates/${integration_name,,}.json"
# Check if integration template exists
if [[ ! -f "$template_file" ]]; then
log_error "Integration template not found: $template_file" "enterprise"
return 1
fi
# Load template
local template_data
template_data=$(jq -r '.' "$template_file")
# Merge custom configuration if provided
if [[ -n "$config_file" && -f "$config_file" ]]; then
if jq empty "$config_file" 2>/dev/null; then
template_data=$(jq -s '.[0] * .[1]' <(echo "$template_data") "$config_file")
else
log_warning "Invalid JSON in integration configuration, using template defaults" "enterprise"
fi
fi
# Add integration to database
jq --arg name "$integration_name" --argjson data "$template_data" \
'.integrations[$name] = $data' "$enterprise_db" > "$enterprise_db.tmp" && mv "$enterprise_db.tmp" "$enterprise_db"
# Test integration connectivity
test_integration_connectivity "$integration_name"
log_success "Integration '$integration_name' enabled successfully" "enterprise"
}
disable_integration() {
local integration_name="$1"
if [[ -z "$integration_name" ]]; then
log_error "Integration name is required" "enterprise"
return 1
fi
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
# Remove integration from database
jq --arg name "$integration_name" 'del(.integrations[$name])' "$enterprise_db" > "$enterprise_db.tmp" && mv "$enterprise_db.tmp" "$enterprise_db"
log_success "Integration '$integration_name' disabled successfully" "enterprise"
}
list_integrations() {
local format="${1:-table}"
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
if [[ ! -f "$enterprise_db" ]]; then
log_error "Enterprise integration database not found" "enterprise"
return 1
fi
case "$format" in
"json")
jq -r '.integrations' "$enterprise_db"
;;
"csv")
echo "integration,type,description,status"
jq -r '.integrations | to_entries[] | [.key, .value.type, .value.description, "enabled"] | @csv' "$enterprise_db"
;;
"table"|*)
echo "Enabled Enterprise Integrations:"
echo "==============================="
jq -r '.integrations | to_entries[] | "\(.key) (\(.value.type)) - \(.value.description)"' "$enterprise_db"
;;
esac
}
# Integration connectivity testing
test_integration_connectivity() {
local integration_name="$1"
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
# Get integration configuration
local integration_config
integration_config=$(jq -r ".integrations[\"$integration_name\"]" "$enterprise_db")
if [[ "$integration_config" == "null" ]]; then
log_error "Integration '$integration_name' not found" "enterprise"
return 1
fi
log_info "Testing connectivity for integration: $integration_name" "enterprise"
# Test primary endpoint
local primary_endpoint
primary_endpoint=$(echo "$integration_config" | jq -r '.endpoints | to_entries[0].value')
if [[ -n "$primary_endpoint" && "$primary_endpoint" != "null" ]]; then
# Test HTTP connectivity
if curl -s --connect-timeout 10 --max-time 30 "$primary_endpoint" > /dev/null 2>&1; then
log_success "Connectivity test passed for $integration_name" "enterprise"
else
log_warning "Connectivity test failed for $integration_name" "enterprise"
fi
else
log_info "No primary endpoint configured for $integration_name" "enterprise"
fi
}
# Event sending functions
send_enterprise_event() {
local integration_name="$1"
local event_type="$2"
local event_data="$3"
if [[ -z "$integration_name" || -z "$event_type" ]]; then
log_error "Integration name and event type are required" "enterprise"
return 1
fi
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
# Get integration configuration
local integration_config
integration_config=$(jq -r ".integrations[\"$integration_name\"]" "$enterprise_db")
if [[ "$integration_config" == "null" ]]; then
log_error "Integration '$integration_name' not found" "enterprise"
return 1
fi
# Check if event type is enabled
local event_enabled
event_enabled=$(echo "$integration_config" | jq -r ".events.$event_type // .triggers.$event_type // false")
if [[ "$event_enabled" != "true" ]]; then
log_debug "Event type '$event_type' not enabled for integration '$integration_name'" "enterprise"
return 0
fi
# Get endpoint for event type
local endpoint
case "$event_type" in
"layer_created"|"layer_deleted"|"security_scan"|"compliance_scan")
endpoint=$(echo "$integration_config" | jq -r '.endpoints.events // .endpoints.alerts')
;;
"security_incident"|"compliance_violation"|"system_failure")
endpoint=$(echo "$integration_config" | jq -r '.endpoints.incidents // .endpoints.alerts')
;;
*)
endpoint=$(echo "$integration_config" | jq -r '.endpoints.events')
;;
esac
if [[ -z "$endpoint" || "$endpoint" == "null" ]]; then
log_error "No endpoint configured for event type '$event_type'" "enterprise"
return 1
fi
# Prepare event payload
local payload
payload=$(prepare_event_payload "$integration_name" "$event_type" "$event_data")
# Send event
send_event_to_integration "$integration_name" "$endpoint" "$payload"
}
prepare_event_payload() {
local integration_name="$1"
local event_type="$2"
local event_data="$3"
# Base event structure
local base_event
base_event=$(cat << 'EOF'
{
"source": "apt-layer",
"integration": "$integration_name",
"event_type": "$event_type",
"timestamp": "$(date -Iseconds)",
"version": "1.0"
}
EOF
)
# Merge with event data if provided
if [[ -n "$event_data" ]]; then
if jq empty <(echo "$event_data") 2>/dev/null; then
echo "$base_event" | jq --argjson data "$event_data" '. + $data'
else
echo "$base_event" | jq --arg data "$event_data" '. + {"message": $data}'
fi
else
echo "$base_event"
fi
}
send_event_to_integration() {
local integration_name="$1"
local endpoint="$2"
local payload="$3"
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
# Get integration configuration
local integration_config
integration_config=$(jq -r ".integrations[\"$integration_name\"]" "$enterprise_db")
# Get authentication details
local auth_type
auth_type=$(echo "$integration_config" | jq -r '.authentication.type')
# Prepare curl command
local curl_cmd="curl -s --connect-timeout $ENTERPRISE_INTEGRATION_TIMEOUT --max-time $ENTERPRISE_INTEGRATION_TIMEOUT"
# Add authentication
case "$auth_type" in
"api_key")
local api_key
api_key=$(echo "$integration_config" | jq -r '.authentication.header // "X-API-Key"')
local key_value
key_value=$(echo "$integration_config" | jq -r '.authentication.key')
curl_cmd="$curl_cmd -H \"$api_key: $key_value\""
;;
"basic_auth")
local username
username=$(echo "$integration_config" | jq -r '.authentication.username')
local password
password=$(echo "$integration_config" | jq -r '.authentication.password')
curl_cmd="$curl_cmd -u \"$username:$password\""
;;
"bearer_token")
local token
token=$(echo "$integration_config" | jq -r '.authentication.token')
curl_cmd="$curl_cmd -H \"Authorization: Bearer $token\""
;;
"oauth2")
local client_id
client_id=$(echo "$integration_config" | jq -r '.authentication.client_id')
local client_secret
client_secret=$(echo "$integration_config" | jq -r '.authentication.client_secret')
curl_cmd="$curl_cmd -H \"X-Client-ID: $client_id\" -H \"X-Client-Secret: $client_secret\""
;;
esac
# Add headers and send
curl_cmd="$curl_cmd -H \"Content-Type: application/json\" -X POST -d '$payload' \"$endpoint\""
# Send with retry logic
local retry_count=0
local max_retries
max_retries=$(echo "$integration_config" | jq -r '.retry_policy.max_retries // 3')
while [[ $retry_count -lt $max_retries ]]; do
local response
response=$(eval "$curl_cmd")
local exit_code=$?
if [[ $exit_code -eq 0 ]]; then
log_debug "Event sent successfully to $integration_name" "enterprise"
return 0
else
retry_count=$((retry_count + 1))
if [[ $retry_count -lt $max_retries ]]; then
local backoff
backoff=$(echo "$integration_config" | jq -r '.retry_policy.backoff_multiplier // 2')
local wait_time=$((retry_count * backoff))
log_warning "Event send failed, retrying in ${wait_time}s (attempt $retry_count/$max_retries)" "enterprise"
sleep "$wait_time"
fi
fi
done
log_error "Failed to send event to $integration_name after $max_retries attempts" "enterprise"
return 1
}
# Hook management functions
register_hook() {
local hook_name="$1"
local hook_script="$2"
local event_types="$3"
if [[ -z "$hook_name" || -z "$hook_script" ]]; then
log_error "Hook name and script are required" "enterprise"
return 1
fi
local enterprise_base="${WORKSPACE}/enterprise"
local hooks_dir="$enterprise_base/hooks"
local enterprise_db="$enterprise_base/integrations.json"
# Create hook file
local hook_file="$hooks_dir/$hook_name.sh"
cat > "$hook_file" << EOF
#!/bin/bash
# Enterprise Integration Hook: $hook_name
# Event Types: $event_types
$hook_script
EOF
chmod +x "$hook_file"
# Register hook in database
jq --arg name "$hook_name" --arg script "$hook_file" --arg events "$event_types" \
'.hooks[$name] = {"script": $script, "events": $events, "enabled": true}' "$enterprise_db" > "$enterprise_db.tmp" && mv "$enterprise_db.tmp" "$enterprise_db"
log_success "Hook '$hook_name' registered successfully" "enterprise"
}
unregister_hook() {
local hook_name="$1"
if [[ -z "$hook_name" ]]; then
log_error "Hook name is required" "enterprise"
return 1
fi
local enterprise_base="${WORKSPACE}/enterprise"
local hooks_dir="$enterprise_base/hooks"
local enterprise_db="$enterprise_base/integrations.json"
# Remove hook file
local hook_file="$hooks_dir/$hook_name.sh"
if [[ -f "$hook_file" ]]; then
rm -f "$hook_file"
fi
# Remove from database
jq --arg name "$hook_name" 'del(.hooks[$name])' "$enterprise_db" > "$enterprise_db.tmp" && mv "$enterprise_db.tmp" "$enterprise_db"
log_success "Hook '$hook_name' unregistered successfully" "enterprise"
}
list_hooks() {
local format="${1:-table}"
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
if [[ ! -f "$enterprise_db" ]]; then
log_error "Enterprise integration database not found" "enterprise"
return 1
fi
case "$format" in
"json")
jq -r '.hooks' "$enterprise_db"
;;
"csv")
echo "hook_name,script,events,enabled"
jq -r '.hooks | to_entries[] | [.key, .value.script, .value.events, .value.enabled] | @csv' "$enterprise_db"
;;
"table"|*)
echo "Registered Enterprise Hooks:"
echo "============================"
jq -r '.hooks | to_entries[] | "\(.key) - \(.value.events) (\(.value.enabled))"' "$enterprise_db"
;;
esac
}
# Hook execution
execute_hooks() {
local event_type="$1"
local event_data="$2"
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
# Get hooks for this event type
local hooks
hooks=$(jq -r ".hooks | to_entries[] | select(.value.events | contains(\"$event_type\")) | .key" "$enterprise_db")
if [[ -z "$hooks" ]]; then
log_debug "No hooks registered for event type: $event_type" "enterprise"
return 0
fi
while IFS= read -r hook_name; do
if [[ -n "$hook_name" ]]; then
execute_single_hook "$hook_name" "$event_type" "$event_data"
fi
done <<< "$hooks"
}
execute_single_hook() {
local hook_name="$1"
local event_type="$2"
local event_data="$3"
local enterprise_base="${WORKSPACE}/enterprise"
local enterprise_db="$enterprise_base/integrations.json"
# Get hook configuration
local hook_config
hook_config=$(jq -r ".hooks[\"$hook_name\"]" "$enterprise_db")
if [[ "$hook_config" == "null" ]]; then
log_error "Hook '$hook_name' not found" "enterprise"
return 1
fi
local enabled
enabled=$(echo "$hook_config" | jq -r '.enabled')
if [[ "$enabled" != "true" ]]; then
log_debug "Hook '$hook_name' is disabled" "enterprise"
return 0
fi
local script_path
script_path=$(echo "$hook_config" | jq -r '.script')
if [[ ! -f "$script_path" ]]; then
log_error "Hook script not found: $script_path" "enterprise"
return 1
fi
# Execute hook with environment variables
log_debug "Executing hook: $hook_name" "enterprise"
export APT_LAYER_EVENT_TYPE="$event_type"
export APT_LAYER_EVENT_DATA="$event_data"
export APT_LAYER_WORKSPACE="$WORKSPACE"
if bash "$script_path"; then
log_debug "Hook '$hook_name' executed successfully" "enterprise"
else
log_error "Hook '$hook_name' execution failed" "enterprise"
fi
}
# Enterprise integration command handler
handle_enterprise_integration_command() {
local command="$1"
shift
case "$command" in
"init")
init_enterprise_integration
;;
"enable")
local integration_name="$1"
local config_file="$2"
enable_integration "$integration_name" "$config_file"
;;
"disable")
local integration_name="$1"
disable_integration "$integration_name"
;;
"list")
local format="$1"
list_integrations "$format"
;;
"test")
local integration_name="$1"
test_integration_connectivity "$integration_name"
;;
"hook")
local hook_command="$1"
shift
case "$hook_command" in
"register")
local hook_name="$1"
local hook_script="$2"
local event_types="$3"
register_hook "$hook_name" "$hook_script" "$event_types"
;;
"unregister")
local hook_name="$1"
unregister_hook "$hook_name"
;;
"list")
local format="$1"
list_hooks "$format"
;;
*)
echo "Hook commands: register, unregister, list"
;;
esac
;;
"send")
local integration_name="$1"
local event_type="$2"
local event_data="$3"
send_enterprise_event "$integration_name" "$event_type" "$event_data"
;;
"help"|*)
echo "Enterprise Integration Commands:"
echo "==============================="
echo " init - Initialize enterprise integration system"
echo " enable <integration> [config_file] - Enable enterprise integration"
echo " disable <integration> - Disable enterprise integration"
echo " list [format] - List enabled integrations (json|csv|table)"
echo " test <integration> - Test integration connectivity"
echo " hook register <name> <script> <events> - Register custom hook"
echo " hook unregister <name> - Unregister hook"
echo " hook list [format] - List registered hooks"
echo " send <integration> <event> [data] - Send event to integration"
echo " help - Show this help"
echo ""
echo "Supported Integrations:"
echo " SIEM, TICKETING, MONITORING, CMDB, BACKUP, SECURITY, COMPLIANCE, DEVOPS, CLOUD, CUSTOM"
;;
esac
}

View file

@ -1,779 +0,0 @@
#!/bin/bash
# Advanced Monitoring & Alerting for apt-layer
# Provides real-time and scheduled monitoring, customizable alerting, and integration with enterprise monitoring platforms
# Monitoring & alerting configuration
MONITORING_ENABLED="${MONITORING_ENABLED:-true}"
ALERTING_ENABLED="${ALERTING_ENABLED:-true}"
MONITORING_INTERVAL="${MONITORING_INTERVAL:-300}"
ALERT_HISTORY_LIMIT="${ALERT_HISTORY_LIMIT:-1000}"
# Thresholds (configurable)
CPU_THRESHOLD="${CPU_THRESHOLD:-2.0}"
CPU_THRESHOLD_5="${CPU_THRESHOLD_5:-2.0}"
CPU_THRESHOLD_15="${CPU_THRESHOLD_15:-1.5}"
MEM_THRESHOLD="${MEM_THRESHOLD:-100000}"
SWAP_THRESHOLD="${SWAP_THRESHOLD:-50000}"
DISK_THRESHOLD="${DISK_THRESHOLD:-500000}"
INODE_THRESHOLD="${INODE_THRESHOLD:-1000}"
DISK_IOWAIT_THRESHOLD="${DISK_IOWAIT_THRESHOLD:-10.0}"
LAYER_COUNT_THRESHOLD="${LAYER_COUNT_THRESHOLD:-100}"
TENANT_COUNT_THRESHOLD="${TENANT_COUNT_THRESHOLD:-10}"
UPTIME_MAX_DAYS="${UPTIME_MAX_DAYS:-180}"
# Key processes to check (comma-separated)
MONITOR_PROCESSES="${MONITOR_PROCESSES:-composefs-alternative.sh,containerd,podman,docker}"
# Supported alert channels
SUPPORTED_ALERT_CHANNELS=(
"EMAIL" # Email notifications
"WEBHOOK" # Webhook notifications
"SIEM" # Security Information and Event Management
"PROMETHEUS" # Prometheus metrics
"GRAFANA" # Grafana alerting
"SLACK" # Slack notifications
"TEAMS" # Microsoft Teams
"CUSTOM" # Custom scripts/hooks
)
# Monitoring agent initialization
init_monitoring_agent() {
log_info "Initializing monitoring and alerting system..." "monitoring"
local monitoring_base="${WORKSPACE}/monitoring"
mkdir -p "$monitoring_base"
mkdir -p "$monitoring_base/alerts"
mkdir -p "$monitoring_base/history"
mkdir -p "$monitoring_base/policies"
mkdir -p "$monitoring_base/integrations"
# Initialize alert history
local alert_history="$monitoring_base/alert-history.json"
if [[ ! -f "$alert_history" ]]; then
echo '{"alerts":[]}' > "$alert_history"
fi
log_success "Monitoring and alerting system initialized" "monitoring"
}
# Monitoring functions
run_monitoring_checks() {
log_info "Running monitoring checks..." "monitoring"
check_system_health
check_layer_health
check_tenant_health
check_security_status
check_compliance_status
log_success "Monitoring checks completed" "monitoring"
}
check_system_health() {
# CPU Load (1, 5, 15 min)
local cpu_load1 cpu_load5 cpu_load15
read cpu_load1 cpu_load5 cpu_load15 _ < /proc/loadavg
# Memory
local mem_free swap_free
mem_free=$(awk '/MemFree/ {print $2}' /proc/meminfo)
swap_free=$(awk '/SwapFree/ {print $2}' /proc/meminfo)
# Disk
local disk_free
disk_free=$(df / | awk 'NR==2 {print $4}')
# Inodes
local inode_free
inode_free=$(df -i / | awk 'NR==2 {print $4}')
# Uptime
local uptime_sec uptime_days
uptime_sec=$(awk '{print $1}' /proc/uptime)
uptime_days=$(awk -v s="$uptime_sec" 'BEGIN {print int(s/86400)}')
# Disk I/O wait (stub, extend with iostat if available)
local disk_iowait="0.0"
if command -v iostat >/dev/null 2>&1; then
disk_iowait=$(iostat -c 1 2 | awk '/^ /{print $4}' | tail -1)
fi
# Process health
IFS=',' read -ra procs <<< "$MONITOR_PROCESSES"
for proc in "${procs[@]}"; do
if ! pgrep -x "$proc" >/dev/null 2>&1; then
trigger_alert "system" "Critical process not running: $proc" "critical"
fi
done
# Threshold checks
if (( $(echo "$cpu_load1 > $CPU_THRESHOLD" | bc -l) )); then
trigger_alert "system" "High 1-min CPU load: $cpu_load1" "critical"
fi
if (( $(echo "$cpu_load5 > $CPU_THRESHOLD_5" | bc -l) )); then
trigger_alert "system" "High 5-min CPU load: $cpu_load5" "warning"
fi
if (( $(echo "$cpu_load15 > $CPU_THRESHOLD_15" | bc -l) )); then
trigger_alert "system" "High 15-min CPU load: $cpu_load15" "info"
fi
if (( mem_free < MEM_THRESHOLD )); then
trigger_alert "system" "Low memory: $mem_free kB" "warning"
fi
if (( swap_free < SWAP_THRESHOLD )); then
trigger_alert "system" "Low swap: $swap_free kB" "warning"
fi
if (( disk_free < DISK_THRESHOLD )); then
trigger_alert "system" "Low disk space: $disk_free kB" "warning"
fi
if (( inode_free < INODE_THRESHOLD )); then
trigger_alert "system" "Low inode count: $inode_free" "warning"
fi
if (( $(echo "$disk_iowait > $DISK_IOWAIT_THRESHOLD" | bc -l) )); then
trigger_alert "system" "High disk I/O wait: $disk_iowait%" "warning"
fi
if (( uptime_days > UPTIME_MAX_DAYS )); then
trigger_alert "system" "System uptime exceeds $UPTIME_MAX_DAYS days: $uptime_days days" "info"
fi
# TODO: Add more enterprise checks (network, kernel, hardware, etc.)
}
check_layer_health() {
# Layer count
local layer_count
layer_count=$(find "${WORKSPACE}/layers" -maxdepth 1 -type d 2>/dev/null | wc -l)
if (( layer_count > LAYER_COUNT_THRESHOLD )); then
trigger_alert "layer" "Layer count exceeds $LAYER_COUNT_THRESHOLD: $layer_count" "info"
fi
# TODO: Add failed/unhealthy layer detection, stale layer checks
}
check_tenant_health() {
local tenant_dir="${WORKSPACE}/tenants"
if [[ -d "$tenant_dir" ]]; then
local tenant_count
tenant_count=$(find "$tenant_dir" -maxdepth 1 -type d 2>/dev/null | wc -l)
if (( tenant_count > TENANT_COUNT_THRESHOLD )); then
trigger_alert "tenant" "Tenant count exceeds $TENANT_COUNT_THRESHOLD: $tenant_count" "info"
fi
# TODO: Add quota usage, unhealthy tenant, cross-tenant contention checks
fi
}
check_security_status() {
# Security scan failures
local security_status_file="${WORKSPACE}/security/last-scan.json"
if [[ -f "$security_status_file" ]]; then
local failed
failed=$(jq -r '.failed // 0' "$security_status_file")
if (( failed > 0 )); then
trigger_alert "security" "Security scan failures: $failed" "critical"
fi
fi
# TODO: Add vulnerability count/severity, policy violation checks
}
check_compliance_status() {
# Compliance scan failures
local compliance_status_file="${WORKSPACE}/compliance/last-scan.json"
if [[ -f "$compliance_status_file" ]]; then
local failed
failed=$(jq -r '.summary.failed // 0' "$compliance_status_file")
if (( failed > 0 )); then
trigger_alert "compliance" "Compliance scan failures: $failed" "critical"
fi
fi
# TODO: Add control failure severity, audit log gap checks
}
# Alerting functions
trigger_alert() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp
timestamp=$(date -Iseconds)
log_warning "ALERT [$severity] from $source: $message" "monitoring"
# Record alert in history
record_alert_history "$source" "$message" "$severity" "$timestamp"
# Dispatch alert
dispatch_alert "$source" "$message" "$severity" "$timestamp"
}
record_alert_history() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp="$4"
local monitoring_base="${WORKSPACE}/monitoring"
local alert_history="$monitoring_base/alert-history.json"
# Add alert to history (limit to ALERT_HISTORY_LIMIT)
local new_alert
new_alert=$(jq -n --arg source "$source" --arg message "$message" --arg severity "$severity" --arg timestamp "$timestamp" '{source:$source,message:$message,severity:$severity,timestamp:$timestamp}')
local updated_history
updated_history=$(jq --argjson alert "$new_alert" '.alerts += [$alert] | .alerts |= (.[-'$ALERT_HISTORY_LIMIT':])' "$alert_history")
echo "$updated_history" > "$alert_history"
}
# Alert dispatch functions
dispatch_alert() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp="$4"
# Check if alert should be suppressed
if is_alert_suppressed "$source" "$message" "$severity"; then
log_debug "Alert suppressed: $source - $message" "monitoring"
return 0
fi
# Check for correlation and grouping
local correlation_key
correlation_key=$(generate_correlation_key "$source" "$message" "$severity")
if is_correlated_alert "$correlation_key"; then
log_debug "Correlated alert, updating existing: $correlation_key" "monitoring"
update_correlated_alert "$correlation_key" "$message" "$timestamp"
return 0
fi
# Dispatch to all configured channels
dispatch_to_email "$source" "$message" "$severity" "$timestamp"
dispatch_to_webhook "$source" "$message" "$severity" "$timestamp"
dispatch_to_siem "$source" "$message" "$severity" "$timestamp"
dispatch_to_prometheus "$source" "$message" "$severity" "$timestamp"
dispatch_to_custom "$source" "$message" "$severity" "$timestamp"
}
# Alert suppression
is_alert_suppressed() {
local source="$1"
local message="$2"
local severity="$3"
# Check suppression policies
local suppression_file="${WORKSPACE}/monitoring/policies/suppression.json"
if [[ -f "$suppression_file" ]]; then
# Check if this alert matches any suppression rules
local suppressed
suppressed=$(jq -r --arg source "$source" --arg severity "$severity" '.rules[] | select(.source == $source and .severity == $severity) | .suppressed' "$suppression_file" 2>/dev/null || echo "false")
if [[ "$suppressed" == "true" ]]; then
return 0 # Suppressed
fi
fi
return 1 # Not suppressed
}
# Event correlation
generate_correlation_key() {
local source="$1"
local message="$2"
local severity="$3"
# Generate a correlation key based on source and message pattern
echo "${source}:${severity}:$(echo "$message" | sed 's/[0-9]*//g' | tr '[:upper:]' '[:lower:]' | tr -d '[:punct:]' | tr -s ' ')"
}
is_correlated_alert() {
local correlation_key="$1"
local correlation_file="${WORKSPACE}/monitoring/correlation.json"
if [[ -f "$correlation_file" ]]; then
jq -e --arg key "$correlation_key" '.correlations[$key]' "$correlation_file" >/dev/null 2>&1
return $?
fi
return 1
}
update_correlated_alert() {
local correlation_key="$1"
local message="$2"
local timestamp="$3"
local correlation_file="${WORKSPACE}/monitoring/correlation.json"
# Update correlation data
local correlation_data
correlation_data=$(jq --arg key "$correlation_key" --arg message "$message" --arg timestamp "$timestamp" \
'.correlations[$key] += {"count": (.correlations[$key].count // 0) + 1, "last_seen": $timestamp, "last_message": $message}' \
"$correlation_file" 2>/dev/null || echo '{"correlations":{}}')
echo "$correlation_data" > "$correlation_file"
}
# Alert dispatch to different channels
dispatch_to_email() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp="$4"
# Check if email alerts are enabled
if [[ "${EMAIL_ALERTS_ENABLED:-false}" != "true" ]]; then
return 0
fi
local email_config="${WORKSPACE}/monitoring/config/email.json"
if [[ ! -f "$email_config" ]]; then
return 0
fi
local smtp_server
smtp_server=$(jq -r '.smtp_server' "$email_config")
local from_email
from_email=$(jq -r '.from_email' "$email_config")
local to_emails
to_emails=$(jq -r '.to_emails[]' "$email_config")
if [[ -z "$smtp_server" || -z "$from_email" ]]; then
return 0
fi
# Create email content
local subject="[ALERT] $severity - $source"
local body="Alert Details:
Source: $source
Severity: $severity
Message: $message
Timestamp: $timestamp
Hostname: $(hostname)"
# Send email (stub - implement with mail command or curl)
log_debug "Sending email alert to: $to_emails" "monitoring"
# echo "$body" | mail -s "$subject" -r "$from_email" "$to_emails"
}
dispatch_to_webhook() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp="$4"
# Check if webhook alerts are enabled
if [[ "${WEBHOOK_ALERTS_ENABLED:-false}" != "true" ]]; then
return 0
fi
local webhook_config="${WORKSPACE}/monitoring/config/webhook.json"
if [[ ! -f "$webhook_config" ]]; then
return 0
fi
local webhook_url
webhook_url=$(jq -r '.url' "$webhook_config")
local auth_token
auth_token=$(jq -r '.auth_token // empty' "$webhook_config")
if [[ -z "$webhook_url" ]]; then
return 0
fi
# Create webhook payload
local payload
payload=$(jq -n \
--arg source "$source" \
--arg message "$message" \
--arg severity "$severity" \
--arg timestamp "$timestamp" \
--arg hostname "$(hostname)" \
'{
"source": $source,
"message": $message,
"severity": $severity,
"timestamp": $timestamp,
"hostname": $hostname
}')
# Send webhook
local curl_cmd="curl -s --connect-timeout 10 --max-time 30 -X POST -H 'Content-Type: application/json'"
if [[ -n "$auth_token" ]]; then
curl_cmd="$curl_cmd -H 'Authorization: Bearer $auth_token'"
fi
curl_cmd="$curl_cmd -d '$payload' '$webhook_url'"
log_debug "Sending webhook alert to: $webhook_url" "monitoring"
eval "$curl_cmd" >/dev/null 2>&1
}
dispatch_to_siem() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp="$4"
# Use enterprise integration if available
if command -v send_enterprise_event >/dev/null 2>&1; then
local event_data
event_data=$(jq -n \
--arg source "$source" \
--arg message "$message" \
--arg severity "$severity" \
--arg timestamp "$timestamp" \
'{
"source": $source,
"message": $message,
"severity": $severity,
"timestamp": $timestamp
}')
send_enterprise_event "SIEM" "alert" "$event_data"
fi
}
dispatch_to_prometheus() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp="$4"
# Check if Prometheus metrics are enabled
if [[ "${PROMETHEUS_METRICS_ENABLED:-false}" != "true" ]]; then
return 0
fi
local prometheus_config="${WORKSPACE}/monitoring/config/prometheus.json"
if [[ ! -f "$prometheus_config" ]]; then
return 0
fi
local pushgateway_url
pushgateway_url=$(jq -r '.pushgateway_url' "$prometheus_config")
if [[ -z "$pushgateway_url" ]]; then
return 0
fi
# Create Prometheus metric
local metric_name="apt_layer_alert"
local metric_value="1"
local labels="source=\"$source\",severity=\"$severity\""
# Send to Pushgateway
local metric_data="$metric_name{$labels} $metric_value"
echo "$metric_data" | curl -s --data-binary @- "$pushgateway_url/metrics/job/apt_layer/instance/$(hostname)" >/dev/null 2>&1
log_debug "Sent Prometheus metric: $metric_data" "monitoring"
}
dispatch_to_custom() {
local source="$1"
local message="$2"
local severity="$3"
local timestamp="$4"
# Execute custom alert scripts
local custom_scripts_dir="${WORKSPACE}/monitoring/scripts"
if [[ -d "$custom_scripts_dir" ]]; then
for script in "$custom_scripts_dir"/*.sh; do
if [[ -f "$script" && -x "$script" ]]; then
export ALERT_SOURCE="$source"
export ALERT_MESSAGE="$message"
export ALERT_SEVERITY="$severity"
export ALERT_TIMESTAMP="$timestamp"
log_debug "Executing custom alert script: $script" "monitoring"
bash "$script" >/dev/null 2>&1
fi
done
fi
}
# Policy management
create_alert_policy() {
local policy_name="$1"
local policy_file="$2"
if [[ -z "$policy_name" || -z "$policy_file" ]]; then
log_error "Policy name and file are required" "monitoring"
return 1
fi
local policies_dir="${WORKSPACE}/monitoring/policies"
local policy_path="$policies_dir/$policy_name.json"
# Copy policy file
if [[ -f "$policy_file" ]]; then
cp "$policy_file" "$policy_path"
log_success "Alert policy '$policy_name' created" "monitoring"
else
log_error "Policy file not found: $policy_file" "monitoring"
return 1
fi
}
list_alert_policies() {
local format="${1:-table}"
local policies_dir="${WORKSPACE}/monitoring/policies"
if [[ ! -d "$policies_dir" ]]; then
log_error "Policies directory not found" "monitoring"
return 1
fi
case "$format" in
"json")
echo "{\"policies\":["
local first=true
for policy in "$policies_dir"/*.json; do
if [[ -f "$policy" ]]; then
if [[ "$first" == "true" ]]; then
first=false
else
echo ","
fi
jq -r '.' "$policy"
fi
done
echo "]}"
;;
"csv")
echo "policy_name,file_path,last_modified"
for policy in "$policies_dir"/*.json; do
if [[ -f "$policy" ]]; then
local policy_name
policy_name=$(basename "$policy" .json)
local last_modified
last_modified=$(stat -c %y "$policy" 2>/dev/null || echo "unknown")
echo "$policy_name,$policy,$last_modified"
fi
done
;;
"table"|*)
echo "Alert Policies:"
echo "==============="
for policy in "$policies_dir"/*.json; do
if [[ -f "$policy" ]]; then
local policy_name
policy_name=$(basename "$policy" .json)
echo "- $policy_name"
fi
done
;;
esac
}
# Alert history and reporting
query_alert_history() {
local source="$1"
local severity="$2"
local days="$3"
local format="${4:-table}"
local monitoring_base="${WORKSPACE}/monitoring"
local alert_history="$monitoring_base/alert-history.json"
if [[ ! -f "$alert_history" ]]; then
log_error "Alert history not found" "monitoring"
return 1
fi
# Build jq filter
local filter=".alerts"
if [[ -n "$source" ]]; then
filter="$filter | map(select(.source == \"$source\"))"
fi
if [[ -n "$severity" ]]; then
filter="$filter | map(select(.severity == \"$severity\"))"
fi
if [[ -n "$days" ]]; then
local cutoff_date
cutoff_date=$(date -d "$days days ago" -Iseconds)
filter="$filter | map(select(.timestamp >= \"$cutoff_date\"))"
fi
case "$format" in
"json")
jq -r "$filter" "$alert_history"
;;
"csv")
echo "source,severity,message,timestamp"
jq -r "$filter | .[] | [.source, .severity, .message, .timestamp] | @csv" "$alert_history"
;;
"table"|*)
echo "Alert History:"
echo "=============="
jq -r "$filter | .[] | \"[\(.severity)] \(.source): \(.message) (\(.timestamp))\"" "$alert_history"
;;
esac
}
generate_alert_report() {
local report_period="${1:-daily}"
local output_format="${2:-html}"
local monitoring_base="${WORKSPACE}/monitoring"
local alert_history="$monitoring_base/alert-history.json"
local report_file="$monitoring_base/reports/alert-report-$(date +%Y%m%d).$output_format"
if [[ ! -f "$alert_history" ]]; then
log_error "Alert history not found" "monitoring"
return 1
fi
# Calculate report period
local start_date
case "$report_period" in
"hourly")
start_date=$(date -d "1 hour ago" -Iseconds)
;;
"daily")
start_date=$(date -d "1 day ago" -Iseconds)
;;
"weekly")
start_date=$(date -d "1 week ago" -Iseconds)
;;
"monthly")
start_date=$(date -d "1 month ago" -Iseconds)
;;
*)
start_date=$(date -d "1 day ago" -Iseconds)
;;
esac
# Generate report
case "$output_format" in
"json")
jq --arg start_date "$start_date" \
'.alerts | map(select(.timestamp >= $start_date)) | group_by(.severity) | map({severity: .[0].severity, count: length, alerts: .})' \
"$alert_history" > "$report_file"
;;
"html")
generate_html_alert_report "$start_date" "$report_file"
;;
*)
log_error "Unsupported output format: $output_format" "monitoring"
return 1
;;
esac
log_success "Alert report generated: $report_file" "monitoring"
}
generate_html_alert_report() {
local start_date="$1"
local report_file="$2"
local monitoring_base="${WORKSPACE}/monitoring"
local alert_history="$monitoring_base/alert-history.json"
# Get alert data
local alert_data
alert_data=$(jq --arg start_date "$start_date" \
'.alerts | map(select(.timestamp >= $start_date)) | group_by(.severity) | map({severity: .[0].severity, count: length, alerts: .})' \
"$alert_history")
# Generate HTML
cat > "$report_file" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Alert Report - $(date)</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.summary { margin: 20px 0; }
.severity { margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 3px; }
.critical { background-color: #f8d7da; border-color: #f5c6cb; }
.warning { background-color: #fff3cd; border-color: #ffeaa7; }
.info { background-color: #d1ecf1; border-color: #bee5eb; }
</style>
</head>
<body>
<div class="header">
<h1>Alert Report</h1>
<p>Generated: $(date)</p>
<p>Period: Since $start_date</p>
</div>
<div class="summary">
<h2>Summary</h2>
<p>Total Alerts: $(echo "$alert_data" | jq -r 'map(.count) | add // 0')</p>
</div>
<div class="alerts">
<h2>Alerts by Severity</h2>
EOF
# Add alerts by severity
echo "$alert_data" | jq -r '.[] | "\(.severity): \(.count)"' | while IFS=':' read -r severity count; do
if [[ -n "$severity" ]]; then
cat >> "$report_file" << EOF
<div class="severity $severity">
<h3>$severity ($count)</h3>
EOF
# Add individual alerts
echo "$alert_data" | jq -r --arg sev "$severity" '.[] | select(.severity == $sev) | .alerts[] | "\(.source): \(.message) (\(.timestamp))"' | while IFS=':' read -r source message; do
if [[ -n "$source" ]]; then
cat >> "$report_file" << EOF
<p><strong>$source</strong>: $message</p>
EOF
fi
done
cat >> "$report_file" << EOF
</div>
EOF
fi
done
cat >> "$report_file" << EOF
</div>
</body>
</html>
EOF
}
# Monitoring command handler
handle_monitoring_command() {
local command="$1"
shift
case "$command" in
"init")
init_monitoring_agent
;;
"check")
run_monitoring_checks
;;
"policy")
local policy_command="$1"
shift
case "$policy_command" in
"create")
local policy_name="$1"
local policy_file="$2"
create_alert_policy "$policy_name" "$policy_file"
;;
"list")
local format="$1"
list_alert_policies "$format"
;;
*)
echo "Policy commands: create, list"
;;
esac
;;
"history")
local source="$1"
local severity="$2"
local days="$3"
local format="$4"
query_alert_history "$source" "$severity" "$days" "$format"
;;
"report")
local period="$1"
local format="$2"
generate_alert_report "$period" "$format"
;;
"help"|*)
echo "Monitoring & Alerting Commands:"
echo "=============================="
echo " init - Initialize monitoring system"
echo " check - Run monitoring checks"
echo " policy create <name> <file> - Create alert policy"
echo " policy list [format] - List alert policies"
echo " history [source] [severity] [days] [format] - Query alert history"
echo " report [period] [format] - Generate alert report"
echo " help - Show this help"
echo ""
echo "Supported Alert Channels:"
echo " EMAIL, WEBHOOK, SIEM, PROMETHEUS, GRAFANA, SLACK, TEAMS, CUSTOM"
;;
esac
}

View file

@ -1,877 +0,0 @@
#!/bin/bash
# Cloud Integration Scriptlet for apt-layer
# Provides cloud provider integrations (AWS, Azure, GCP) for cloud-native deployment
# Cloud integration functions
cloud_integration_init() {
log_info "Initializing cloud integration system..."
# Create cloud integration directories
mkdir -p "${PARTICLE_WORKSPACE}/cloud"
mkdir -p "${PARTICLE_WORKSPACE}/cloud/aws"
mkdir -p "${PARTICLE_WORKSPACE}/cloud/azure"
mkdir -p "${PARTICLE_WORKSPACE}/cloud/gcp"
mkdir -p "${PARTICLE_WORKSPACE}/cloud/configs"
mkdir -p "${PARTICLE_WORKSPACE}/cloud/credentials"
mkdir -p "${PARTICLE_WORKSPACE}/cloud/deployments"
# Initialize cloud configuration database
if [[ ! -f "${PARTICLE_WORKSPACE}/cloud/cloud-config.json" ]]; then
cat > "${PARTICLE_WORKSPACE}/cloud/cloud-config.json" << 'EOF'
{
"providers": {
"aws": {
"enabled": false,
"regions": [],
"services": {
"ecr": false,
"s3": false,
"ec2": false,
"eks": false
},
"credentials": {
"profile": "",
"access_key": "",
"secret_key": ""
}
},
"azure": {
"enabled": false,
"subscriptions": [],
"services": {
"acr": false,
"storage": false,
"vm": false,
"aks": false
},
"credentials": {
"tenant_id": "",
"client_id": "",
"client_secret": ""
}
},
"gcp": {
"enabled": false,
"projects": [],
"services": {
"gcr": false,
"storage": false,
"compute": false,
"gke": false
},
"credentials": {
"service_account": "",
"project_id": ""
}
}
},
"deployments": [],
"last_updated": ""
}
EOF
fi
log_success "Cloud integration system initialized"
}
# AWS Integration Functions
aws_init() {
log_info "Initializing AWS integration..."
# Check for AWS CLI
if ! command -v aws &> /dev/null; then
log_error "AWS CLI not found. Please install awscli package."
return 1
fi
# Check AWS credentials
if ! aws sts get-caller-identity &> /dev/null; then
log_warning "AWS credentials not configured. Please run 'aws configure' first."
return 1
fi
# Get AWS account info
local account_id=$(aws sts get-caller-identity --query Account --output text)
local user_arn=$(aws sts get-caller-identity --query Arn --output text)
log_info "AWS Account ID: ${account_id}"
log_info "AWS User ARN: ${user_arn}"
# Update cloud config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg account_id "$account_id" --arg user_arn "$user_arn" \
'.providers.aws.enabled = true | .providers.aws.account_id = $account_id | .providers.aws.user_arn = $user_arn' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "AWS integration initialized"
}
aws_configure_services() {
local services=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
log_info "Configuring AWS services: ${services[*]}"
for service in "${services[@]}"; do
case "$service" in
"ecr")
aws_configure_ecr
;;
"s3")
aws_configure_s3
;;
"ec2")
aws_configure_ec2
;;
"eks")
aws_configure_eks
;;
*)
log_warning "Unknown AWS service: $service"
;;
esac
done
}
aws_configure_ecr() {
log_info "Configuring AWS ECR..."
# Get default region
local region=$(aws configure get region)
if [[ -z "$region" ]]; then
region="us-east-1"
log_info "Using default region: $region"
fi
# Create ECR repository if it doesn't exist
local repo_name="ubuntu-ublue-layers"
if ! aws ecr describe-repositories --repository-names "$repo_name" --region "$region" &> /dev/null; then
log_info "Creating ECR repository: $repo_name"
aws ecr create-repository --repository-name "$repo_name" --region "$region"
fi
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg region "$region" --arg repo "$repo_name" \
'.providers.aws.services.ecr = true | .providers.aws.ecr.region = $region | .providers.aws.ecr.repository = $repo' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "AWS ECR configured"
}
aws_configure_s3() {
log_info "Configuring AWS S3..."
# Get default region
local region=$(aws configure get region)
if [[ -z "$region" ]]; then
region="us-east-1"
fi
# Create S3 bucket if it doesn't exist
local bucket_name="ubuntu-ublue-layers-$(date +%s)"
if ! aws s3api head-bucket --bucket "$bucket_name" --region "$region" &> /dev/null; then
log_info "Creating S3 bucket: $bucket_name"
aws s3api create-bucket --bucket "$bucket_name" --region "$region"
fi
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg region "$region" --arg bucket "$bucket_name" \
'.providers.aws.services.s3 = true | .providers.aws.s3.region = $region | .providers.aws.s3.bucket = $bucket' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "AWS S3 configured"
}
aws_configure_ec2() {
log_info "Configuring AWS EC2..."
# Get available regions
local regions=$(aws ec2 describe-regions --query 'Regions[].RegionName' --output text)
log_info "Available AWS regions: $regions"
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq '.providers.aws.services.ec2 = true' "$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "AWS EC2 configured"
}
aws_configure_eks() {
log_info "Configuring AWS EKS..."
# Check for kubectl
if ! command -v kubectl &> /dev/null; then
log_warning "kubectl not found. Please install kubectl for EKS integration."
return 1
fi
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq '.providers.aws.services.eks = true' "$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "AWS EKS configured"
}
# Azure Integration Functions
azure_init() {
log_info "Initializing Azure integration..."
# Check for Azure CLI
if ! command -v az &> /dev/null; then
log_error "Azure CLI not found. Please install azure-cli package."
return 1
fi
# Check Azure login
if ! az account show &> /dev/null; then
log_warning "Azure not logged in. Please run 'az login' first."
return 1
fi
# Get Azure account info
local subscription_id=$(az account show --query id --output tsv)
local tenant_id=$(az account show --query tenantId --output tsv)
local user_name=$(az account show --query user.name --output tsv)
log_info "Azure Subscription ID: $subscription_id"
log_info "Azure Tenant ID: $tenant_id"
log_info "Azure User: $user_name"
# Update cloud config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg sub_id "$subscription_id" --arg tenant_id "$tenant_id" --arg user "$user_name" \
'.providers.azure.enabled = true | .providers.azure.subscription_id = $sub_id | .providers.azure.tenant_id = $tenant_id | .providers.azure.user = $user' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "Azure integration initialized"
}
azure_configure_services() {
local services=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
log_info "Configuring Azure services: ${services[*]}"
for service in "${services[@]}"; do
case "$service" in
"acr")
azure_configure_acr
;;
"storage")
azure_configure_storage
;;
"vm")
azure_configure_vm
;;
"aks")
azure_configure_aks
;;
*)
log_warning "Unknown Azure service: $service"
;;
esac
done
}
azure_configure_acr() {
log_info "Configuring Azure Container Registry..."
# Get resource group
local resource_group="ubuntu-ublue-rg"
local location="eastus"
local acr_name="ubuntuublueacr$(date +%s)"
# Create resource group if it doesn't exist
if ! az group show --name "$resource_group" &> /dev/null; then
log_info "Creating resource group: $resource_group"
az group create --name "$resource_group" --location "$location"
fi
# Create ACR if it doesn't exist
if ! az acr show --name "$acr_name" --resource-group "$resource_group" &> /dev/null; then
log_info "Creating Azure Container Registry: $acr_name"
az acr create --resource-group "$resource_group" --name "$acr_name" --sku Basic
fi
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg rg "$resource_group" --arg location "$location" --arg acr "$acr_name" \
'.providers.azure.services.acr = true | .providers.azure.acr.resource_group = $rg | .providers.azure.acr.location = $location | .providers.azure.acr.name = $acr' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "Azure ACR configured"
}
azure_configure_storage() {
log_info "Configuring Azure Storage..."
local resource_group="ubuntu-ublue-rg"
local location="eastus"
local storage_account="ubuntuubluestorage$(date +%s)"
# Create storage account if it doesn't exist
if ! az storage account show --name "$storage_account" --resource-group "$resource_group" &> /dev/null; then
log_info "Creating storage account: $storage_account"
az storage account create --resource-group "$resource_group" --name "$storage_account" --location "$location" --sku Standard_LRS
fi
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg rg "$resource_group" --arg location "$location" --arg sa "$storage_account" \
'.providers.azure.services.storage = true | .providers.azure.storage.resource_group = $rg | .providers.azure.storage.location = $location | .providers.azure.storage.account = $sa' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "Azure Storage configured"
}
azure_configure_vm() {
log_info "Configuring Azure VM..."
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq '.providers.azure.services.vm = true' "$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "Azure VM configured"
}
azure_configure_aks() {
log_info "Configuring Azure AKS..."
# Check for kubectl
if ! command -v kubectl &> /dev/null; then
log_warning "kubectl not found. Please install kubectl for AKS integration."
return 1
fi
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq '.providers.azure.services.aks = true' "$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "Azure AKS configured"
}
# GCP Integration Functions
gcp_init() {
log_info "Initializing GCP integration..."
# Check for gcloud CLI
if ! command -v gcloud &> /dev/null; then
log_error "Google Cloud CLI not found. Please install google-cloud-cli package."
return 1
fi
# Check GCP authentication
if ! gcloud auth list --filter=status:ACTIVE --format="value(account)" | grep -q .; then
log_warning "GCP not authenticated. Please run 'gcloud auth login' first."
return 1
fi
# Get GCP project info
local project_id=$(gcloud config get-value project)
local account=$(gcloud auth list --filter=status:ACTIVE --format="value(account)" | head -1)
log_info "GCP Project ID: $project_id"
log_info "GCP Account: $account"
# Update cloud config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg project_id "$project_id" --arg account "$account" \
'.providers.gcp.enabled = true | .providers.gcp.project_id = $project_id | .providers.gcp.account = $account' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "GCP integration initialized"
}
gcp_configure_services() {
local services=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
log_info "Configuring GCP services: ${services[*]}"
for service in "${services[@]}"; do
case "$service" in
"gcr")
gcp_configure_gcr
;;
"storage")
gcp_configure_storage
;;
"compute")
gcp_configure_compute
;;
"gke")
gcp_configure_gke
;;
*)
log_warning "Unknown GCP service: $service"
;;
esac
done
}
gcp_configure_gcr() {
log_info "Configuring Google Container Registry..."
local project_id=$(gcloud config get-value project)
local region="us-central1"
# Enable Container Registry API
gcloud services enable containerregistry.googleapis.com --project="$project_id"
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg project_id "$project_id" --arg region "$region" \
'.providers.gcp.services.gcr = true | .providers.gcp.gcr.project_id = $project_id | .providers.gcp.gcr.region = $region' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "GCP Container Registry configured"
}
gcp_configure_storage() {
log_info "Configuring Google Cloud Storage..."
local project_id=$(gcloud config get-value project)
local bucket_name="ubuntu-ublue-layers-$(date +%s)"
local location="US"
# Create storage bucket if it doesn't exist
if ! gsutil ls -b "gs://$bucket_name" &> /dev/null; then
log_info "Creating storage bucket: $bucket_name"
gsutil mb -p "$project_id" -c STANDARD -l "$location" "gs://$bucket_name"
fi
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg project_id "$project_id" --arg bucket "$bucket_name" --arg location "$location" \
'.providers.gcp.services.storage = true | .providers.gcp.storage.project_id = $project_id | .providers.gcp.storage.bucket = $bucket | .providers.gcp.storage.location = $location' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "GCP Storage configured"
}
gcp_configure_compute() {
log_info "Configuring Google Compute Engine..."
local project_id=$(gcloud config get-value project)
# Enable Compute Engine API
gcloud services enable compute.googleapis.com --project="$project_id"
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg project_id "$project_id" \
'.providers.gcp.services.compute = true | .providers.gcp.compute.project_id = $project_id' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "GCP Compute Engine configured"
}
gcp_configure_gke() {
log_info "Configuring Google Kubernetes Engine..."
# Check for kubectl
if ! command -v kubectl &> /dev/null; then
log_warning "kubectl not found. Please install kubectl for GKE integration."
return 1
fi
local project_id=$(gcloud config get-value project)
# Enable GKE API
gcloud services enable container.googleapis.com --project="$project_id"
# Update config
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
jq --arg project_id "$project_id" \
'.providers.gcp.services.gke = true | .providers.gcp.gke.project_id = $project_id' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "GCP GKE configured"
}
# Cloud Deployment Functions
cloud_deploy_layer() {
local layer_name="$1"
local provider="$2"
local service="$3"
shift 3
local options=("$@")
log_info "Deploying layer $layer_name to $provider $service"
case "$provider" in
"aws")
case "$service" in
"ecr")
aws_deploy_to_ecr "$layer_name" "${options[@]}"
;;
"s3")
aws_deploy_to_s3 "$layer_name" "${options[@]}"
;;
*)
log_error "Unknown AWS service: $service"
return 1
;;
esac
;;
"azure")
case "$service" in
"acr")
azure_deploy_to_acr "$layer_name" "${options[@]}"
;;
"storage")
azure_deploy_to_storage "$layer_name" "${options[@]}"
;;
*)
log_error "Unknown Azure service: $service"
return 1
;;
esac
;;
"gcp")
case "$service" in
"gcr")
gcp_deploy_to_gcr "$layer_name" "${options[@]}"
;;
"storage")
gcp_deploy_to_storage "$layer_name" "${options[@]}"
;;
*)
log_error "Unknown GCP service: $service"
return 1
;;
esac
;;
*)
log_error "Unknown cloud provider: $provider"
return 1
;;
esac
}
aws_deploy_to_ecr() {
local layer_name="$1"
shift
local options=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local region=$(jq -r '.providers.aws.ecr.region' "$config_file")
local repo=$(jq -r '.providers.aws.ecr.repository' "$config_file")
local account_id=$(jq -r '.providers.aws.account_id' "$config_file")
log_info "Deploying $layer_name to AWS ECR"
# Get ECR login token
aws ecr get-login-password --region "$region" | docker login --username AWS --password-stdin "$account_id.dkr.ecr.$region.amazonaws.com"
# Tag and push image
local image_tag="$account_id.dkr.ecr.$region.amazonaws.com/$repo:$layer_name"
docker tag "$layer_name" "$image_tag"
docker push "$image_tag"
log_success "Layer $layer_name deployed to AWS ECR"
}
aws_deploy_to_s3() {
local layer_name="$1"
shift
local options=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local bucket=$(jq -r '.providers.aws.s3.bucket' "$config_file")
local region=$(jq -r '.providers.aws.s3.region' "$config_file")
log_info "Deploying $layer_name to AWS S3"
# Create layer archive
local archive_file="${PARTICLE_WORKSPACE}/cloud/deployments/${layer_name}.tar.gz"
tar -czf "$archive_file" -C "${PARTICLE_WORKSPACE}/layers" "$layer_name"
# Upload to S3
aws s3 cp "$archive_file" "s3://$bucket/layers/$layer_name.tar.gz" --region "$region"
log_success "Layer $layer_name deployed to AWS S3"
}
azure_deploy_to_acr() {
local layer_name="$1"
shift
local options=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local acr_name=$(jq -r '.providers.azure.acr.name' "$config_file")
local resource_group=$(jq -r '.providers.azure.acr.resource_group' "$config_file")
log_info "Deploying $layer_name to Azure ACR"
# Get ACR login server
local login_server=$(az acr show --name "$acr_name" --resource-group "$resource_group" --query loginServer --output tsv)
# Login to ACR
az acr login --name "$acr_name"
# Tag and push image
local image_tag="$login_server/$layer_name:latest"
docker tag "$layer_name" "$image_tag"
docker push "$image_tag"
log_success "Layer $layer_name deployed to Azure ACR"
}
azure_deploy_to_storage() {
local layer_name="$1"
shift
local options=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local storage_account=$(jq -r '.providers.azure.storage.account' "$config_file")
local resource_group=$(jq -r '.providers.azure.storage.resource_group' "$config_file")
log_info "Deploying $layer_name to Azure Storage"
# Create layer archive
local archive_file="${PARTICLE_WORKSPACE}/cloud/deployments/${layer_name}.tar.gz"
tar -czf "$archive_file" -C "${PARTICLE_WORKSPACE}/layers" "$layer_name"
# Upload to Azure Storage
az storage blob upload --account-name "$storage_account" --container-name layers --name "$layer_name.tar.gz" --file "$archive_file"
log_success "Layer $layer_name deployed to Azure Storage"
}
gcp_deploy_to_gcr() {
local layer_name="$1"
shift
local options=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local project_id=$(jq -r '.providers.gcp.gcr.project_id' "$config_file")
local region=$(jq -r '.providers.gcp.gcr.region' "$config_file")
log_info "Deploying $layer_name to Google Container Registry"
# Configure docker for GCR
gcloud auth configure-docker --project="$project_id"
# Tag and push image
local image_tag="gcr.io/$project_id/$layer_name:latest"
docker tag "$layer_name" "$image_tag"
docker push "$image_tag"
log_success "Layer $layer_name deployed to Google Container Registry"
}
gcp_deploy_to_storage() {
local layer_name="$1"
shift
local options=("$@")
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local bucket=$(jq -r '.providers.gcp.storage.bucket' "$config_file")
local project_id=$(jq -r '.providers.gcp.storage.project_id' "$config_file")
log_info "Deploying $layer_name to Google Cloud Storage"
# Create layer archive
local archive_file="${PARTICLE_WORKSPACE}/cloud/deployments/${layer_name}.tar.gz"
tar -czf "$archive_file" -C "${PARTICLE_WORKSPACE}/layers" "$layer_name"
# Upload to GCS
gsutil cp "$archive_file" "gs://$bucket/layers/$layer_name.tar.gz"
log_success "Layer $layer_name deployed to Google Cloud Storage"
}
# Cloud Status and Management Functions
cloud_status() {
local provider="$1"
if [[ -z "$provider" ]]; then
log_info "Cloud integration status:"
echo
cloud_status_aws
echo
cloud_status_azure
echo
cloud_status_gcp
return 0
fi
case "$provider" in
"aws")
cloud_status_aws
;;
"azure")
cloud_status_azure
;;
"gcp")
cloud_status_gcp
;;
*)
log_error "Unknown cloud provider: $provider"
return 1
;;
esac
}
cloud_status_aws() {
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local enabled=$(jq -r '.providers.aws.enabled' "$config_file")
echo "AWS Integration:"
if [[ "$enabled" == "true" ]]; then
echo " Status: ${GREEN}Enabled${NC}"
local account_id=$(jq -r '.providers.aws.account_id' "$config_file")
echo " Account ID: $account_id"
# Check services
local services=$(jq -r '.providers.aws.services | to_entries[] | select(.value == true) | .key' "$config_file")
if [[ -n "$services" ]]; then
echo " Enabled Services:"
echo "$services" | while read -r service; do
echo " - $service"
done
fi
else
echo " Status: ${RED}Disabled${NC}"
fi
}
cloud_status_azure() {
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local enabled=$(jq -r '.providers.azure.enabled' "$config_file")
echo "Azure Integration:"
if [[ "$enabled" == "true" ]]; then
echo " Status: ${GREEN}Enabled${NC}"
local subscription_id=$(jq -r '.providers.azure.subscription_id' "$config_file")
echo " Subscription ID: $subscription_id"
# Check services
local services=$(jq -r '.providers.azure.services | to_entries[] | select(.value == true) | .key' "$config_file")
if [[ -n "$services" ]]; then
echo " Enabled Services:"
echo "$services" | while read -r service; do
echo " - $service"
done
fi
else
echo " Status: ${RED}Disabled${NC}"
fi
}
cloud_status_gcp() {
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local enabled=$(jq -r '.providers.gcp.enabled' "$config_file")
echo "GCP Integration:"
if [[ "$enabled" == "true" ]]; then
echo " Status: ${GREEN}Enabled${NC}"
local project_id=$(jq -r '.providers.gcp.project_id' "$config_file")
echo " Project ID: $project_id"
# Check services
local services=$(jq -r '.providers.gcp.services | to_entries[] | select(.value == true) | .key' "$config_file")
if [[ -n "$services" ]]; then
echo " Enabled Services:"
echo "$services" | while read -r service; do
echo " - $service"
done
fi
else
echo " Status: ${RED}Disabled${NC}"
fi
}
cloud_list_deployments() {
local config_file="${PARTICLE_WORKSPACE}/cloud/cloud-config.json"
local deployments_file="${PARTICLE_WORKSPACE}/cloud/deployments/deployments.json"
if [[ ! -f "$deployments_file" ]]; then
log_info "No deployments found"
return 0
fi
log_info "Cloud deployments:"
jq -r '.deployments[] | "\(.layer_name) -> \(.provider)/\(.service) (\(.timestamp))"' "$deployments_file"
}
# Cloud cleanup functions
cloud_cleanup() {
local provider="$1"
local service="$2"
log_info "Cleaning up cloud resources"
case "$provider" in
"aws")
aws_cleanup "$service"
;;
"azure")
azure_cleanup "$service"
;;
"gcp")
gcp_cleanup "$service"
;;
*)
log_error "Unknown cloud provider: $provider"
return 1
;;
esac
}
aws_cleanup() {
local service="$1"
case "$service" in
"ecr")
log_info "Cleaning up AWS ECR resources"
# Implementation for ECR cleanup
;;
"s3")
log_info "Cleaning up AWS S3 resources"
# Implementation for S3 cleanup
;;
*)
log_warning "Unknown AWS service for cleanup: $service"
;;
esac
}
azure_cleanup() {
local service="$1"
case "$service" in
"acr")
log_info "Cleaning up Azure ACR resources"
# Implementation for ACR cleanup
;;
"storage")
log_info "Cleaning up Azure Storage resources"
# Implementation for Storage cleanup
;;
*)
log_warning "Unknown Azure service for cleanup: $service"
;;
esac
}
gcp_cleanup() {
local service="$1"
case "$service" in
"gcr")
log_info "Cleaning up GCP Container Registry resources"
# Implementation for GCR cleanup
;;
"storage")
log_info "Cleaning up GCP Storage resources"
# Implementation for Storage cleanup
;;
*)
log_warning "Unknown GCP service for cleanup: $service"
;;
esac
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,135 +0,0 @@
#!/bin/bash
# Multi-Cloud Deployment Scriptlet for apt-layer
# Provides unified multi-cloud deployment, migration, and management
# === Initialization ===
multicloud_init() {
log_info "Initializing multi-cloud deployment system..."
mkdir -p "${PARTICLE_WORKSPACE}/multicloud"
mkdir -p "${PARTICLE_WORKSPACE}/multicloud/profiles"
mkdir -p "${PARTICLE_WORKSPACE}/multicloud/deployments"
mkdir -p "${PARTICLE_WORKSPACE}/multicloud/migrations"
mkdir -p "${PARTICLE_WORKSPACE}/multicloud/logs"
# Create config if missing
if [[ ! -f "${PARTICLE_WORKSPACE}/multicloud/multicloud-config.json" ]]; then
cat > "${PARTICLE_WORKSPACE}/multicloud/multicloud-config.json" << 'EOF'
{
"profiles": {},
"deployments": {},
"migrations": {},
"policies": {},
"last_updated": ""
}
EOF
fi
log_success "Multi-cloud deployment system initialized"
}
# === Cloud Profile Management ===
multicloud_add_profile() {
local provider="$1"
local profile_name="$2"
local credentials_file="$3"
if [[ -z "$provider" || -z "$profile_name" || -z "$credentials_file" ]]; then
log_error "Provider, profile name, and credentials file required"
return 1
fi
log_info "Adding multi-cloud profile: $profile_name ($provider)"
local config_file="${PARTICLE_WORKSPACE}/multicloud/multicloud-config.json"
jq --arg provider "$provider" --arg name "$profile_name" --arg creds "$credentials_file" \
'.profiles[$name] = {"provider": $provider, "credentials": $creds, "created": now}' \
"$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
log_success "Profile $profile_name added"
}
multicloud_list_profiles() {
local config_file="${PARTICLE_WORKSPACE}/multicloud/multicloud-config.json"
jq '.profiles' "$config_file"
}
# === Unified Multi-Cloud Deployment ===
multicloud_deploy() {
local layer_name="$1"
local provider="$2"
local profile_name="$3"
local region="$4"
local options="$5"
if [[ -z "$layer_name" || -z "$provider" ]]; then
log_error "Layer name and provider required for multi-cloud deployment"
return 1
fi
log_info "Deploying $layer_name to $provider (profile: $profile_name, region: $region)"
case "$provider" in
aws)
multicloud_deploy_aws "$layer_name" "$profile_name" "$region" "$options"
;;
azure)
multicloud_deploy_azure "$layer_name" "$profile_name" "$region" "$options"
;;
gcp)
multicloud_deploy_gcp "$layer_name" "$profile_name" "$region" "$options"
;;
*)
log_error "Unsupported provider: $provider"
return 1
;;
esac
}
multicloud_deploy_aws() {
local layer_name="$1"; local profile="$2"; local region="$3"; local options="$4"
log_info "[AWS] Deploying $layer_name (profile: $profile, region: $region)"
# TODO: Implement AWS deployment logic
log_success "[AWS] Deployment stub complete"
}
multicloud_deploy_azure() {
local layer_name="$1"; local profile="$2"; local region="$3"; local options="$4"
log_info "[Azure] Deploying $layer_name (profile: $profile, region: $region)"
# TODO: Implement Azure deployment logic
log_success "[Azure] Deployment stub complete"
}
multicloud_deploy_gcp() {
local layer_name="$1"; local profile="$2"; local region="$3"; local options="$4"
log_info "[GCP] Deploying $layer_name (profile: $profile, region: $region)"
# TODO: Implement GCP deployment logic
log_success "[GCP] Deployment stub complete"
}
# === Cross-Cloud Migration ===
multicloud_migrate() {
local layer_name="$1"
local from_provider="$2"
local to_provider="$3"
local options="$4"
if [[ -z "$layer_name" || -z "$from_provider" || -z "$to_provider" ]]; then
log_error "Layer, from_provider, and to_provider required for migration"
return 1
fi
log_info "Migrating $layer_name from $from_provider to $to_provider"
# TODO: Implement migration logic (export, transfer, import)
log_success "Migration stub complete"
}
# === Multi-Cloud Status and Reporting ===
multicloud_status() {
local config_file="${PARTICLE_WORKSPACE}/multicloud/multicloud-config.json"
echo "Multi-Cloud Profiles:"
jq -r '.profiles | to_entries[] | " - \(.key): \(.value.provider)"' "$config_file"
echo
echo "Deployments:"
jq -r '.deployments | to_entries[] | " - \(.key): \(.value.provider) (status: \(.value.status))"' "$config_file"
echo
echo "Migrations:"
jq -r '.migrations | to_entries[] | " - \(.key): \(.value.from) -> \(.value.to) (status: \(.value.status))"' "$config_file"
}
# === Policy-Driven Placement (Stub) ===
multicloud_policy_apply() {
local policy_name="$1"
local layer_name="$2"
log_info "Applying policy $policy_name to $layer_name"
# TODO: Implement policy-driven placement logic
log_success "Policy application stub complete"
}

View file

@ -1,722 +0,0 @@
#!/bin/bash
# Cloud-Native Security Features for apt-layer
# Provides cloud workload security scanning, cloud provider security service integration,
# policy enforcement, and automated vulnerability detection for cloud deployments.
# ============================================================================
# CLOUD-NATIVE SECURITY FUNCTIONS
# ============================================================================
# Initialize cloud security system
cloud_security_init() {
log_info "Initializing cloud security system..." "apt-layer"
# Create cloud security directories
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
mkdir -p "$cloud_security_dir"/{scans,policies,reports,integrations}
# Create cloud security configuration
local config_file="$cloud_security_dir/cloud-security-config.json"
if [[ ! -f "$config_file" ]]; then
cat > "$config_file" << 'EOF'
{
"enabled_providers": ["aws", "azure", "gcp"],
"scan_settings": {
"container_scanning": true,
"image_scanning": true,
"layer_scanning": true,
"infrastructure_scanning": true,
"compliance_scanning": true
},
"policy_enforcement": {
"iam_policies": true,
"network_policies": true,
"compliance_policies": true,
"auto_remediation": false
},
"integrations": {
"aws_inspector": false,
"azure_defender": false,
"gcp_security_center": false,
"third_party_scanners": []
},
"reporting": {
"html_reports": true,
"json_reports": true,
"email_alerts": false,
"webhook_alerts": false
},
"retention": {
"scan_reports_days": 30,
"policy_violations_days": 90,
"security_events_days": 365
}
}
EOF
log_info "Created cloud security configuration: $config_file" "apt-layer"
fi
# Create policy templates
local policies_dir="$cloud_security_dir/policies"
mkdir -p "$policies_dir"
# IAM Policy Template
cat > "$policies_dir/iam-policy-template.json" << 'EOF'
{
"name": "default-iam-policy",
"description": "Default IAM policy for apt-layer deployments",
"rules": [
{
"name": "least-privilege",
"description": "Enforce least privilege access",
"severity": "high",
"enabled": true
},
{
"name": "no-root-access",
"description": "Prevent root access to resources",
"severity": "critical",
"enabled": true
},
{
"name": "mfa-required",
"description": "Require multi-factor authentication",
"severity": "high",
"enabled": true
}
]
}
EOF
# Network Policy Template
cat > "$policies_dir/network-policy-template.json" << 'EOF'
{
"name": "default-network-policy",
"description": "Default network policy for apt-layer deployments",
"rules": [
{
"name": "secure-ports-only",
"description": "Allow only secure ports (22, 80, 443, 8080)",
"severity": "medium",
"enabled": true
},
{
"name": "no-public-access",
"description": "Prevent public access to sensitive resources",
"severity": "high",
"enabled": true
},
{
"name": "vpc-isolation",
"description": "Enforce VPC isolation",
"severity": "medium",
"enabled": true
}
]
}
EOF
# Compliance Policy Template
cat > "$policies_dir/compliance-policy-template.json" << 'EOF'
{
"name": "default-compliance-policy",
"description": "Default compliance policy for apt-layer deployments",
"frameworks": {
"sox": {
"enabled": true,
"controls": ["access-control", "audit-logging", "data-protection"]
},
"pci-dss": {
"enabled": true,
"controls": ["network-security", "access-control", "vulnerability-management"]
},
"hipaa": {
"enabled": false,
"controls": ["privacy", "security", "breach-notification"]
}
}
}
EOF
log_info "Cloud security system initialized successfully" "apt-layer"
log_info "Configuration: $config_file" "apt-layer"
log_info "Policies: $policies_dir" "apt-layer"
}
# Scan cloud workload for security vulnerabilities
cloud_security_scan_workload() {
local layer_name="$1"
local provider="$2"
local scan_type="${3:-comprehensive}"
log_info "Starting cloud security scan for layer: $layer_name (Provider: $provider, Type: $scan_type)" "apt-layer"
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
local scan_dir="$cloud_security_dir/scans"
local timestamp=$(date +%Y%m%d_%H%M%S)
local scan_id="${layer_name//\//_}_${provider}_${timestamp}"
local scan_file="$scan_dir/${scan_id}.json"
# Create scan result structure
local scan_result=$(cat << 'EOF'
{
"scan_id": "$scan_id",
"layer_name": "$layer_name",
"provider": "$provider",
"scan_type": "$scan_type",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"status": "running",
"findings": [],
"summary": {
"total_findings": 0,
"critical": 0,
"high": 0,
"medium": 0,
"low": 0,
"info": 0
}
}
EOF
)
echo "$scan_result" > "$scan_file"
case "$scan_type" in
"container")
cloud_security_scan_container "$layer_name" "$provider" "$scan_file"
;;
"image")
cloud_security_scan_image "$layer_name" "$provider" "$scan_file"
;;
"infrastructure")
cloud_security_scan_infrastructure "$layer_name" "$provider" "$scan_file"
;;
"compliance")
cloud_security_scan_compliance "$layer_name" "$provider" "$scan_file"
;;
"comprehensive")
cloud_security_scan_container "$layer_name" "$provider" "$scan_file"
cloud_security_scan_image "$layer_name" "$provider" "$scan_file"
cloud_security_scan_infrastructure "$layer_name" "$provider" "$scan_file"
cloud_security_scan_compliance "$layer_name" "$provider" "$scan_file"
;;
*)
log_error "Invalid scan type: $scan_type" "apt-layer"
return 1
;;
esac
# Update scan status to completed
jq '.status = "completed"' "$scan_file" > "${scan_file}.tmp" && mv "${scan_file}.tmp" "$scan_file"
# Generate summary
local total_findings=$(jq '.findings | length' "$scan_file")
local critical=$(jq '.findings | map(select(.severity == "critical")) | length' "$scan_file")
local high=$(jq '.findings | map(select(.severity == "high")) | length' "$scan_file")
local medium=$(jq '.findings | map(select(.severity == "medium")) | length' "$scan_file")
local low=$(jq '.findings | map(select(.severity == "low")) | length' "$scan_file")
local info=$(jq '.findings | map(select(.severity == "info")) | length' "$scan_file")
jq --arg total "$total_findings" \
--arg critical "$critical" \
--arg high "$high" \
--arg medium "$medium" \
--arg low "$low" \
--arg info "$info" \
'.summary.total_findings = ($total | tonumber) |
.summary.critical = ($critical | tonumber) |
.summary.high = ($high | tonumber) |
.summary.medium = ($medium | tonumber) |
.summary.low = ($low | tonumber) |
.summary.info = ($info | tonumber)' "$scan_file" > "${scan_file}.tmp" && mv "${scan_file}.tmp" "$scan_file"
log_info "Cloud security scan completed: $scan_file" "apt-layer"
log_info "Findings: $total_findings total ($critical critical, $high high, $medium medium, $low low, $info info)" "apt-layer"
# Generate HTML report
cloud_security_generate_report "$scan_file" "html"
echo "$scan_file"
}
# Scan container security
cloud_security_scan_container() {
local layer_name="$1"
local provider="$2"
local scan_file="$3"
log_info "Scanning container security for layer: $layer_name" "apt-layer"
# Simulate container security findings
local findings=(
'{"id": "CONTAINER-001", "title": "Container running as root", "description": "Container is configured to run as root user", "severity": "high", "category": "privilege-escalation", "remediation": "Use non-root user in container"}'
'{"id": "CONTAINER-002", "title": "Missing security context", "description": "Container lacks proper security context configuration", "severity": "medium", "category": "configuration", "remediation": "Configure security context with appropriate settings"}'
'{"id": "CONTAINER-003", "title": "Unnecessary capabilities", "description": "Container has unnecessary Linux capabilities enabled", "severity": "medium", "category": "privilege-escalation", "remediation": "Drop unnecessary capabilities"}'
)
for finding in "${findings[@]}"; do
jq --argjson finding "$finding" '.findings += [$finding]' "$scan_file" > "${scan_file}.tmp" && mv "${scan_file}.tmp" "$scan_file"
done
}
# Scan image security
cloud_security_scan_image() {
local layer_name="$1"
local provider="$2"
local scan_file="$3"
log_info "Scanning image security for layer: $layer_name" "apt-layer"
# Simulate image security findings
local findings=(
'{"id": "IMAGE-001", "title": "Vulnerable base image", "description": "Base image contains known vulnerabilities", "severity": "critical", "category": "vulnerability", "remediation": "Update to latest base image version"}'
'{"id": "IMAGE-002", "title": "Sensitive data in image", "description": "Image contains sensitive data or secrets", "severity": "high", "category": "data-exposure", "remediation": "Remove sensitive data and use secrets management"}'
'{"id": "IMAGE-003", "title": "Large image size", "description": "Image size exceeds recommended limits", "severity": "low", "category": "performance", "remediation": "Optimize image layers and remove unnecessary files"}'
)
for finding in "${findings[@]}"; do
jq --argjson finding "$finding" '.findings += [$finding]' "$scan_file" > "${scan_file}.tmp" && mv "${scan_file}.tmp" "$scan_file"
done
}
# Scan infrastructure security
cloud_security_scan_infrastructure() {
local layer_name="$1"
local provider="$2"
local scan_file="$3"
log_info "Scanning infrastructure security for layer: $layer_name" "apt-layer"
# Simulate infrastructure security findings
local findings=(
'{"id": "INFRA-001", "title": "Public access enabled", "description": "Resource is publicly accessible", "severity": "high", "category": "network-security", "remediation": "Restrict access to private networks only"}'
'{"id": "INFRA-002", "title": "Weak IAM policies", "description": "IAM policies are too permissive", "severity": "high", "category": "access-control", "remediation": "Apply principle of least privilege"}'
'{"id": "INFRA-003", "title": "Missing encryption", "description": "Data is not encrypted at rest", "severity": "medium", "category": "data-protection", "remediation": "Enable encryption for all data storage"}'
)
for finding in "${findings[@]}"; do
jq --argjson finding "$finding" '.findings += [$finding]' "$scan_file" > "${scan_file}.tmp" && mv "${scan_file}.tmp" "$scan_file"
done
}
# Scan compliance
cloud_security_scan_compliance() {
local layer_name="$1"
local provider="$2"
local scan_file="$3"
log_info "Scanning compliance for layer: $layer_name" "apt-layer"
# Simulate compliance findings
local findings=(
'{"id": "COMPLIANCE-001", "title": "SOX Control Failure", "description": "Access control logging not properly configured", "severity": "high", "category": "sox", "remediation": "Enable comprehensive access logging"}'
'{"id": "COMPLIANCE-002", "title": "PCI-DSS Violation", "description": "Cardholder data not properly encrypted", "severity": "critical", "category": "pci-dss", "remediation": "Implement encryption for all cardholder data"}'
'{"id": "COMPLIANCE-003", "title": "GDPR Compliance Issue", "description": "Data retention policy not defined", "severity": "medium", "category": "gdpr", "remediation": "Define and implement data retention policies"}'
)
for finding in "${findings[@]}"; do
jq --argjson finding "$finding" '.findings += [$finding]' "$scan_file" > "${scan_file}.tmp" && mv "${scan_file}.tmp" "$scan_file"
done
}
# Check policy compliance
cloud_security_check_policy() {
local layer_name="$1"
local policy_name="$2"
local provider="$3"
log_info "Checking policy compliance for layer: $layer_name (Policy: $policy_name, Provider: $provider)" "apt-layer"
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
local policies_dir="$cloud_security_dir/policies"
local policy_file="$policies_dir/${policy_name}.json"
if [[ ! -f "$policy_file" ]]; then
log_error "Policy file not found: $policy_file" "apt-layer"
return 1
fi
local timestamp=$(date +%Y%m%d_%H%M%S)
local check_id="${layer_name//\//_}_${policy_name}_${timestamp}"
local check_file="$cloud_security_dir/reports/${check_id}.json"
# Create policy check result
local check_result=$(cat << 'EOF'
{
"check_id": "$check_id",
"layer_name": "$layer_name",
"policy_name": "$policy_name",
"provider": "$provider",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"status": "completed",
"compliance": true,
"violations": [],
"summary": {
"total_rules": 0,
"passed": 0,
"failed": 0,
"warnings": 0
}
}
EOF
)
echo "$check_result" > "$check_file"
# Simulate policy violations
local violations=(
'{"rule": "least-privilege", "description": "IAM policy too permissive", "severity": "high", "remediation": "Restrict IAM permissions"}'
'{"rule": "network-isolation", "description": "Public access not restricted", "severity": "medium", "remediation": "Configure private network access"}'
)
local total_rules=5
local passed=3
local failed=2
local warnings=0
for violation in "${violations[@]}"; do
jq --argjson violation "$violation" '.violations += [$violation]' "$check_file" > "${check_file}.tmp" && mv "${check_file}.tmp" "$check_file"
done
# Update compliance status
if [[ $failed -gt 0 ]]; then
jq '.compliance = false' "$check_file" > "${check_file}.tmp" && mv "${check_file}.tmp" "$check_file"
fi
# Update summary
jq --arg total "$total_rules" \
--arg passed "$passed" \
--arg failed "$failed" \
--arg warnings "$warnings" \
'.summary.total_rules = ($total | tonumber) |
.summary.passed = ($passed | tonumber) |
.summary.failed = ($failed | tonumber) |
.summary.warnings = ($warnings | tonumber)' "$check_file" > "${check_file}.tmp" && mv "${check_file}.tmp" "$check_file"
log_info "Policy compliance check completed: $check_file" "apt-layer"
log_info "Compliance: $([[ $failed -eq 0 ]] && echo "PASSED" || echo "FAILED") ($passed/$total_rules rules passed)" "apt-layer"
# Generate HTML report
cloud_security_generate_policy_report "$check_file" "html"
echo "$check_file"
}
# Generate security report
cloud_security_generate_report() {
local scan_file="$1"
local format="${2:-html}"
if [[ ! -f "$scan_file" ]]; then
log_error "Scan file not found: $scan_file" "apt-layer"
return 1
fi
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
local reports_dir="$cloud_security_dir/reports"
local scan_data=$(cat "$scan_file")
case "$format" in
"html")
local report_file="${scan_file%.json}.html"
cloud_security_generate_html_report "$scan_data" "$report_file"
log_info "HTML report generated: $report_file" "apt-layer"
;;
"json")
# JSON report is already the scan file
log_info "JSON report available: $scan_file" "apt-layer"
;;
*)
log_error "Unsupported report format: $format" "apt-layer"
return 1
;;
esac
}
# Generate HTML security report
cloud_security_generate_html_report() {
local scan_data="$1"
local report_file="$2"
local layer_name=$(echo "$scan_data" | jq -r '.layer_name')
local provider=$(echo "$scan_data" | jq -r '.provider')
local timestamp=$(echo "$scan_data" | jq -r '.timestamp')
local total_findings=$(echo "$scan_data" | jq -r '.summary.total_findings')
local critical=$(echo "$scan_data" | jq -r '.summary.critical')
local high=$(echo "$scan_data" | jq -r '.summary.high')
local medium=$(echo "$scan_data" | jq -r '.summary.medium')
local low=$(echo "$scan_data" | jq -r '.summary.low')
cat > "$report_file" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Cloud Security Scan Report - $layer_name</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.summary { margin: 20px 0; }
.finding { margin: 10px 0; padding: 10px; border-left: 4px solid #ccc; }
.critical { border-left-color: #ff0000; background-color: #ffe6e6; }
.high { border-left-color: #ff6600; background-color: #fff2e6; }
.medium { border-left-color: #ffcc00; background-color: #fffbf0; }
.low { border-left-color: #00cc00; background-color: #f0fff0; }
.info { border-left-color: #0066cc; background-color: #f0f8ff; }
</style>
</head>
<body>
<div class="header">
<h1>Cloud Security Scan Report</h1>
<p><strong>Layer:</strong> $layer_name</p>
<p><strong>Provider:</strong> $provider</p>
<p><strong>Scan Time:</strong> $timestamp</p>
</div>
<div class="summary">
<h2>Summary</h2>
<p><strong>Total Findings:</strong> $total_findings</p>
<p><strong>Critical:</strong> $critical | <strong>High:</strong> $high | <strong>Medium:</strong> $medium | <strong>Low:</strong> $low</p>
</div>
<div class="findings">
<h2>Findings</h2>
EOF
# Add findings
echo "$scan_data" | jq -r '.findings[] | " <div class=\"finding \(.severity)\">" +
"<h3>\(.title)</h3>" +
"<p><strong>ID:</strong> \(.id)</p>" +
"<p><strong>Severity:</strong> \(.severity)</p>" +
"<p><strong>Category:</strong> \(.category)</p>" +
"<p><strong>Description:</strong> \(.description)</p>" +
"<p><strong>Remediation:</strong> \(.remediation)</p>" +
"</div>"' >> "$report_file"
cat >> "$report_file" << EOF
</div>
</body>
</html>
EOF
}
# Generate policy compliance report
cloud_security_generate_policy_report() {
local check_file="$1"
local format="${2:-html}"
if [[ ! -f "$check_file" ]]; then
log_error "Policy check file not found: $check_file" "apt-layer"
return 1
fi
case "$format" in
"html")
local report_file="${check_file%.json}.html"
local check_data=$(cat "$check_file")
cloud_security_generate_policy_html_report "$check_data" "$report_file"
log_info "Policy HTML report generated: $report_file" "apt-layer"
;;
"json")
log_info "Policy JSON report available: $check_file" "apt-layer"
;;
*)
log_error "Unsupported report format: $format" "apt-layer"
return 1
;;
esac
}
# Generate HTML policy report
cloud_security_generate_policy_html_report() {
local check_data="$1"
local report_file="$2"
local layer_name=$(echo "$check_data" | jq -r '.layer_name')
local policy_name=$(echo "$check_data" | jq -r '.policy_name')
local provider=$(echo "$check_data" | jq -r '.provider')
local timestamp=$(echo "$check_data" | jq -r '.timestamp')
local compliance=$(echo "$check_data" | jq -r '.compliance')
local total_rules=$(echo "$check_data" | jq -r '.summary.total_rules')
local passed=$(echo "$check_data" | jq -r '.summary.passed')
local failed=$(echo "$check_data" | jq -r '.summary.failed')
cat > "$report_file" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Policy Compliance Report - $layer_name</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.summary { margin: 20px 0; }
.violation { margin: 10px 0; padding: 10px; border-left: 4px solid #ff0000; background-color: #ffe6e6; }
.compliant { color: green; }
.non-compliant { color: red; }
</style>
</head>
<body>
<div class="header">
<h1>Policy Compliance Report</h1>
<p><strong>Layer:</strong> $layer_name</p>
<p><strong>Policy:</strong> $policy_name</p>
<p><strong>Provider:</strong> $provider</p>
<p><strong>Check Time:</strong> $timestamp</p>
</div>
<div class="summary">
<h2>Compliance Summary</h2>
<p><strong>Status:</strong> <span class="$(if [[ "$compliance" == "true" ]]; then echo "compliant"; else echo "non-compliant"; fi)">$(if [[ "$compliance" == "true" ]]; then echo "COMPLIANT"; else echo "NON-COMPLIANT"; fi)</span></p>
<p><strong>Rules:</strong> $passed/$total_rules passed ($failed failed)</p>
</div>
<div class="violations">
<h2>Policy Violations</h2>
EOF
# Add violations
echo "$check_data" | jq -r '.violations[] | " <div class=\"violation\">" +
"<h3>\(.rule)</h3>" +
"<p><strong>Severity:</strong> \(.severity)</p>" +
"<p><strong>Description:</strong> \(.description)</p>" +
"<p><strong>Remediation:</strong> \(.remediation)</p>" +
"</div>"' >> "$report_file"
cat >> "$report_file" << EOF
</div>
</body>
</html>
EOF
}
# List security scans
cloud_security_list_scans() {
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
local scans_dir="$cloud_security_dir/scans"
if [[ ! -d "$scans_dir" ]]; then
log_info "No security scans found" "apt-layer"
return 0
fi
log_info "Security scans:" "apt-layer"
for scan_file in "$scans_dir"/*.json; do
if [[ -f "$scan_file" ]]; then
local scan_data=$(cat "$scan_file")
local scan_id=$(echo "$scan_data" | jq -r '.scan_id')
local layer_name=$(echo "$scan_data" | jq -r '.layer_name')
local provider=$(echo "$scan_data" | jq -r '.provider')
local timestamp=$(echo "$scan_data" | jq -r '.timestamp')
local total_findings=$(echo "$scan_data" | jq -r '.summary.total_findings')
local critical=$(echo "$scan_data" | jq -r '.summary.critical')
echo " $scan_id: $layer_name ($provider) - $total_findings findings ($critical critical) - $timestamp"
fi
done
}
# List policy checks
cloud_security_list_policy_checks() {
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
local reports_dir="$cloud_security_dir/reports"
if [[ ! -d "$reports_dir" ]]; then
log_info "No policy checks found" "apt-layer"
return 0
fi
log_info "Policy compliance checks:" "apt-layer"
for check_file in "$reports_dir"/*.json; do
if [[ -f "$check_file" ]]; then
local check_data=$(cat "$check_file")
local check_id=$(echo "$check_data" | jq -r '.check_id')
local layer_name=$(echo "$check_data" | jq -r '.layer_name')
local policy_name=$(echo "$check_data" | jq -r '.policy_name')
local compliance=$(echo "$check_data" | jq -r '.compliance')
local timestamp=$(echo "$check_data" | jq -r '.timestamp')
echo " $check_id: $layer_name ($policy_name) - $(if [[ "$compliance" == "true" ]]; then echo "COMPLIANT"; else echo "NON-COMPLIANT"; fi) - $timestamp"
fi
done
}
# Clean up old security reports
cloud_security_cleanup() {
local days="${1:-30}"
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
local scans_dir="$cloud_security_dir/scans"
local reports_dir="$cloud_security_dir/reports"
log_info "Cleaning up security reports older than $days days..." "apt-layer"
local deleted_scans=0
local deleted_reports=0
# Clean up scan files
if [[ -d "$scans_dir" ]]; then
while IFS= read -r -d '' file; do
if [[ -f "$file" ]]; then
rm "$file"
((deleted_scans++))
fi
done < <(find "$scans_dir" -name "*.json" -mtime +$days -print0)
fi
# Clean up report files
if [[ -d "$reports_dir" ]]; then
while IFS= read -r -d '' file; do
if [[ -f "$file" ]]; then
rm "$file"
((deleted_reports++))
fi
done < <(find "$reports_dir" -name "*.json" -mtime +$days -print0)
fi
log_info "Cleanup completed: $deleted_scans scan files, $deleted_reports report files deleted" "apt-layer"
}
# Show cloud security status
cloud_security_status() {
local cloud_security_dir="${PARTICLE_WORKSPACE:-/var/lib/particle-os}/cloud-security"
log_info "Cloud Security System Status" "apt-layer"
echo "=================================="
# Check if system is initialized
if [[ -d "$cloud_security_dir" ]]; then
echo "â System initialized: $cloud_security_dir"
# Check configuration
local config_file="$cloud_security_dir/cloud-security-config.json"
if [[ -f "$config_file" ]]; then
echo "â Configuration: $config_file"
local enabled_providers=$(jq -r '.enabled_providers[]' "$config_file" 2>/dev/null | tr '\n' ', ' | sed 's/,$//')
echo " Enabled providers: $enabled_providers"
else
echo "â Configuration missing"
fi
# Check directories
local dirs=("scans" "policies" "reports" "integrations")
for dir in "${dirs[@]}"; do
if [[ -d "$cloud_security_dir/$dir" ]]; then
echo "â $dir directory: $cloud_security_dir/$dir"
else
echo "â $dir directory missing"
fi
done
# Count files
local scan_count=$(find "$cloud_security_dir/scans" -name "*.json" 2>/dev/null | wc -l)
local policy_count=$(find "$cloud_security_dir/policies" -name "*.json" 2>/dev/null | wc -l)
local report_count=$(find "$cloud_security_dir/reports" -name "*.json" 2>/dev/null | wc -l)
echo "ð Statistics:"
echo " Security scans: $scan_count"
echo " Policy files: $policy_count"
echo " Compliance reports: $report_count"
else
echo "â System not initialized"
echo " Run 'cloud-security init' to initialize"
fi
}

View file

@ -1,393 +0,0 @@
#!/bin/bash
# Hardware Detection and Auto-Configuration
# Inspired by uBlue-OS akmods system
# Automatically detects hardware and enables appropriate kernel modules
# Hardware detection functions
detect_gpu() {
log_info "Detecting GPU hardware..."
# Detect NVIDIA GPUs
if lspci | grep -i nvidia > /dev/null 2>&1; then
log_info "NVIDIA GPU detected"
local nvidia_model=$(lspci | grep -i nvidia | head -1 | cut -d' ' -f4-)
log_info "NVIDIA Model: $nvidia_model"
# Determine which NVIDIA driver to use based on hardware
if echo "$nvidia_model" | grep -E "(RTX 50|RTX 40|RTX 30|RTX 20|GTX 16)" > /dev/null; then
echo "nvidia-open"
else
echo "nvidia"
fi
return 0
fi
# Detect AMD GPUs
if lspci | grep -i amd > /dev/null 2>&1; then
log_info "AMD GPU detected"
local amd_model=$(lspci | grep -i amd | head -1 | cut -d' ' -f4-)
log_info "AMD Model: $amd_model"
echo "amd"
return 0
fi
# Detect Intel GPUs
if lspci | grep -i intel > /dev/null 2>&1; then
log_info "Intel GPU detected"
local intel_model=$(lspci | grep -i intel | head -1 | cut -d' ' -f4-)
log_info "Intel Model: $intel_model"
echo "intel"
return 0
fi
log_warning "No dedicated GPU detected, using integrated graphics"
echo "integrated"
}
detect_cpu() {
log_info "Detecting CPU hardware..."
# Detect AMD Ryzen CPUs
if grep -i "amd" /proc/cpuinfo > /dev/null 2>&1; then
local cpu_model=$(grep "model name" /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)
log_info "AMD CPU detected: $cpu_model"
# Check for Ryzen SMU support
if echo "$cpu_model" | grep -i "ryzen" > /dev/null; then
log_info "AMD Ryzen CPU detected - enabling ryzen-smu support"
echo "amd_ryzen"
else
echo "amd"
fi
return 0
fi
# Detect Intel CPUs
if grep -i "intel" /proc/cpuinfo > /dev/null 2>&1; then
local cpu_model=$(grep "model name" /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)
log_info "Intel CPU detected: $cpu_model"
echo "intel"
return 0
fi
log_warning "Unknown CPU architecture"
echo "unknown"
}
detect_motherboard() {
log_info "Detecting motherboard hardware..."
# Detect System76 hardware
if dmidecode -s system-manufacturer 2>/dev/null | grep -i "system76" > /dev/null; then
log_info "System76 hardware detected"
echo "system76"
return 0
fi
# Detect GPD hardware
if dmidecode -s system-product-name 2>/dev/null | grep -i "gpd" > /dev/null; then
log_info "GPD hardware detected"
echo "gpd"
return 0
fi
# Detect AMD B550 chipset
if lspci | grep -i "nct6687" > /dev/null 2>&1; then
log_info "AMD B550 chipset detected (NCT6687)"
echo "amd_b550"
return 0
fi
log_info "Standard motherboard detected"
echo "standard"
}
detect_storage() {
log_info "Detecting storage hardware..."
# Check for ZFS pools
if command -v zpool > /dev/null 2>&1 && zpool list > /dev/null 2>&1; then
log_info "ZFS storage detected"
echo "zfs"
return 0
fi
# Check for Btrfs filesystems
if findmnt -t btrfs > /dev/null 2>&1; then
log_info "Btrfs storage detected"
echo "btrfs"
return 0
fi
log_info "Standard storage detected"
echo "standard"
}
detect_network() {
log_info "Detecting network hardware..."
# Detect Intel NICs
if lspci | grep -i "intel.*ethernet" > /dev/null 2>&1; then
log_info "Intel network adapter detected"
echo "intel_nic"
return 0
fi
# Detect Broadcom NICs
if lspci | grep -i "broadcom.*ethernet" > /dev/null 2>&1; then
log_info "Broadcom network adapter detected"
echo "broadcom_nic"
return 0
fi
log_info "Standard network adapter detected"
echo "standard"
}
# Auto-configure kernel modules based on detected hardware
auto_configure_kernel_modules() {
log_info "Auto-configuring kernel modules based on detected hardware..."
local config_file="/usr/local/etc/particle-os/kernel-modules.json"
local temp_config="/tmp/kernel-modules-auto.json"
# Create backup of current configuration
if [ -f "$config_file" ]; then
cp "$config_file" "${config_file}.backup.$(date +%Y%m%d_%H%M%S)"
fi
# Load current configuration
if [ -f "$config_file" ]; then
cp "$config_file" "$temp_config"
else
log_warning "Kernel modules configuration not found, creating default"
cat > "$temp_config" << 'EOF'
{
"kernel_modules": {
"common": {
"description": "Common kernel modules for general hardware support",
"modules": {
"v4l2loopback": {
"description": "Virtual video devices for screen recording and streaming",
"package": "v4l2loopback-dkms",
"kernel_args": [],
"enabled": false
}
}
},
"nvidia": {
"description": "NVIDIA GPU driver support",
"modules": {
"nvidia": {
"description": "NVIDIA closed proprietary drivers for legacy hardware",
"package": "nvidia-driver-535",
"kernel_args": ["nvidia-drm.modeset=1"],
"enabled": false
},
"nvidia-open": {
"description": "NVIDIA open source drivers for latest hardware",
"package": "nvidia-driver-open-535",
"kernel_args": ["nvidia-drm.modeset=1"],
"enabled": false
}
}
}
}
}
EOF
fi
# Detect hardware
local gpu_type=$(detect_gpu)
local cpu_type=$(detect_cpu)
local motherboard_type=$(detect_motherboard)
local storage_type=$(detect_storage)
local network_type=$(detect_network)
log_info "Hardware detection results:"
log_info " GPU: $gpu_type"
log_info " CPU: $cpu_type"
log_info " Motherboard: $motherboard_type"
log_info " Storage: $storage_type"
log_info " Network: $network_type"
# Enable appropriate modules based on hardware
local changes_made=false
# GPU-specific modules
case "$gpu_type" in
"nvidia"|"nvidia-open")
log_info "Enabling NVIDIA driver support"
jq '.kernel_modules.nvidia.modules.nvidia.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
jq '.kernel_modules.nvidia.modules.nvidia-open.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
esac
# CPU-specific modules
case "$cpu_type" in
"amd_ryzen")
log_info "Enabling AMD Ryzen SMU support"
jq '.kernel_modules.common.modules.ryzen-smu.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
esac
# Motherboard-specific modules
case "$motherboard_type" in
"system76")
log_info "Enabling System76 hardware support"
jq '.kernel_modules.common.modules.system76.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
"gpd")
log_info "Enabling GPD hardware support"
jq '.kernel_modules.common.modules.gpd-fan-kmod.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
"amd_b550")
log_info "Enabling AMD B550 chipset support"
jq '.kernel_modules.common.modules.nct6687d.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
esac
# Storage-specific modules
case "$storage_type" in
"zfs")
log_info "Enabling ZFS support"
jq '.kernel_modules.storage.modules.zfs.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
"btrfs")
log_info "Enabling Btrfs support"
jq '.kernel_modules.storage.modules.btrfs.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
esac
# Network-specific modules
case "$network_type" in
"intel_nic")
log_info "Enabling Intel NIC support"
jq '.kernel_modules.network.modules.intel-nic.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
"broadcom_nic")
log_info "Enabling Broadcom NIC support"
jq '.kernel_modules.network.modules.broadcom-nic.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
;;
esac
# Always enable v4l2loopback for general use
log_info "Enabling v4l2loopback for screen recording support"
jq '.kernel_modules.common.modules.v4l2loopback.enabled = true' "$temp_config" > "${temp_config}.tmp" && mv "${temp_config}.tmp" "$temp_config"
changes_made=true
if [ "$changes_made" = true ]; then
# Install the updated configuration
mkdir -p "$(dirname "$config_file")"
mv "$temp_config" "$config_file"
log_success "Kernel modules auto-configured based on detected hardware"
log_info "Configuration saved to: $config_file"
# Show enabled modules
log_info "Enabled kernel modules:"
jq -r '.kernel_modules | to_entries[] | .key as $category | .value.modules | to_entries[] | select(.value.enabled == true) | " \($category): \(.key) - \(.value.description)"' "$config_file" 2>/dev/null || log_warning "Could not parse enabled modules"
else
log_info "No hardware-specific modules needed, using default configuration"
rm -f "$temp_config"
fi
}
# Install enabled kernel modules
install_enabled_kernel_modules() {
log_info "Installing enabled kernel modules..."
local config_file="/usr/local/etc/particle-os/kernel-modules.json"
if [ ! -f "$config_file" ]; then
log_error "Kernel modules configuration not found"
return 1
fi
# Get list of enabled modules
local enabled_modules=$(jq -r '.kernel_modules | to_entries[] | .value.modules | to_entries[] | select(.value.enabled == true) | .value.package' "$config_file" 2>/dev/null)
if [ -z "$enabled_modules" ]; then
log_info "No kernel modules enabled in configuration"
return 0
fi
log_info "Installing enabled kernel modules:"
echo "$enabled_modules" | while read -r module_package; do
if [ -n "$module_package" ]; then
log_info " Installing: $module_package"
apt-layer --dkms-install "$module_package" || log_warning "Failed to install $module_package"
fi
done
log_success "Kernel module installation completed"
}
# Main hardware detection and configuration function
configure_hardware_support() {
log_info "Starting hardware detection and configuration..."
# Check if hardware detection is enabled
local auto_detect=$(jq -r '.hardware_detection.auto_detect // true' "/usr/local/etc/particle-os/kernel-modules.json" 2>/dev/null)
if [ "$auto_detect" != "true" ]; then
log_info "Hardware auto-detection is disabled"
return 0
fi
# Auto-configure kernel modules
auto_configure_kernel_modules
# Install enabled modules if requested
if [ "${1:-}" = "--install" ]; then
install_enabled_kernel_modules
fi
log_success "Hardware detection and configuration completed"
}
# Hardware detection commands
show_hardware_info() {
log_info "Hardware Information:"
echo "======================"
echo "GPU:"
detect_gpu
echo
echo "CPU:"
detect_cpu
echo
echo "Motherboard:"
detect_motherboard
echo
echo "Storage:"
detect_storage
echo
echo "Network:"
detect_network
echo
}
# Export functions for use in main script
export -f detect_gpu
export -f detect_cpu
export -f detect_motherboard
export -f detect_storage
export -f detect_network
export -f auto_configure_kernel_modules
export -f install_enabled_kernel_modules
export -f configure_hardware_support
export -f show_hardware_info

View file

@ -1,410 +0,0 @@
#!/bin/bash
# Kernel Patching System for Ubuntu
# Inspired by uBlue-OS but adapted for Ubuntu kernels
# Handles downloading, applying, and managing kernel patches
# Load kernel patches configuration
load_kernel_patches_config() {
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
if [ ! -f "$config_file" ]; then
log_error "Kernel patches configuration not found: $config_file"
return 1
fi
# Validate JSON configuration
if ! jq empty "$config_file" 2>/dev/null; then
log_error "Invalid JSON in kernel patches configuration"
return 1
fi
log_info "Loaded kernel patches configuration from: $config_file"
return 0
}
# Get current kernel version
get_current_kernel_version() {
local kernel_version=$(uname -r)
local major_minor=$(echo "$kernel_version" | cut -d'-' -f1)
log_info "Current kernel version: $kernel_version (major.minor: $major_minor)"
echo "$major_minor"
}
# Check if patch is compatible with current kernel
is_patch_compatible() {
local patch_name="$1"
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
local current_kernel=$(get_current_kernel_version)
# Get supported kernel versions for this patch
local supported_versions=$(jq -r ".kernel_patches | to_entries[] | .value.patches | to_entries[] | select(.key == \"$patch_name\") | .value.kernel_versions[]" "$config_file" 2>/dev/null)
if [ -z "$supported_versions" ]; then
log_warning "Could not determine kernel version compatibility for patch: $patch_name"
return 1
fi
# Check if current kernel version is supported
while IFS= read -r version; do
if [ "$version" = "$current_kernel" ]; then
log_info "Patch $patch_name is compatible with kernel $current_kernel"
return 0
fi
done <<< "$supported_versions"
log_warning "Patch $patch_name is not compatible with kernel $current_kernel"
return 1
}
# Download kernel patch
download_kernel_patch() {
local patch_name="$1"
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
local patch_dir="/var/lib/particle-os/kernel-patches"
# Create patch directory if it doesn't exist
mkdir -p "$patch_dir"
# Get patch URL
local patch_url=$(jq -r ".kernel_patches | to_entries[] | .value.patches | to_entries[] | select(.key == \"$patch_name\") | .value.url" "$config_file" 2>/dev/null)
if [ -z "$patch_url" ] || [ "$patch_url" = "null" ]; then
log_error "Could not find URL for patch: $patch_name"
return 1
fi
local patch_file="$patch_dir/${patch_name}.patch"
log_info "Downloading patch $patch_name from: $patch_url"
# Download patch with error handling
if curl -L -o "$patch_file" "$patch_url" 2>/dev/null; then
log_success "Downloaded patch: $patch_file"
return 0
else
log_error "Failed to download patch: $patch_name"
return 1
fi
}
# Apply kernel patch
apply_kernel_patch() {
local patch_name="$1"
local patch_dir="/var/lib/particle-os/kernel-patches"
local patch_file="$patch_dir/${patch_name}.patch"
local backup_dir="/var/lib/particle-os/kernel-patches/backup"
# Create backup directory
mkdir -p "$backup_dir"
# Check if patch file exists
if [ ! -f "$patch_file" ]; then
log_error "Patch file not found: $patch_file"
return 1
fi
log_info "Applying kernel patch: $patch_name"
# Create backup of current kernel configuration
local backup_file="$backup_dir/kernel-config-$(date +%Y%m%d_%H%M%S).bak"
if [ -f "/boot/config-$(uname -r)" ]; then
cp "/boot/config-$(uname -r)" "$backup_file"
log_info "Created kernel config backup: $backup_file"
fi
# Apply patch using Ubuntu's patch method
local apply_method=$(jq -r '.patch_application.ubuntu_specific.apply_method' "/usr/local/etc/particle-os/kernel-patches.json" 2>/dev/null)
if [ -z "$apply_method" ] || [ "$apply_method" = "null" ]; then
apply_method="patch -p1"
fi
# Note: In a real implementation, this would apply to kernel source
# For now, we'll simulate the patch application
log_info "Would apply patch using: $apply_method < $patch_file"
log_info "Patch application simulated (requires kernel source tree)"
# In a real implementation, this would be:
# cd /usr/src/linux-source-$(uname -r)
# $apply_method < "$patch_file"
log_success "Kernel patch $patch_name applied successfully"
return 0
}
# Get kernel arguments for a patch
get_patch_kernel_args() {
local patch_name="$1"
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
# Get kernel arguments for this patch
local kernel_args=$(jq -r ".kernel_patches | to_entries[] | .value.patches | to_entries[] | select(.key == \"$patch_name\") | .value.kernel_args[]" "$config_file" 2>/dev/null)
if [ -n "$kernel_args" ] && [ "$kernel_args" != "null" ]; then
echo "$kernel_args"
fi
}
# List available patches
list_available_patches() {
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
local current_kernel=$(get_current_kernel_version)
log_info "Available kernel patches for kernel $current_kernel:"
echo "=================================================="
# Iterate through patch categories
jq -r '.kernel_patches | to_entries[] | .key as $category | .value.patches | to_entries[] | "\($category): \(.key) - \(.value.description) [enabled: \(.value.enabled)]"' "$config_file" 2>/dev/null | while IFS= read -r line; do
if [ -n "$line" ] && [ "$line" != "null" ]; then
echo " $line"
fi
done
echo
log_info "Use 'apt-layer --apply-patch <patch-name>' to apply a specific patch"
}
# List enabled patches
list_enabled_patches() {
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
log_info "Enabled kernel patches:"
echo "========================="
# Get enabled patches
jq -r '.kernel_patches | to_entries[] | .key as $category | .value.patches | to_entries[] | select(.value.enabled == true) | "\($category): \(.key) - \(.value.description)"' "$config_file" 2>/dev/null | while IFS= read -r line; do
if [ -n "$line" ] && [ "$line" != "null" ]; then
echo " $line"
fi
done
}
# Enable a patch
enable_patch() {
local patch_name="$1"
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
local temp_config="/tmp/kernel-patches-enable.json"
# Check if patch exists
if ! jq -e ".kernel_patches | to_entries[] | .value.patches | has(\"$patch_name\")" "$config_file" > /dev/null 2>&1; then
log_error "Patch not found: $patch_name"
return 1
fi
# Check kernel compatibility
if ! is_patch_compatible "$patch_name"; then
log_error "Patch $patch_name is not compatible with current kernel"
return 1
fi
# Enable the patch
jq ".kernel_patches | to_entries[] | .value.patches[\"$patch_name\"].enabled = true" "$config_file" > "$temp_config" 2>/dev/null
if [ $? -eq 0 ]; then
# Update the configuration file
mv "$temp_config" "$config_file"
log_success "Enabled patch: $patch_name"
return 0
else
log_error "Failed to enable patch: $patch_name"
rm -f "$temp_config"
return 1
fi
}
# Disable a patch
disable_patch() {
local patch_name="$1"
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
local temp_config="/tmp/kernel-patches-disable.json"
# Check if patch exists
if ! jq -e ".kernel_patches | to_entries[] | .value.patches | has(\"$patch_name\")" "$config_file" > /dev/null 2>&1; then
log_error "Patch not found: $patch_name"
return 1
fi
# Disable the patch
jq ".kernel_patches | to_entries[] | .value.patches[\"$patch_name\"].enabled = false" "$config_file" > "$temp_config" 2>/dev/null
if [ $? -eq 0 ]; then
# Update the configuration file
mv "$temp_config" "$config_file"
log_success "Disabled patch: $patch_name"
return 0
else
log_error "Failed to disable patch: $patch_name"
rm -f "$temp_config"
return 1
fi
}
# Apply all enabled patches
apply_enabled_patches() {
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
local auto_apply=$(jq -r '.patch_application.auto_apply // false' "$config_file" 2>/dev/null)
if [ "$auto_apply" != "true" ]; then
log_info "Auto-apply is disabled, patches must be applied manually"
return 0
fi
log_info "Applying all enabled kernel patches..."
# Get list of enabled patches
local enabled_patches=$(jq -r '.kernel_patches | to_entries[] | .value.patches | to_entries[] | select(.value.enabled == true) | .key' "$config_file" 2>/dev/null)
if [ -z "$enabled_patches" ]; then
log_info "No patches are currently enabled"
return 0
fi
local applied_count=0
local failed_count=0
# Apply each enabled patch
while IFS= read -r patch_name; do
if [ -n "$patch_name" ] && [ "$patch_name" != "null" ]; then
log_info "Processing patch: $patch_name"
# Check compatibility
if ! is_patch_compatible "$patch_name"; then
log_warning "Skipping incompatible patch: $patch_name"
((failed_count++))
continue
fi
# Download patch
if download_kernel_patch "$patch_name"; then
# Apply patch
if apply_kernel_patch "$patch_name"; then
log_success "Successfully applied patch: $patch_name"
((applied_count++))
else
log_error "Failed to apply patch: $patch_name"
((failed_count++))
fi
else
log_error "Failed to download patch: $patch_name"
((failed_count++))
fi
fi
done <<< "$enabled_patches"
log_info "Patch application completed: $applied_count applied, $failed_count failed"
if [ $failed_count -gt 0 ]; then
return 1
else
return 0
fi
}
# Update kernel arguments for applied patches
update_kernel_arguments() {
local config_file="/usr/local/etc/particle-os/kernel-patches.json"
local kernel_args_file="/etc/default/grub"
log_info "Updating kernel arguments for applied patches..."
# Get all kernel arguments from enabled patches
local all_kernel_args=$(jq -r '.kernel_patches | to_entries[] | .value.patches | to_entries[] | select(.value.enabled == true) | .value.kernel_args[]' "$config_file" 2>/dev/null)
if [ -z "$all_kernel_args" ]; then
log_info "No kernel arguments to update"
return 0
fi
# Build new GRUB_CMDLINE_LINUX_DEFAULT
local new_args=""
while IFS= read -r arg; do
if [ -n "$arg" ] && [ "$arg" != "null" ]; then
if [ -z "$new_args" ]; then
new_args="$arg"
else
new_args="$new_args $arg"
fi
fi
done <<< "$all_kernel_args"
log_info "New kernel arguments: $new_args"
# In a real implementation, this would update GRUB configuration
# For now, we'll just log what would be done
log_info "Would update $kernel_args_file with new kernel arguments"
log_info "Would run: update-grub to apply changes"
log_success "Kernel arguments updated successfully"
return 0
}
# Main kernel patching function
manage_kernel_patches() {
local action="$1"
local patch_name="$2"
# Load configuration
if ! load_kernel_patches_config; then
return 1
fi
case "$action" in
"list")
list_available_patches
;;
"list-enabled")
list_enabled_patches
;;
"enable")
if [ -z "$patch_name" ]; then
log_error "Patch name required for enable action"
return 1
fi
enable_patch "$patch_name"
;;
"disable")
if [ -z "$patch_name" ]; then
log_error "Patch name required for disable action"
return 1
fi
disable_patch "$patch_name"
;;
"apply")
if [ -n "$patch_name" ]; then
# Apply specific patch
if download_kernel_patch "$patch_name" && apply_kernel_patch "$patch_name"; then
log_success "Applied patch: $patch_name"
else
log_error "Failed to apply patch: $patch_name"
return 1
fi
else
# Apply all enabled patches
apply_enabled_patches
fi
;;
"update-args")
update_kernel_arguments
;;
*)
log_error "Unknown action: $action"
return 1
;;
esac
}
# Export functions for use in main script
export -f load_kernel_patches_config
export -f get_current_kernel_version
export -f is_patch_compatible
export -f download_kernel_patch
export -f apply_kernel_patch
export -f get_patch_kernel_args
export -f list_available_patches
export -f list_enabled_patches
export -f enable_patch
export -f disable_patch
export -f apply_enabled_patches
export -f update_kernel_arguments
export -f manage_kernel_patches

View file

@ -12,17 +12,9 @@ apt-layer:
- composefs
- container
- live-overlay
- dkms
- nvidia
- rpm-ostree-compat
- atomic-transactions
- layer-signing
- audit-reporting
- security-scanning
- multi-tenant
- enterprise-integration
- cloud-integration
- kubernetes-integration
- dpkg-direct-install
EOF
}
@ -52,16 +44,7 @@ Layer Management:
--live-commit Commit live overlay changes
--live-rollback Rollback live overlay changes
DKMS & NVIDIA Support:
--dkms-status Show DKMS module status
--dkms-install Install DKMS module
--dkms-remove Remove DKMS module
--dkms-rebuild Rebuild DKMS module
--dkms-rebuild-all Rebuild all DKMS modules
--nvidia-install Install NVIDIA drivers
--nvidia-status Show NVIDIA driver status
--gpu-switch Switch GPU (integrated/nvidia/auto)
--nvidia-prime-configure Configure NVIDIA Prime
Image Management:
--list List available images
@ -193,175 +176,20 @@ IMAGE MANAGEMENT:
apt-layer --oci-status
# Show OCI integration system status
ADVANCED PACKAGE MANAGEMENT:
apt-layer --advanced-install packages
# Install packages with security checks and dependency resolution
SYSTEM MANAGEMENT:
apt-layer --init
# Initialize Particle-OS system
apt-layer --advanced-remove packages
# Remove packages with dependency checking and safety validation
apt-layer --reset
# Reset Particle-OS system
apt-layer --advanced-update packages
# Update packages with rollback capability and backup creation
apt-layer --add-user username role
# Add user to package management system with specified role
apt-layer --remove-user username
# Remove user from package management system
apt-layer --list-users
# List all package management users and roles
apt-layer --package-info package
# Get detailed information about a package
apt-layer --package-status
# Show advanced package management system status
apt-layer --list-backups
# List all package backups
apt-layer --cleanup-backups [days]
# Clean up backups older than specified days (default: 30)
DKMS & NVIDIA SUPPORT:
apt-layer --dkms-status
# Show DKMS module status and configuration
apt-layer --dkms-install module-name version
# Install DKMS module with atomic transaction support
apt-layer --dkms-remove module-name version
# Remove DKMS module with rollback capability
apt-layer --dkms-rebuild module-name version [kernel-version]
# Rebuild DKMS module for specific kernel version
apt-layer --dkms-rebuild-all [kernel-version]
# Rebuild all installed DKMS modules
apt-layer --dkms-list
# List all installed DKMS modules
apt-layer --nvidia-install [driver-version]
# Install NVIDIA drivers using graphics-drivers PPA (auto-detects optimal version)
apt-layer --nvidia-status
# Show NVIDIA driver status and GPU information
apt-layer --gpu-switch gpu-type
# Switch GPU using NVIDIA Prime (integrated/nvidia/auto)
apt-layer --nvidia-prime-configure
# Configure NVIDIA Prime for GPU switching
LAYER SIGNING & VERIFICATION:
apt-layer --generate-key key-name type
# Generate signing key pair (sigstore, gpg)
apt-layer --sign-layer layer path key-name
# Sign layer with specified key
apt-layer --verify-layer layer path
# Verify layer signature
apt-layer --revoke-layer layer path [reason]
# Revoke layer (mark as untrusted)
apt-layer --list-keys
# List all signing keys
apt-layer --list-signatures
# List all layer signatures
apt-layer --layer-status layer path
# Show layer signing status
AUDIT & COMPLIANCE:
apt-layer --query-audit format [filters...]
# Query audit logs with filters (json, csv, table)
apt-layer --export-audit format [output-file] [filters...]
# Export audit logs to file (json, csv, html)
apt-layer --generate-compliance-report framework [period] [format]
# Generate compliance report (sox, pci-dss)
apt-layer --list-audit-reports
# List all audit reports
apt-layer --audit-status
# Show audit system status
apt-layer --cleanup-audit-logs [days]
# Clean up old audit logs (default: 90 days)
SECURITY SCANNING:
apt-layer --scan-package package-name [version] [scan-level]
# Scan package for vulnerabilities (standard, thorough, quick)
apt-layer --scan-layer layer-path [scan-level]
# Scan layer for vulnerabilities
apt-layer --generate-security-report type [format] [scan-level]
# Generate security report (package, layer, system)
apt-layer --security-status
# Show security scanning system status
apt-layer --update-cve-database
# Update CVE database from NVD
apt-layer --cleanup-security-reports [days]
# Clean up old security reports (default: 90 days)
ADMIN UTILITIES:
apt-layer admin health
# System health check and diagnostics
apt-layer admin perf
# Performance analytics and resource usage
apt-layer admin cleanup
# Maintenance cleanup
apt-layer admin backup
# Backup configs and layers
apt-layer admin restore
# Restore from backup
ENTERPRISE FEATURES:
apt-layer tenant action [options]
# Multi-tenant management
apt-layer compliance action [options]
# Compliance framework management
apt-layer enterprise action [options]
# Enterprise integration
apt-layer monitoring action [options]
# Monitoring and alerting
CLOUD INTEGRATION:
apt-layer cloud action [options]
# Cloud provider integration (AWS, Azure, GCP)
apt-layer kubernetes action [options]
# Kubernetes integration (EKS, AKS, GKE, OpenShift)
apt-layer orchestration action [options]
# Container orchestration
apt-layer multicloud action [options]
# Multi-cloud deployment
apt-layer cloud-security action [options]
# Cloud-native security
For category-specific help: apt-layer category --help
For examples: apt-layer --examples
EXAMPLES:
apt-layer ubuntu-ublue/base/24.04 ubuntu-ublue/gaming/24.04 steam wine
apt-layer --container ubuntu-ublue/base/24.04 ubuntu-ublue/dev/24.04 vscode git
apt-layer --dpkg-install curl wget
apt-layer --live-install firefox
apt-layer install steam wine
apt-layer status
EOF
}
@ -495,11 +323,12 @@ Examples:
EOF
}
# Show image management help
show_image_help() {
cat << 'EOF'
Image Management Commands
IMAGE MANAGEMENT COMMANDS:
BASIC IMAGE OPERATIONS:
IMAGE OPERATIONS:
apt-layer --list
# List all available ComposeFS images/layers
@ -519,12 +348,11 @@ OCI INTEGRATION:
apt-layer --oci-status
# Show OCI integration system status
Examples:
EXAMPLES:
apt-layer --list
apt-layer --info ubuntu-ublue/gaming/24.04
apt-layer --remove old-image
apt-layer --oci-export ubuntu-ublue/gaming/24.04 ubuntu-ublue/gaming:latest
apt-layer --oci-import ubuntu:24.04 ubuntu-ublue/base/24.04
apt-layer --info ubuntu-ublue/base/24.04
apt-layer --remove old-layer
apt-layer --oci-export my-image oci:my-registry/my-image:latest
EOF
}
@ -737,53 +565,6 @@ Examples:
EOF
}
show_dkms_help() {
cat << 'EOF'
DKMS & NVIDIA Support Commands
DKMS MODULE MANAGEMENT:
apt-layer --dkms-status
# Show DKMS module status and configuration
apt-layer --dkms-install module-name version
# Install DKMS module with atomic transaction support
apt-layer --dkms-remove module-name version
# Remove DKMS module with rollback capability
apt-layer --dkms-rebuild module-name version [kernel-version]
# Rebuild DKMS module for specific kernel version
apt-layer --dkms-rebuild-all [kernel-version]
# Rebuild all installed DKMS modules
apt-layer --dkms-list
# List all installed DKMS modules
NVIDIA DRIVER SUPPORT:
apt-layer --nvidia-install [driver-version]
# Install NVIDIA drivers using graphics-drivers PPA
# Auto-detects optimal driver version if not specified
apt-layer --nvidia-status
# Show NVIDIA driver status and GPU information
apt-layer --gpu-switch gpu-type
# Switch GPU using NVIDIA Prime
# Options: integrated, nvidia, auto
apt-layer --nvidia-prime-configure
# Configure NVIDIA Prime for GPU switching
Examples:
apt-layer --dkms-install nvidia-driver 535
apt-layer --dkms-rebuild virtualbox-dkms 6.1.38
apt-layer --nvidia-install auto
apt-layer --gpu-switch nvidia
apt-layer --dkms-status
EOF
}
# Show examples
show_examples() {
cat << 'EOF'
@ -834,48 +615,6 @@ IMAGE MANAGEMENT:
# Export as OCI image
apt-layer --oci-export ubuntu-ublue/gaming/24.04 ubuntu-ublue/gaming:latest
ADVANCED FEATURES:
# Generate signing key
apt-layer --generate-key my-key sigstore
# Sign layer
apt-layer --sign-layer layer.squashfs my-key
# Security scan
apt-layer --scan-package firefox
# System health check
apt-layer admin health
DKMS & NVIDIA SUPPORT:
# Install NVIDIA drivers
apt-layer --nvidia-install auto
# Install DKMS module
apt-layer --dkms-install virtualbox-dkms 6.1.38
# Rebuild DKMS modules after kernel update
apt-layer --dkms-rebuild-all
# Switch to NVIDIA GPU
apt-layer --gpu-switch nvidia
# Check DKMS status
apt-layer --dkms-status
ENTERPRISE FEATURES:
# Create tenant
apt-layer tenant create my-org
# Enable compliance framework
apt-layer compliance enable SOX
# Cloud deployment
apt-layer cloud deploy ubuntu-ublue/gaming/24.04 aws ecr
# Kubernetes deployment
apt-layer kubernetes deploy ubuntu-ublue/gaming/24.04 gaming-ns
EOF
}
@ -1078,12 +817,6 @@ main() {
exit 0
fi
;;
dkms)
if [[ "${2:-}" == "--help" || "${2:-}" == "-h" ]]; then
show_dkms_help
exit 0
fi
;;
security)
if [[ "${2:-}" == "--help" || "${2:-}" == "-h" ]]; then
show_security_help

View file

@ -1,207 +0,0 @@
# Particle-OS apt-layer Test Scripts
This directory contains comprehensive test scripts for validating Particle-OS apt-layer functionality, including package management, layer creation, and atomic transactions.
## Test Scripts Overview
### Core Functionality Tests
#### `test-apt-layer-basic.sh`
**Purpose**: Validates core apt-layer functionality and basic operations.
**Tests**:
- Help system and command validation
- System status and health checks
- Image and layer listing functionality
- Base image creation with multi-layer support
- Package installation and management
- Layer creation from base images
- Image mounting and content access
- DKMS functionality and NVIDIA support
- Cleanup and maintenance operations
- Image removal and cleanup
**Usage**:
```bash
sudo ./test-apt-layer-basic.sh
```
**Requirements**:
- Particle-OS tools installed
- Root privileges
- apt-layer script available at `/usr/local/bin/apt-layer.sh`
## Test Environment Setup
### Prerequisites
1. **Install Particle-OS Tools**:
```bash
sudo ./install-particle-os.sh
```
2. **Install Required Packages**:
```bash
sudo apt update
sudo apt install squashfs-tools jq coreutils util-linux
```
### Test Execution
#### Running Individual Tests
```bash
# Basic functionality test
sudo ./test-scripts/test-apt-layer-basic.sh
```
#### Running All Tests
```bash
# Run all tests sequentially
for test in test-scripts/test-*.sh; do
echo "Running $test..."
sudo "$test"
echo "Completed $test"
echo "---"
done
```
## Test Results Interpretation
### Success Criteria
- **Basic Tests**: All core functionality working correctly
- **Package Management**: Package installation and layer creation working
- **DKMS Tests**: DKMS functionality available and working
- **NVIDIA Tests**: NVIDIA support available and working
### Common Issues and Solutions
#### Permission Denied Errors
```
[ERROR] Permission denied
```
**Solution**: Ensure running with root privileges
```bash
sudo ./test-script.sh
```
#### apt-layer Script Not Found
```
[ERROR] apt-layer script not found
```
**Solution**: Install Particle-OS tools
```bash
sudo ./install-particle-os.sh
```
#### Package Installation Failures
```
[WARNING] Package installation test failed
```
**Solution**: Check network connectivity and package availability
```bash
sudo apt update
sudo apt install curl wget
```
## Test Customization
### Environment Variables
```bash
# Set backend preference
export UBLUE_COMPOSEFS_BACKEND="erofs" # or "squashfs" or "auto"
# Set compression method
export UBLUE_SQUASHFS_COMPRESSION="lz4" # or "xz" or "gzip"
# Run test with custom settings
sudo UBLUE_COMPOSEFS_BACKEND="erofs" ./test-apt-layer-basic.sh
```
### Test Parameters
Each test script can be customized by modifying:
- Test package lists
- Layer creation parameters
- Performance thresholds
- Test duration and iterations
## Integration with CI/CD
### Automated Testing
```bash
#!/bin/bash
# Example CI/CD test script for apt-layer
set -euo pipefail
# Run all tests and collect results
test_results=()
for test in test-scripts/test-*.sh; do
if sudo "$test"; then
test_results+=("PASS: $(basename "$test")")
else
test_results+=("FAIL: $(basename "$test")")
fi
done
# Report results
echo "Test Results:"
for result in "${test_results[@]}"; do
echo " $result"
done
# Exit with failure if any test failed
if [[ " ${test_results[*]} " =~ " FAIL: " ]]; then
exit 1
fi
```
## Troubleshooting
### Debug Mode
Enable verbose output for debugging:
```bash
# Set debug environment
export PARTICLE_DEBUG=1
sudo ./test-scripts/test-apt-layer-basic.sh
```
### Log Analysis
Check logs for detailed error information:
```bash
# View apt-layer logs
sudo tail -f /var/log/particle-os/apt-layer.log
# View system logs
sudo journalctl -f -u particle-os
```
### System Requirements Verification
```bash
# Check system requirements
sudo ./test-scripts/test-apt-layer-basic.sh 2>&1 | grep -E "(ERROR|WARNING|REQUIRED)"
```
## Contributing
### Adding New Tests
1. **Follow naming convention**: `test-<feature>-<type>.sh`
2. **Include proper cleanup**: Use trap handlers for cleanup
3. **Add documentation**: Update this README with new test details
4. **Test thoroughly**: Validate on multiple systems
### Test Standards
- **Error handling**: Comprehensive error checking and reporting
- **Cleanup**: Proper resource cleanup in all scenarios
- **Documentation**: Clear test purpose and requirements
- **Portability**: Work across different Ubuntu versions
## Support
For issues with test scripts:
1. Check the troubleshooting section above
2. Review system requirements and prerequisites
3. Check Particle-OS documentation
4. Report issues with detailed system information
---
**Note**: These test scripts are designed to validate Particle-OS apt-layer functionality and help ensure system reliability. Regular testing is recommended for development and deployment environments.

View file

@ -1,332 +0,0 @@
#!/bin/bash
################################################################################################################
# #
# Particle-OS apt-layer Basic Test Script #
# Tests basic apt-layer functionality including layer creation, package management, and atomic transactions #
# #
################################################################################################################
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Configuration
APT_LAYER_SCRIPT="/usr/local/bin/apt-layer.sh"
TEST_DIR="/tmp/particle-os-apt-layer-basic-test-$$"
TEST_BASE_IMAGE="test-base-image"
TEST_APP_IMAGE="test-app-image"
# Cleanup function
cleanup() {
log_info "Cleaning up test environment..."
# Remove test images
"$APT_LAYER_SCRIPT" remove "$TEST_APP_IMAGE" 2>/dev/null || true
"$APT_LAYER_SCRIPT" remove "$TEST_BASE_IMAGE" 2>/dev/null || true
# Remove test directory
rm -rf "$TEST_DIR" 2>/dev/null || true
log_info "Cleanup completed"
}
# Set up trap for cleanup
trap cleanup EXIT INT TERM
# Test functions
test_apt_layer_help() {
log_info "Testing apt-layer help system..."
if "$APT_LAYER_SCRIPT" help >/dev/null 2>&1; then
log_success "Help system test passed"
return 0
else
log_error "Help system test failed"
return 1
fi
}
test_apt_layer_status() {
log_info "Testing apt-layer status..."
if "$APT_LAYER_SCRIPT" status >/dev/null 2>&1; then
log_success "Status test passed"
return 0
else
log_error "Status test failed"
return 1
fi
}
test_apt_layer_list_commands() {
log_info "Testing apt-layer listing commands..."
# Test list-images
if "$APT_LAYER_SCRIPT" list-images >/dev/null 2>&1; then
log_success "list-images test passed"
else
log_error "list-images test failed"
return 1
fi
# Test list-layers
if "$APT_LAYER_SCRIPT" list-layers >/dev/null 2>&1; then
log_success "list-layers test passed"
else
log_error "list-layers test failed"
return 1
fi
# Test list-mounts
if "$APT_LAYER_SCRIPT" list-mounts >/dev/null 2>&1; then
log_success "list-mounts test passed"
else
log_error "list-mounts test failed"
return 1
fi
return 0
}
test_apt_layer_base_image_creation() {
log_info "Testing apt-layer base image creation..."
# Create test source directory
local test_source="$TEST_DIR/base"
mkdir -p "$test_source"
# Add some basic content
echo "Base system content" > "$test_source/base.txt"
mkdir -p "$test_source/etc"
echo "base_config=value" > "$test_source/etc/base.conf"
# Create base image
if "$APT_LAYER_SCRIPT" create "$TEST_BASE_IMAGE" "$test_source"; then
log_success "Base image creation test passed"
return 0
else
log_error "Base image creation test failed"
return 1
fi
}
test_apt_layer_package_installation() {
log_info "Testing apt-layer package installation..."
# Test installing a simple package (using a mock approach)
# In a real test, this would use actual package names
local test_packages=("curl" "wget")
for package in "${test_packages[@]}"; do
log_info "Testing package installation: $package"
# Check if package is available (mock test)
if apt-cache show "$package" >/dev/null 2>&1; then
log_success "Package $package is available"
else
log_warning "Package $package not available (skipping)"
continue
fi
done
log_success "Package installation test completed"
return 0
}
test_apt_layer_layer_creation() {
log_info "Testing apt-layer layer creation..."
# Create a new layer based on the base image
local test_packages=("curl")
if "$APT_LAYER_SCRIPT" install "$TEST_BASE_IMAGE" "$TEST_APP_IMAGE" "${test_packages[@]}"; then
log_success "Layer creation test passed"
return 0
else
log_warning "Layer creation test failed (may be expected in test environment)"
return 0 # Not a critical failure in test environment
fi
}
test_apt_layer_image_mounting() {
log_info "Testing apt-layer image mounting..."
# Create mount point
local mount_point="$TEST_DIR/mount"
mkdir -p "$mount_point"
# Try to mount the app image
if "$APT_LAYER_SCRIPT" mount "$TEST_APP_IMAGE" "$mount_point"; then
log_success "Image mounting test passed"
# Test content access
if [[ -f "$mount_point/base.txt" ]]; then
log_success "Content access test passed"
else
log_warning "Content access test failed"
fi
# Unmount
"$APT_LAYER_SCRIPT" unmount "$mount_point"
return 0
else
log_warning "Image mounting test failed (may be expected in test environment)"
return 0 # Not a critical failure in test environment
fi
}
test_apt_layer_cleanup() {
log_info "Testing apt-layer cleanup..."
if "$APT_LAYER_SCRIPT" cleanup >/dev/null 2>&1; then
log_success "Cleanup test passed"
return 0
else
log_warning "Cleanup test failed (may be normal if no unreferenced layers)"
return 0 # Not a critical failure
fi
}
test_apt_layer_image_removal() {
log_info "Testing apt-layer image removal..."
# Remove test images
if "$APT_LAYER_SCRIPT" remove "$TEST_APP_IMAGE"; then
log_success "App image removal test passed"
else
log_warning "App image removal test failed"
fi
if "$APT_LAYER_SCRIPT" remove "$TEST_BASE_IMAGE"; then
log_success "Base image removal test passed"
return 0
else
log_error "Base image removal test failed"
return 1
fi
}
test_apt_layer_dkms_functionality() {
log_info "Testing apt-layer DKMS functionality..."
# Test DKMS status
if "$APT_LAYER_SCRIPT" dkms-status >/dev/null 2>&1; then
log_success "DKMS status test passed"
else
log_warning "DKMS status test failed (may be expected if no DKMS modules)"
fi
# Test DKMS list
if "$APT_LAYER_SCRIPT" dkms-list >/dev/null 2>&1; then
log_success "DKMS list test passed"
else
log_warning "DKMS list test failed (may be expected if no DKMS modules)"
fi
return 0
}
test_apt_layer_nvidia_functionality() {
log_info "Testing apt-layer NVIDIA functionality..."
# Test NVIDIA status
if "$APT_LAYER_SCRIPT" nvidia-status >/dev/null 2>&1; then
log_success "NVIDIA status test passed"
else
log_warning "NVIDIA status test failed (may be expected if no NVIDIA hardware)"
fi
return 0
}
# Main test execution
main() {
log_info "Starting Particle-OS apt-layer Basic Tests"
log_info "Test directory: $TEST_DIR"
log_info "apt-layer script: $APT_LAYER_SCRIPT"
# Check if apt-layer script exists
if [[ ! -x "$APT_LAYER_SCRIPT" ]]; then
log_error "apt-layer script not found: $APT_LAYER_SCRIPT"
log_info "Please install Particle-OS tools first"
exit 1
fi
# Create test directory
mkdir -p "$TEST_DIR"
# Test counter
local total_tests=0
local passed_tests=0
local failed_tests=0
# Run tests
local tests=(
"test_apt_layer_help"
"test_apt_layer_status"
"test_apt_layer_list_commands"
"test_apt_layer_base_image_creation"
"test_apt_layer_package_installation"
"test_apt_layer_layer_creation"
"test_apt_layer_image_mounting"
"test_apt_layer_cleanup"
"test_apt_layer_image_removal"
"test_apt_layer_dkms_functionality"
"test_apt_layer_nvidia_functionality"
)
for test_func in "${tests[@]}"; do
total_tests=$((total_tests + 1))
log_info "Running test: $test_func"
if "$test_func"; then
passed_tests=$((passed_tests + 1))
log_success "Test passed: $test_func"
else
failed_tests=$((failed_tests + 1))
log_error "Test failed: $test_func"
fi
echo
done
# Summary
log_info "Test Summary:"
log_info " Total tests: $total_tests"
log_info " Passed: $passed_tests"
log_info " Failed: $failed_tests"
if [[ $failed_tests -eq 0 ]]; then
log_success "All tests passed! apt-layer basic functionality is working correctly."
exit 0
else
log_warning "Some tests failed. Check the output above for details."
exit 1
fi
}
# Run main function
main "$@"