RDF Industries
All insights
SOHO AI Build · Part 6 of 9By · Josh Rogers

Endpoint Security Basics for Local AI Tools

Endpoint security basics for local AI tools: hardening the box that holds the models when no cloud vendor is doing it for you.

Part 6 of a 9-part series: teaching CompTIA A+ (Core 1 / 220-1101 and Core 2 / 220-1102) through a real build, a private, local AI workstation/server for a small business.


The question nobody asks until it's too late

The AI stack is up, running locally, no data leaving the building. It feels inherently private, until someone points out that the API port is open to every device on the LAN, the inference endpoint is reachable from office Wi-Fi, and the disk holding the database isn't encrypted. The box is air-gapped from the internet and wide open to anyone inside the building.

Local does not mean secure. An unauthorized user who can reach the API port can query and extract documents. A compromised laptop on the same switch is inside the perimeter. A stolen drive is a database dump with no decryption required.

This article closes those gaps, layered endpoint hardening on a single workstation/server, covering the 1102 2.x security objectives on the CompTIA exam.


📘 Objectives covered (220-1102) >Core 2 (220-1102)- 2.1, Security measures and their purposes: least privilege, RBAC, host firewall, physical vs. logical controls, data-at-rest encryption (BitLocker/LUKS), patch management.- 2.2, Authentication methods: authentication factors (something you know / have / are), multi-factor authentication, account lockout.- 2.3, Detect, remove, and prevent malware: malware types, symptoms, removal process, endpoint protection.- 2.4, Securing devices: IP allow/deny, firewall rules, user account best practices, encryption. >Concepts taught below: least privilege & RBAC, host firewall, disk encryption,authentication factors and MFA, IP blocking, patch cadence, malware types,physical vs. logical controls, and how a layered policy config ties it together.

Concepts: defense in depth on one box

"Defense in depth" describes something real: no single control stops all attacks, so you layer them such that bypassing one layer doesn't immediately mean owning the system. For a local AI workstation, that looks like this, outside in:

Physical controls      ← locked room, cable locks
Host firewall          ← which ports accept connections at all
IP allow/deny          ← which source addresses can reach open ports
TLS/HTTPS             ← traffic encrypted in transit
Authentication         ← factors: something you know + have + are
RBAC / least privilege ← authenticated users get only what they need
Data-at-rest encryption← stolen drive stays encrypted
Audit logging          ← tamper-evident record of who did what

Least privilege and RBAC (1102 2.1)

Principle of least privilege: give every account only the permissions it needs to do its job, nothing more. Admin accounts should be used only when genuinely needed, not as a convenience default.

Role-Based Access Control (RBAC) is the mechanism: define roles with specific permission sets, assign users to roles. The permission model follows resource.action (jobs.read, jobs.create, settings.manage) so you can be precise about what each role touches.

A sensible four-role hierarchy, narrowest to broadest:

Role

Permissions

viewer

Read-only: see results, status, logs

analyst

viewer + create and run jobs, view reports

operator

analyst + manage service nodes, restart services

admin

Full system access including user management and config

New accounts default to viewer and are elevated only with a reason. An operator account that also carries admin permissions doubles the blast radius of that credential being compromised. Separate the privileges; contain the damage.

Host firewall (1102 2.1)

A firewall controls which connections reach the system at all. On Linux, ufw (Ubuntu/Debian) and firewalld (RHEL-family) both sit in front of the OS's iptables/nftables rules. The correct default posture:

ufw default deny incoming
ufw default allow outgoing
ufw allow from 192.168.1.0/24 to any port 22 proto tcp   # SSH — admin only
ufw allow 443/tcp                                          # HTTPS — the API
# Database, cache, model server ports: NO rule = default-deny catches them
ufw enable

What a firewall does not do: it doesn't authenticate users, encrypt traffic, or restrict what an authenticated user can do. The firewall decides whether a packet arrives. Authentication and RBAC decide what happens after.

A common mistake is leaving service ports, the database port, the model server's port: reachable from the LAN because "it's internal." Internal is not a trust boundary. Close everything that doesn't need to be open.

Data-at-rest encryption (1102 2.1)

If a drive can be physically removed, data on it is at risk unless the drive is encrypted. On Windows, BitLocker, full-drive encryption built into Windows Pro and higher, backed by the TPM: encrypts the entire volume at the block level. Booting normally works because the TPM holds the key; plugging the drive into a different machine returns unintelligible data.

On Linux, LUKS (Linux Unified Key Setup) + dm-crypt is the equivalent, configured at install time. It operates at the block device layer; the filesystem sits on top of an encrypted container.

Two things that defeat encryption-at-rest:

  1. The key sitting next to the drive (a recovery key taped to the machine).
  2. Unencrypted backup copies: a plaintext backup on a NAS share makes the endpoint encryption irrelevant. Encrypt backups before they leave the host.

Authentication factors (1102 2.2)

The exam categorizes three authentication factors:

  • Something you know, password, PIN.
  • Something you have, hardware token, TOTP authenticator app, smart card.
  • Something you are, biometric: fingerprint, face, iris.

MFA requires two of these three different categories. Password + TOTP code is MFA (know + have). Password + security question is not MFA (both are "know").

For a local AI service: strong password (12+ characters, complexity required) plus TOTP is the practical minimum. Hardware keys (WebAuthn/FIDO2, such as a YubiKey) are phishing-resistant (the credential is bound to the specific domain) and worth the cost for admin accounts.

From the policy config:

authentication:
  password:
    min_length: 12
    require_uppercase: true
    require_digits: true
    require_special: true
    lockout_attempts: 5
    lockout_duration_minutes: 30
  mfa:
    required: true          # Enforce — never leave false in production
    totp:
      digits: 6
      period: 30
    webauthn:
      enabled: true

The lockout_attempts / lockout_duration_minutes pair mitigates brute force at the cost of some availability (a legitimate user gets locked out too). Five attempts / 30-minute lockout is a reasonable small-business balance.

IP allow/deny (1102 2.4)

Authentication controls who can access the service given a valid credential. IP filtering adds a layer before authentication: from which addresses can connections attempt to authenticate at all?

An IP allowlist limits the service to specific known ranges: a local AI tool used only in the office would restrict to the LAN subnet. An IP blocklist works the other way: after an IP shows a credential-stuffing pattern (repeated failures against multiple accounts), block that IP for a cooling-off period regardless of whether subsequent requests carry correct credentials.

The middleware runs before authentication handlers on every inbound request. If the source IP has an active block record in the database, the request gets a 403 before authentication is even attempted. Block-hit events are themselves logged: "this IP tried again while blocked" is a signal with its own forensic value.

Malware basics (1102 2.3)

Key types and what distinguishes them:

Type

Defining characteristic

Virus

Attaches to files; spreads when infected file runs

Worm

Self-propagates over the network; no user interaction needed

Trojan

Disguised as legitimate software

Ransomware

Encrypts data; demands payment; targets backup copies too

Spyware

Silently collects and exfiltrates data

Rootkit

Hides at OS/firmware level; hardest to detect and remove

Keylogger

Records keystrokes; targets credentials

For a local AI server, ransomware and spyware are most relevant: ransomware because encrypted model data and databases represent days of work, and spyware because the entire premise is keeping queries private.

Common symptoms (step 1 of removal is recognizing these): unexplained slowdowns or sustained high CPU/disk activity; unknown new processes appearing in Task Manager; unexpected outbound network traffic to unfamiliar destinations; antivirus or security tools disabled without user action; browser redirects or sudden pop-ups; renamed files or new file extensions (the ransomware signature: report.docx becomes report.docx.locked).

Endpoint protection software provides the first automated line of defense: real-time (on-access) scanning checks files as they're opened or written, using signature databases for known threats and behavioral/heuristic analysis for unknown ones. Quarantine moves a suspect file to an isolated container rather than deleting it outright, preserving evidence. Microsoft Defender (built into Windows 10/11) is the baseline, always enabled, no license cost, and sufficient for most small-business workloads. For higher-assurance environments, EDR (endpoint detection and response) adds continuous behavioral telemetry and automated response playbooks. On the local AI server, these tools protect the box that holds both the document store and the model weights: a ransomware hit on that host means days of rebuild.

The CompTIA A+ 7-step malware removal procedure (220-1102 canonical order):

  1. Investigate and verify malware symptoms.
  2. Quarantine the infected system(s): disconnect from the network.
  3. Disable System Restore in Windows: prevents malware sheltering in restore points.
  4. Remediate: update anti-malware software, then scan and remove in Safe Mode or a pre-installation environment if normal-mode scanning can't reach the infection.
  5. Schedule scans and run updates: verify the infection is fully cleared.
  6. Enable System Restore and create a new restore point in Windows.
  7. Educate the end user: explain how the infection occurred and what to avoid.

Physical vs. logical controls (1102 2.1)

Physical controls prevent or detect physical access: locked server room, cable locks, cameras, screen locks engaged on inactivity timeout.

Logical controls are enforced by software: firewalls, RBAC, encryption, MFA, audit logging.

The exam asks which type addresses which threat. A thief walking out with the server is physical, logical controls don't stop the theft, but disk encryption limits the damage. A user with valid credentials accessing data they shouldn't is logical, RBAC and audit logs catch that, not a lock. A locked cabinet and screen-lock policy close gaps no amount of software hardening can address.

Patching (1102 2.1)

Unpatched software is the most common real-world attack vector and entirely preventable. When a CVE is published, it's effectively a public attack recipe: researchers and threat actors both read the same advisories. The window between disclosure and patch deployment is when exploitation spikes: attackers target unpatched systems specifically because they know the vulnerability details and know most organizations haven't applied the fix yet. Patch management means actively tracking available updates and applying them on a defined cadence, not just knowing the commands exist. Three layers to track:

  • OS patches: unattended-upgrades (Ubuntu) or dnf-automatic (RHEL-family) handles security patches automatically.
  • Container images: periodically pull new base images and rebuild: restarting existing containers doesn't pull patches.
  • Application dependencies: pip list --outdated, npm audit. Language-level packages don't get OS-level patching and are often the forgotten layer.

Hands-on walkthrough: the hardening policy

The policy config

Every control described above, encryption algorithm, TLS version, password rules, MFA enforcement, session limits, RBAC roles, audit settings: lives in a single security.yaml file that is checked into version control. Having all of it in one place means the security posture is reviewable in a single diff and auditable as a changelog rather than scattered across a dozen service configs.

# security.yaml — endpoint hardening policy

security:
  encryption:
    enabled: true
    algorithm: "AES-256-GCM"        # Authenticated encryption: covers confidentiality + integrity
    key_derivation: "scrypt"         # Memory-hard; resists GPU-based brute force
    key_management:
      provider: "vault"              # Keys in a secrets manager, not on disk
      key_rotation_days: 90

  tls:
    enabled: true
    min_version: "1.2"              # 1.3 preferred; 1.2 minimum
    prefer_server_ciphers: true

authentication:
  password:
    min_length: 12
    require_uppercase: true
    require_digits: true
    require_special: true
    max_age_days: 90
    history_count: 12               # Can't reuse last 12 passwords
    lockout_attempts: 5
    lockout_duration_minutes: 30
  mfa:
    required: true
    webauthn:
      enabled: true
      user_verification: "preferred"
  session:
    absolute_timeout_hours: 24
    idle_timeout_minutes: 30
    max_sessions_per_user: 5

authorization:
  default_role: "viewer"            # New accounts start at least privilege
  roles:
    admin:
      permissions: ["*.admin"]
    operator:
      permissions: ["services.*", "nodes.read", "nodes.manage", "monitoring.read"]
    analyst:
      permissions: ["jobs.read", "jobs.create", "reports.read", "reports.create"]
    viewer:
      permissions: ["jobs.read", "monitoring.read"]

audit:
  enabled: true
  hash_chain_enabled: true          # Each log entry hashes the previous — tamper-evident
  events:
    authentication: true
    authorization: true
    data_access: true
    configuration: true

Two stanzas worth internalizing: mfa.required: true is the enforce flag, if this is false, MFA is optional and every user who skips setup logs in with password alone. The audit.hash_chain_enabled: true setting makes the log tamper-evident; each entry hashes the previous one, so deleting or rewriting an entry breaks the chain and is detectable.

RBAC enforcement in code

# Route handler — enforce permission at the boundary, not in business logic
@require_permission("jobs.create")
async def create_job(request: Request):
    ...   # Handler only runs if permission check passes

# The decorator rejects with 403 before the handler sees the request.
# Audit log records a denied-access event. Business logic never runs.

IP block middleware (shape)

async def dispatch(request):
    if request.method == "OPTIONS":         # CORS preflight: always pass
        return await call_next(request)
    if path.startswith("/health"):          # Health checks: always pass
        return await call_next(request)

    blocked_until = await lookup_active_block(request.client.host)
    if blocked_until:
        log_audit("IP_BLOCKED", ip=request.client.host)   # Signal: tried again while blocked
        return JSONResponse(status_code=403, content={
            "detail": "Source temporarily blocked.",
            "blocked_until": blocked_until.isoformat(),
        })
    return await call_next(request)

The block is created automatically when the system detects a credential-stuffing pattern: one source IP accumulating failures across multiple accounts in a short window. No manual intervention required.


Verification: confirm the controls are active

1. Unauthorized request is rejected.

curl -s -o /dev/null -w "%{http_code}" http://node-1:8080/api/v1/jobs
# 401 — not authenticated; request reached auth, no token provided

curl -s -o /dev/null -w "%{http_code}" http://node-1:8080/api/v1/settings/manage
# 403 — authenticated (token present) but role lacks permission

401 vs. 403 is a meaningful distinction: 401 = not authenticated, 403 = authenticated but not authorized. Neither leaks data.

2. Blocked IP is rejected before authentication.

# From an IP that has exceeded the failure threshold:
curl -s http://node-1:8080/api/v1/auth/login \
  -d '{"username":"admin","password":"anything"}'
# {"detail": "Source temporarily blocked.", "blocked_until": "2026-06-30T14:30:00+00:00"}
# HTTP 403 — IP block fired before authentication was evaluated

3. Disk encryption confirmed.

On Linux:

cryptsetup status /dev/mapper/data-encrypted
# Status: active  ← LUKS container is open and the logical volume is on it

On Windows:

manage-bde -status C:
# Protection Status: Protection On
# Encryption Method: XTS-AES 256

Protection Off means BitLocker is installed but suspended: a common maintenance state that persists longer than intended. Verify after every maintenance window.


🎯 What the exam asks >Authentication factors, three categories: something you know (password,PIN), something you have (TOTP app, smart card, hardware key), something you are(biometric). MFA requires two different categories. Two passwords is not MFA.Exam questions give a scenario and ask which factor category is being used. >Least privilege and ACL: "a user should have access only to the resourcesrequired for their job role." Exam tests both directions: recognizingover-broad permissions as a violation, and selecting the correct role for adescribed job function. >Account lockout: exists to prevent brute force; defined by attempt countand lock duration. Know: a user claiming "I'm locked out and didn't do anything"may be the victim of someone deliberately locking their account (a denial-of-service attack on that account). Know who can unlock. >Malware types and removal, distinguish: virus (spreads via infected files),worm (self-propagates over network, no user interaction), Trojan (disguised aslegitimate), ransomware (encrypts + demands payment), spyware (exfiltratessilently), rootkit (hides at OS/firmware level). The CompTIA 7-step removalprocedure: (1) investigate and verify symptoms → (2) quarantine → (3) disableSystem Restore → (4) remediate (update anti-malware, scan in Safe Mode) →(5) schedule scans and run updates → (6) enable System Restore and create arestore point → (7) educate the end user. Step 7 is the closing step; it's onthe exam. >BitLocker / LUKS framing: BitLocker requires a TPM for automatic unlock atboot and a recovery key for manual unlock. LUKS is the Linux equivalent. Bothencrypt at the block-device layer. Critical nuance: encryption at rest protectsdata when the drive is removed; it does not protect data from a logged-in useror a running OS: authentication and RBAC cover that surface. >Physical vs. logical controls: scenario: "a laptop was stolen." Thepreventive physical control was a cable lock or locked room; the mitigatinglogical control (limits damage) is full-disk encryption. Expect questions thatask which type of control addresses the specific threat described. >Host firewall, the exam distinguishes host-based firewall (software on theendpoint itself, e.g., Windows Defender Firewall or ufw) from a network firewall(dedicated device or router). For A+: host firewall controls inbound/outbound onthat specific host; default-deny inbound is the secure baseline.

Common pitfalls

MFA configured but not required. The config has required: false in development and it never gets flipped to true in production. Users who set up MFA use it; everyone else logs in with just a password. Always enforce MFA in production: optionality is a vulnerability.

Over-broad roles by convenience. "Everyone gets operator because it's easier" collapses RBAC into a flat model where every account is high-privilege. The blast radius of any compromised account is the entire operator surface. Minimum role; elevate for specific tasks; revert.

Firewall open to the LAN. The database (5432), cache (6379), and model server (11434) should not be reachable from arbitrary LAN addresses. Any device that can hit those ports directly can read or manipulate data without going through the authenticated API. Close them at the firewall: ufw default deny incoming means no rule = blocked.

Unencrypted backups. The disk is encrypted with LUKS, but the nightly backup runs rsync to a NAS share in plaintext. The backup is now the weak point, unencrypted, accessible from multiple machines, and often less physically secured than the server. Encrypt at the application layer before data leaves the host.

Relying on network isolation alone. "It's not on the internet" describes one absent attack vector, not a security posture. Insider threats, compromised LAN devices, and physical access need no internet. Limit what an attacker can do once inside.

Audit logs never reviewed. Logs are written, tamper-evident, and unread. A daily scan of failed-auth events, IP block activations, and admin-permission uses takes minutes and catches credential attacks early.


Recap + what's next

You hardened the endpoint: layered RBAC over a four-role least-privilege hierarchy; set the host firewall to default-deny; encrypted data at rest with LUKS and BitLocker; enforced MFA with TOTP and hardware-key support; added IP-based blocking for credential-stuffing; wired tamper-evident audit logging; and covered malware removal and physical vs. logical control boundaries. The policy YAML ties it together in one reviewable file.

The FastAPI application itself, authenticating users, issuing tokens, handling MFA challenges, enforcing rate limits: has its own deployment-time security checklist. Getting the service running is not the same as getting it running securely.

Next up: Part 7: "Secure Deployment Checklist for a Private FastAPI Service." TLS termination, JWT session tokens, brute-force lockout, secure headers, secrets handling, and a repeatable pre-exposure checklist: covering 1102 2.x security and 1102 4.x operational procedures. See you there.