616 lines
14 KiB
Plaintext
616 lines
14 KiB
Plaintext
# 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'
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<service>
|
|
<short>WireGuard</short>
|
|
<description>WireGuard VPN tunnel</description>
|
|
<port protocol="udp" port="51820"/>
|
|
</service>
|
|
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) |