Documentation
¶
Overview ¶
Package linux holds the Linux check implementations.
Each check operates on the "linux.host" Resources emitted by the linux collector (internal/collectors/linux). Helper functions live here for resource attribute extraction common across many checks.
Per v0.2 ROADMAP §9, the Linux check set targets CIS Ubuntu / Debian directives weighted for "what actually matters in 2026". v0.2 ships 15 checks total; this file holds the five sshd hardening checks.
Index ¶
- Constants
- Variables
- func ASLREnabled(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func AppArmorActive(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func AuditdRunning(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func DistroSupported(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func EncryptMethod(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func FirewallActive(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func FirewallDefaultDeny(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func FirewallNFTablesOnRHEL(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func FirewallSomeActive(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func FirewallUFWDefaultDenyOutgoing(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func JournaldPersistent(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func NoEmptyPasswords(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func NoSourceRouting(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func PassMaxDays(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func PassMinDays(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func PassWarnAge(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func PasswdPerms(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func SELinuxEnforcing(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func SSHDLoginGraceTime(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func SSHDMaxAuthTries(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func SSHDNoPasswordAuth(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func SSHDNoRootLogin(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func SSHDProtocol2(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func ShadowPerms(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func UIDZeroOnlyRoot(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
- func UmaskCheck(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
Constants ¶
const LoginGraceTimeCeilingSeconds = 60
LoginGraceTimeCeilingSeconds is the maximum LoginGraceTime in seconds. Lower values frustrate online brute-force by tying up fewer connection slots.
const MaxAuthTriesCeiling = 4
MaxAuthTriesCeiling is the highest value at which MaxAuthTries remains compliant. Operators routinely lower it further; 4 is the CIS-recommended ceiling.
Variables ¶
var CheckASLREnabled = compliancekit.Check{ ID: "linux-aslr-enabled", Title: "Address Space Layout Randomization must be fully enabled", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "kernel", ResourceType: linuxcol.HostType, Description: "ASLR randomizes the address space of running " + "processes, raising the cost of memory-corruption exploits. " + "kernel.randomize_va_space=2 is the full-strength setting " + "(stack + heap + brk + vdso + mmap). 0 disables; 1 is a " + "weakened subset. CIS Ubuntu 3.2.1.", Remediation: "sysctl -w kernel.randomize_va_space=2 (runtime) and " + "add the line to /etc/sysctl.conf or a drop-in under " + "/etc/sysctl.d/ for persistence.", Frameworks: map[string][]string{ "soc2": {"CC6.6"}, "iso27001": {"A.8.8"}, "cis-v8": {"4.1"}, }, Tags: []string{"kernel", "exploit-mitigation"}, Scanner: "kernel.ASLREnabled", }
CheckASLREnabled requires kernel.randomize_va_space=2.
var CheckAppArmorActive = compliancekit.Check{ ID: "linux-mac-apparmor-active", Title: "AppArmor must be active on Debian-family hosts", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "mac", ResourceType: docol.HostType, Description: "AppArmor is the Debian/Ubuntu MAC layer. Active = kernel module loaded " + "AND at least one profile loaded. CIS Linux Server v8 §1.7.2.", Remediation: "sudo apt-get install -y apparmor apparmor-utils\nsudo systemctl enable --now apparmor\nsudo aa-enforce /etc/apparmor.d/*", Frameworks: map[string][]string{ "soc2": {"CC6.6"}, "iso27001": {"A.8.7"}, "cis-v8": {"1.7.2"}, "cis-linux-server": {"1.7.2"}, }, Tags: []string{"mac", "apparmor"}, Scanner: "linux.mac.AppArmorActive", }
var CheckAuditdRunning = compliancekit.Check{ ID: "linux-auditd-running", Title: "auditd must be running", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "audit", ResourceType: linuxcol.HostType, Description: "auditd captures syscall-level audit events that " + "satisfy 'log access to sensitive systems' controls. Without " + "it, evidence for SOC 2 CC7.2, ISO 27001 A.8.15, and CIS " + "Controls v8 8.5 is hard to produce.", Remediation: "Install and enable auditd: " + "'sudo apt install auditd && sudo systemctl enable --now auditd' " + "(Debian/Ubuntu) or the equivalent on your distro.", Frameworks: map[string][]string{ "soc2": {"CC7.2", "CC7.3"}, "iso27001": {"A.8.15"}, "cis-v8": {"8.5"}, }, Tags: []string{"audit", "logging"}, Scanner: "audit.AuditdRunning", }
CheckAuditdRunning requires auditd to be active.
var CheckDistroSupported = compliancekit.Check{ ID: "linux-distro-supported", Title: "/etc/os-release ID must be on the supported-distro allowlist", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "distro", ResourceType: docol.HostType, Description: "v0.20 introduces per-distro behavior in many Linux checks " + "(package manager, init system, sysctl key names). The collector " + "reads /etc/os-release at the top of every gather pass; if the " + "ID isn't on the allowlist (debian, ubuntu, rhel, centos, rocky, " + "almalinux, fedora, alpine, amzn) downstream checks fall through " + "to generic defaults that may misclassify findings. Pin the host " + "to a supported distro OR open a tracking issue to extend the " + "allowlist.", Remediation: "Either migrate the workload to a supported distro " + "(Ubuntu LTS / Debian Stable / RHEL family / Alpine / Amazon " + "Linux 2 or 2023), or open an issue at " + "https://github.com/darpanzope/compliancekit/issues with the " + "target distro + /etc/os-release contents so it can be added to " + "`supportedDistros` in `internal/checks/linux/distro.go`.", Frameworks: map[string][]string{ "soc2": {"CC7.1"}, "iso27001": {"A.8.8"}, "cis-v8": {"7.3"}, }, Tags: []string{"distro", "platform"}, Scanner: "linux.distro.Supported", }
var CheckEncryptMethod = compliancekit.Check{ ID: "linux-login-defs-encrypt-method", Title: "/etc/login.defs ENCRYPT_METHOD must be SHA512 or YESCRYPT", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "auth", ResourceType: docol.HostType, Description: "ENCRYPT_METHOD controls the hash algorithm used to store new " + "user passwords in /etc/shadow. SHA512 + YESCRYPT are the only " + "acceptable choices in 2026 (DES + MD5 are trivially crackable; " + "SHA256 is acceptable but SHA512 is the explicit CIS pick). " + "CIS Linux Server v8 §5.5.1.4.", Remediation: "/etc/login.defs:\n ENCRYPT_METHOD YESCRYPT # or SHA512\nRehash existing accounts on next password change.", Frameworks: map[string][]string{ "soc2": {"CC6.7"}, "iso27001": {"A.8.24"}, "cis-v8": {"5.5.1.4"}, }, Tags: []string{"auth", "password-hashing"}, Scanner: "linux.login.EncryptMethod", }
var CheckFirewallActive = compliancekit.Check{ ID: "linux-firewall-active", Title: "A host firewall must be active", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "firewall", ResourceType: linuxcol.HostType, Description: "A host with no active firewall accepts every packet " + "its NIC sees. ufw and nftables are the two modern Linux " + "options; this check passes when either reports an active " + "state. SOC 2 CC6.6, ISO 27001 A.8.20, and CIS Controls v8 " + "4.4 all require network access controls on production hosts.", Remediation: "Enable ufw ('sudo ufw enable' on Debian/Ubuntu) or " + "nftables ('sudo systemctl enable --now nftables'). Verify " + "with 'sudo ufw status' or 'sudo nft list ruleset'.", Frameworks: map[string][]string{ "soc2": {"CC6.6", "CC6.1"}, "iso27001": {"A.8.20"}, "cis-v8": {"4.4", "12.2"}, }, Tags: []string{"firewall", "network"}, Scanner: "firewall.Active", }
CheckFirewallActive requires ufw or nftables to be active.
var CheckFirewallDefaultDeny = compliancekit.Check{ ID: "linux-firewall-default-deny", Title: "Firewall default-incoming policy must be deny", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "firewall", ResourceType: linuxcol.HostType, Description: "An active firewall whose default policy is allow is " + "only slightly safer than no firewall at all -- every port " + "without an explicit deny rule is reachable. Default-deny " + "with explicit allows is the only defensible posture. SOC 2 " + "CC6.6, ISO 27001 A.8.20, and CIS Controls v8 4.4 require this.", Remediation: "On ufw: 'sudo ufw default deny incoming'. On nftables, " + "set the inet filter input chain policy to drop.", Frameworks: map[string][]string{ "soc2": {"CC6.6", "CC6.1"}, "iso27001": {"A.8.20"}, "cis-v8": {"4.4", "12.2"}, }, Tags: []string{"firewall", "network", "default-policy"}, Scanner: "firewall.DefaultDeny", }
CheckFirewallDefaultDeny requires ufw's default-incoming policy to be "deny". This is a ufw-specific check; nftables-only hosts are Skipped because the equivalent assertion requires parsing nft rules.
var CheckFirewallNFTablesOnRHEL = compliancekit.Check{ ID: "linux-firewall-nftables-on-rhel", Title: "RHEL-family hosts should run nftables (modern replacement for iptables)", Severity: compliancekit.SeverityLow, Provider: "linux", Service: "firewall", ResourceType: docol.HostType, Description: "nftables is the upstream replacement for iptables; RHEL 8+ ships with " + "firewalld backed by nftables. Hosts in the RHEL family running iptables-only " + "miss the cleaner rule grammar + atomic rule replacement. Debian/Ubuntu still " + "defaults to ufw — this check skips there.", Remediation: "sudo systemctl enable --now nftables\nMigrate iptables rules via `iptables-restore-translate -f /etc/sysconfig/iptables`.", Frameworks: map[string][]string{ "soc2": {"CC6.6"}, "iso27001": {"A.8.20"}, "cis-v8": {"3.4.2"}, "cis-linux-server": {"3.4.2"}, }, Tags: []string{"firewall", "nftables", "rhel"}, Scanner: "linux.firewall.NFTablesOnRHEL", }
var CheckFirewallSomeActive = compliancekit.Check{ ID: "linux-firewall-some-active", Title: "Some firewall must be active (ufw, nftables, or firewalld)", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "firewall", ResourceType: docol.HostType, Description: "A host with NO active firewall trusts the upstream cloud provider's " + "security groups entirely. Defense in depth wants both — at minimum a nftables " + "default-deny INPUT table on RHEL-family or ufw active on Debian-family.", Remediation: "Debian/Ubuntu: sudo ufw enable\nRHEL family: sudo systemctl enable --now nftables firewalld", Frameworks: map[string][]string{ "soc2": {"CC6.6"}, "iso27001": {"A.8.20"}, "cis-v8": {"3.4.1"}, "cis-linux-server": {"3.4.1"}, }, Tags: []string{"firewall", "must-active"}, Scanner: "linux.firewall.SomeActive", }
var CheckFirewallUFWDefaultDenyOutgoing = compliancekit.Check{ ID: "linux-firewall-ufw-default-deny-outgoing", Title: "ufw default policy: outgoing must be deny on egress-controlled hosts", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "firewall", ResourceType: docol.HostType, Description: "Default-deny egress is the modern way to constrain a compromised process " + "from beacons / data-exfil. CIS Linux Server v8 §3.4.2.1 recommends explicit " + "egress allow-lists with default deny. Waive on hosts that need broad outbound " + "access (build runners, package mirrors).", Remediation: "sudo ufw default deny outgoing\n" + "sudo ufw allow out 443/tcp comment 'HTTPS'\n" + "sudo ufw allow out 53 comment 'DNS'\n" + "sudo ufw reload", Frameworks: map[string][]string{ "soc2": {"CC6.6"}, "iso27001": {"A.8.20"}, "cis-v8": {"3.4.2.1"}, "cis-linux-server": {"3.4.2.1"}, }, Tags: []string{"firewall", "ufw", "egress"}, Scanner: "linux.firewall.UFWDefaultDenyOutgoing", }
var CheckJournaldPersistent = compliancekit.Check{ ID: "linux-journald-persistent", Title: "journald must use persistent storage", Severity: compliancekit.SeverityLow, Provider: "linux", Service: "audit", ResourceType: linuxcol.HostType, Description: "systemd's journald default ('auto') writes to disk " + "only if /var/log/journal exists, and falls back to a " + "volatile ramdisk otherwise. A reboot wipes the latter and " + "breaks the audit trail. Setting Storage=persistent forces " + "disk storage and creates the directory if missing.", Remediation: "Set 'Storage=persistent' in /etc/systemd/journald.conf " + "and 'systemctl restart systemd-journald'. Confirm with " + "'journalctl --header | head'.", Frameworks: map[string][]string{ "soc2": {"CC7.2"}, "iso27001": {"A.8.15"}, "cis-v8": {"8.5", "8.10"}, }, Tags: []string{"audit", "logging", "journald"}, Scanner: "audit.JournaldPersistent", }
CheckJournaldPersistent requires journald Storage=persistent so logs survive reboots and produce auditor-acceptable evidence.
var CheckNoEmptyPasswords = compliancekit.Check{ ID: "linux-no-empty-passwords", Title: "No account may have an empty password", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "users", ResourceType: linuxcol.HostType, Description: "An account whose /etc/shadow password field is " + "literally empty can be logged in to with any password (or " + "no password, depending on PAM config). CIS Ubuntu 7.2.4 " + "requires that no entry have an empty hash; locked accounts " + "use '!' or '*' instead.", Remediation: "passwd -l <user> to lock the account, or set a " + "strong password.", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.8.5"}, "cis-v8": {"5.2"}, }, Tags: []string{"users", "passwords"}, Scanner: "users.NoEmptyPasswords", }
CheckNoEmptyPasswords requires no /etc/shadow entry to have an empty password hash field.
var CheckNoSourceRouting = compliancekit.Check{ ID: "linux-no-source-routing", Title: "Kernel must not accept source-routed packets", Severity: compliancekit.SeverityLow, Provider: "linux", Service: "kernel", ResourceType: linuxcol.HostType, Description: "Source-routed packets let a sender dictate the path " + "taken across the network, defeating egress filtering and " + "enabling spoofing. Modern Linux defaults to 0 (drop); this " + "check confirms the default has not been overridden. " + "CIS Ubuntu 3.3.1.", Remediation: "sysctl -w net.ipv4.conf.all.accept_source_route=0 " + "and persist via /etc/sysctl.d/.", Frameworks: map[string][]string{ "soc2": {"CC6.6"}, "iso27001": {"A.8.20"}, "cis-v8": {"12.2"}, }, Tags: []string{"kernel", "network"}, Scanner: "kernel.NoSourceRouting", }
CheckNoSourceRouting requires net.ipv4.conf.all.accept_source_route=0.
var CheckPassMaxDays = compliancekit.Check{ ID: "linux-login-defs-pass-max-days", Title: "/etc/login.defs PASS_MAX_DAYS must be ≤ 365", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "auth", ResourceType: docol.HostType, Description: "PASS_MAX_DAYS bounds the maximum password lifetime for accounts " + "created from /etc/login.defs defaults. CIS Linux Server v8 §5.5.1.1 " + "requires ≤365 (NIST 800-63B aligned). Existing accounts may need " + "`chage --maxdays` separately.", Remediation: "Edit /etc/login.defs:\n PASS_MAX_DAYS 365\nApply to existing users:\n awk -F: '($3>=1000 && $3<60000) {print $1}' /etc/passwd | xargs -I{} chage --maxdays 365 {}", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.5.17"}, "cis-v8": {"5.5.1.1"}, }, Tags: []string{"auth", "password-age"}, Scanner: "linux.login.PassMaxDays", }
var CheckPassMinDays = compliancekit.Check{ ID: "linux-login-defs-pass-min-days", Title: "/etc/login.defs PASS_MIN_DAYS must be ≥ 1", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "auth", ResourceType: docol.HostType, Description: "PASS_MIN_DAYS prevents a user from cycling through their password " + "history in a single sitting (defeats reuse-prevention). CIS §5.5.1.2 requires ≥1.", Remediation: "/etc/login.defs:\n PASS_MIN_DAYS 1", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.5.17"}, "cis-v8": {"5.5.1.2"}, }, Tags: []string{"auth", "password-age"}, Scanner: "linux.login.PassMinDays", }
var CheckPassWarnAge = compliancekit.Check{ ID: "linux-login-defs-pass-warn-age", Title: "/etc/login.defs PASS_WARN_AGE must be ≥ 7", Severity: compliancekit.SeverityLow, Provider: "linux", Service: "auth", ResourceType: docol.HostType, Description: "PASS_WARN_AGE controls how many days ahead of expiry the user " + "sees a warning at login. ≥7 days gives the user a meaningful chance " + "to rotate before being locked out. CIS §5.5.1.3.", Remediation: "/etc/login.defs:\n PASS_WARN_AGE 7", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.5.17"}, "cis-v8": {"5.5.1.3"}, }, Tags: []string{"auth", "password-age"}, Scanner: "linux.login.PassWarnAge", }
var CheckPasswdPerms = compliancekit.Check{ ID: "linux-passwd-perms", Title: "/etc/passwd must be 0644 or stricter", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "filesystem", ResourceType: linuxcol.HostType, Description: "/etc/passwd must be world-readable (login commands " + "need it) but must not be writable by anyone but root. CIS " + "Ubuntu 7.1.2 prescribes mode 0644 exactly; we accept 0644 " + "or stricter (0640, 0600).", Remediation: "chmod 0644 /etc/passwd && chown root:root /etc/passwd.", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.8.3"}, "cis-v8": {"3.3"}, }, Tags: []string{"filesystem", "passwd"}, Scanner: "filesystem.PasswdPerms", }
CheckPasswdPerms requires /etc/passwd to be mode 0644 or stricter.
var CheckSELinuxEnforcing = compliancekit.Check{ ID: "linux-mac-selinux-enforcing", Title: "SELinux must be enforcing on RHEL-family hosts", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "mac", ResourceType: docol.HostType, Description: "SELinux 'enforcing' is the production posture — 'permissive' logs " + "violations without blocking them (useful only during policy tuning); " + "'disabled' removes the MAC layer entirely. CIS Linux Server v8 §1.7.1.4 " + "requires enforcing on RHEL-family hosts.", Remediation: "sudo setenforce 1 # live\nsudo sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config # persist", Frameworks: map[string][]string{ "soc2": {"CC6.6"}, "iso27001": {"A.8.7"}, "cis-v8": {"1.7.1.4"}, "cis-linux-server": {"1.7.1.4"}, }, Tags: []string{"mac", "selinux"}, Scanner: "linux.mac.SELinuxEnforcing", }
var CheckSSHDLoginGraceTime = compliancekit.Check{ ID: "linux-sshd-login-grace-time", Title: "SSH LoginGraceTime should be 60 seconds or less", Severity: compliancekit.SeverityLow, Provider: "linux", Service: "sshd", ResourceType: linuxcol.HostType, Description: "LoginGraceTime is the window between connection " + "and authentication completion. A long window lets a misbehaving " + "client (or attacker) hold a connection slot open, enabling " + "slowloris-style resource exhaustion. OpenSSH default is 2 " + "minutes; CIS recommends 60 seconds or less.", Remediation: "Set 'LoginGraceTime 60' in /etc/ssh/sshd_config and " + "reload sshd.", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.8.20", "A.8.21"}, "cis-v8": {"5.2", "8.5"}, }, Tags: []string{"sshd", "resource-exhaustion"}, Scanner: "sshd.LoginGraceTime", }
CheckSSHDLoginGraceTime flags LoginGraceTime > 60s.
var CheckSSHDMaxAuthTries = compliancekit.Check{ ID: "linux-sshd-max-auth-tries", Title: "SSH MaxAuthTries should be 4 or less", Severity: compliancekit.SeverityLow, Provider: "linux", Service: "sshd", ResourceType: linuxcol.HostType, Description: "MaxAuthTries caps the number of authentication " + "attempts per connection; a low value frustrates online " + "brute-force. The OpenSSH default is 6; CIS Controls v8 " + "recommends 4 or less.", Remediation: "Set 'MaxAuthTries 4' (or lower) in /etc/ssh/sshd_config " + "and reload sshd.", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.8.21"}, "cis-v8": {"5.2"}, }, Tags: []string{"sshd", "brute-force"}, Scanner: "sshd.MaxAuthTries", }
CheckSSHDMaxAuthTries flags MaxAuthTries > MaxAuthTriesCeiling.
var CheckSSHDNoPasswordAuth = compliancekit.Check{ ID: "linux-sshd-no-password-auth", Title: "SSH must not accept password authentication", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "sshd", ResourceType: linuxcol.HostType, Description: "Password authentication exposes SSH to credential " + "stuffing and online brute-force. Public-key authentication " + "is the modern baseline. SOC 2 CC6.1 and CIS Controls v8 5.2 " + "both require strong authentication for remote administrative " + "access.", Remediation: "Set 'PasswordAuthentication no' in /etc/ssh/sshd_config " + "(and confirm operators have working public-key access first to " + "avoid lockout). Reload sshd to apply.", Frameworks: map[string][]string{ "soc2": {"CC6.1", "CC6.6"}, "iso27001": {"A.8.5", "A.8.21"}, "cis-v8": {"5.2", "6.5"}, }, Tags: []string{"sshd", "authentication"}, Scanner: "sshd.NoPasswordAuth", }
CheckSSHDNoPasswordAuth requires PasswordAuthentication=no.
var CheckSSHDNoRootLogin = compliancekit.Check{ ID: "linux-sshd-no-root-login", Title: "SSH must not permit root login", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "sshd", ResourceType: linuxcol.HostType, Description: "Direct root SSH logins bypass per-user auditability " + "and remove the speed bump that catches automated brute-force. " + "SOC 2 CC6.1 / CC6.6, ISO 27001 A.8.21, and CIS Controls v8 " + "5.4 all require unique attribution for privileged access.", Remediation: "Set 'PermitRootLogin no' in /etc/ssh/sshd_config and " + "reload sshd (systemctl reload sshd). Operators should use a " + "named user + sudo instead.", Frameworks: map[string][]string{ "soc2": {"CC6.1", "CC6.6"}, "iso27001": {"A.8.21"}, "cis-v8": {"5.4"}, }, Tags: []string{"sshd", "access-control"}, Scanner: "sshd.NoRootLogin", }
CheckSSHDNoRootLogin requires PermitRootLogin=no.
var CheckSSHDProtocol2 = compliancekit.Check{ ID: "linux-sshd-protocol-2", Title: "SSH must use protocol version 2 only", Severity: compliancekit.SeverityLow, Provider: "linux", Service: "sshd", ResourceType: linuxcol.HostType, Description: "SSH-1 was retired in 2017 and is cryptographically " + "broken. Modern OpenSSH defaults to Protocol 2 and refuses to " + "build SSH-1 without explicit flags; this check confirms the " + "observed config has not been weakened. Mostly an audit-trail " + "check at this point.", Remediation: "Remove any 'Protocol 1' line from /etc/ssh/sshd_config " + "(or set 'Protocol 2' explicitly). Reload sshd to apply.", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.8.20"}, "cis-v8": {"3.10"}, }, Tags: []string{"sshd", "crypto"}, Scanner: "sshd.Protocol2", }
CheckSSHDProtocol2 requires Protocol 2 (SSH-1 is ancient and broken).
var CheckShadowPerms = compliancekit.Check{ ID: "linux-shadow-perms", Title: "/etc/shadow must be 0640 root:shadow", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "filesystem", ResourceType: linuxcol.HostType, Description: "/etc/shadow holds the password hashes for every local " + "account. Read access for non-root, non-shadow users enables " + "offline cracking and is the textbook CIS Ubuntu 7.1.3 finding. " + "Correct ownership is root:shadow with mode 0640.", Remediation: "chmod 0640 /etc/shadow && chown root:shadow /etc/shadow.", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.8.3"}, "cis-v8": {"3.3", "5.1"}, }, Tags: []string{"filesystem", "shadow"}, Scanner: "filesystem.ShadowPerms", }
CheckShadowPerms requires /etc/shadow to be mode 0640 and owned root:shadow (CIS Ubuntu 22.04 benchmark 7.1.3).
var CheckUIDZeroOnlyRoot = compliancekit.Check{ ID: "linux-uid-zero-only-root", Title: "Only the root account may have UID 0", Severity: compliancekit.SeverityHigh, Provider: "linux", Service: "users", ResourceType: linuxcol.HostType, Description: "A second account with UID 0 is a stealth backdoor: " + "sudo / auditd see the username but every privilege check " + "resolves to root. CIS Ubuntu 5.4.3 requires that only the " + "literal 'root' user holds UID 0.", Remediation: "userdel <hidden-root-account> or change its UID to a " + "non-zero value with usermod -u <uid> <name>.", Frameworks: map[string][]string{ "soc2": {"CC6.1", "CC6.6"}, "iso27001": {"A.8.2"}, "cis-v8": {"5.4", "6.8"}, }, Tags: []string{"users", "privilege"}, Scanner: "users.UIDZeroOnlyRoot", }
CheckUIDZeroOnlyRoot requires that only the "root" account has UID 0.
var CheckUmask = compliancekit.Check{ ID: "linux-login-defs-umask", Title: "/etc/login.defs UMASK must be 027 or stricter", Severity: compliancekit.SeverityMedium, Provider: "linux", Service: "auth", ResourceType: docol.HostType, Description: "Default UMASK 022 (group + world readable) is too permissive for " + "shared / multi-tenant systems. 027 (no group write, no world access) " + "is the CIS Linux Server v8 §5.5.5 recommendation.", Remediation: "/etc/login.defs:\n UMASK 027\nAlso check /etc/profile.d/*.sh + /etc/bashrc for shell-level overrides.", Frameworks: map[string][]string{ "soc2": {"CC6.1"}, "iso27001": {"A.8.7"}, "cis-v8": {"5.5.5"}, }, Tags: []string{"auth", "umask"}, Scanner: "linux.login.Umask", }
Functions ¶
func ASLREnabled ¶
func ASLREnabled(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
ASLREnabled is the CheckFunc for CheckASLREnabled.
func AppArmorActive ¶ added in v0.20.0
func AppArmorActive(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func AuditdRunning ¶
func AuditdRunning(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
AuditdRunning is the CheckFunc for CheckAuditdRunning.
func DistroSupported ¶ added in v0.20.0
func DistroSupported(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func EncryptMethod ¶ added in v0.20.0
func EncryptMethod(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func FirewallActive ¶
func FirewallActive(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
FirewallActive is the CheckFunc for CheckFirewallActive.
func FirewallDefaultDeny ¶
func FirewallDefaultDeny(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
FirewallDefaultDeny is the CheckFunc for CheckFirewallDefaultDeny.
Behavior:
- host unreachable / firewall probe failed -> Skip
- ufw active and default_incoming == "deny" -> Pass
- ufw active and default_incoming == anything else -> Fail
- nftables active but no ufw -> Skip (we don't parse nft rules yet)
- neither active -> Fail (covered better by FirewallActive, but this check also fires for completeness)
func FirewallNFTablesOnRHEL ¶ added in v0.20.0
func FirewallNFTablesOnRHEL(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func FirewallSomeActive ¶ added in v0.20.0
func FirewallSomeActive(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func FirewallUFWDefaultDenyOutgoing ¶ added in v0.20.0
func FirewallUFWDefaultDenyOutgoing(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func JournaldPersistent ¶
func JournaldPersistent(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
JournaldPersistent is the CheckFunc for CheckJournaldPersistent.
func NoEmptyPasswords ¶
func NoEmptyPasswords(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
NoEmptyPasswords is the CheckFunc for CheckNoEmptyPasswords.
func NoSourceRouting ¶
func NoSourceRouting(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
NoSourceRouting is the CheckFunc for CheckNoSourceRouting.
func PassMaxDays ¶ added in v0.20.0
func PassMaxDays(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func PassMinDays ¶ added in v0.20.0
func PassMinDays(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func PassWarnAge ¶ added in v0.20.0
func PassWarnAge(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func PasswdPerms ¶
func PasswdPerms(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
PasswdPerms is the CheckFunc for CheckPasswdPerms.
func SELinuxEnforcing ¶ added in v0.20.0
func SELinuxEnforcing(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
func SSHDLoginGraceTime ¶
func SSHDLoginGraceTime(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
SSHDLoginGraceTime is the CheckFunc for CheckSSHDLoginGraceTime.
func SSHDMaxAuthTries ¶
func SSHDMaxAuthTries(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
SSHDMaxAuthTries is the CheckFunc for CheckSSHDMaxAuthTries.
func SSHDNoPasswordAuth ¶
func SSHDNoPasswordAuth(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
SSHDNoPasswordAuth is the CheckFunc for CheckSSHDNoPasswordAuth.
func SSHDNoRootLogin ¶
func SSHDNoRootLogin(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
SSHDNoRootLogin is the CheckFunc for CheckSSHDNoRootLogin.
func SSHDProtocol2 ¶
func SSHDProtocol2(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
SSHDProtocol2 is the CheckFunc for CheckSSHDProtocol2.
func ShadowPerms ¶
func ShadowPerms(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
ShadowPerms is the CheckFunc for CheckShadowPerms.
func UIDZeroOnlyRoot ¶
func UIDZeroOnlyRoot(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
UIDZeroOnlyRoot is the CheckFunc for CheckUIDZeroOnlyRoot.
func UmaskCheck ¶ added in v0.20.0
func UmaskCheck(_ context.Context, g *compliancekit.ResourceGraph) ([]compliancekit.Finding, error)
Types ¶
This section is empty.