# Fedora Kinoite SAW Kickstart File ## Overview This kickstart file creates a custom Fedora Kinoite ISO for the Secure Air-Gapped Workstation (SAW) implementation. **Key Features:** - Custom CA certificate pre-installed - WireGuard VPN pre-configured - Package verification enabled - Security hardening applied - Minimal package set (only essential packages) ## Kickstart File ```bash # Kickstart file for Fedora Kinoite SAW # Version: 1.0 # Date: 2026-04-02 # Use text mode installation text # System language lang en_US.UTF-8 # Keyboard layout keyboard --vckeymap=us --layout=US # Network configuration network --bootproto=dhcp --device=eth0 --activate # Root password (change this!) rootpw --iscrypted YOUR_ENCRYPTED_PASSWORD_HERE # Root password (uncomment for interactive) # rootpw # User configuration user --name=saw-user --password=changeme --groups=wheel --shell=/bin/bash # After lockdown, user will be removed from wheel group # SELinux configuration selinux --enforcing # Firewall configuration firewall --enabled --service=ssh # Timezone timezone America/New_York --utc # System bootloader bootloader --location=partition --boot-drive=sda # Partition information clearpart --all --initlabel part / --fstype="ext4" --size=20480 --grow part /boot/efi --fstype="efi" --size=512 --grow # Repositories repo --name=fedora --baseurl=file:///mnt/source repo --name=updates --baseurl=file:///mnt/source/updates # Package selection %packages @^kinoite-desktop @base @core @standard # Add your custom packages here # Example: vim-enhanced git wget # Remove unnecessary packages -ibus-angry -ibus-bopomofo -ibus-chewing -ibus-hangul -ibus-kkc -ibus-pinyin -ibus-array -ibus-typing-booster -ibus-m17n -ibus-rawcode -ibus-lua -ibus-sayura -ibus-table -ibus-table-cantonese -ibus-table-erbi -ibus-table-ipa -ibus-table-jyutping -ibus-table-wubi -ibus-table-wbx -ibus-table-wm -ibus-table-wm86 -ibus-table-wm95 -ibus-table-wm98 -ibus-table-wubi -ibus-table-wubi-huizhou -ibus-table-wubi-pinyin -ibus-table-wubi-wx -ibus-table-wubi-wx86 -ibus-table-wubi-wx95 -ibus-table-wubi-wx98 -ibus-table-wubi-wx98p -ibus-table-wubi-wx98p2 -ibus-table-wubi-wx98p2b -ibus-table-wubi-wx98pb -ibus-table-wubi-wx98pbc -ibus-table-wubi-wx98pbcd -ibus-table-wubi-wx98pbcd %end # CA Certificate Installation %include /tmp/kickstart-ca-certificate.ks # WireGuard Configuration %include /tmp/kickstart-wireguard.ks # Package Verification Configuration %include /tmp/kickstart-package-verification.ks # Post-install configuration %post --erroronfail # Remove user from wheel group (disable sudo) gpasswd -d saw-user wheel # Disable root SSH login sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config # Enable auditd systemctl enable auditd # Enable SELinux setenforce 1 # Configure DNS to use VPN gateway only cat > /etc/dnsmasq.d/vpn-dns.conf << 'EOF' # VPN-only DNS configuration # All DNS queries go through VPN gateway server=10.0.0.1 server=::1 bogus-priv no-resolv no-poll no-hosts cache-size=10000 log-facility=@/var/log/dnsmasq.log EOF # Configure resolv.conf to use dnsmasq echo "nameserver 127.0.0.1" > /etc/resolv.conf # Configure firewall cat > /etc/firewalld/services/wireguard.xml << 'EOF' WireGuard WireGuard VPN tunnel EOF # Add WireGuard to firewall firewall-cmd --permanent --add-service=wireguard firewall-cmd --permanent --add-port=51820/udp # Configure DNF to require signatures cat > /etc/dnf/dnf.conf << 'EOF' # DNF configuration for SAW # Require GPG signature verification gpgcheck=1 repo_gpgcheck=1 # Disable metadata cache (force refresh) metadata_expire=1h # Disable fastest mirror (use direct repos) fastestmirror=False EOF # Create rpm-ostree configuration cat > /etc/rpm-ostreed.conf << 'EOF' [Service] # Auto-download updates DownloadOnly=true # Keep previous deployments KeepOld=2 # Enable automatic cleanup AutomaticCleanup=true EOF # Set up package verification scripts mkdir -p /usr/local/bin mkdir -p /etc/package-verification # Copy CA certificate to DNF key directory cp /etc/pki/ca-trust/source/anchors/ca.crt /etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca # Create package verification script cat > /usr/local/bin/verify-package.sh << 'VERIFYEOF' #!/bin/bash # Package verification script # Verifies package signatures against custom CA CA_KEY="/etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca" CRL_FILE="/etc/pki/ca-trust/source/anchors/crl.pem" # Check if CA key exists if [ ! -f "$CA_KEY" ]; then echo "ERROR: CA key not found: $CA_KEY" exit 1 fi # Verify CRL if available if [ -f "$CRL_FILE" ]; then # Check CRL signature if ! openssl verify -CAfile "$CA_KEY" "$CRL_FILE" >/dev/null 2>&1; then echo "WARNING: CRL signature verification failed" fi fi # Verify package signature for pkg in "$@"; do if ! rpm --checksig "$pkg" >/dev/null 2>&1; then echo "ERROR: Package signature verification failed: $pkg" exit 1 fi done echo "All packages verified successfully" exit 0 VERIFYEOF chmod +x /usr/local/bin/verify-package.sh # Create update approval script cat > /usr/local/bin/approve-update.sh << 'APPROVEEOF' #!/bin/bash # Update approval script for SAW # Shows update details and requires confirmation echo "=== Fedora Kinoite SAW Update Approval ===" echo "" # Check for updates echo "Checking for updates..." sudo rpm-ostree update --check 2>&1 | tee /tmp/update-check.txt if [ ${PIPESTATUS[0]} -ne 0 ]; then echo "No updates available" exit 0 fi echo "" echo "Review the update above." echo "Type 'yes' to apply, 'no' to cancel:" read -r response if [ "$response" = "yes" ]; then echo "Applying update..." sudo rpm-ostree upgrade else echo "Update cancelled" exit 0 fi APPROVEEOF chmod +x /usr/local/bin/approve-update.sh # Create daily CRL updater script cat > /usr/local/bin/daily-crl-update.sh << 'CRLEOF' #!/bin/bash # Daily CRL update script for SAW # Downloads and verifies CRL from CA server CRL_URL="https://your-ca-server.com/crl.pem" CRL_FILE="/etc/pki/ca-trust/source/anchors/crl.pem" CA_KEY="/etc/pki/ca-trust/source/anchors/ca.crt" LOG_FILE="/var/log/crl-update.log" echo "$(date): Starting CRL update" >> "$LOG_FILE" # Download CRL if ! curl -s -o "$CRL_FILE" "$CRL_URL"; then echo "$(date): ERROR: Failed to download CRL" >> "$LOG_FILE" exit 1 fi echo "$(date): CRL downloaded successfully" >> "$LOG_FILE" # Verify CRL signature if ! openssl crl -in "$CRL_FILE" -CAfile "$CA_KEY" -noout 2>&1; then echo "$(date): ERROR: CRL signature verification failed" >> "$LOG_FILE" exit 1 fi echo "$(date): CRL signature verified" >> "$LOG_FILE" # Update CA trust update-ca-trust extract echo "$(date): CRL update completed successfully" >> "$LOG_FILE" # Check for packages with revoked certificates if rpm -qa --queryformat='%{NAME} %{SIGPGP:pgpsig}\n' 2>/dev/null | grep -q "0x0"; then echo "$(date): WARNING: Found packages with revoked certificates" >> "$LOG_FILE" fi exit 0 CRLEOF chmod +x /usr/local/bin/daily-crl-update.sh # Create security audit script cat > /usr/local/bin/security-audit.sh << 'AUDITEOF' #!/bin/bash # Security audit script for SAW echo "=== Fedora Kinoite SAW Security Audit ===" echo "Date: $(date)" echo "" # Check system state echo "1. System State:" rpm-ostree status | head -5 echo "" # Check sudo access echo "2. Sudo Access:" if id -nG "$USER" | grep -q wheel; then echo " WARNING: User is in wheel group (sudo enabled)" else echo " OK: User is not in wheel group" fi echo "" # Check SELinux echo "3. SELinux Status:" sestatus | grep "Current mode" echo "" # Check auditd echo "4. Auditd Status:" systemctl is-active auditd || echo " auditd not running" echo "" # Check firewall echo "5. Firewall Status:" firewall-cmd --state 2>/dev/null || echo " firewalld not running" echo "" # Check VPN echo "6. VPN Status:" wg show 2>/dev/null || echo " WireGuard not configured" echo "" # Check for recent audit events echo "7. Recent Audit Events:" ausearch -m all -ts recent 2>/dev/null | head -10 echo "" # Check for failed sudo attempts echo "8. Failed Sudo Attempts:" grep "authentication failure" /var/log/secure 2>/dev/null | tail -5 echo "" echo "=== Audit Complete ===" AUDITEOF chmod +x /usr/local/bin/security-audit.sh # Create check-verification script cat > /usr/local/bin/check-verification.sh << 'CHECKEOF' #!/bin/bash # Check all package verifications for SAW echo "=== Package Verification Check ===" # Check CA certificate if [ -f /etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca ]; then echo "OK: CA certificate installed" else echo "ERROR: CA certificate not found" exit 1 fi # Check DNF configuration if grep -q "^gpgcheck=1" /etc/dnf/dnf.conf; then echo "OK: DNF signature verification enabled" else echo "ERROR: DNF signature verification not enabled" exit 1 fi # Check SELinux if [ "$(sestatus | grep "Current mode" | awk '{print $3}')" = "enforcing" ]; then echo "OK: SELinux enforcing" else echo "WARNING: SELinux not enforcing" fi # Check auditd if systemctl is-active auditd >/dev/null 2>&1; then echo "OK: Auditd running" else echo "WARNING: Auditd not running" fi # Check firewall if firewall-cmd --state 2>/dev/null | grep -q "running"; then echo "OK: Firewall running" else echo "WARNING: Firewall not running" fi echo "=== Verification Complete ===" CHECKEOF chmod +x /usr/local/bin/check-verification.sh # Set up CRL update cron job cat > /etc/cron.d/crl-update << 'CRONEOF' # Daily CRL update for SAW # Run at 2:00 AM 0 2 * * * root /usr/local/bin/daily-crl-update.sh >> /var/log/crl-update.log 2>&1 CRONEOF # Create initial VPN configuration cat > /tmp/wireguard.conf << 'WGEOF' [Interface] # Replace with your WireGuard private key PrivateKey = YOUR_PRIVATE_KEY_HERE # Replace with your VPN interface IP Address = 10.0.0.2/24 # Replace with your DNS server (VPN gateway) DNS = 10.0.0.1 [Peer] # Replace with your VPN server public key PublicKey = YOUR_SERVER_PUBLIC_KEY_HERE # Replace with your VPN server endpoint Endpoint = vpn.example.com:51820 # Allow all traffic through VPN AllowedIPs = 0.0.0.0/0, ::/0 # Replace with your VPN gateway IP AllowedIPs = 10.0.0.0/24 WGEOF # Copy WireGuard config to system cp /tmp/wireguard.conf /etc/wireguard/wg0.conf chmod 600 /etc/wireguard/wg0.conf # Enable WireGuard service systemctl enable wg-quick@wg0 # Final system updates dnf update -y # Clean up dnf clean all rm -rf /tmp/kickstart-*.ks rm -rf /tmp/wireguard.conf exit 0 %end ``` ## Customization Instructions ### 1. Generate Root Password ```bash # Generate encrypted password openssl passwd -6 # Replace YOUR_ENCRYPTED_PASSWORD_HERE with the output ``` ### 2. Configure CA Certificate Create a separate file `kickstart-ca-certificate.ks`: ```bash # Copy CA certificate %include /tmp/kickstart-ca-certificate.ks # Create kickstart-ca-certificate.ks: # Copy CA certificate to system mkdir -p /etc/pki/ca-trust/source/anchors cp /run/install/repo/ca.crt /etc/pki/ca-trust/source/anchors/ca.crt # Update CA trust database update-ca-trust extract # Copy to DNF key directory cp /etc/pki/ca-trust/source/anchors/ca.crt \ /etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca # Import into RPM database rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca ``` ### 3. Configure WireGuard Update the WireGuard configuration in the kickstart: ```bash # Replace these values: PrivateKey = YOUR_PRIVATE_KEY_HERE Address = 10.0.0.2/24 DNS = 10.0.0.1 PublicKey = YOUR_SERVER_PUBLIC_KEY_HERE Endpoint = vpn.example.com:51820 ``` ### 4. Add Custom Packages Add your packages to the `%packages` section: ```bash %packages @^kinoite-desktop @base @core @standard # Add your custom packages your-package-1 your-package-2 # Remove unnecessary packages (optional) -ibus-angry %end ``` ### 5. Configure Package Verification Update the package verification section with your CA details: ```bash # Copy CA certificate cp /etc/pki/ca-trust/source/anchors/ca.crt \ /etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca # Verify CA key format openssl x509 -in /etc/pki/ca-trust/source/anchors/ca.crt -text -noout ``` ## Troubleshooting ### Kickstart Validation ```bash # Validate kickstart syntax ksvalidator kinoite-saw.ks # Check for errors # Fix any syntax errors ``` ### ISO Build Debugging ```bash # Add debug output %post --erroronfail --log=/tmp/kickstart.log # Check log after build cat /tmp/kickstart.log ``` ### Network Issues ```bash # Add static network configuration network --bootproto=static --ip=192.168.1.100 \ --netmask=255.255.255.0 --gateway=192.168.1.1 \ --nameserver=8.8.8.8 --device=eth0 ``` ### Package Repository Issues ```bash # Add additional repositories repo --name=custom --baseurl=http://your-repo.com ``` ## Security Considerations 1. **CA Key Security:** - Store CA private key offline - Use strong encryption for keys - Never include private keys in kickstart 2. **Package Signing:** - Sign all packages with your CA - Verify signatures before installation - Keep CRL updated 3. **Network Security:** - Use VPN for all traffic - Block all direct internet access - Implement DNS lockdown 4. **Update Security:** - Require approval for updates - Verify update signatures - Test updates before deployment ## References - [Kickstart Syntax Reference](https://pykickstart.readthedocs.io/) - [Fedora Kinoite Installation](https://kinoite.fedoraproject.org/) - [RPM Signature Verification](https://docs.fedoraproject.org/en-US/fedora-coreos/security-verification/) - [WireGuard Documentation](https://www.wireguard.com/install/) --- **Previous:** [Installation Guide](INSTALLATION_GUIDE.md) **Next:** [Lockdown Script](../post-install/lockdown.sh)