# Linux resources

> The nine resource types that inspect Linux subsystems.

Source: https://refpoint.dev/docs/resources/linux

These nine resource types read Linux subsystems that have no cross-platform
equivalent. Give a control that uses them `platform = ["linux"]`, so it is
omitted on other targets rather than erroring there.

Most of them are label-only: nothing needs addressing because the check
inspects a subsystem as a whole, so the check name is just the report label.

## auditd

Label-only. Reads `auditctl -l`, falling back to the rules files under
`/etc/audit/`.

| Attribute | Type | Notes |
|---|---|---|
| `rule` | string, required | Go regex matched against each audit rule line |
| `present` | bool | Default true |

## cron

Label-only.

| Attribute | Type | Notes |
|---|---|---|
| `pattern` | string, required | Go regex matched against each crontab line |
| `user` | string | Whose crontab. Empty means the system crontabs, `/etc/crontab` plus `/etc/cron.d/*` |
| `present` | bool | Default true |

## mount

Path-addressed at the mount point, read via `findmnt`.

| Attribute | Type | Notes |
|---|---|---|
| `path` | string, address | |
| `mounted` | bool | |
| `options` | list(string) | All must be present, for example `["noexec", "nosuid"]` |
| `device` | string | Substring against the source device |
| `fstype` | string | Exact match |

```hcl
check "tmp-hardening" "mount" {
  path    = "/tmp"
  mounted = true
  options = ["noexec", "nosuid", "nodev"]
}
```

## firewall

Label-only, conventionally addressed as `default`. Probes ufw, then firewalld,
then nftables. This is the Linux counterpart to `windows_firewall`.

| Attribute | Type | Notes |
|---|---|---|
| `enabled` | bool | Some backend must be active |
| `backend` | string | `ufw`, `firewalld`, `nftables`. Unset means the first active backend in probe order |
| `default_incoming` | string | `deny`, `reject`, `allow`. ufw and firewalld only |
| `default_outgoing` | string | ufw only |

## sshd_config

Label-only. Asserts on the effective configuration via `sshd -T`, so it sees
`Include` files, `Match` blocks, and compiled-in defaults. Grepping
`sshd_config` cannot do that, and it can be fooled by a drop-in or by a
default that was never written down.

| Block | Attribute | Notes |
|---|---|---|
| `option "<Name>"` | | The label is matched case-insensitively |
| | `value` | Exact effective value, case-insensitive |
| | `min_value` / `max_value` | Numeric options such as `maxauthtries` |
| | `contains` | A token in a comma-separated value such as `ciphers`, `macs`, `kexalgorithms` |

Option labels are matched case-insensitively, so `option "PermitRootLogin"` and
`option "permitrootlogin"` are the same assertion. The example below uses the
lowercase form because that is how `sshd -T` prints its keywords, which makes a
check easy to compare against the command's output by hand. The examples
elsewhere in these docs use the `sshd_config(5)` spelling, and behave
identically.

```hcl
check "sshd" "sshd_config" {
  option "permitrootlogin" {
    value = "no"
  }
  option "maxauthtries" {
    max_value = 4
  }
  option "ciphers" {
    contains = "chacha20-poly1305@openssh.com"
  }
}
```

## user_db

Label-only. Account database hygiene across `/etc/passwd` and `/etc/shadow` as
a whole, complementing the single-account `user` resource. Failure messages
name the offending accounts.

| Attribute | Type | Notes |
|---|---|---|
| `no_duplicate_uids` | bool | |
| `no_uid0_besides_root` | bool | |
| `no_empty_passwords` | bool | Reads `/etc/shadow`, so pair it with `--sudo` |
| `max_password_age_days` | int | Shadow field 5 |
| `min_password_age_days` | int | Shadow field 4 |

## timesync

Label-only. Uses `timedatectl`, falling back to `chronyc tracking`.

| Attribute | Type | Notes |
|---|---|---|
| `synchronized` | bool | |
| `service` | string | `chrony`, `systemd-timesyncd`, `ntpd`, mapped onto systemd units |
| `max_offset_ms` | int | Absolute clock offset bound. Requires chrony, since `chronyc tracking` is the only portable offset source, and fails with an explanation elsewhere |

## mac

Label-only. Mandatory access control status: SELinux via `getenforce`, AppArmor
via `aa-status`.

| Attribute | Type | Notes |
|---|---|---|
| `system` | string | **Required.** `selinux` or `apparmor`. Only that system is probed |
| `enabled` | bool | The named system is installed and switched on |
| `enforcing` | bool | SELinux `Enforcing`, or AppArmor with at least one profile in enforce mode. Permissive and complain-only count as not enforcing |

A check names one system, so the resource never guesses which is in play.
SELinux installed but `Disabled` reports `system: selinux` with
`enabled: false`, separating "switched off" from "not installed".

To accept either system, put both checks in an `any_of` group and let the group
decide:

```hcl
any_of "mac-active" {
  check "selinux" "mac" {
    system    = "selinux"
    enabled   = true
    enforcing = true
  }
  check "apparmor" "mac" {
    system  = "apparmor"
    enabled = true
  }
}
```

## boot_params

Label-only. Reads `/proc/cmdline`, the runtime truth, rather than parsing grub
configuration variants. It therefore reflects what the kernel actually booted
with, including parameters the bootloader injected.

| Attribute | Type |
|---|---|
| `contains` | list(string) |
| `not_contains` | list(string) |

Entries match whole parameters. `audit=1` matches only the token `audit=1`,
while a bare `audit` matches `audit` or any `audit=<value>`.