Comprehensive security guide for deploying and using hyper2kvm in production environments.
hyper2kvm processes privileged operations on VM disk images. Key security concerns:
Always verify package signatures before installation:
# For RPM installations
rpm --checksig hyper2kvm-*.rpm
# Verify GPG signature
rpm --import https://download.hyper2kvm.io/GPG-KEY
rpm -K hyper2kvm-*.rpm
# For pip installations
pip install hyper2kvm --require-hashes
# ✅ GOOD: Official PyPI
pip install hyper2kvm
# ✅ GOOD: Official GitHub releases
wget https://github.com/yourorg/hyper2kvm/releases/download/v1.0.0/hyper2kvm.rpm
# ❌ BAD: Unknown third-party mirrors
pip install -i http://unknown-mirror.com/simple hyper2kvm
# Download checksum file
wget https://download.hyper2kvm.io/hyper2kvm-1.0.0.tar.gz.sha256
# Verify checksum
sha256sum -c hyper2kvm-1.0.0.tar.gz.sha256
When using Docker:
# Use specific version tags (not 'latest')
FROM hyper2kvm/hyper2kvm:1.0.0
# Run as non-root user
USER hyper2kvm
# Read-only root filesystem
RUN chmod -R a-w /app
# Drop capabilities
RUN setcap cap_sys_admin+ep /usr/bin/hyper2kvm
Set restrictive permissions on configuration files:
# Configuration files - owner read/write only
chmod 600 /etc/hyper2kvm/config.yaml
chown hyper2kvm:hyper2kvm /etc/hyper2kvm/config.yaml
# Credentials file - owner read only
chmod 400 /etc/hyper2kvm/credentials
chown hyper2kvm:hyper2kvm /etc/hyper2kvm/credentials
# Log directory - owner read/write/execute
chmod 700 /var/log/hyper2kvm
chown hyper2kvm:hyper2kvm /var/log/hyper2kvm
# Output directory - owner read/write/execute
chmod 700 /var/lib/libvirt/images
chown hyper2kvm:qemu /var/lib/libvirt/images
Create a dedicated service account:
# Create hyper2kvm user
useradd -r -s /sbin/nologin -d /var/lib/hyper2kvm hyper2kvm
# Add to necessary groups
usermod -aG qemu hyper2kvm
usermod -aG libvirt hyper2kvm
# Configure sudo for specific commands only
cat > /etc/sudoers.d/hyper2kvm << 'EOF'
hyper2kvm ALL=(root) NOPASSWD: /usr/bin/guestfish
hyper2kvm ALL=(root) NOPASSWD: /usr/bin/virt-inspector
hyper2kvm ALL=(root) NOPASSWD: /usr/bin/qemu-img
EOF
chmod 440 /etc/sudoers.d/hyper2kvm
Enable mandatory access control:
# Check SELinux status
getenforce
# Create custom policy
cat > hyper2kvm.te << 'EOF'
module hyper2kvm 1.0;
require {
type unconfined_t;
type virt_image_t;
class file { read write open };
}
#============= unconfined_t ==============
allow unconfined_t virt_image_t:file { read write open };
EOF
# Compile and load policy
checkmodule -M -m -o hyper2kvm.mod hyper2kvm.te
semodule_package -o hyper2kvm.pp -m hyper2kvm.mod
semodule -i hyper2kvm.pp
# Set correct contexts
semanage fcontext -a -t virt_image_t "/var/lib/libvirt/images(/.*)?"
restorecon -Rv /var/lib/libvirt/images
# Create AppArmor profile
cat > /etc/apparmor.d/usr.bin.hyper2kvm << 'EOF'
#include <tunables/global>
/usr/bin/hyper2kvm {
#include <abstractions/base>
#include <abstractions/python>
# Allow reading VM images
/var/lib/libvirt/images/** r,
# Allow writing converted images
/var/lib/libvirt/images/** w,
# Allow temporary files
/tmp/** rw,
# Deny network access
deny network,
# Deny capability changes
deny capability setuid,
deny capability setgid,
}
EOF
# Load profile
apparmor_parser -r /etc/apparmor.d/usr.bin.hyper2kvm
Restrict network access:
# Allow only necessary connections
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="vcenter.example.com"
port protocol="tcp" port="443"
accept'
# Block all other outbound HTTPS
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 \
-p tcp --dport 443 -j REJECT
firewall-cmd --reload
Always verify SSL certificates:
# config.yaml - GOOD
vsphere:
host: vcenter.example.com
verify_ssl: true
ca_bundle: /etc/pki/tls/certs/ca-bundle.crt
# config.yaml - BAD (only for testing!)
vsphere:
host: vcenter.example.com
verify_ssl: false # ❌ INSECURE
Use dedicated network segment for VM migrations:
# Create dedicated VLAN for migrations
ip link add link eth0 name eth0.100 type vlan id 100
ip addr add 192.168.100.10/24 dev eth0.100
ip link set eth0.100 up
# Route vSphere traffic through migration VLAN
ip route add vcenter.example.com via 192.168.100.1 dev eth0.100
Always validate images before processing:
import hashlib
def validate_image_checksum(image_path, expected_checksum):
"""Validate image hasn't been tampered with."""
sha256 = hashlib.sha256()
with open(image_path, 'rb') as f:
while chunk := f.read(8192):
sha256.update(chunk)
actual = sha256.hexdigest()
if actual != expected_checksum:
raise SecurityError(f"Image checksum mismatch: {actual} != {expected_checksum}")
# Use in pipeline
validate_image_checksum(
"/exports/vm-001/disk-001.vmdk",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
)
Scan images for malware before conversion:
# Install ClamAV
dnf install clamav clamd
# Update virus definitions
freshclam
# Scan image
clamscan --infected --recursive /exports/vm-001/
# Automated scanning
cat > /usr/local/bin/scan-vm-image.sh << 'EOF'
#!/bin/bash
IMAGE=$1
clamscan --infected --max-filesize=4000M "$IMAGE"
if [ $? -ne 0 ]; then
echo "⚠️ Malware detected in $IMAGE"
exit 1
fi
EOF
chmod +x /usr/local/bin/scan-vm-image.sh
Encrypt images at rest:
# Create encrypted volume
cryptsetup luksFormat /dev/sdb
cryptsetup luksOpen /dev/sdb encrypted_images
# Create filesystem
mkfs.xfs /dev/mapper/encrypted_images
# Mount
mount /dev/mapper/encrypted_images /var/lib/libvirt/images
# Add to /etc/crypttab
echo "encrypted_images /dev/sdb none" >> /etc/crypttab
# Add to /etc/fstab
echo "/dev/mapper/encrypted_images /var/lib/libvirt/images xfs defaults 0 2" >> /etc/fstab
Securely delete temporary files:
# Overwrite before deletion
shred -vfz -n 3 /tmp/temp-vm-image.qcow2
# Use secure temp directory
export TMPDIR=/dev/shm # RAM-based, not persisted to disk
# ❌ BAD - Hardcoded credentials
vsphere:
username: administrator@vsphere.local
password: MySecretPassword123
# ✅ GOOD - Environment variables
vsphere:
username: ${VSPHERE_USERNAME}
password: ${VSPHERE_PASSWORD}
# Store credentials in Vault
vault kv put secret/hyper2kvm/vsphere \
username=administrator@vsphere.local \
password=MySecretPassword123
# Retrieve in script
export VSPHERE_USERNAME=$(vault kv get -field=username secret/hyper2kvm/vsphere)
export VSPHERE_PASSWORD=$(vault kv get -field=password secret/hyper2kvm/vsphere)
hyper2kvm --vsphere-user "$VSPHERE_USERNAME" --vsphere-password "$VSPHERE_PASSWORD" ...
apiVersion: v1
kind: Secret
metadata:
name: vsphere-credentials
type: Opaque
stringData:
username: administrator@vsphere.local
password: MySecretPassword123
---
apiVersion: v1
kind: Pod
metadata:
name: hyper2kvm
spec:
containers:
- name: hyper2kvm
image: hyper2kvm/hyper2kvm:1.0.0
env:
- name: VSPHERE_USERNAME
valueFrom:
secretKeyRef:
name: vsphere-credentials
key: username
- name: VSPHERE_PASSWORD
valueFrom:
secretKeyRef:
name: vsphere-credentials
key: password
Implement regular credential rotation:
#!/bin/bash
# rotate-credentials.sh
# Generate new password
NEW_PASSWORD=$(openssl rand -base64 32)
# Update in vCenter
govc user.update -password "$NEW_PASSWORD" administrator@vsphere.local
# Update in Vault
vault kv put secret/hyper2kvm/vsphere \
username=administrator@vsphere.local \
password="$NEW_PASSWORD"
echo "✓ Credentials rotated successfully"
# config.yaml
logging:
level: INFO
audit_log: /var/log/hyper2kvm/audit.log
security_events: true
include_checksums: true
log_all_api_calls: true
Use structured JSON logging:
import logging
import json
class SecurityAuditLogger:
def log_conversion_start(self, user, vm_name, source):
event = {
"timestamp": time.time(),
"event": "conversion_start",
"user": user,
"vm_name": vm_name,
"source": source,
"checksum": self.calculate_checksum(source),
}
logging.info(json.dumps(event))
Forward logs to SIEM:
# Configure rsyslog
cat > /etc/rsyslog.d/hyper2kvm.conf << 'EOF'
# Forward hyper2kvm logs to SIEM
if $programname == 'hyper2kvm' then @@siem.example.com:514
& stop
EOF
systemctl restart rsyslog
# Configure logrotate
cat > /etc/logrotate.d/hyper2kvm << 'EOF'
/var/log/hyper2kvm/*.log {
daily
rotate 365
compress
delaycompress
notifempty
create 0600 hyper2kvm hyper2kvm
postrotate
systemctl reload hyper2kvm-daemon
endscript
}
EOF
Data protection considerations:
# Secure deletion script
#!/bin/bash
# gdpr-delete.sh
VM_IMAGE=$1
# Verify it's a temporary file
if [[ "$VM_IMAGE" != /tmp/hyper2kvm/* ]]; then
echo "Can only delete temporary files"
exit 1
fi
# Secure deletion
shred -vfz -n 7 "$VM_IMAGE"
# Log deletion
logger -t hyper2kvm "GDPR deletion: $VM_IMAGE by $USER"
For environments processing payment data:
# config.yaml - PCI-DSS compliant configuration
security:
require_encryption: true
mfa_required: true
audit_logging: true
network_segmentation: true
approved_sources:
- vcenter-pci.example.com
prohibited_destinations:
- "*" # Whitelist only
For healthcare environments:
Monitor for suspicious activities:
# Detect unusual file access
auditctl -w /var/lib/libvirt/images -p wa -k vm_image_access
# Monitor for privilege escalation
auditctl -w /etc/sudoers -p wa -k sudoers_changes
# Detect credential access
auditctl -w /etc/hyper2kvm/credentials -p r -k credential_access
# Immediately stop hyper2kvm service
systemctl stop hyper2kvm-daemon
# Block network access
iptables -A OUTPUT -j REJECT
# Preserve evidence
cp -a /var/log/hyper2kvm /evidence/hyper2kvm-logs-$(date +%Y%m%d-%H%M%S)
cp -a /var/lib/hyper2kvm /evidence/hyper2kvm-data-$(date +%Y%m%d-%H%M%S)
# Review audit logs
ausearch -k vm_image_access -ts recent
# Check for unauthorized changes
rpm -Va hyper2kvm
# Review access logs
grep -E "(FAILED|ERROR|DENIED)" /var/log/hyper2kvm/audit.log
# Reinstall from trusted source
dnf reinstall hyper2kvm
# Restore configuration from backup
cp /backup/config.yaml /etc/hyper2kvm/config.yaml
# Rotate credentials
./rotate-credentials.sh
# Restart service
systemctl start hyper2kvm-daemon
#!/bin/bash
# collect-forensics.sh
EVIDENCE_DIR="/evidence/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$EVIDENCE_DIR"
# Collect logs
cp -a /var/log/hyper2kvm "$EVIDENCE_DIR/logs"
# Collect configuration
cp -a /etc/hyper2kvm "$EVIDENCE_DIR/config"
# Collect system state
ps aux > "$EVIDENCE_DIR/processes.txt"
netstat -tulpn > "$EVIDENCE_DIR/network.txt"
lsof > "$EVIDENCE_DIR/open-files.txt"
# Collect audit logs
ausearch -ts boot > "$EVIDENCE_DIR/audit.txt"
# Create tarball with hash
tar czf "$EVIDENCE_DIR.tar.gz" "$EVIDENCE_DIR"
sha256sum "$EVIDENCE_DIR.tar.gz" > "$EVIDENCE_DIR.tar.gz.sha256"
echo "✓ Forensic data collected: $EVIDENCE_DIR.tar.gz"
Use this checklist before production deployment:
Report security vulnerabilities to: