Staff access MFA plan
Status: proposal. “Verify” means we couldn’t confirm the setting from the repo or from public probes. Log in and check it.
Context
- Staff: two people.
- Larry: the only person with production access (AWS, Supabase, Cloudflare, Stripe, servers).
- Laura: no production access. She does use admin.gevell.com (triage, content CMS), which is Access-gated and reads production data through the API. This deserves one sentence in the questionnaire (see Q46).
- Posture: there’s no remote/local distinction. Internal resources are meant to be reachable only through Cloudflare Tunnels, and connections are always encrypted.
- SSH: production SSH goes away when the office processing server is retired (#2246). The EC2 servers that replace it have no SSH; administration is through AWS Systems Manager Session Manager, behind IAM Identity Center MFA (#7). Direct LAN SSH remains only to internal hosts that hold no customer data (backups, CI runners, staging). That’s a lower-priority gap (item 6).
Inventory
| # | Access path | Who | Current auth (evidence) | MFA enforced? | How to enforce | Priority |
|---|---|---|---|---|---|---|
| 1 | Cloudflare dashboard (account c6cce84d…, also 3c71e2b8…), the root of DNS, Access, Tunnels, WAF, R2, Workers and the registrar (gevell.com and theaccessible.org both show Registrar: Cloudflare in whois) | Larry | Email + password (verify) | Verify | Turn on 2FA with a Touch ID passkey (WebAuthn), plus TOTP as a backup. Store the recovery codes offline. Under account Members, turn on “Enforce two-factor authentication” (verify the setting name). Remove unused members and old API tokens, and scope the remaining tokens. | Must |
| 2 | Cloudflare Access / Zero Trust (team anglin.cloudflareaccess.com) covering admin.gevell.com, admin-docs.gevell.com and both *.pages.dev aliases | Larry, Laura | Verified gated: all four return 302 to the Access login. Login method: the README allows “Google or one-time-PIN email” (verify which is live). | No, if One-time PIN is enabled, because an emailed PIN is a single factor. | (a) Make Google Workspace the only IdP and remove One-time PIN. (b) Turn on Access independent MFA (GA April 2026) and require Security key or Biometrics on the admin apps’ policies. Turn on “Use IdP MFA” / AMR matching so users aren’t prompted twice. (c) Policy: include only the 2 named emails, not @gevell.com. (d) Session length ≤ 12 h. | Must |
| 3 | Admin API /api/admin/* (on the Lambda and Node APIs) | Larry, Laura (via the admin UI) | Supabase JWT + requireAdmin. Not behind Access (see waf-ruleset.md rule 11). | Only as strong as the Supabase login (see #4) | Route it through Access (a same-origin proxy on admin.gevell.com) and verify the Access JWT in requireAdmin. Admin actions then inherit #2’s hardware-key MFA. | Must |
| 4 | Supabase app login for staff admin accounts (email OTP / magic link) | Larry, Laura | Email OTP (docs/admin/access/email-otp-login.md) | Single factor: whoever controls the mailbox gets in. That’s acceptable only because #3 puts Access in front. | Supabase Auth MFA (TOTP/WebAuthn) for is_admin users. Enforce aal2 in requireAdmin (verify plan support). | Should |
| 5 | Supabase dashboard (project vuvwmfxssjosfphzpzim, service-role keys, SQL editor) | Larry | Password or GitHub SSO (verify) | Verify | Turn on account MFA. Turn on the organization setting “Require MFA to access organization” (verify it’s on our plan). If signing in via GitHub, #9 covers it. | Must |
| 6 | SSH to internal LAN hosts (backups, GitHub backup, CI runners, staging). No customer data; production SSH ends with the EC2 migration | Larry | Key-only via direct LAN. PasswordAuthentication status: verify. | No (key only, no second factor) | Put the SSH private keys in the Mac’s Secure Enclave, unlocked by Touch ID (for example the free Secretive app). The key can’t be copied off the laptop and every use needs a fingerprint, which gives a second factor without a hardware key. Set sshd: PasswordAuthentication no, PermitRootLogin no. Optionally move to Cloudflare Access for Infrastructure later. | Should |
| 7 | AWS IAM Identity Center portal (d-90667c73d1.awsapps.com/start, user larry) | Larry | Password + MFA (docs/admin/access/aws-access.md) | Yes (documented). Verify the enforcement mode. | Identity Center → Settings → Authentication → MFA: “Every time they sign in (always-on)”, allowed types Security keys and built-in authenticators only (Touch ID counts as a built-in authenticator; turn off authenticator apps once two are enrolled), “If a user does not yet have a registered MFA device: Block sign-in”. | Must (check) |
| 8 | AWS root ([email protected]) and cdk-deployer break-glass IAM user | Larry | Root: MFA, no access keys (documented). cdk-deployer: long-lived access key. | Root: yes. cdk-deployer: no, because a static key bypasses MFA. | Root: register a Touch ID passkey plus a backup (a second device or the optional break-glass YubiKey; AWS allows up to 8 MFA devices). cdk-deployer: deactivate the key and store it re-activatable, or attach a deny-unless-aws:MultiFactorAuthPresent policy and use it via sts get-session-token --serial-number. Also note: the github-actions-deploy OIDC role trusts repo:LarryAnglin/theaccessible-platform:* with AdministratorAccess. Narrow it to ref:refs/heads/main / environment production (not MFA, but same risk class). | Must |
| 9 | GitHub (LarryAnglin personal account owns theaccessible-platform; org anglinai owns @anglinai/ui packages) | Larry (Laura: verify) | Verify | GitHub requires 2FA for code contributors (verify on the account) | Add passkeys/security keys to the account and remove SMS. Org anglinai: Settings → Authentication security → Require two-factor authentication (and “require secure methods”, if offered). Review PATs and deploy keys (runner deploy keys are read-only per mac-mini-t2-ubuntu.md). | Must |
| 10 | Google Workspace (gevell.com mail; IdP for Access) | Larry, Laura | Verify | Verify | Admin console → Security → 2-Step Verification: Enforce for all users, with passkeys or security keys only for the admin OU (Touch ID passkeys qualify). Turn on Advanced Protection for Larry (the super admin). Keep a second super-admin break-glass account with its own keys. Because this is the IdP for #2, it’s the keystone. | Must |
| 11 | Stripe | Larry | Verify | Stripe requires 2-step for dashboard users (verify) | Add security keys/passkeys. Keep the team at 1 admin. Use restricted API keys. | Must (check) |
| 12 | Resend (transactional email; API key in SSM/Workers) | Larry | Verify | Verify | Turn on 2FA. Check team members. | Should |
| 13 | Backblaze B2 (AAServerBackup, the off-site backup) | Larry | Verify | Verify | Turn on 2FA. Make application keys bucket-scoped. Consider Object Lock on the backup bucket (ransomware). | Should |
| 14 | Twilio (Voice/SMS OTP, docs/admin/access/voice-otp-setup.md) | Larry | Verify | Verify (Twilio has pushed 2FA by default) | Turn on 2FA (Authy/TOTP or passkey). Rotate the auth token into an API key. | Should |
| 15 | Domain registrar | Larry | Cloudflare Registrar (whois), so it’s covered by #1 | Same as #1 | Covered by #1. Also turn on registrar lock. | (via #1) |
| 16 | Grafana / Loki / Uptime Kuma | Larry | The repo shows only lab hostnames (grafana.test.lan, kuma.test.lan). Production exposure: verify. | Verify | If they’re reachable, publish them only as Access self-hosted apps via Tunnel (same policy as #2). Local admin passwords stay as a second layer. | Should |
| 17 | status.gevell.com admin API (CF Worker + D1, bearer token at ~/.config/gevell-status-admin-token) | Larry | Static bearer token | No | Put the admin paths behind Access (service token for scripts), or accept the risk (low: status data only). | Nice-to-have |
| 18 | Mac laptops, personally owned (the workstations that hold SSO sessions, ~/.aws, .env*, SSH keys) | Larry, Laura | Verify | n/a | FileVault on, Touch ID + strong password, auto-lock ≤ 5 min, automatic OS updates, firewall on, Find My. .env.production.local and similar secrets live on disk, so disk encryption is the control. See ids-ips-and-threat-monitoring.md for EDR. | Must (for Q47) |
| 19 | Anthropic console / AWS Bedrock / other AI vendors, Apple developer, npm/GitHub Packages tokens | Larry | Verify | Verify | 2FA everywhere. Scope and expire tokens (~/.npmrc token: expiry noted in memory). | Should |
Phishing-resistant options and cost (estimates, verify current prices)
| Option | Cost | Works with |
|---|---|---|
| YubiKey 5 NFC (FIDO2/WebAuthn + PIV + OpenPGP) | ~$55 each | Everything above, including SSH PIV/FIDO2 for Access Infrastructure and ed25519-sk |
| YubiKey Security Key NFC (FIDO2 only) | ~$29 each | WebAuthn/passkeys. Not PIV, so use FIDO2 for SSH. |
| Platform passkeys (Touch ID / iCloud Keychain) | $0 | Google, GitHub, AWS Identity Center (built-in authenticator), Cloudflare Access “Biometrics”, Stripe |
| Cloudflare Zero Trust (Access, Tunnel, Infrastructure, independent MFA) | $0 (free tier ≤ 50 users) | #2, #3, #6, #16 |
Recommendation: use the laptops’ Touch ID as the MFA device. A passkey created with Touch ID is a FIDO2 credential whose private key lives in the Mac’s Secure Enclave. It is phishing-resistant, the same standard as a hardware key. Every service in the must-do list accepts it: Google Workspace, AWS IAM Identity Center (“built-in authenticators”), Cloudflare dashboard and Access (“Biometrics”), GitHub and Stripe.
- Backup: register a second authenticator for every account so a lost or dead laptop doesn’t lock you out. iCloud Keychain syncs passkeys to each person’s iPhone, which covers most services automatically. Also store each service’s recovery codes in the break-glass vault (#3294).
- What protects the passkey: synced passkeys are only as safe as the Apple Account that syncs them. Protect it with its own MFA and Advanced Data Protection.
- Hardware keys: optional. Consider one YubiKey (about $55) only for the two accounts that control everything else, the Google Workspace super admin and AWS root, stored in the break-glass kit. It is a backup that doesn’t depend on Apple, not the everyday factor. Total hardware cost: $0–110.
- Where a service allows it, remove SMS and email as fallback factors.
Priorities
Must-do (before claiming Q46/Q47):
- Google Workspace 2SV enforced, passkey/security-key only for admins, Advanced Protection for Larry (#10).
- Cloudflare dashboard 2FA with a Touch ID passkey (#1). This also covers the registrar.
- Access: remove One-time PIN, Google as the only IdP, independent MFA requiring a security key or biometrics, explicit two-email policy (#2).
- AWS Identity Center always-on MFA with built-in authenticators (Touch ID) or security keys only; root with a Touch ID passkey plus a backup;
cdk-deployerkey deactivated or MFA-conditioned (#7, #8). - GitHub passkeys and org 2FA requirement (#9); Supabase org MFA (#5).
- Admin API behind Access (#3).
- Mac baseline: FileVault, auto-lock, updates (#18).
Should-do: Touch ID–bound SSH keys for internal LAN hosts (#6); Stripe/Resend/Backblaze/Twilio 2FA checks (#11–14); Supabase Auth MFA for admin accounts (#4); Grafana/Kuma via Access (#16); narrow the OIDC trust (#8).
Nice-to-have: status admin via Access (#17); a written quarterly access review; an AAGUID allow-list so only approved authenticators (Apple Touch ID passkeys and any break-glass YubiKey) can enroll in Access.
Does this help the questionnaire?
- Q46 (staff access / MFA): yes, directly. Once the must-do items are done, we can truthfully answer: “All staff access to production systems and administrative interfaces requires phishing-resistant MFA (FIDO2 passkeys bound to each laptop’s secure hardware and unlocked by biometrics) through Google Workspace, AWS IAM Identity Center and Cloudflare Access. Administrative web interfaces are reachable only through Cloudflare Access, and production servers have no SSH; administration is through AWS Systems Manager. Only one person holds production credentials. The second staff member’s access is limited to an Access-gated admin interface.” Today the HECVAT draft says “MFA on GitHub/AWS/Cloudflare/Supabase/Stripe” but its own checklist item 6 says to confirm it. Until the checks above are done, the claim isn’t evidence-backed.
- Q47 (remote workstation security): partly. MFA and Access/Tunnel cover how staff connect. Q47 also asks about the endpoint itself: disk encryption, patching, screen lock and anti-malware/EDR. Item #18 and the EDR recommendation in
ids-ips-and-threat-monitoring.mdcomplete the answer. Because we have no remote/local distinction, the honest answer is that every workstation meets the “remote” standard at all times.