◇ OpenCyber Academy
Technologist · Chapter 7 · English

Chapter 7 — Identity and access foundations

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 7 — Identity and access foundations

Lesson map

Lesson 07 published. Map, example, EX019.

flowchart TD
  N0["Learning outcomes and connection"]
  N1["7.1 Identify, authenticate, authorize"]
  N2["7.2 Kinds of account"]
  N3["7.3 The joiner–mover–leaver process"]
  N4["7.4 The access review"]
  N5["7.6 Practical activity: access review"]
  N6["Chapter synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
  N6 --> EX["Worked example"]
  EX --> Q["Exercise EX019"]

Logical drawing

flowchart LR
  N0["Learning outcomes and connection"]
  N1["7.1 Identify, authenticate, authorize"]
  N2["7.2 Kinds of account"]
  N3["7.3 The joiner–mover–leaver process"]
  N4["7.4 The access review"]
  N5["7.6 Practical activity: access review"]
  N6["Chapter synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX019"]
[Learning outcomes and connection]
    |
    v
[7.1 Identify, authenticate, authorize]
    |
    v
[7.2 Kinds of account]
    |
    v
[7.3 The joiner–mover–leaver process]
    |
    v
[7.4 The access review]
    |
    v
[7.6 Practical activity: access review]
    |
    v
[Chapter synthesis]
    |
    v
[Worked example] --> [Exercise EX019]

Learning outcomes and connection

After this chapter you should be able to:

In the incident reports of Chapter 5, access is a recurring thread: remote access with shared passwords, supplier accounts that were never removed. For an implementer, identity is not a product; it is a set of records and routines that have to stay accurate as people join, move and leave.

7.1 Identify, authenticate, authorize

Identification is claiming an identity ("I am b.lind"). Authentication is proving it — with something you know (a password), have (a hardware key, an authenticator app) or are (a biometric). Authorization is deciding what that identity may do. NIST's digital identity guidelines describe authenticator types and assurance levels, and recommend phishing-resistant multi-factor authentication for higher-assurance access (NIST SP 800-63B). In practice: every privileged or remote access to a LANTERN host requires multi-factor authentication (MFA), and the factor should resist phishing where the platform allows.

7.2 Kinds of account

7.3 The joiner–mover–leaver process

Accounts go wrong at transitions. A joiner gets access copied from a colleague and inherits privileges they do not need. A mover keeps old access when gaining new. A leaver's accounts remain enabled because nobody told the system owner. The fix is a process linked to an authoritative source — the HR roster — and a periodic access review that catches what the process missed.

Lab 7's export shows all three failures: c.mendes is a leaver whose account stayed enabled after 31 August, d.reyes keeps historian admin that Clinical Engineering does not need, and vendor-kell is standing supplier access never tied to a ticket.

7.4 The access review

An access review compares three things: the accounts that exist on a system (exported from it, not from memory), the roster of people and their status, and a statement of need — which roles each team requires on each system. Findings fall into recognizable types: orphans (accounts with no matching person), leavers still enabled (worse if used after leaving), unjustified roles, privileged access without MFA, dormant accounts, shared accounts, and standing supplier access.

For RLY-01 and HIST-01, the export lists nine accounts and the roster tells you that f.ito matches nobody.

7.5 Worked example: quarterly review of RLY-01 and HIST-01 (synthetic)

The export has nine accounts; Lab 7 finds nine findings across five of them. Two need immediate action rather than a ticket in the next quarter. c.mendes left on 31 August and the account was used on 14 September: that is a potential incident, not an administrative tidy-up — preserve logs, disable the account, and ask whether someone else used the credentials (Chapter 20). vendor-kell is a standing administrator account on the relay without MFA, idle for 85 days. Other findings are serious but routine: d.reyes holds admin on the historian, which Clinical Engineering has no need for, without MFA, and has not logged in for 224 days; opsuser is a shared administrator without MFA; f.ito is not on the roster at all — perhaps a contractor recorded elsewhere, perhaps an account nobody can explain.

Note what the script does not flag: svc-relay has no MFA, which is normal for a service account, but its credential's storage and rotation are not visible in this export and must be checked separately.

7.6 Practical activity: access review

Lab 7 (save as lab07.py, run with python3 lab07.py):

# Lab 7 - quarterly access review for the relay and historian (offline, standard library only)
# Synthetic account export and HR roster; "today" is 2026-10-12.
from datetime import date
today = date(2026, 10, 12)
roster = {"a.okafor": ("Water Ops", "active"), "b.lind": ("FSTS Security", "active"),
          "c.mendes": ("Water Ops", "left 2026-08-31"), "d.reyes": ("Clinical Eng", "active"),
          "e.strand": ("FSTS Platform", "active")}
accounts = [  # name, system, role, last_login, mfa, kind
    ("a.okafor", "HIST-01", "operator", "2026-10-10", True, "person"),
    ("b.lind", "RLY-01", "admin", "2026-10-11", True, "person"),
    ("c.mendes", "HIST-01", "engineer", "2026-09-14", True, "person"),
    ("d.reyes", "HIST-01", "admin", "2026-03-02", False, "person"),
    ("e.strand", "RLY-01", "admin", "2026-10-01", True, "person"),
    ("opsuser", "HIST-01", "admin", "2026-10-11", False, "shared"),
    ("svc-relay", "HIST-01", "writer", "2026-10-12", False, "service"),
    ("vendor-kell", "RLY-01", "admin", "2026-07-19", False, "vendor"),
    ("f.ito", "RLY-01", "operator", "2026-10-05", True, "person")]
need = {("Water Ops", "HIST-01"): {"operator", "engineer"}, ("FSTS Security", "RLY-01"): {"admin"},
        ("FSTS Platform", "RLY-01"): {"admin"}, ("Clinical Eng", "HIST-01"): set()}
findings = []
for name, sysid, role, last, mfa, kind in accounts:
    idle = (today - date.fromisoformat(last)).days
    if kind == "person":
        if name not in roster: findings.append((name, sysid, "not on HR roster (orphan)"))
        else:
            dept, status = roster[name]
            if status != "active": findings.append((name, sysid, f"leaver ({status}) still enabled; used after leaving" if last > status[5:] else f"leaver ({status})"))
            elif role not in need.get((dept, sysid), set()): findings.append((name, sysid, f"role {role} not justified for {dept}"))
    if kind == "shared": findings.append((name, sysid, "shared account: no individual accountability"))
    if kind == "vendor" and idle > 30: findings.append((name, sysid, f"vendor account standing, idle {idle} d: make time-bound"))
    if role == "admin" and not mfa and kind != "service": findings.append((name, sysid, "privileged without MFA"))
    if idle > 90 and kind == "person": findings.append((name, sysid, f"dormant {idle} d"))
for f in findings: print(f"{f[0]:<12} {f[1]:<8} {f[2]}")
print("accounts:", len(accounts), "findings:", len(findings), "accounts with >=1 finding:", len({f[0] for f in findings}))

Expected output (Python 3.13.5):

c.mendes     HIST-01  leaver (left 2026-08-31) still enabled; used after leaving
d.reyes      HIST-01  role admin not justified for Clinical Eng
d.reyes      HIST-01  privileged without MFA
d.reyes      HIST-01  dormant 224 d
opsuser      HIST-01  shared account: no individual accountability
opsuser      HIST-01  privileged without MFA
vendor-kell  RLY-01   vendor account standing, idle 85 d: make time-bound
vendor-kell  RLY-01   privileged without MFA
f.ito        RLY-01   not on HR roster (orphan)
accounts: 9 findings: 9 accounts with >=1 finding: 5

Sort the nine findings by what must happen today. c.mendes, used on 14 September after leaving on 31 August, goes to the incident process: preserve the authentication logs before disabling the account. vendor-kell, a standing administrator on the relay with no MFA and 85 idle days, is disabled and re-enabled only per ticket. d.reyes, opsuser and f.ito become tickets with owners. Then look for what the script cannot see, such as how svc-relay's credential is stored and when it was last rotated.

7.7 Common errors and limits

An access review shows the state of accounts at one moment. It does not show how credentials are used, which needs logs (Chapter 17), and it is only as good as the roster and the statement of need.

Exercises — chapter 7

EX019 — Prioritize the findings. Objective: separate incidents from housekeeping. Inputs: Lab 7 output. Constraints: three priority bands: today, this week, this quarter. Steps: (1) put every finding in a band; (2) for each "today" item, write the first two actions in order. Expected evidence: table. Rubric: 3 = c.mendes used-after-leaving and the standing vendor admin without MFA in "today", with "preserve logs" before "disable" for c.mendes and confirmation with Kell before disabling where operations depend on it; d.reyes and opsuser this week; f.ito investigated this week; 2 = bands sensible, actions in wrong order; 1 = all "today"; 0 = none.

EX020 — Time-bound supplier access. Objective: design a supplier enablement process. Inputs: Kell Instruments needs relay admin access about four times a year, sometimes urgently at night. Constraints: must be usable at 03:00 by the on-call technologist; must leave evidence. Steps: (1) describe request, approval, enablement, monitoring and disablement; (2) state the maximum time to enable; (3) say what evidence is kept. Expected evidence: procedure of at most ten steps. Rubric: 3 = request tied to a ticket, on-call approval with operations informed, account enabled for a fixed window with MFA, session recorded or logged, automatic expiry, review next working day; 2 = missing expiry or evidence; 1 = "enable when asked"; 0 = none.

EX021 — Extend the review. Objective: add a check to the tool. Inputs: Lab 7. Constraints: standard library only. Steps: (1) add a check that flags any person holding admin on both RLY-01 and HIST-01 (a concentration of privilege); (2) add an account b.lind on HIST-01 as admin with MFA and today's date as last login; (3) run and report the new finding. Expected evidence: code and output. Rubric: 3 = check implemented over the whole account list, b.lind flagged, no false flags; also notes the new account is itself unjustified because FSTS Security has no stated need on HIST-01; 2 = works without noticing the need finding; 1 = not run; 0 = none.

Chapter synthesis

Identity is a set of records and routines. Authenticate by what an account can do; separate personal, privileged, service and supplier accounts and remove shared ones or control them in a vault; tie accounts to the joiner–mover–leaver process; and review them regularly against an export, a roster and a statement of need. Some review findings — a leaver's account used after leaving — are incidents, and evidence comes before clean-up.

Continue studying — chapter 07 of 30

← Chapter 06 · Course chapter index · Chapter 08 →

Continue to the next authored lesson.

Worked answers

EX019 — Prioritize the findings. Today: c.mendes used after leaving — (1) preserve authentication and session logs for HIST-01, (2) disable the account and open an incident; vendor-kell standing admin without MFA — (1) confirm with Water that no Kell work is in progress, (2) disable the account and move to time-bound enablement. This week: d.reyes (remove admin, confirm need with Clinical Engineering), opsuser (plan migration to personal accounts or a vault without breaking emergency operation), f.ito (identify; disable if nobody can vouch for it). This quarter: process fixes for joiner/leaver feeds. Full credit puts preservation before disabling.

EX020 — Time-bound supplier access. (1) Kell opens a ticket or calls the FSTS on-call with a job reference; (2) on-call checks the job with the Water duty manager; (3) on-call enables vendor-kell through the access tool for a fixed window (for example four hours) — target under 15 minutes from request; (4) Kell authenticates with MFA via the jump host; (5) the session is recorded or logged; (6) an alert fires on any Kell login outside an enabled window; (7) the account expires automatically; (8) next working day, FSTS Security reviews the session log against the job. Evidence kept: ticket, approval, enablement and expiry logs, session record, review note.

EX021 — Extend the review. Add after the loop: build admins = {} mapping each person to the set of systems where they hold admin, then flag anyone with both RLY-01 and HIST-01. With the new account ("b.lind", "HIST-01", "admin", "2026-10-12", True, "person"), the output adds b.lind HIST-01 role admin not justified for FSTS Security and the concentration finding b.lind admin on both RLY-01 and HIST-01. No other person is flagged (e.strand and d.reyes each hold admin on one system). Full credit notices the "not justified" finding: the need table gives FSTS Security no role on HIST-01.