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:
- distinguish identification, authentication and authorization, and say which control acts at each step;
- choose authentication strength by what an account can do, not by who holds it;
- manage the four kinds of account found in every critical service — personal, privileged, service and supplier — and the shared accounts that should not exist;
- run an access review that compares accounts with an authoritative roster and a statement of need.
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
- Personal accounts belong to one person and are the default for every human.
- Privileged accounts can change configuration, accounts or security settings. They should be separate from a person's everyday account, require MFA, and be few.
- Service accounts are used by software (the relay writing to the historian). They should have only the permissions the software needs, no interactive login, and credentials that are rotated and stored in a protected place — not in a script.
- Supplier (vendor) accounts give an outside party access. They should be time-bound: enabled for a specific job, monitored while in use, and disabled afterwards.
- Shared accounts ("opsuser") are used by several people. They destroy accountability — the log says "opsuser" did it — and their passwords leak with every leaver. Where a device genuinely cannot support individual accounts, control the shared credential in a vault that records who checked it out, and when.
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
- Reviewing accounts from a list someone typed, instead of an export from the system.
- Copying a colleague's access for a joiner.
- Treating a leaver's account that was used after leaving as a housekeeping item.
- Giving supplier accounts standing access "to save time in an emergency"; design a fast, logged enablement process instead.
- Requiring MFA for people but leaving service-account secrets in plain-text scripts.
- Removing a shared account on a control device before confirming how operators will log in during an emergency.
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.