#!/usr/bin/env bash # Device security facts, as JSON. # # Everything here is READ-ONLY and deliberately so. Secure Boot, TPM presence, # disk encryption, SELinux mode and the firewall are set in firmware, at install # time, or by system policy -- none of them is a desktop preference, and a # settings app that offered to toggle them would either fail or do something # far-reaching from a switch that looks like any other. # # What it is for is answering "is this machine set up the way I think it is", # which is the question GNOME's Device Security panel exists to answer and which # otherwise needs five commands and root. # # Each fact is reported as {value, ok} where `ok` marks the reassuring state, so # the UI can highlight what deserves attention without hard-coding the meaning # of each string. Anything that cannot be determined reports "Unknown" with # ok:false rather than guessing, because a security readout that quietly reports # "fine" when it failed to look is worse than no readout. set -uo pipefail fact() { jq -cn --arg label "$1" --arg value "$2" --argjson ok "$3" --arg detail "${4:-}" \ '{label: $label, value: $value, ok: $ok, detail: $detail}' } facts=() # ── Secure Boot ────────────────────────────────────────────────────────────── if command -v mokutil >/dev/null 2>&1; then case "$(mokutil --sb-state 2>/dev/null)" in *"SecureBoot enabled"*) facts+=("$(fact "Secure Boot" "Enabled" true "Firmware verifies the bootloader and kernel signatures")" ) ;; *"SecureBoot disabled"*) facts+=("$(fact "Secure Boot" "Disabled" false "Firmware does not verify what it boots")") ;; *) facts+=("$(fact "Secure Boot" "Unknown" false "The firmware did not report a Secure Boot state")") ;; esac elif [[ -d /sys/firmware/efi ]]; then facts+=("$(fact "Secure Boot" "Unknown" false "Install mokutil to report this")") else facts+=("$(fact "Secure Boot" "Not applicable" false "This machine booted in legacy BIOS mode")") fi # ── TPM ────────────────────────────────────────────────────────────────────── tpm_major="$(cat /sys/class/tpm/tpm0/tpm_version_major 2>/dev/null || true)" if [[ -n "$tpm_major" ]]; then facts+=("$(fact "TPM" "Version $tpm_major" true "A trusted platform module is present and usable")") elif [[ -e /sys/class/tpm/tpm0 ]]; then facts+=("$(fact "TPM" "Present" true "A trusted platform module is present")") else facts+=("$(fact "TPM" "None" false "No trusted platform module, so keys cannot be sealed to this machine")") fi # ── Disk encryption ────────────────────────────────────────────────────────── # Counts LUKS mappings rather than naming them: which volume is encrypted is # more detail than this readout needs, and device names are not meaningful here. crypt_count="$(lsblk -o TYPE 2>/dev/null | grep -c '^crypt$' || true)" [[ "$crypt_count" =~ ^[0-9]+$ ]] || crypt_count=0 if (( crypt_count > 0 )); then facts+=("$(fact "Disk encryption" "$crypt_count encrypted volume$( (( crypt_count == 1 )) || printf 's')" true "Data at rest is protected by LUKS")") else facts+=("$(fact "Disk encryption" "None" false "No LUKS volume is unlocked on this machine")") fi # ── SELinux ────────────────────────────────────────────────────────────────── if command -v getenforce >/dev/null 2>&1; then case "$(getenforce 2>/dev/null)" in Enforcing) facts+=("$(fact "SELinux" "Enforcing" true "Policy violations are blocked")") ;; Permissive) facts+=("$(fact "SELinux" "Permissive" false "Violations are logged but allowed")") ;; Disabled) facts+=("$(fact "SELinux" "Disabled" false "Mandatory access control is off")") ;; *) facts+=("$(fact "SELinux" "Unknown" false "")") ;; esac fi # ── Firewall ───────────────────────────────────────────────────────────────── if systemctl list-unit-files firewalld.service >/dev/null 2>&1; then if [[ "$(systemctl is-active firewalld 2>/dev/null)" == "active" ]]; then facts+=("$(fact "Firewall" "Active" true "firewalld is filtering incoming connections")") else facts+=("$(fact "Firewall" "Inactive" false "firewalld is installed but not running")") fi fi printf '[%s]\n' "$(IFS=,; printf '%s' "${facts[*]}")"