WRKLOG-2026-06-02

Summary

Tuesday. Fill summary at end of day.

URGENT - All Domains

Carryover Backlog (CRITICAL)

Task Details Origin Days Status

MSCHAPv2 Migration Report

Report due. 6-sheet Standard Report (exec summary, trend, waves, device detail, stale, policy match). Sheet 6 added 05-14: policy match by protocol for removal planning + anonymous identity validation. Migration window 2026-05-04 to 2026-05-30. ~6,227 devices, 5 waves.

2026-04-17

49

P0 - DUE — run report this week

Abnormal Security — ✅ COMPLETE

CR-2026-05-07-abnormal-read-write. CAB approved 2026-05-12. Implemented successfully 2026-05-13. Read/write enabled for pilot group. Post-deployment validation pending.

2026-05-07

29

✅ IMPLEMENTED — post-validation pending

SIEM QRadar → Sentinel Migration

Lead role. Monad console error RESOLVED 2026-05-12 — secrets configured in CHLA production tenant. ISE secure syslog integration in progress — cert imported, remote logging target configured, streaming errors under investigation. Blocking: DCR not created (Rule ID + Stream Name). Azure private network policy unresolved. Victor + Mauricio action.

2026-04-10

56

P0 - ACTIVE — ISE syslog + DCR blocking

Monad Pipeline Evaluation

Sentinel output connector. Console error resolved. 3 of 6 values configured. Remaining: Endpoint URL (have it), Rule ID + Stream Name (need DCR). ISE Remote Logging Target configured 2026-05-18 — TLS cert imported, secure syslog target created. Streaming errors in Monad console under investigation.

2026-03-11

86

P0 - ACTIVE — ISE integration in progress

Guest Redirect ACL

Guest redirect ACL work needed. Related to Mandiant remediation findings.

2026-05-12

24

P0 - TODO

ISE Patch 10 (CVE-2026-20147 CVSS 9.9)

ISE 3.2 Patch 10. Supersedes Patch 9. 61 days on a CVSS 9.9 — schedule maintenance window. Write CR if needed.

2026-03-12

85

P0 - OVERDUE — schedule immediately

k3s NAT verification

NAT rule 170 for 10.42.0.0/16 pod network - test internet connectivity. 64 days — test this week or defer to Q3.

2026-03-09

88

P0 - BLOCKING — TRIAGE: schedule or defer

Wazuh indexer recovery

Restart pod after NAT confirmed working - SIEM visibility blocked. Blocked by k3s NAT — cannot proceed until above resolved.

2026-03-09

88

P0 - Blocked by k3s

Strongline Gateway VLAN fix

8 devices in wrong identity group (David Rukiza assigned)

2026-03-16

81

P0 - TODO

TCP Clocks deployment

ISE identity group validation, query outputs, comms with team. Active d001 data Apr 22-23.

2026-04-22

44

P0 - ACTIVE

IoT Dr. Kim — recurring

Sleep study devices (Apr 15-16), watches recurrence (Apr 22). 5 incident versions in d001. Validate iPSK enrollment.

2026-04-15

51

P0 - RECURRING

Murus Portae (WAF) — Phase 0

FMC cert expired, ACP returns zero rules. d001: zone map, architecture D2, FMC API reference, ops script.

2026-04-16

50

P0 - INVESTIGATING

Vocera EAP-TLS Supplicant Fix

~10 phones failing 802.1X, missing supplicant config. 61 days — schedule with clinical engineering team.

2026-03-12

85

P1 - TODO — schedule

ISE MnT Messaging Service

Enable "Use ISE Messaging Service for UDP syslogs delivery". 61 days — low risk, schedule with ISE Patch 10 maintenance window.

2026-03-12

85

P2 - BUNDLE with Patch 10

Professional backlog remains critical. Check Days column for priorities.

BLOCKERS — Fix Immediately

Task Details Origin Days Impact

Z Fold 7 Termux

gopass and SSH not working

2026-03-10

58

BLOCKER — Cannot access passwords on mobile

gopass v3 organization

Inconsistent structure, poor key-value usage

2026-03-20

48

Inefficient password management, no aggregation

Git history scrub — sensitive personal terms

Plaintext references to personal legal matters in committed worklogs (WRKLOG-2026-03-14, WRKLOG-2026-04-18). Forward-fixed but old commits still contain strings. Requires git filter-repo + force-push. See runbook below.

2026-04-22

15

SECURITY — sensitive terms in public git history

Runbook: Git History Scrub (d000 Personal Terms)

Problem: Two committed worklogs contained plaintext references to personal legal matters. The files have been edited (forward-fix), but git history retains the original text in prior commits.

Affected commits: Any commit touching these files:

# Identify affected commits
git log --oneline -- \
  docs/modules/ROOT/pages/2026/03/WRKLOG-2026-03-14.adoc \
  docs/modules/ROOT/pages/2026/04/WRKLOG-2026-04-18.adoc

Scrub procedure:

# 1. BEFORE: Full backup of the repo
cp -a ~/atelier/_bibliotheca/domus-captures ~/atelier/_bibliotheca/domus-captures.bak

# 2. Install git-filter-repo (if not present)
# Arch: pacman -S git-filter-repo
# pip: pip install git-filter-repo

# 3. Create expressions file for replacement
cat > /tmp/scrub-expressions.txt << 'EXPR'
regex:(?i)divorce==[REDACTED]
regex:(?i)dissolutio(?!n\.adoc\.age)==[REDACTED-LEGAL]
regex:(?i)iliana==[REDACTED-NAME]
regex:(?i)angulo-arreola==[REDACTED-NAME]
regex:legal-divorce-notes\.age==legal-notes.age
regex:1099-NEC-iliana==1099-NEC
EXPR

# 4. Verify before (dry run — count matches in history)
git log -p --all -S 'divorce' -- '*.adoc' | grep -c 'divorce' || echo "0 matches"
git log -p --all -S 'iliana' -- '*.adoc' | grep -c 'iliana' || echo "0 matches"

# 5. Run filter-repo (DESTRUCTIVE — rewrites all commit hashes)
git filter-repo --replace-text /tmp/scrub-expressions.txt --force

# 6. Verify after
git log -p --all -S 'divorce' -- '*.adoc' | grep -c 'divorce' || echo "0 matches — CLEAN"
git log -p --all -S 'iliana' -- '*.adoc' | grep -c 'iliana' || echo "0 matches — CLEAN"

# 7. Re-add remotes (filter-repo removes them)
git remote add origin git@github.com:<user>/domus-captures.git
# Add any other remotes (Gitea, etc.)

# 8. Force-push to all remotes (DESTRUCTIVE — overwrites remote history)
git remote | xargs -I{} git push {} main --force

# 9. Clean up
rm /tmp/scrub-expressions.txt
rm -rf ~/atelier/_bibliotheca/domus-captures.bak  # only after verifying

Post-scrub checklist:

  • Backup created before running

  • git filter-repo installed

  • Expressions file reviewed — no false positives (e.g., Don Quijote "Angulo el Malo" is in segunda-parte/texto/texto-011.adoc — the regex targets angulo-arreola specifically to avoid this)

  • Dry-run counts match expectations

  • Filter-repo executed

  • Post-scrub verification shows 0 matches

  • Remotes re-added

  • Force-pushed to all remotes

  • Cloudflare Pages rebuild verified

  • Local clones on other machines re-cloned or git fetch --all && git reset --hard origin/main

  • Backup removed

URGENT - Requires Immediate Action

Item Details Deadline Status Impact

Housing Search

Granada Hills area - apartments/rooms

TBD

In Progress

Quality of life, commute

2025 Tax — IRS Transcript Review

MFJ filed 2026-04-22. Pull IRS Return Transcript to verify contents. Consult attorney re: Form 8857 (Innocent Spouse Relief). Details in encrypted case file.

Before attorney meeting

In Progress

Financial — liability exposure. See data/d000/personal/dissolutio/

Rack Relocation

Physical move of server rack. CR written: CR-2026-04-18 (pending in infra-ops). Borg backup completed. VM XML dumps, switch save, shutdown/startup procedure documented.

TBD

Pending

Infrastructure downtime — all services offline during move

D000 Legal Planning

Encrypted case file: data/d000/personal/dissolutio/. Open: dissolutio-open. Close: dissolutio-close. 19 partials + assembler. PDF build for attorney handoff. Critical deadline: Jan 2029.

Before Jan 2029

Active — escalating

Life transition — see case file for details

Credit Report Review

Pull reports from all 3 bureaus via annualcreditreport.com. Verify no unknown joint accounts or debts. Credentials in gopass: v3/personal/finance/credit/annual_credit_report

TBD

In Progress

Financial discovery — FL-142 preparation

Gopass Security Audit

Rotate passwords on shared/known accounts. Add 2FA backup codes to v3/personal/recovery/. Create missing government entries (IRS, SSA, VA, DMV). Add last_login field to active entries.

TBD

Pending

Digital security — pre-filing preparation

Subscription Audit

Download 3 months bank/CC statements (Chase, NFCU, USAA). Identify all recurring charges. Cancel unnecessary. Document active subscriptions for FL-150.

TBD

Pending

Financial — expense documentation

401(k) Enrollment

Enroll in CHLA 401(k) immediately. Post-separation contributions are 100% separate property. Reduces gross income for support calculations. Max 2026: $23,500/yr.

In progress (started 5/4)

In Progress

Financial — support calculation + retirement

URGENT — Performance Review Certifications

Certification Provider Deadline Status Impact

CISSP

ISC² — Certified Information Systems Security Professional

July 12, 2026

ACTIVE — Week 2 of 10 (Project)

Required for performance review. 10-week accelerated plan.

RHCSA 9

Red Hat Certified System Administrator

Q3 2026

ACTIVE — 21-phase curriculum (Project)

After CISSP. Required for performance review.

CISSP: 41 days remaining (exam July 12). Domain 1 study in progress. Schedule exam today (06-01).

Early Morning - 5:30am

Regex Training (CRITICAL CARRYOVER)

  • Session 3 - Character classes, word boundaries

  • Practice drills from regex-mastery curriculum

  • Status: 52 days carried over (since 2026-03-16) — CRITICAL

Regex training continues to slip. This is the foundation for all CLI mastery.

Daily Notes

Triage Status

Item Status Outcome

CR Board: Guest ACL Hardening (CR-2026-05-28)

APPROVED

Schedule implementation with Tony Sun + David Rukiza

CR Board: Anonymous Identity Test (CR-2026-05-28)

APPROVED

Schedule with Argam (AirWatch profile push)

Linux Remediation Kickoff (MTG)

Done

Meeting complete — raised NAC/SSH/cert/hardening points

Abnormal Security Meeting — DKIM + Migration

Done

DKIM claimed implemented but PowerShell shows disabled. Policy review started.

ISE Annual Cert Renewal Meeting

Done

Cert expires July 24 (52 days). DigiCert CA. CSR generation ready.

Android Handheld Scanners — Argam escalation

New task

Shared devices need ISE policy for device-based auth. June 8 vendor onsite.

Alex Pena — ISE device adds

Pending verification

Need to run ERS API + DataConnect checks

Tube System Re-run (iTrack 3528165)

Carry-forward

Scripts fixed 06-01, re-run not completed today

Linux Inventory Discovery

Started

SQL queries written, need to run dc-run-sql

Abnormal ESA→EOP Policy Review

Started

Policy mapping complete, deliverable in d001

CISSP (39 days to July 12 exam)

Evening

Linux Remediation — Meeting Notes

Linux Remediation — Kickoff Notes

Capture raw notes below during the call. Move decisions/actions to the MTG doc after.

Points I Raised
  • NAC/802.1X enrollment for Linux — invisible to policy if unenrolled

  • SSH key governance — orphaned keys, CA-signed certificate model

  • Certificate lifecycle — machine certs, PKI integration

  • Config drift — CIS/STIG baseline, drift detection tooling

  • Research exception process — flexibility ≠ invisibility, minimum compliance tier

  • Decommission verification — cleanup checklist (DNS, DHCP, firewall, CMDB, certs)

  • Success criteria — define "remediated" with measurable targets

Abnormal Security — DKIM + Migration Status

Abnormal Security — Meeting Notes (2026-06-02)

Update: DKIM has been implemented.

DKIM Implementation Status
  • Implemented: details — which domains, selector, key size

  • Verification: DKIM test results

  • DNS records: published?

ESA → EOP Migration Status
  • Pilot scope: security group only / expanded / full org?

  • Policies migrated: which of the 5 EOP cmdlets are live?

  • ESA decom timeline: target date?

Abnormal Platform Status
  • Read/write mode: confirmed active since 05-14?

  • Detection metrics: any catches since go-live?

  • False positive rate: any tuning needed?

Questions Raised
  • Abnormal AI vs EOP overlap — complementary or redundant?

  • AutoForwardingMode Off — confirmed?

  • VIP list sync between Abnormal and EOP?

  • Bulk threshold tuning for healthcare?

  • Unmapped ESA policies (DLP, encryption, message filters)?

ISE Annual Certificate Renewal — Meeting Prep

ISE Annual Certificate Renewal — Meeting Prep

Meeting Details

Date: 2026-06-02
Topic: ISE annual certificate renewal planning
Attendees: fill in
Goal: Understand current cert state, plan renewal timeline, identify risks

Pre-Meeting Recon — Run These NOW
1. Current Certificate Inventory (All ISE Nodes)
Check all ISE node certs via netapi
netapi ise get-nodes --certs
Manual check — admin cert (port 443)
# PAN
openssl s_client -connect {ise-pan-fqdn}:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -serial

# PSN nodes (repeat for each)
openssl s_client -connect {ise-psn-fqdn}:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -serial
EAP-TLS cert (port 1812 — RADIUS)
openssl s_client -connect {ise-pan-fqdn}:1812 -starttls radius </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
Portal cert (port 8443 — guest/sponsor/BYOD)
openssl s_client -connect {ise-pan-fqdn}:8443 </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
pxGrid cert (if applicable)
openssl s_client -connect {ise-pan-fqdn}:8910 </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
2. Days Until Expiry (All Certs)
Quick expiry check per node
for host in {ise-pan-fqdn} {ise-psn1-fqdn} {ise-psn2-fqdn}; do
  for port in 443 8443; do
    expiry=$(openssl s_client -connect "$host:$port" </dev/null 2>/dev/null \
      | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
    if [[ -n "$expiry" ]]; then
      days=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))
      printf "%-45s port:%-5s %s days (%s)\n" "$host" "$port" "$days" "$expiry"
    else
      printf "%-45s port:%-5s FAILED TO CONNECT\n" "$host" "$port"
    fi
  done
done
3. Full Certificate Details (Fingerprints, SANs, Key Usage)
Detailed cert dump — use for meeting reference
openssl s_client -connect {ise-pan-fqdn}:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -text | grep -A1 'Subject:\|Issuer:\|Not Before\|Not After\|Subject Alternative\|Key Usage\|Serial'
SHA-256 fingerprint (for cert comparison during renewal)
openssl s_client -connect {ise-pan-fqdn}:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -fingerprint -sha256
4. Certificate Chain Validation
Verify full chain — root to leaf
openssl s_client -connect {ise-pan-fqdn}:443 -showcerts </dev/null 2>/dev/null \
  | awk '/BEGIN/,/END/{print}' | openssl verify -show_chain
Show each cert in chain (count should be 2-3: leaf + intermediate + optional root)
openssl s_client -connect {ise-pan-fqdn}:443 -showcerts </dev/null 2>/dev/null \
  | awk '/BEGIN/,/END/{if(/BEGIN/)n++; print > "/tmp/ise-chain-cert-"n".pem"}'

# Then inspect each:
for f in /tmp/ise-chain-cert-*.pem; do
  echo "=== $f ==="
  openssl x509 -in "$f" -noout -subject -issuer -dates
  echo
done
5. ISE Internal CA (if using ISE as CA)
Check ISE internal CA cert via admin GUI path
Administration > System > Certificates > Certificate Authority > CA Certificates
-- Note: expiry, key size, and whether endpoints trust this CA
Check ISE system certificates via admin GUI
Administration > System > Certificates > System Certificates
-- Each cert shows: Friendly Name, Used By (Admin/EAP/Portal/pxGrid), Expiry
6. Trusted Certificate Store
ISE admin GUI path
Administration > System > Certificates > Trusted Certificates
-- Verify: root CA, issuing CA, any external CAs (AD CS, Vault, Entrust, etc.)
-- Check expiry on EACH trusted cert
Certificate Inventory Table

Fill in during/after recon:

Node Role (Admin/EAP/Portal/pxGrid) Subject Issuer Expiry Days Left

pan

Admin

CN=…​

CN=…​

date

N

pan

EAP

CN=…​

CN=…​

date

N

pan

Portal

CN=…​

CN=…​

date

N

psn1

Admin

CN=…​

CN=…​

date

N

psn1

EAP

CN=…​

CN=…​

date

N

Renewal Planning — Discussion Points
Scope: Which Certs Need Renewal?
Certificate Used By Risk If Expired Renewal Method

Admin (443)

ISE admin GUI, inter-node communication

CRITICAL — nodes lose trust, deployment breaks

CSR from ISE → CA signs → import

EAP (1812)

RADIUS EAP-TLS authentication

CRITICAL — all 802.1X auth fails

CSR from ISE → CA signs → import. Supplicants must trust new cert.

Portal (8443)

Guest, Sponsor, BYOD, Client Provisioning

HIGH — portal users see cert warnings, BYOD fails

CSR from ISE → CA signs → import

pxGrid (8910)

pxGrid integrations (SIEM, MDM, threat)

MEDIUM — integrations break, not end-user facing

CSR from ISE → CA signs → import

Internal CA

ISE-issued endpoint certs (if applicable)

CRITICAL — all ISE-signed endpoint certs become untrusted

Renew CA cert, re-issue endpoint certs

Trusted CAs

Root and intermediate CAs in trusted store

CRITICAL — chain validation fails for all certs signed by that CA

Import renewed CA cert before old one expires

Timeline & Sequencing
Order Step Notes

1

Inventory all certs with expiry dates (today)

Fill in table above

2

Identify CA — who signs ISE certs? (AD CS / Vault / Entrust / self-signed)

Determines renewal workflow

3

Generate CSRs from ISE (per node, per role)

ISE Admin > System > Certificates > System Certificates > Generate CSR

4

Submit CSRs to CA, receive signed certs

Track turnaround time — external CAs may take days

5

Import signed certs to ISE (per node, per role)

ISE Admin > System > Certificates > System Certificates > Import

6

Bind certs to correct roles (Admin, EAP, Portal, pxGrid)

ISE prompts for role assignment during import

7

Restart ISE application services (per node, rolling)

OUTAGE WINDOW — services restart when admin cert changes

8

Verify — run all recon commands again

Confirm new dates, chain valid, no warnings

9

Update trusted stores on supplicants (if CA changed)

GPO push for Windows, MDM for mobile, manual for Linux

10

Monitor for 48h — watch for auth failures

ISE live logs + RADIUS error view

Critical Risks
  • Service restart required when admin cert is replaced — plan maintenance window

  • EAP cert change may cause supplicant disconnects if intermediate CA changes — clients need the new CA in their trust store BEFORE the ISE cert swap

  • Multi-node deployment — certs must be replaced on ALL nodes. If one node has an expired cert, inter-node communication breaks

  • Clock skew — if ISE node clock drifts, certs may appear expired prematurely. Verify NTP: show ntp

  • Wildcard vs SAN — wildcard certs simplify multi-node but ISE requires SAN entries for each node FQDN. Check current cert type.

ISE CLI Verification (Post-Renewal)
! SSH to ISE node
show application status ise
show ntp
show version
show running-config | include certificate

! From workstation — verify new cert is served
openssl s_client -connect {ise-pan-fqdn}:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -serial -fingerprint -sha256
Current Certificate Analysis (2026-06-02)
Field Value

CN

access2.ise.chla.org — correct, no wildcard

SAN

access2.ise.chla.org, *.ise.chla.org — correct, wildcard in SAN only

Issuer

GeoTrust TLS RSA CA G1 (DigiCert) — external CA

Valid

Jul 25 2025 → Jul 24 2026 — 52 days remaining

Key Size

2048-bit RSA (upgrading to 4096 in renewal)

EKU

Server Authentication, Client Authentication — correct for multi-role

CRL

cdp.geotrust.com/GeoTrustTLSRSACAG1.crl

OCSP

status.geotrust.com

Auth Failure Baseline (Pre-Renewal)

Captured 2026-06-02 12:48–14:48 (2-hour window). This is the pre-renewal baseline — not caused by cert changes.

Count Failure Reason Assessment

1,852

null (no reason logged)

Investigate — ISE should always log a reason

398

Supplicant declined inner EAP method

EAP negotiation mismatch — likely MSCHAPv2 clients hitting EAP-TLS policy

237

Unknown CA in client cert chain (12514)

Axis cameras — vendor CA not in ISE trusted store. Pre-existing, not renewal-related.

209

Rejected per authorization profile (15039)

Policy denials — expected behavior

79

Machine account disabled in AD (24486)

Stale AD computer accounts — AD cleanup needed

62

Subject not found in identity store (22056)

Unknown identities — investigate

21

PEAP SSL/TLS handshake after client alert (12322)

Client doesn’t trust ISE cert or supplicant misconfigured

19

RADIUS token server failed (24613)

Token/MFA backend issue

16

Expired certificate in client chain (12516)

N55181 — machine cert expired, needs GPO/SCEP renewal

12

EAP-TLS handshake after client alert (12521)

Client rejected ISE cert during handshake

Total baseline: ~2,908 failures / 2 hours

Post-renewal, filter out Axis camera noise (237) and monitor for any spike above ~2,670/2h.

Renewal Next Steps
Priority Action Status

P0

Generate CSR (OpenSSL, 4096-bit) — CN={cert-cn}, SAN={cert-san}

Ready — config and commands in d001

P0

Submit CSR to DigiCert (same CA as current cert)

Pending

P1

Schedule maintenance window for cert import (services restart on admin role change)

Pending

P1

Baseline failure rate before renewal for comparison

Done — 2,908/2h captured above

P2

Investigate Axis camera failures (12514) — add vendor CA to ISE trusted store

Pre-existing, not blocking renewal

P2

Investigate N55181 expired client cert (12516)

Pre-existing

P2

Investigate null failure reasons (1,852 events with no reason)

Pre-existing

Raw Audit Output

Full cert dump and DataConnect failure output (contains MACs, usernames, IPs) stored encrypted at:

data/d001/projects/ise-annual-cert-renewal/partials/cert-audit-output-2026-06-02.adoc

d001 open cert-renewal
# View: partials/cert-audit-output-2026-06-02.adoc
Action Items
Action Owner Due

CR Board Follow-up

CR Board Follow-up (06-02)

CR Board Outcome Next Step

Guest ACL Hardening (CR-2026-05-28)

APPROVED

Schedule implementation window with Tony Sun (ISE dACL + switch ACL). Coordinate FSS pilot date.

Anonymous Identity Test (CR-2026-05-28)

APPROVED

Schedule with Argam (AirWatch profile push). One pilot device. Evan validates ISE logs.

MDM Profile Testing (NEW)

Deferred

Needs CR drafted first — see Android handheld scanners partial

Notes
  • C-level feedback: elevator pitch was effective — "if you were selling a car, I’d buy it"

  • Both CRs approved on first presentation — no objections, no deferrals

  • Next: schedule implementation windows and notify implementers (Tony Sun, Argam, David Rukiza)

Android Handheld Scanners

Android Handheld Scanners — ISE Network Access

Date: 2026-06-02 13:44
Triggered by: Argam (Intune/MDM) escalation — shared Android devices need CHLA_Staff network access
Vendor: Sachin, Truptesh (onsite, 3-hour drive — next visit June 8)
ISE Owner: Evan Rosado

Problem Statement

Shared Android handheld scanner devices need access to the CHLA_Staff wireless network. These devices:

  • Have no AD user identity — they are shared, not assigned to individuals

  • Cannot authenticate via user-based 802.1X (EAP-TLS/PEAP with user credentials)

  • Need device-based authentication through MDM certificate enrollment

  • Must be authorized through a specific ISE policy that does not require user identity

Architecture — How This Works
Android Scanner → CHLA_Staff SSID (802.1X)
    → ISE RADIUS Authentication:
        Device cert from Intune MDM (SCEP/PKCS) — no user identity needed
    → ISE RADIUS Authorization:
        Match on: certificate CN/SAN + endpoint identity group + MDM compliance
        Result: DACL/VLAN for scanner devices
Action Items
Action Owner Due Status

Create Intune MDM profile for shared devices — SCEP certificate enrollment without AD user binding

Argam

Before June 8

{status-pending}

Confirm ISE authentication policy supports device cert auth (no user identity in the RADIUS request)

Evan

Before June 8

{status-pending}

Create ISE authorization policy for Android scanner endpoints — match on cert attributes + MDM compliance

Evan

Before June 8

{status-pending}

Test with 2 pilot devices during Sachin/Truptesh onsite (June 8)

All

June 8

{status-pending}

ISE Configuration — What Needs to Happen
1. Authentication Policy

The existing CHLA_Staff 802.1X authentication policy should work if it accepts EAP-TLS with device certificates. Verify:

  • Policy allows EAP-TLS (not just PEAP with MSCHAPv2)

  • Identity source includes certificate authentication profile

  • Certificate CN/SAN from Intune SCEP is trusted (Intune CA in ISE trusted store)

Verify current auth policy for CHLA_Staff
ISE Admin > Policy > Authentication
  Filter: Policy Set = "Wired_Wireless" (or applicable)
  Check: Allowed Protocols includes EAP-TLS
  Check: Identity Source Sequence includes Certificate Authentication Profile
2. Endpoint Identity Group

Create a dedicated identity group for these devices:

  • Group name: Android_Handheld_Scanners (or similar)

  • Population method: static assignment after MDM enrollment, or profiler-based

ISE Admin path
Administration > Identity Management > Groups > Endpoint Identity Groups
  > Add: Android_Handheld_Scanners
3. Authorization Policy

Create a new authorization rule specifically for scanner devices. This rule should:

  • Match after the authentication policy succeeds (device cert validated)

  • Condition: Endpoint Identity Group = Android_Handheld_Scanners AND/OR Certificate attributes

  • Result: Authorization profile with appropriate DACL and VLAN

ISE Admin path
ISE Admin > Policy > Authorization
  > Add Rule (position it correctly in rule order):
    Name: Android_Handheld_Scanner_Access
    Conditions:
      - EndpointIdentityGroup = Android_Handheld_Scanners
      - (optional) Certificate:Subject contains "scanner" or MDM attribute
    Result:
      - Authorization Profile: Scanner_Access (DACL + VLAN)
4. Intune CA Trust

The Intune SCEP CA certificate must be in ISE’s trusted certificate store, otherwise ISE will reject the device certificate during EAP-TLS handshake.

Verify Intune CA is trusted
ISE Admin > Administration > System > Certificates > Trusted Certificates
  Search for: "Microsoft Intune" or the Intune CA CN
  If missing: import the Intune Root CA + Intermediate CA
Key Questions for Argam (MDM)
  • What certificate template will Intune use for SCEP enrollment? (CN format, SAN, EKU)

  • Will the cert CN identify the device somehow (serial number, asset tag)?

  • Is MDM compliance check needed before granting network access? (ISE can query MDM)

  • How will devices be enrolled in Intune without a user identity? (device enrollment manager account? autopilot?)

Key Questions for Sachin/Truptesh (Vendor)
  • How many total devices?

  • What Android version?

  • Do the devices support 802.1X EAP-TLS natively, or is a supplicant app needed?

  • Can they pre-enroll in Intune before the June 8 onsite?

  • What network resources do the scanners need access to? (specific servers, VLANs, subnets)

Risk Considerations
  • No user accountability — these are shared devices. Logging will show device identity only, not who was using it. Ensure this is accepted by security/compliance.

  • Certificate lifecycle — SCEP certs expire. Who monitors and renews? Intune auto-renewal must be configured.

  • Device loss/theft — process to revoke cert and remove from ISE identity group if a device is lost.

  • Profiler accuracy — ISE may profile these as generic "Android" devices. The identity group assignment needs to be explicit, not profiler-dependent.

Teams Conversation (Raw)
Sachin: Hi Argam - any updates from your end. We were onsite and had
the test devices. Not sure if they are configured to be used with
chla staff network

Sachin: Hi Argam - Any updates on the 2 test devices - We are onsite
today and our next onsite is on 8th

Argam: Hi Sachin — I will need to work with Evan before setting these
up. As the security appliance need AD identity that these shared
device don't have

Sachin: ok - then we will wait to hear back. let me know if you have
a ETA so that we could plan our onsites accordingly. its a 3 hour
drive for us - me and Truptesh so we plan accordingly based on other
priorities

Argam: I have asked Evan for a quick call, will decide and update
after our discussion

Sachin: awesome. Thank you so much
  • ISE cert renewal project — same ISE deployment

  • Intune SCEP cert investigation — see daily-notes/2026-06-01/anthony-cert-investigation.adoc (similar cert auth pattern)

Tube System Upgrade — Re-run Status

Tube System Re-run (iTrack 3528165)

Status: Scripts fixed 06-01, all 15 MACs confirmed NOT IN ISE — re-run required today.

Re-run batch onboard
dsource d001 dev/network/ise
./scripts/ise-batch-onboard.sh /tmp/tube-system-macs.txt IoT_Onboard \
  "2026-06-02 ER - Tube System 10in TS stations iTrack-3528165"
Validate post-onboard
./scripts/ise-check-macs.sh /tmp/tube-system-macs.txt
Results

Paste output here after re-run.

Alex Pena — ISE Device Verification

Alex Pena — ISE Device Addition Verification

Source: Email from Alex Pena
Claim: Devices added to ISE
Status: Verifying via ERS API + DataConnect

Devices to Verify

Paste MAC addresses from Alex’s email here.

# One MAC per line
Verification — ERS API (Endpoint Exists?)
Load credentials and source check script
dsource d001 dev/network/ise
Check each MAC via ERS (single MAC)
# Replace with actual MAC
curl -sk "https://$ISE_PAN_FQDN:$ISE_ERS_PORT/ers/config/endpoint?filter=mac.EQ.AA:BB:CC:DD:EE:FF" \
  -u "$ISE_API_USER:$ISE_API_PASS" \
  -H "Accept: application/json" | jq '.SearchResult.total, .SearchResult.resources[]'
Batch check — all MACs at once (save to file first)
# Save Alex's MACs to file
cat > /tmp/alex-pena-macs.txt << 'EOF'
# paste MACs here
EOF

# Run batch check
source scripts/ise-check-macs.sh /tmp/alex-pena-macs.txt
Verification — DataConnect (Auth History)
Dynamic queries (variable MAC lists) use the dc_query bash function from data/shared/partials/ise-dataconnect/helpers.adoc. Static .sql files use dc-run-sql. Copy-paste dc_query into your terminal session before running — it is not auto-loaded.
Are they authenticating? (last 7 days)
# Build a SQL IN clause from the MAC file
macs=$(awk '{printf "'\''%s'\'',",$0}' /tmp/alex-pena-macs.txt | sed 's/,$//')

dc_query "
SELECT
    calling_station_id AS mac,
    username,
    identity_group,
    endpoint_profile,
    authentication_protocol,
    passed,
    failed,
    timestamp_timezone
FROM radius_authentications_week
WHERE calling_station_id IN ($macs)
ORDER BY timestamp_timezone DESC
FETCH FIRST 50 ROWS ONLY
"
Endpoint profile and identity group assignment
dc_query "
SELECT
    e.mac_address,
    e.endpoint_policy AS profile,
    g.name AS identity_group,
    e.endpoint_ip,
    e.hostname,
    e.static_assignment,
    e.create_time_without_tz,
    e.update_time_without_tz
FROM endpoints_data e
LEFT JOIN endpoint_identity_groups g ON e.identity_group_id = g.id
WHERE e.mac_address IN ($macs)
ORDER BY e.mac_address
"
Results
MAC In ISE? Identity Group Authenticating? Notes

mac

yes/no

group

pass/fail/none

notes

Response to Alex

Draft response here after verification.

Abnormal ESA→EOP Policy Review

ESA → EOP/MDO/Abnormal Policy Review

Status: Initial review complete from 2026-06-02 audit output
Deliverable: d001 build esa-policy-migration-review pdf --theme navy
Team: Cox/William, Landeros/Jason, Rosado/Evan, Naranjo/Mauricio, Sandoval/Carlos

Critical Findings (Action Required)
Severity Finding

HIGH

DKIM Enabled: False on all domains — contradicts claim of implementation today

HIGH

AutoForwardingMode: On — data exfiltration risk via auto-forward rules

MEDIUM

ESA outbound connector still active — all outbound routes through ESA

MEDIUM

Abnormal policies scoped to pilot group only — not full org

MEDIUM

Built-In Safe Links allows clickthrough for non-pilot users

What I Did Today
  • Ran full MDO/EOP PowerShell audit (output encrypted in d001)

  • Mapped all ESA policies to EOP/MDO/Abnormal equivalents

  • Identified DKIM, auto-forwarding, and pilot scoping gaps

  • Created buildable policy review deliverable

Next Steps
  • Investigate DKIM — why PowerShell shows disabled if just implemented

  • Discuss AutoForwardingMode change with team (Off vs Automatic)

  • Plan ESA connector cutover timeline

  • Plan Abnormal policy rollout from pilot to full org

  • Review Jihad’s spreadsheet against this mapping — reconcile green/yellow/red

  • Schedule Tyler call to review findings

Linux Inventory — Multi-Source Discovery

Linux Inventory Discovery

The Visibility Problem
Segment ISE Sees It? Why

Access layer (wired 802.1X)

✅ Yes

Endpoints authenticate through ISE on access ports

Data center (server VLANs)

❌ No

No 802.1X on DC ports — ISE is blind to these

Research systems

⚠️ Partial

Some on access ports, some in DC, some ISE profiles as "Unknown"

Three sources needed for complete picture:

  1. ISE DataConnect — access layer Linux (you own this)

  2. SIEM (QRadar/Sentinel) — everything including DC

  3. Network infrastructure — ARP/DHCP as ground truth

Source 1: ISE DataConnect (Run Today)

SQL queries at: data/d001/projects/linux-research/sql/

Executive summary — how many Linux does ISE see?
dsource d001 dev/network/ise
dc-run-sql data/d001/projects/linux-research/sql/linux-inventory-summary.sql /tmp/linux-inventory-summary.json
Full profiler inventory — every Linux endpoint with group, IP, hostname
dc-run-sql data/d001/projects/linux-research/sql/linux-inventory-ise-profiler.sql /tmp/linux-inventory-profiler.json
RADIUS auth history — Linux by authentication behavior (last 30d)
dc-run-sql data/d001/projects/linux-research/sql/linux-inventory-ise-radius.sql /tmp/linux-inventory-radius.json
Unknown/unclassified — potential hidden Linux (ISE profiler missed)
dc-run-sql data/d001/projects/linux-research/sql/linux-inventory-ise-unknown.sql /tmp/linux-inventory-unknown.json
Export combined to CSV for meeting
jq -r '(.[0] | keys_unsorted) as $k | $k, (.[] | [.[$k[]]] | map(tostring)) | @csv' \
  /tmp/linux-inventory-profiler.json > /tmp/linux-inventory-access-layer.csv
ISE Results

Paste counts here after running.

  • Known Linux (profiler): _

  • Linux by RADIUS auth: _

  • Unknown (potential Linux): _

Source 2: SIEM — Data Center Coverage

QRadar (still active):

  • Request: Read access to log sources filtered by OS type

  • Query: Events where log source type contains Linux identifiers

  • Syslog from DC servers shows kernel version, systemd entries — confirms OS

Sentinel (if ingesting):

// All Linux syslog sources — last 7 days
Syslog
| where TimeGenerated > ago(7d)
| where Computer != ""
| summarize
    LastSeen = max(TimeGenerated),
    EventCount = count()
    by Computer, HostIP, Facility
| order by EventCount desc
// Linux hosts by kernel identifier in syslog
Syslog
| where TimeGenerated > ago(7d)
| where SyslogMessage has_any ("Linux", "kernel:", "systemd")
| summarize
    LastSeen = max(TimeGenerated),
    EventCount = count()
    by Computer, HostIP
| order by EventCount desc
// CommonSecurityLog — Linux security events (if CEF-forwarded)
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where DeviceProduct has_any ("linux", "syslog")
| summarize count() by DeviceVendor, DeviceProduct, SourceIP
| order by count_ desc
SIEM Results
  • QRadar access: requested / granted / pending

  • Sentinel access: requested / granted / pending

  • DC Linux found: _

Source 3: Network Infrastructure (ARP/DHCP/DNS)

Request from network team — switch ARP table dumps from DC core.

DC core switches — every device with an IP
! Run on DC core/distribution switches
show ip arp | include Vlan
show ip arp vrf <vrf-name> | include Vlan

! DHCP leases (if centralized DHCP)
show ip dhcp binding

! MAC address table — which port, which VLAN
show mac address-table | include <vlan-id>
Reverse DNS on discovered IPs (from your workstation)
# After collecting IPs from ARP dumps
while read -r ip; do
    host=$(dig +short -x "$ip" 2>/dev/null)
    printf '%s\t%s\n' "$ip" "${host:-(no PTR)}"
done < /tmp/dc-linux-ips.txt | tee /tmp/linux-dns-reverse.txt
Network Infra Results
  • ARP dump requested: yes / pending

  • DC Linux IPs found: _

  • With PTR records: _

  • Without PTR (unknown): _

Delta Analysis

The gap between all three sources IS the remediation scope.

System In ISE? In SIEM? In CMDB?

hostname

yes/no

yes/no

yes/no

Action Items from This Discovery
  • Run ISE DataConnect queries (today)

  • Request QRadar/Sentinel read access for Linux log sources

  • Request DC core ARP table exports from network team

  • Cross-reference all three lists — identify delta

  • Present delta at next remediation meeting as concrete inventory gap

ISE Cert Renewal — SharePoint Search Queries

Run these during or after the meeting to locate all renewal-related artifacts.

Find Prior Renewal Documentation
Connect-PnPOnline -Url "https://chla.sharepoint.com/sites/InfoSec" -Interactive

# Broad search — any ISE cert docs
Submit-PnPSearchQuery -Query "ISE certificate renewal" -MaxResults 30 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { [PSCustomObject]@{
    Title    = $_["Title"]
    Path     = $_["Path"]
    Modified = $_["LastModifiedTime"]
    Author   = $_["Author"]
  }} | Format-Table -AutoSize
Find CSR / Certificate Files
# CSR files
Submit-PnPSearchQuery -Query "filename:ISE filetype:csr OR filetype:pem OR filetype:cer OR filetype:pfx" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { $_["Title"], $_["Path"] }

# Any cert-related Excel tracking sheets
Submit-PnPSearchQuery -Query "filetype:xlsx certificate ISE expiry OR renewal OR expiration" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { [PSCustomObject]@{
    Title = $_["Title"]
    Path  = $_["Path"]
  }} | Format-Table -AutoSize
Find Change Requests for Prior Renewals
Submit-PnPSearchQuery -Query "ISE certificate change request OR iTrack OR CR" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { [PSCustomObject]@{
    Title = $_["Title"]
    Path  = $_["Path"]
    Modified = $_["LastModifiedTime"]
  }} | Format-Table -AutoSize
Find Vendor Docs (Cisco TAC, Entrust, AD CS)
# Cisco TAC cases related to ISE certs
Submit-PnPSearchQuery -Query "Cisco TAC ISE certificate" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { $_["Title"], $_["Path"] }

# CA-related (AD CS, Entrust, DigiCert)
Submit-PnPSearchQuery -Query "certificate authority CHLASUBCA OR Entrust OR DigiCert" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { $_["Title"], $_["Path"] }
Find Runbooks / SOPs
Submit-PnPSearchQuery -Query "ISE runbook OR SOP OR procedure certificate" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { [PSCustomObject]@{
    Title = $_["Title"]
    Path  = $_["Path"]
    Author = $_["Author"]
  }} | Format-Table -AutoSize
Download What You Find
# Download to local for review
Get-PnPFile -Url "/sites/InfoSec/Shared Documents/path/to/cert-renewal-procedure.docx" -Path "C:\temp" -AsFile

# Download multiple files from a folder
Get-PnPFolderItem -FolderSiteRelativeUrl "Shared Documents/ISE Certificates" -ItemType File |
  ForEach-Object {
    Get-PnPFile -Url $_.ServerRelativeUrl -Path "C:\temp\ise-certs" -AsFile
    Write-Host "Downloaded: $($_.Name)"
  }
Results

Paste findings here:

Document Location Author Relevant?

title

sharepoint path

who

yes/no

Email Security Stack Reference

Email Security Stack — Quick Reference

Microsoft Defender for Office 365 (MDO)
Term Full Name What It Is

MDO

Microsoft Defender for Office 365

Umbrella product — anti-phish, Safe Links, Safe Attachments, threat investigation. Plan 1 = protection. Plan 2 = + threat hunting, AIR automation.

EOP

Exchange Online Protection

Built-in baseline filtering (anti-spam, anti-malware, spoof). Every O365 tenant gets this free. MDO sits on top of EOP.

Safe Links

MDO Safe Links

URL rewriting + time-of-click verification. Rewrites URLs to route through Microsoft proxy.

Safe Attachments

MDO Safe Attachments

Detonation sandbox — opens attachments in a VM before delivery.

AIR

Automated Investigation & Response

MDO Plan 2 — automated playbooks that investigate and remediate threats.

ZAP

Zero-hour Auto Purge

Retroactively removes messages from mailboxes after delivery if reclassified as malicious.

SCL

Spam Confidence Level

Score 0–9 assigned by EOP. Maps to -BulkThreshold in New-HostedContentFilterPolicy.

Email Authentication (DNS-based)
Term Full Name What It Is

DKIM

DomainKeys Identified Mail

Cryptographic signing of outbound mail. ✅ Implemented 2026-06-02.

DMARC

Domain-based Message Authentication

Policy layer on top of SPF + DKIM — tells receivers what to do with failures (none / quarantine / reject).

SPF

Sender Policy Framework

DNS TXT record listing authorized mail senders for the domain.

Architecture Terms
Term Full Name What It Is

SEG

Secure Email Gateway

Inline MTA filtering before delivery — what Cisco ESA/IronPort is. Being replaced.

Abnormal

Abnormal Security

API-based email security — behavioral AI, post-delivery detection, no MX change. Complements MDO.

BEC

Business Email Compromise

Social engineering attacks with no malicious payload — Abnormal’s primary detection target.

ESA

Email Security Appliance

Cisco IronPort — the SEG being decommissioned in this migration.

MX

Mail Exchanger

DNS record pointing to the inbound mail server. Abnormal does NOT require an MX change (API-based).

Target Architecture (Post-Migration)
Inbound:
  Internet → EOP (baseline) → MDO (advanced) → Mailbox
                                                  ↑
                                          Abnormal (API — behavioral AI, post-delivery)

Outbound:
  Mailbox → EOP → Internet
              ↓
         DKIM signed ✅ · SPF validated · DMARC enforced

Key distinction: MDO catches known threats (signatures, malicious URLs, weaponized attachments). Abnormal catches social engineering and BEC that MDO misses — no payload, just human manipulation. They are complementary, not competing.

EOP PowerShell Cmdlets (from ESA policy mapping)
Cmdlet Maps From

New-HostedContentFilterPolicy

ESA Incoming Mail Policy — anti-spam verdicts, bulk thresholds, allow/block

New-HostedContentFilterRule

ESA Incoming Mail Policy — recipient binding

New-HostedOutboundSpamFilterPolicy

ESA Outgoing Mail Policy — rate limits, forwarding controls

New-HostedOutboundSpamFilterRule

ESA Outgoing Mail Policy — sender binding

New-AntiPhishPolicy

ESA Content + Outbreak Filters — impersonation, spoof intel, VIP protection

MDO / EOP PowerShell Commands

MDO / EOP PowerShell — Email & Collaboration

Prerequisites
Connect to Exchange Online PowerShell
# Install module (one-time)
Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser

# Connect (interactive — prompts for MFA)
Connect-ExchangeOnline -UserPrincipalName admin@yourdomain.com

# Verify connection
Get-OrganizationConfig | Select-Object Name, IsDehydrated
Anti-Spam (EOP — Hosted Content Filter)
List all anti-spam policies
Get-HostedContentFilterPolicy | Format-List Name, BulkThreshold, MarkAsSpamBulkMail, SpamAction, HighConfidenceSpamAction
List anti-spam rules (who gets which policy)
Get-HostedContentFilterRule | Format-List Name, HostedContentFilterPolicy, SentTo, SentToMemberOf, RecipientDomainIs, State
Check outbound spam filter
Get-HostedOutboundSpamFilterPolicy | Format-List Name, AutoForwardingMode, RecipientLimitPerDay, ActionWhenThresholdReached
Check outbound rules
Get-HostedOutboundSpamFilterRule | Format-List Name, HostedOutboundSpamFilterPolicy, From, FromMemberOf, State
Anti-Phishing (MDO)
List all anti-phish policies
Get-AntiPhishPolicy | Format-List Name, Enabled, EnableTargetedUserProtection, TargetedUsersToProtect, EnableMailboxIntelligenceProtection, EnableSpoofIntelligence, PhishThresholdLevel
List anti-phish rules
Get-AntiPhishRule | Format-List Name, AntiPhishPolicy, SentTo, SentToMemberOf, RecipientDomainIs, Priority, State
Check impersonation protection targets (VIP list)
Get-AntiPhishPolicy | Where-Object { $_.TargetedUsersToProtect -ne $null } | Select-Object Name, @{N='VIPs';E={$_.TargetedUsersToProtect -join "`n"}}
List all Safe Links policies
Get-SafeLinksPolicy | Format-List Name, EnableSafeLinksForEmail, EnableSafeLinksForTeams, EnableSafeLinksForOffice, TrackClicks, AllowClickThrough, ScanUrls, EnableForInternalSenders
List Safe Links rules
Get-SafeLinksRule | Format-List Name, SafeLinksPolicy, SentTo, SentToMemberOf, RecipientDomainIs, State
Safe Attachments (MDO)
List all Safe Attachments policies
Get-SafeAttachmentPolicy | Format-List Name, Enable, Action, ActionOnError, Redirect, RedirectAddress
List Safe Attachments rules
Get-SafeAttachmentRule | Format-List Name, SafeAttachmentPolicy, SentTo, SentToMemberOf, RecipientDomainIs, State
Global Safe Attachments for SharePoint/OneDrive/Teams
Get-AtpPolicyForO365 | Format-List EnableATPForSPOTeamsODB, EnableSafeDocs, AllowSafeDocsOpen
DKIM
Check DKIM signing status for all domains
Get-DkimSigningConfig | Format-List Domain, Enabled, Status, Selector1CNAME, Selector2CNAME, LastCheckedTime
Enable DKIM for a domain
# Set-DkimSigningConfig -Identity "yourdomain.com" -Enabled $true
DMARC
Check DMARC policy
# DMARC is DNS-based, but MDO honors it:
Get-AntiPhishPolicy | Format-List Name, HonorDmarcPolicy, DmarcQuarantineAction, DmarcRejectAction
Mail Flow Rules (Transport Rules)
List all transport rules
Get-TransportRule | Format-List Name, State, Priority, Mode, Description
Get details of a specific rule
Get-TransportRule -Identity "External Sender Disclaimer" | Format-List *
List rules that modify messages (disclaimers, headers)
Get-TransportRule | Where-Object { $_.ApplyHtmlDisclaimerText -ne $null -or $_.SetHeaderName -ne $null } | Select-Object Name, State, Priority
Threat Logs & Message Trace
Message trace — last 48 hours
Get-MessageTrace -StartDate (Get-Date).AddDays(-2) -EndDate (Get-Date) | Select-Object Received, SenderAddress, RecipientAddress, Subject, Status, MessageTraceId | Format-Table -AutoSize
Message trace — filter by sender
Get-MessageTrace -SenderAddress "sender@external.com" -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) | Format-Table Received, RecipientAddress, Subject, Status
Message trace — filter by status (failed, quarantined)
Get-MessageTrace -Status "FilteredAsSpam" -StartDate (Get-Date).AddDays(-2) -EndDate (Get-Date) | Format-Table Received, SenderAddress, Subject
Get-MessageTrace -Status "Quarantined" -StartDate (Get-Date).AddDays(-2) -EndDate (Get-Date) | Format-Table Received, SenderAddress, Subject
Detailed message trace (for messages older than 48h, up to 90 days)
Start-HistoricalSearch -ReportTitle "Abnormal Investigation" -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) -ReportType MessageTrace -SenderAddress "suspect@external.com"
Get-HistoricalSearch | Format-List ReportTitle, Status, SubmitDate, Rows
Quarantine
List quarantined messages
Get-QuarantineMessage -StartReceivedDate (Get-Date).AddDays(-7) -EndReceivedDate (Get-Date) | Select-Object ReceivedTime, SenderAddress, RecipientAddress, Subject, Type, QuarantineTypes | Format-Table -AutoSize
Get quarantine details
Get-QuarantineMessage -MessageId "<message-id>" | Get-QuarantineMessageHeader
Release from quarantine
# Release-QuarantineMessage -Identity "<quarantine-id>" -ReleaseToAll
Threat Explorer Data (MDO Plan 2)
Get threat protection status report
Get-MailDetailATPReport -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) | Select-Object Date, SenderAddress, RecipientAddress, Subject, ThreatType, DetectionMethod | Format-Table -AutoSize
Safe Links click data
Get-SafeLinksDetailReport -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) | Select-Object ClickTime, NetworkMessageId, Url, Action, IsClickedThrough | Format-Table -AutoSize
Rule Discovery & Change Audit
Recently created/modified transport rules
Get-TransportRule | Sort-Object WhenChanged -Descending | Format-Table Name, State, Priority, WhenChanged, CreatedBy -AutoSize
Full details on newest rules
Get-TransportRule | Sort-Object WhenChanged -Descending | Select-Object -First 5 | Format-List Name, State, Priority, WhenChanged, CreatedBy, Description, Conditions, Actions, *Disclaimer*, *Header*, SentTo*, FromScope, *Domain*
Rules created/modified in last 7 days
Get-TransportRule | Where-Object { $_.WhenChanged -gt (Get-Date).AddDays(-7) } | Format-List Name, State, WhenChanged, CreatedBy, Description
Connector changes (inbound/outbound)
Get-InboundConnector | Sort-Object WhenChanged -Descending | Format-Table Name, Enabled, WhenChanged, ConnectorType -AutoSize
Get-OutboundConnector | Sort-Object WhenChanged -Descending | Format-Table Name, Enabled, WhenChanged, ConnectorType -AutoSize
Audit log — WHO created/modified rules (definitive)
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) -Operations "New-TransportRule","Set-TransportRule" -ResultSize 25 | Select-Object CreationDate, UserIds, Operations, AuditData | Format-List
CreatedBy on Get-TransportRule is sometimes blank. The unified audit log UserIds field is authoritative — it always shows who made the change.
Broader Exchange Admin Center audit (all admin actions)
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) -RecordType ExchangeAdmin -ResultSize 50 | Select-Object CreationDate, UserIds, Operations | Format-Table -AutoSize
ORCA — Configuration Health Check
Install and run ORCA (Office 365 ATP Recommended Config Analyzer)
Install-Module -Name ORCA -Scope CurrentUser
Connect-ExchangeOnline
Get-ORCAReport
# Generates HTML report with recommendations vs current config
Quick Audit Script — Run All at Once
Full MDO/EOP audit (copy-paste block)
# Connect first
Connect-ExchangeOnline

Write-Host "=== Anti-Spam Policies ===" -ForegroundColor Cyan
Get-HostedContentFilterPolicy | Format-Table Name, BulkThreshold, SpamAction, HighConfidenceSpamAction -AutoSize

Write-Host "`n=== Outbound Spam ===" -ForegroundColor Cyan
Get-HostedOutboundSpamFilterPolicy | Format-Table Name, AutoForwardingMode, RecipientLimitPerDay -AutoSize

Write-Host "`n=== Anti-Phish Policies ===" -ForegroundColor Cyan
Get-AntiPhishPolicy | Format-Table Name, Enabled, EnableTargetedUserProtection, PhishThresholdLevel -AutoSize

Write-Host "`n=== Safe Links ===" -ForegroundColor Cyan
Get-SafeLinksPolicy | Format-Table Name, EnableSafeLinksForEmail, EnableSafeLinksForTeams, TrackClicks -AutoSize

Write-Host "`n=== Safe Attachments ===" -ForegroundColor Cyan
Get-SafeAttachmentPolicy | Format-Table Name, Enable, Action, Redirect -AutoSize

Write-Host "`n=== DKIM ===" -ForegroundColor Cyan
Get-DkimSigningConfig | Format-Table Domain, Enabled, Status -AutoSize

Write-Host "`n=== Transport Rules ===" -ForegroundColor Cyan
Get-TransportRule | Format-Table Name, State, Priority -AutoSize

Write-Host "`n=== Global ATP Settings ===" -ForegroundColor Cyan
Get-AtpPolicyForO365 | Format-List EnableATPForSPOTeamsODB, EnableSafeDocs

Write-Host "`nAudit complete." -ForegroundColor Green
Audit Output (2026-06-02)

Raw output from all commands above is stored encrypted at:

data/d001/projects/abnormal-security/partials/mdo-eop-audit-output-2026-06-02.adoc

# View the output
d001 open-file abnormal

# Or decrypt directly
decrypt-file data/d001/projects/abnormal-security/partials/mdo-eop-audit-output-2026-06-02.adoc.age

SharePoint File Search Reference

SharePoint File Search (PnP PowerShell)

Setup
Install-Module -Name PnP.PowerShell -Scope CurrentUser
Connect-PnPOnline -Url "https://chla.sharepoint.com/sites/InfoSec" -Interactive
Search by Filename
Submit-PnPSearchQuery -Query "filename:certificate-renewal" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { [PSCustomObject]@{
    Title    = $_["Title"]
    Path     = $_["Path"]
    Modified = $_["LastModifiedTime"]
    Author   = $_["Author"]
  }} | Format-Table -AutoSize
Search by Keyword in Content
Submit-PnPSearchQuery -Query "ISE certificate renewal" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { [PSCustomObject]@{
    Title  = $_["Title"]
    Path   = $_["Path"]
    Author = $_["Author"]
  }} | Format-Table -AutoSize
Search by File Type
# Excel files about ISE
Submit-PnPSearchQuery -Query "filetype:xlsx ISE" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { $_["Title"], $_["Path"] }

# PDFs about certificates
Submit-PnPSearchQuery -Query "filetype:pdf certificate renewal" -MaxResults 20 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { $_["Title"], $_["Path"] }
Browse a Library
# List files in a folder
Get-PnPFolderItem -FolderSiteRelativeUrl "Shared Documents" -ItemType File |
  Select-Object Name, TimeLastModified, Length | Format-Table -AutoSize

# Recursive — all files in all subfolders
Get-PnPFolderItem -FolderSiteRelativeUrl "Shared Documents" -ItemType File -Recursive |
  Select-Object Name, ServerRelativeUrl, TimeLastModified | Format-Table -AutoSize
Download a File
Get-PnPFile -Url "/sites/InfoSec/Shared Documents/path/to/file.xlsx" -Path "C:\temp" -AsFile
Cross-Site Search (Admin)
Connect-PnPOnline -Url "https://chla-admin.sharepoint.com" -Interactive

Submit-PnPSearchQuery -Query "ISE certificate" -MaxResults 50 |
  Select-Object -ExpandProperty ResultRows |
  ForEach-Object { [PSCustomObject]@{
    Title = $_["Title"]
    Site  = $_["SPSiteUrl"]
    Path  = $_["Path"]
  }} | Format-Table -AutoSize

File Insertion Patterns (CLI)

File Insertion Patterns

Recon — Understand the File Before Touching It
How big is it? Get line count and structure overview
wc -l file.adoc
View the whole file with line numbers (short files)
awk '{printf "%4d  %s\n", NR, $0}' file.adoc
View specific line range
awk 'NR>=10 && NR<=20' file.adoc
First and last N lines (orientation)
awk 'NR<=10' file.adoc            # first 10
awk 'END{start=NR-9} NR>=start' file.adoc  # last 10
Find all section headers (AsciiDoc structure map)
grep -n '^=\+ ' file.adoc
Find all include directives (dependency map)
grep -n 'include::' file.adoc
Find all anchors, tags, and conditionals
grep -n -E '^\[\[|^// tag::|^// end::|^ifdef|^endif' file.adoc
Find the line number of a pattern
grep -n 'pattern' file.adoc
View context around a pattern (±3 lines)
grep -n -B3 -A3 'pattern' file.adoc
Count occurrences of a pattern (is it unique? will sed hit one or many?)
grep -c 'pattern' file.adoc
Find blank lines / insertion-friendly gaps
awk '/^$/{printf "%4d  (blank)\n", NR}' file.adoc
Diff-friendly snapshot before editing (belt-and-suspenders)
cp file.adoc /tmp/file.adoc.bak
# After editing:
diff /tmp/file.adoc.bak file.adoc
Verify Target — Immediately Before the Change
Confirm the exact line you’re about to modify
# By line number
awk 'NR==25' file.adoc

# By pattern — make sure it's unique
grep -n 'pattern' file.adoc
# If count > 1, narrow with context or line range:
awk 'NR>=20 && NR<=30 && /pattern/' file.adoc
Prepend (Insert at Top)
Single line — sed
sed -i '1i\// New header line' file.adoc
Multi-line block — sed
sed -i '1i\// Line one\n// Line two\n// Line three' file.adoc
Prepend from another file — process substitution
cat <(echo "= New Title") existing.adoc > /tmp/tmp && mv /tmp/tmp existing.adoc
Prepend with awk (computed content)
awk 'BEGIN{print "// Prepended by script"} {print}' file.adoc > /tmp/tmp && mv /tmp/tmp file.adoc
Insert at Specific Line
After line N — sed
# Insert after line 15
sed -i '15a\New content after line 15' file.adoc
Before line N — sed
# Insert before line 15
sed -i '15i\New content before line 15' file.adoc
Insert block after a pattern — sed
sed -i '/== Summary/a\\ninclude::partial$worklog/new-section.adoc[]\n' file.adoc
Insert block before a pattern — sed
sed -i '/== Related/i\\ninclude::partial$worklog/new-section.adoc[]\n' file.adoc
Insert with awk (multi-line block after pattern)
awk '/== Summary/{print; print ""; print "include::partial$new.adoc[]"; print ""; next} {print}' \
  file.adoc > /tmp/tmp && mv /tmp/tmp file.adoc
Append (Insert at Bottom)
Single line — >>
echo 'New last line' >> file.adoc
Append before a specific marker (e.g., before ---)
sed -i '/^---$/i\New content before the horizontal rule' file.adoc
Replace a Line or Block
Replace line N — sed
# Verify first
awk 'NR==25' file.adoc

# Replace
sed -i '25s|.*|New content for line 25|' file.adoc

# Verify after
awk 'NR==25' file.adoc
Replace pattern match — sed
sed -i 's|old content|new content|' file.adoc
Replace a block between two patterns — sed
sed -i '/^== Old Section$/,/^== Next Section$/c\== New Section\n\nNew content here.\n\n== Next Section' file.adoc
Safe Patterns (Verify → Change → Verify)
Full verify-change-verify cycle
# 1. Before — find insertion point
grep -n 'pattern' file.adoc

# 2. Change — insert after pattern
sed -i '/pattern/a\New line after pattern' file.adoc

# 3. After — confirm
grep -n -A1 'pattern' file.adoc
Idempotent insert (only if not already present)
grep -q 'new-section' file.adoc || sed -i '/== Summary/a\\ninclude::partial$new-section.adoc[]' file.adoc
Gotchas
Issue Fix

sed -i on macOS requires sed -i ''

Use gsed (GNU sed) on macOS, or sed -i '' for BSD sed

Backslashes in sed insert

Escape or use a different delimiter: sed -i '1i\path/to/file'

Special chars in replacement (&, /)

Use | as delimiter: sed -i 's|old|new|'

Lost file on failed mv

Use sponge from moreutils to avoid temp files: { cmd; } | sponge file

Multi-line sed -i portability

For complex blocks, prefer awk — cleaner multi-line handling

Troubleshooting / Tareas Imprevistas

Troubleshooting / Tareas Imprevistas

Unplanned debugging sessions, escalations, investigations.

*

Ad-Hoc Requests

Ad-Hoc Requests

Capture walk-ups, Teams pings, and unplanned work here.

*

CLI & Nvim Skill-Up (Work Directive)

CLI & Nvim — Daily Practice

awk

Skill gap: Arrays, user-defined functions, multi-file (FNR/FILENAME)
Today’s practice:

*

Command tried
# paste command here with real output
grep / find / xargs

Today’s practice:

*

Command tried
# paste command here with real output
sed

Today’s practice:

*

Command tried
# paste command here with real output
nvim

Skill gap: Registers, macros, Ex commands (:norm, :g, :v), Lua config
Today’s practice:

  • Used a named register

  • Recorded/replayed a macro

  • Used :g or :v for a real task

  • Explored a plugin or config change

Nvim technique learned
# keystroke sequence or :command here
Automation / Scripting

Today’s practice:

*

Script or pipeline
# paste here
Concepts Graduated to Codex

When a pattern has 3+ uses, move it to the codex (STD-019).

  • none yet today

Education — Evening Sessions

CISSP Study Session

Domain focus: fill in

Questions Completed
  • 25 daily questions (Pocket Prep / Boson)

  • Score: _ / 25

Chapter Reading
  • chapter/section here

Don Quijote — Lectura del día

Capítulo: número y título
Parte: Primera / Segunda

Resumen breve

Escribe en español.

Vocabulario nuevo
Palabra Definición Ejemplo en contexto

palabra

definición

cita del texto

Análisis personal

Reflexión en español — temas, técnica narrativa, conexión con capítulos anteriores.

Notas para SIELE/DELE
  • Registro formal observado:

  • Estructura sintáctica compleja:

Violin Practice Session

Duration: 45 min
Focus: fill in — what did you work on?

Warm-up & Scales
  • Scale: key

  • Tempo: _

  • Notes:

Technique
  • Bow work:

  • Left hand:

Repertoire
  • Piece:

  • Measures worked:

  • Notes:

Self-Assessment
  • What went well:

  • What needs work:


Work (CHLA)

CHARGE TIME IN PEOPLESOFT - CRITICAL. Do this NOW before anything else.

Critical (P0)

Project Description Owner Status Due Blocker

Linux Research (Xianming Ding)

EAP-TLS for Linux workstations, dACL, UFW

Evan

BEHIND (72 days overdue)

02-24

Certificate "password required" - nmcli fix documented

iPSK Manager

Pre-shared key automation

Ben Castillo

BEHIND

 — 

DB replication issues

MSCHAPv2 Migration

Legacy auth deprecation — 6,227 devices, 5 waves. 6 batch SQL queries + 3-API endpoint profile script added (05-11). Report due.

Evan

25% — Report due, batch queries ready

05-30

Report to turn in

Research Segmentation

All endpoints to Untrusted VLAN

Evan

BLOCKED

 — 

CISO decision pending

Disaster Recovery

ISE DR scoping — dot1x closed mode = total blackout

Evan

Scoping

 — 

 — 

Mandiant Remediation

Copy 4/16 findings, Guest ACL lab, Q2 assessment

Evan

Active

 — 

 — 

SIEM QRadar → Sentinel

Full SIEM platform transition. Monad console error resolved 05-12. Secrets configured. Blocked on DCR creation (Rule ID + Stream Name). Azure private network policy unresolved.

Evan

Active — blocked on DCR

Q2 2026

Victor/Mauricio: create DCR, resolve Azure network policy

Abnormal Security

AI email platform — ESA cutover. CR assigned, CAB May 12 15:00. Implementation May 14 10:00.

Evan

Active — CAB today 15:00

05-14

Pre-CAB checklist: confirm Tyler, Jason, Sarah

High Priority (P1)

Project Description Owner Status Target

ISE 3.4 Migration

Upgrade from 3.2p9

Evan

Blocked — maintenance window needed

Q2 2026

Switch Upgrades

IOS-XE fleet update (C9300, 3560CX)

Evan

Pending

Q2 2026

Spikewell BYOD VPN

dACL SQL, AD group integration

Evan

Active

 — 

Strongline Gateway

MAC capture, Identity Group setup — 37 days aging

Evan

Active — David Rukiza assigned

 — 

Abnormal Security

AI email security platform research, ESA cutover timeline

Evan

Newly assigned

 — 

DMZ Migration

External services audit behind NetScaler

Evan

Audit phase

 — 

Firewall Audit (murus-portae)

EtherChannel query, prefilter, policy assignments

Evan

Scoping — ASA API creds needed

 — 

iPSK Manager HA

Server 2 config, TLS, SQL security audit

Evan

In progress

 — 

Sentinel KQL

Build proficiency, distinguish from team

Evan

Onboarding

 — 

VNC Blocking

Block and eliminate VNC protocol enterprise-wide

Evan

Active — Phase 0 (Discovery)

Mid-June 2026

Strategic (P2)

Project Description Owner Status

HHS Regulatory Compliance

New HHS security policies implementation

TBD

NOT STARTED

InfoSec Reporting Dashboard

PowerBI metrics for executives

TBD

NOT STARTED

EDR Migration (AMP → Defender)

Endpoint protection consolidation

TBD

NOT STARTED

Azure Legacy Migration

Modern landing zone

Team

In Progress

ChromeOS EAP-TLS

SCEP + Victor, Paul testing

Victor

In Progress

P0 — Critical / Blocking

Security & Compliance

  • ISE 3.2 Patch 10 upgrade — CVE-2026-20147 CVSS 9.9 / CVE-2026-20148. Propose maintenance window once patch confirmed on software.cisco.com.

  • ISE Advisory sa-ise-rce-traversal-8bYndVrZ — check Patch 10 availability

  • Mandiant Remediation — findings status tracked. Working session prep + defensive posture documented (comms-2026-04-24). Copy 4/16 updates into Excel at work. Guest ACL lockdown (WIR-M-01) pending lab validation. appendix-todos updated with MSCHAPv2 milestones.

  • Guest ACL update — guest redirect ACL work needed. Lab validate GUEST_CWA_REDIRECT_MAX_SECURITY in d000, then joint CR with NE. On today’s task list.

  • Disaster Recovery & Downtime Procedures — ISE top priority (dot1x closed mode = SPOF for network access)

    • ISE DR: Document failover sequence — PAN, MnT, PSN priority order

    • ISE DR: RADIUS dead-server detection on WLCs/switches — critical-auth VLAN fallback

    • ISE DR: Backup/restore procedures — scheduled config backups, tested restores

    • FTD/FMC DR: FMC loss = no policy management

    • Network DR: Core/distribution switch failure, STP reconvergence, HSRP failover

    • Document RTO/RPO per system

SIEM Migration (QRadar → Sentinel)

  • SIEM QRadar → Sentinel Migration — LEAD ROLE. 4 collection iterations (Apr 16, 17, 17-streamlined, 20-streamlined). Python chart pipeline built (qradar-charts.py). Migration XLSX generated. Verification pending. Comms sent Apr 23.

    • d001 artifacts: 8 JSON exports, 2 CSV inventories, migration XLSX, top5 source SVG/PNG, verification doc

    • Dependency: Monad pipeline for log source transition

    • Dependency: Sentinel KQL proficiency for query migration

  • Monad Pipeline Evaluation (origin: 2026-03-11) — lead role. Console error RESOLVED 05-12 — secrets configured in CHLA production tenant. Blocked on DCR creation (Rule ID + Stream Name). Azure private network policy unresolved. 10am call today 05-12.

  • Sentinel KQL — build proficiency, distinguish from team. Azure portal access acquired.

  • QRadar log source report — run AQL queries, fetch JSON, generate Python Excel

Active Deployments & Migrations

  • MSCHAPv2 Migration — Report due. 6-sheet Standard Report ready (Sheet 6: policy match by protocol added 05-14 for removal planning + anonymous identity validation on cert profiles). Migration window 5/4 – 5/30. 6,227 MSCHAPv2 devices, 14,249 EAP-TLS/TEAP (70% migrated). Focus: run Standard Report, turn in spreadsheet.

  • MSCHAPv2 weekly cadence — recurring Wednesday call established (first 04-22). Completed 2026-04-22.

  • MSCHAPv2 ownership matrix — sent in scoping email 4/24 with manager callouts (@Albert, @John). Completed 2026-04-24.

  • TCP Clocks deployment — new device added via ERS POST and confirmed (04-24). 7+ clocks validated. v2 query file with partials architecture. Revalidate full set — confirm no flapping.

  • SRT Research VLAN — confirm roles with Tony Sun: Tony implementor, Evan tester. CAB approved 04-21.

  • Downtime Computers enforcement — draft ISE AuthZ rule: medigate_724 + Wireless = DenyAccess. Separate CR. d001: DC queries, audit CSVs (v1-v3), wireless violations report delivered 04-21.

  • Enterprise Linux 802.1X — standardize Shahab/Ding deployment (CISO priority). Overdue since 02-24. Blocked by nmcli cert fix.

  • Abnormal Security — CR-2026-05-07-abnormal-read-write. CAB 05-12 approved, implementation 05-14. Jason Landeros implements, Evan presents. 06-01 update: Review Jihad’s policy mapping XLSX + Tyler’s Policy and Rules Migration doc before next call. Plan email migration expansion beyond security group to full environment — priority to move off ESA. Exchange rule considerations: external sender disclaimer (sender not company, outside org, not internal IP → prepend disclaimer).

    • Team: Cox/William, Landeros/Jason, Rosado/Evan, Naranjo/Mauricio, Sandoval/Carlos

Tube System Upgrade (NEW — 06-01)

  • Tube System Upgrade — iTrack 3528165. 15x 10" TS stations need MAC addresses added to ISE identity group IoT_Onboard. MACs received from vendor (C8:1A:FE:20:xx:xx series). Station list spans ICU (CTICU, PICU, BMT, NICU, NICCU), ED, Surgery, Trauma, Pharmacy. Vendor contact: John Genest. Rationale: manufacturer no longer supports current system; failure risks delayed/missed patient care.

BMS Device Inventory (NEW — 04-24)

  • BMS Device Inventory — 72 devices discovered across 37 switches (04-24). Profile-driven architecture (Claroty/Medigate). 16 queries built. Phase 0 complete. Next: cross-reference with Visio diagrams, classify by function, begin D2 diagrams. Cleanup: delete 4 orphaned test groups, migrate 4 retire-dACL devices, investigate 3 null-profile devices.

VNC Blocking (NEW — 05-11)

  • VNC Blocking — block and eliminate VNC enterprise-wide. Due mid-June 2026. Phase 0: discovery. January AQL query baseline to incorporate. Cross-reference BMS inventory for VNC-capable devices.

Investigations & Audits

  • Murus Portae (WAF) — Phase 0 discovery in progress. FMC cert expired. d001: DMZ NetScaler WAF investigation, zone map, architecture D2 diagrams (v1+v2 SVGs), FMC REST API reference guide, ops script. FMC API returning zero ACP rules — under investigation.

  • Firewall audit — FMC discovery inventory done (d001: fmc-discovery-2026-04-16). EtherChannel query, prefilter, policy assignments pending.

  • IoT Dr. Kim devices — RECURRING. All 4 MACs validated in IoT_iPSK_VLAN1620_Misc (04-24). v2 validation queries built with 7 deep analysis queries (group flapping, credential leakage, profile drift, NAS tracking, remediation timeline, deny audit, OUI scan). Revalidate — confirm no flapping since 04-24.

  • IoT device validation queries — v2 created with partials architecture, 16 queries across ERS/MnT/DataConnect/FMC. Completed 2026-04-24.

Stale Blockers (carried via carryover tracker)

  • k3s NAT verification — rule 170, 10.42.0.0/16 pod network (origin: 2026-03-09). 59 days. Blocks Wazuh indexer recovery → blocks SIEM visibility. Weekend task?

  • Strongline Gateway VLAN fix — 8 devices wrong identity group (origin: 2026-03-16). 52 days. David Rukiza assigned — follow up on status.

Administrative

  • PeopleSoft — track time for current week

  • iTrack tickets — close open tickets

  • KQL library — build initial queries in codex + d001

  • Linux Research project — finalize and review

  • Tax filing 2025 (MFJ) — see encrypted case file in data/d000/personal/ for details and action items

P1 — Important

  • MSCHAPv2 action-item tracker — owner/status/next-steps per workstream

  • ISE admin MFA enforcement — recommendation tied to advisory (interim control pending Patch 10)

  • DMZ Migration — external services audit behind NetScaler. Linked to Murus Portae investigation.

  • Vocera/Wyse iTrack RCA — complete root cause report

  • GCC ISE Support — 3/4 nodes restored, PSN-04 deferred

  • Wazuh indexer recovery — blocked by k3s NAT (origin: 2026-03-09)

  • Vocera EAP-TLS Supplicant Fix (origin: 2026-03-12)

  • iPSK Manager HA — blocked by DB replication (Ben Castillo)

  • ISE 3.4 Migration — depends on Patch 10 completion first

  • Git history scrub — murus-portae-output.md + ise-analytics CSVs

  • Encrypt prep-cmds-2026-04-15.adoc — plaintext committed to git

  • ISE MnT Messaging Service — enable UDP syslog delivery (maintenance window needed)

Infrastructure (Personal)

  • Borg backups — test and validate on ALL systems (Razer, P16g, vault-01, bind-01, kvm-01, kvm-02)

  • Borg — verify backup script paths updated from dotfiles-optimus to dots-quantum

  • Borg — create initial archive for ThinkPad P16g if none exists

  • Libvirt VLAN hook debug on both KVMs

  • Te1/0/2 cable replacement and re-test

  • Vault Raft cluster — verify vault-01 rejoined

  • Fix EAP-TLS keyring/secrets issue on Razer workstation

Completed (confirmed — do not delete, archive only)

  • CR-2026-04-15 SRT Research VLAN — submitted to iTrack. Completed 2026-04-15.

  • CAB presentation 4/21 — SRT Research VLAN 233 → CHLA-Research. APPROVED. Completed 2026-04-21.

  • Downtime Computers wireless audit — 45 computers, 16 violating, v3 report delivered. Completed 2026-04-21.

  • Git identity fix — dots-quantum/git/.gitconfig email corrected. Completed 2026-04-21.

  • MSCHAPv2 10:30 meeting — next steps + ACL coordination. Completed 2026-04-17.

Service Requests (SR)

SR# Request Requestor Opened Status

3508542

Zoll cards connection issue

STALE — verify in iTrack

3508524

Disable dot1x on (2) network ports - 5th floor 3250 Wilshire (PXE-boot imaging issues)

STALE — verify in iTrack (issues persisted after disable)

3528165

Tube System Upgrade — 15 stations, MAC addresses for ISE IoT_Onboard identity group

Genest, John (vendor contact)

2026-06-01

NEW — MACs received, need ISE onboarding

Incidents (INC)

INC# Priority Description Opened SLA Status

1911859

Strongline Gateways in Miscellaneous Subnet

STALE — verify in iTrack (related to carryover P0)

Change Requests - Emergency (ECAB)

CR# Description Opened Scheduled Status

No emergency changes

Change Requests - Normal

CR# Description Opened Scheduled Status

No normal changes

Change Requests - Scheduled/Standard

CR# Description Opened Window Status

No scheduled changes

Change Requests - Root Cause / Post-Incident

CR# Description Related INC Opened Status

100451

Vocera Phones and Wyse devices went off network

STALE — verify in iTrack


Session Accomplishments (Claude Code)

Day-specific accomplishments here.


Personal

In Progress

Project Description Status Notes

k3s Platform

Production k3s cluster on kvm-01

Active

Prometheus, Grafana, Wazuh deployed

Wazuh Archives

Enable archives indexing in Filebeat

Active

PVC fix pending

kvm-02 Hardware

Supermicro B deployment

Active

Hardware ready, RAM upgrade done

Planned

Project Description Target Blocked By

Vault HA (3-node)

vault-02, vault-03 on kvm-02

Q2 2026 (slipped from Q1)

kvm-02 deployment

k3s HA (3-node)

Control plane HA

Q2 2026 (slipped from Q1)

kvm-02 deployment

ArgoCD GitOps

k3s GitOps deployment

After k3s stable

 — 

MinIO S3

Object storage for k3s

After ArgoCD

 — 

Domus Inventory

Personal asset management (YAML + CLI + AsciiDoc)

Q2 2026

Schema approved

Active — Infrastructure

Task Details Priority Status Due

Wazuh agent deployment

Deploy agents to all infrastructure hosts

P2

Pending

After archives fix

k3s Platform

Production k3s cluster on kvm-01

P1

In Progress

 — 

Wazuh Archives

Enable archives indexing in Filebeat, PVC fix

P1

In Progress

 — 

kvm-02 Hardware

Supermicro B deployment, RAM upgrade done

P1

In Progress

 — 


Active — Security & Encryption

Task Details Priority Status Due

Configure 4th YubiKey

SSH FIDO2 keys

P1

TODO

 — 

Cold storage M-DISC backup

age-encrypted archives

P1

TODO

After YubiKey setup


Active — Development & Tools

Task Details Priority Status Due

netapi Commercialization

Go CLI rewrite with Cobra-style argument discovery, package for distribution

P0

Active

 — 

Ollama API Service

FastAPI (17 endpoints), productize — config audit, doc tools, runbook gen

P0

Active

 — 

Shell functions (fe, fec, fef)

File hunting helpers

P3

TODO

 — 


Active — Documentation

Task Details Priority Status Due

D2 Catppuccin Mocha styling

domus-* spoke repos (177 files total)

P3

In Progress

 — 


Active — Financial

Task Details Priority Status Due

Amazon order history import

Download CSV from Privacy Central → parse with awk → populate subscriptions tracker

P1

Waiting

Pending Amazon data export (requested 2026-04-04)


Active — Education

Task Details Priority Status Due

No active education tasks — see education trackers


Active — Personal & Life Admin

Task Details Priority Status Due

ThinkPad T16g Setup

Arch install, stow dotfiles, Ollama stack, netapi dev env

P0

Pending

 — 

P50 Arch to Ubuntu migration

CR-2026-03-12

P2

In Progress

 — 

X1 Carbon Ubuntu installs

2 laptops, LUKS encryption

P2

In Progress

 — 

P50 Steam Test

Test Flatpak Steam + apt cleanup of broken i386 packages

P3

Pending

 — 

Documentation Sites

Notes

Day-specific personal notes here.


Education

Claude Code Mastery

Resource Details Progress Status

Claude Code Full Course (4 hrs)

Nick Saraev - YouTube comprehensive course

26:49 / 4:00:00

IN PROGRESS

Claude Code Certification

Anthropic official certification (newly released)

Not started

GOAL

Skills Mastery (Critical)

Certification Deadlines

  • CISSP - July 12, 2026 (10-week plan active — Week 1)

  • RHCSA 9 - Q3 2026 (after CISSP)

  • LPIC-1 - Renewal required (blocks LPIC-2)

Spanish C1 Certification Goals

Certification Provider Target Status Strategy

SIELE C1

Instituto Cervantes / UNAM / Salamanca

Q2 2026

ACTIVE

Computer-based, faster results - take FIRST

DELE C1

Instituto Cervantes

Q3/Q4 2026

PLANNED

After SIELE success, harder exam

DELE C2

Instituto Cervantes

2027

FUTURE

Mastery level - requires extensive immersion

SIELE is computer-adaptive, results in 3 weeks. DELE is paper-based, results in 3-4 months. Do SIELE first to validate readiness.

Don Quijote Writing Practice - DELE C1/C2 Initiative

Method:

  1. Read chapter in original Spanish

  2. Write personal analysis/understanding en espanol

  3. AI review for grammar, vocabulary, register

  4. Build comprehensive understanding of literary elements

Today’s Study

  • Focus: CISSP (41 days to July 12 exam — schedule exam today 06-01), MSCHAPv2 migration wrap-up

  • Secondary: RHCSA curriculum, Spanish SIELE C1

  • CISSP — Security & Risk Management (continuing). Schedule exam this afternoon.

  • RHCSA — continue curriculum phase

  • Spanish — Don Quijote reading + analysis (DTLA study day)

  • MSCHAPv2 — migration window closed 05-30, review final report

Regex Training (CRITICAL)

  • Status: 52 days carried over (since 2026-03-16)

  • Priority: After PeopleSoft, before Quijote

  • Session: Character classes, word boundaries


Infrastructure

Documentation Sites

Site URL Status Actions Needed

Domus Digitalis

docs.domusdigitalis.dev

Active

Validate, harden, improve

Architectus

docs.architectus.dev

Active

Public portfolio site - maintain

HA Deployment Status

System Description Status Notes

VyOS HA

vyos-01 (kvm-01) + vyos-02 (kvm-02) with VRRP VIP

✅ COMPLETE

2026-03-07 - pfSense decommissioned

BIND DNS HA

bind-01 (kvm-01) + bind-02 (kvm-02) with AXFR

✅ COMPLETE

Zone transfer operational

Vault HA

Raft cluster (vault-01/02/03)

✅ COMPLETE

Integrated with PKI

Keycloak Rebuild

keycloak-01 corrupted, rebuild from scratch

🔄 NEXT

Priority P3 - SSO broken

FreeIPA HA

ipa-02 replica planned

📋 PLANNED

Linux auth redundancy

AD DC HA

home-dc02 replication

📋 PLANNED

Windows auth redundancy

iPSK Manager HA

ipsk-mgr-02 with MySQL replication

📋 PLANNED

PSK portal redundancy

ISE HA

PAN HA (ise-01 reconfigure)

⏳ DEFERRED

Wait until ise-02 stable

ISE 3.5 Migration

Upgrade path: 3.2p9 → 3.4 (P1) → 3.5 (target)

📋 PLANNED

After 3.4 Migration completes (Q2 2026)

Single Points of Failure (CRITICAL)

These systems have NO redundancy - outage impacts production.
System Impact if Down Mitigation

ISE (ise-02)

All 802.1X stops - wired and wireless auth fails

ise-01 reconfiguration deferred until ise-02 stable

Keycloak (keycloak-01)

SAML/OIDC SSO broken (ISE admin, Grafana, etc.)

NEXT PRIORITY - Rebuild runbook

FreeIPA (ipa-01)

Linux auth, sudo rules, HBAC fails

ipa-02 replica planned

AD DC (home-dc01)

Windows auth, Kerberos, GPO fails

home-dc02 replica planned

iPSK Manager

Self-service PSK portal unavailable

ipsk-mgr-02 with MySQL replication planned

Validation Tasks

Task Details Status

docs.domusdigitalis.dev validation

Test all cross-references, search, rendering

TODO

docs.domusdigitalis.dev hardening

HTTPS, CSP headers, security review

TODO

docs.architectus.dev validation

Public site content review

TODO

Hub-spoke sync verification

All components building correctly

Ongoing


Quick Commands

Git & GitHub CLI

create GitHub repo from existing local repo
gh repo create <name> --private --source . --remote origin --push
clone a forked repo into a specific directory
gh repo clone EvanusModestus/PowerShell ~/atelier/_projects/work/PowerShell
gh repo clone defaults to SSH. If key is passphrase-protected, load agent first: eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519_github
cross-repo commit search — all domus repos on a specific date
for repo in ~/atelier/_bibliotheca/domus-*/ ~/atelier/_projects/personal/domus-*/; do
  [ -d "$repo/.git" ] || continue
  name=$(basename "$repo")
  git -C "$repo" log --since="2026-04-06" --until="2026-04-07" --format="%h %aI %s" 2>/dev/null |
    awk -v r="$name" '{print r, $0}'
done
commit history touching only today’s modified files
git log --oneline -- $(find . -name "*.adoc" -type f -newermt "$(date +%F)")
unstage a file without losing changes
git restore --staged data/d001/api/ise-dataconnect/output/output-2026-04-24

Safe — removes from staging area only. Working tree is untouched. Use when you accidentally git add a plaintext or output file.

gh CLI — repo discovery and filtering

list repos by name pattern (domus/antora ecosystem)
gh repo list --limit 100 --json name,description \
  | jq -r '.[] | select(.name | test("domus|antora|asciidoc"; "i")) | "\(.name)\t\(.description)"'
top 20 most recently updated repos
gh repo list --limit 100 --json name,description,updatedAt \
  | jq -r 'sort_by(.updatedAt) | reverse | .[:20] | .[] | "\(.updatedAt[:10])\t\(.name)\t\(.description)"'
top 10 repos by disk usage
gh repo list --limit 100 --json name,diskUsage \
  | jq -r '.[] | "\(.diskUsage)\t\(.name)"' | sort -rn | head -10
clone a repo that’s not local yet
gh repo clone EvanusModestus/<repo-name> ~/atelier/_bibliotheca/<repo-name>

find & grep

files modified since midnight today (precise — not "last 24 hours")
find . -name "*.adoc" -type f -newermt "$(date +%F)" | sort
-mtime 0 means "last 24 hours", not "today". -newermt "$(date +%F)" compares against midnight — exact.
case-insensitive file search
find . -iname "*mschap*" -type f | sort
multiple name patterns with -o
find . -type f \( -iname "*ise*" -o -iname "*mschap*" \) | sort
same thing, single regex — fewer parens, extensible
find . -type f -iregex '.*\(ise\|mschap\).*'
exclude directories
find . -type f -iname "*meeting*" \
  -not -path "*/node_modules/*" \
  -not -path "*/.git/*" \
  -not -path "*/build/*"
recent drafts by modification time (newest first)
find .drafts -type f -printf '%T@ %Tc %p\n' | sort -rn | awk '{$1="";print}' | head -3
grep — know what you’re counting
grep -rl "pattern" . --include="*.adoc"         # file count (which files)
grep -rn "pattern" . --include="*.adoc"         # line matches (every occurrence)
grep -rc "pattern" . --include="*.adoc" | grep -v ':0$'  # match count per file
search with context — avoid opening the file
grep -rn -E 'git init|gh repo create' docs/ --include='*.adoc' -B2 -A2

Search codex by content — which files contain a command?

find all PowerShell files that use a specific cmdlet
find docs/modules/ROOT/examples/codex/powershell -type f -name "*.adoc" \
  -exec grep -l 'Get-Process\|Start-Process\|pipeline\|Where-Object' {} \;

Pattern: find -exec grep -l returns only filenames with matches — like grep -rl but with find’s `-type f -name filtering. Use \| for OR in grep basic regex. Swap the pattern for any cmdlet or keyword to locate coverage across the codex.

inventory a codex tool directory — count files per tier
find docs/modules/ROOT -name "powershell" -type d \
  -exec sh -c 'echo "$1: $(find "$1" -type f | wc -l) files"' _ {} \;
find orphaned examples (not included by any page)
for f in $(find docs/modules/ROOT/examples/codex/powershell -name "*.adoc" -type f); do
  base=$(basename "$f")
  dir_parent=$(basename $(dirname "$f"))
  grep -rq "$dir_parent/$base" docs/modules/ROOT/pages/codex/powershell/ \
    docs/modules/ROOT/examples/codex/powershell/*.adoc 2>/dev/null \
    || echo "ORPHAN: $f"
done

find → grep → open in nvim

find by path + content, open result in nvim
nvim $(find -path '*oauth*' -name '*.adoc' -type f \
  -exec grep -l 'timeout\|expire\|reconfig\|token' {} \;)

Command substitution $(…​) feeds all matches as arguments to nvim — opens every hit as a buffer. :bn/:bp to cycle, :ls to list. One file? Opens directly. Five files? All loaded, ready to navigate.

find by content across entire tree, open in nvim
nvim $(find docs/modules/ROOT -name '*.adoc' -type f \
  -exec grep -l 'token.*expire\|oauth.*refresh' {} \;)
open one at a time (sequential — -exec nvim per match)
find -path '*oauth*' -name '*.adoc' -type f \
  -exec grep -l 'timeout\|expire' {} \; \
  -exec nvim {} \;
Trailing \| in grep patterns matches empty string — every file matches. Always end with a term, not a pipe: 'timeout\|expire\|token' not 'timeout\|expire\|token\|'.

Trace Antora partial inclusion chains

who includes this partial? (one level up)
grep -rl 'commands/shell' docs/modules/ROOT/partials/
count all pages that include a partial
grep -rl 'quick-commands' docs/modules/ROOT | wc -l
full chain: partial → assembler → every page that uses it
file="commands/shell"
grep -rl "$file" docs/modules/ROOT/partials/ | while read f; do
  parent=$(basename "$f" .adoc)
  echo "$file -> $parent"
  grep -rl "$parent" docs/modules/ROOT/pages/ | while read p; do
    echo "  -> $(basename "$p")"
  done
done

Pattern: grep -rl finds which files contain the string. Chain two passes — first finds the assembler partial, second finds every page that includes it. Works for any partial in the Antora include hierarchy.

Multi-pattern file search — worklog partial discovery

brute force — one find per partial name
find docs/modules/ROOT -name "*urgent.adoc*" -type f
find docs/modules/ROOT -name "*morning.adoc*" -type f
consolidated — single find with regex (production approach)
find docs/modules/ROOT -type f -regextype posix-extended \
  -regex '.*(urgent|morning|work-chla|personal|education|infrastructure|quick-commands|related)\.adoc' \
  | sort

Pattern: -regextype posix-extended enables | alternation without escaping. One process, one sort — versus 8 separate finds. The sort deduplicates visually and groups by path.

pipeline alternative — find piped to grep
find docs/modules/ROOT -type f -name "*.adoc" \
  | grep -E 'urgent|morning|work-chla|personal|education|infrastructure|quick-commands|related'

Trade-off: the pipeline version is more readable but spawns two processes. The regex version is a single find — faster on large trees, same result.

Cross-repo literary term search — bibliotheca-wide discovery

When searching for a term across the entire _bibliotheca (multiple repos, mixed file types), these patterns escalate from narrow to broad.

1. Single repo — count matches per file
grep -rn --include='*.adoc' -c 'sanchuelo' . | grep -v ':0$'
2. Cross-repo — filenames only (all bibliotheca)
grep -rl --include='*.adoc' -i 'sanchuelo' ~/atelier/_bibliotheca/ | sort
3. Cross-repo with context — see the line in situ
grep -rn --include='*.adoc' -i -B1 -A1 'sanchuelo' ~/atelier/_bibliotheca/domus-captures/
4. Multi-filetype — .adoc + .txt (catches source texts)
grep -rl -i 'sanchuelo' ~/atelier/_bibliotheca/ --include='*.txt' --include='*.adoc' | sort
5. Null-safe find + xargs — handles spaces in paths
find ~/atelier/_bibliotheca/ -type f \( -name '*.adoc' -o -name '*.txt' \) -print0 \
  | xargs -0 grep -li 'sanchuelo' | sort
6. Open all hits directly in nvim
grep -rl -i 'sanchuelo' ~/atelier/_bibliotheca/ --include='*.adoc' --include='*.txt' | xargs nvim

Pattern escalation: #1 confirms the term exists and where. #2 expands to all repos. #3 shows context without opening files. #4 adds plain text sources (Quijote .txt originals). #5 is the safe version for automation. #6 opens everything for editing.

Trade-off: grep -r --include is faster for known file types. find | xargs grep is safer for paths with spaces and more extensible (add -name '*.md' etc.). For literary searches across the bibliotheca, #4 or #5 is usually the right starting point — the source texts are .txt, not .adoc.

Email thread analysis — extract people, dates, commitments, silence

who’s in the thread (@ mentions + From headers)
grep -P '(@\w+|^From:.*<)' comms.adoc
timeline — every date with context
grep -nP '\d{1,2}/\d{1,2}/\d{2,4}|20\d{2}-\d{2}-\d{2}' comms.adoc
commitments — who promised what
grep -niP '(I can |I will |I.ll |we will |we.ll )' comms.adoc
open questions and unknowns
grep -niP '(\?|need to confirm|need to validate|TBD|pending)' comms.adoc

comm — set difference (who hasn’t replied)

# All recipients
grep -oP '<\K[^>]+' comms.adoc | sort -u > /tmp/all-recipients

# All senders
grep -P '^From:' comms.adoc | grep -oP '<\K[^>]+' | sort -u > /tmp/replied

# Who's silent — follow-up targets
comm -23 /tmp/all-recipients /tmp/replied

comm -23 outputs lines only in file 1 (recipients not in senders). Requires sorted input. grep -oP '<\K[^>]+' uses PCRE lookbehind — match < but don’t include it, capture until >.

awk, sed, jq

awk — field extraction

print second field (whitespace-delimited)
awk '{print $2}' file.txt
custom delimiter — colon-separated (like /etc/passwd)
awk -F: '{print $1, $3}' /etc/passwd
extract JSON code blocks from AsciiDoc
awk '/\[source,json\]/{getline; if ($0 ~ /^----/) {p=1; next}} p && /^----/{p=0; next} p' file.adoc
field extraction with printf formatting
awk '{printf "%-30s %s\n", $1, $2}' file.txt

sed — stream editing

in-place replacement with verify-before/after
# Before
awk 'NR==73' /etc/ssh/sshd_config
# Change
sed -i '73s/#GSSAPIAuthentication no/GSSAPIAuthentication yes/' /etc/ssh/sshd_config
# After
awk 'NR==73' /etc/ssh/sshd_config
extract line range
sed -n '10,20p' file.txt

jq — JSON processing

extract nested fields
curl -s localhost:8080/stats | jq '.stats.total_files'
filter array by property
jq '.results[] | select(.category == "standards")' response.json
transform to TSV for spreadsheets
jq -r '.[] | [.title, .path] | @tsv' response.json | column -t -s $'\t'
GitHub API + jq — commit history by path
gh api "repos/EvanusModestus/domus-captures/commits?path=docs/&per_page=10" |
  jq -r '.[] | "\(.commit.author.date[:10]) \(.sha[:7]) \(.commit.message | split("\n")[0])"'

Shell Patterns

xargs — when the next command reads arguments, not stdin

Next command reads…​ Use

stdin (awk, grep, wc, sort)

pipe directly

arguments (stat, rm, cp, nvim, git add)

xargs

copy today’s files to backup — -I{} placeholder
mkdir -p /tmp/adoc-backup-$(date +%F) && \
  find . -name "*.adoc" -type f -newermt "$(date +%F)" | \
  xargs -I{} cp {} /tmp/adoc-backup-$(date +%F)/
parallel validation — -P4 runs 4 at a time
find .drafts -name "*.adoc" -type f | xargs -P4 -I{} asciidoctor -o /dev/null {}
null-delimited pipeline — safe for filenames with spaces
find . -name "*.adoc" -type f -print0 | xargs -0 wc -l

Process substitution — <(cmd) treats output as a file

compare tracker state: yesterday vs today
diff <(grep '|' partials/trackers/work/adhoc/carryover.adoc | head -20) \
     <(git show HEAD~1:partials/trackers/work/adhoc/carryover.adoc | grep '|' | head -20)
files on disk vs files in nav — drift detection
diff <(find docs/modules/ROOT/pages/projects/chla/mschapv2-migration -name "*.adoc" -type f | sort) \
     <(grep -oP 'mschapv2-migration/[^[]+\.adoc' docs/modules/ROOT/nav.adoc | sort)

Command substitution — embed output as arguments

open most recently modified file in nvim
nvim "$(find data/ -name '*.adoc' -type f -printf '%T@ %p\n' | sort -rn | awk 'NR==1{print $2}')"
line count across a project
wc -l $(find docs/modules/ROOT -path '*mschapv2*' -name '*.adoc' -type f)

Conditional execution — capture, test, act

open matching files only if they exist
files=$(find .drafts -name 'in*' -type f) && [ -n "$files" ] && nvim $files
open files that contain unchecked items
files=$(grep -rl '\[ \]' .drafts/*.adoc) && [ -n "$files" ] && nvim $files
guard with grep -q — only act if pattern matches
grep -q 'TODO\|FIXME\|\[ \]' "$file" && nvim "$file"

Pattern: $(capture)[ -n ] tests non-empty → && only proceeds if true. grep -q is the idempotent guard — run repeatedly, only opens when there’s work.

Decrypt and open — find .age, decrypt, nvim in one shot

files=$(find . -name "*tcp-clock*.age" -type f) && \
  [ -n "$files" ] && echo "$files" | xargs -I{} decrypt-file {} && \
  nvim $(echo "$files" | sed 's/\.age$//')

Pattern: find .age only (never tries plaintext), sed derives the decrypted path, guard prevents empty nvim. Change the glob to match any project.

tee_clean — color on screen, clean text in file

tee_clean() {
  tee >(sed 's/\x1b\[[0-9;]*m//g' > "$1")
}

# Color output on terminal, stripped in file
jq -C '.' data.json | tee_clean output.json
xq -C '.' data.xml | tee_clean output.json

# Wrap a whole block
{
  echo "=== Summary ==="
  jq -C '.[] | .name' data.json
} | tee_clean summary.txt

The >(cmd) is process substitution — tee writes to stdout AND to the subshell pipe. sed strips ANSI escape sequences (\x1b\[[0-9;]*m) before they hit the file.

Dependency check — verify toolchain in one shot

for cmd in asciidoctor asciidoctor-pdf pandoc rouge d2 mmdc age; do
  printf "%-20s %s\n" "$cmd" "$(command -v $cmd >/dev/null 2>&1 && echo 'OK' || echo 'MISSING')"
done

Pattern: command -v checks if binary exists on PATH. >/dev/null 2>&1 suppresses output — we only care about exit code. Swap the tool list for any project’s dependencies.

printf safety — dashes as data, not options

wrong — printf treats --- as invalid option
printf '---\n\n'
right — %s format string treats --- as data
printf '%s\n\n' '---'

Kill stuck SSH sessions

Find established SSH connections
lsof -i TCP -n -P | awk '/ssh.*ESTABLISHED/ {print $2, $9}'
Kill all stuck SSH sessions to a specific host
lsof -i TCP -n -P | awk '/ssh.*kvm-01.*ESTABLISHED/ {print $2}' | sort -u | xargs kill
Kill ALL stuck SSH sessions
lsof -i TCP -n -P | awk '/ssh.*ESTABLISHED/ {print $2}' | sort -u | xargs kill

lsof -i TCP -n -P lists all TCP connections. awk filters for SSH + ESTABLISHED, prints only the PID ($2). sort -u deduplicates (multiple file descriptors per process). xargs kill sends SIGTERM to each.

File Descriptors & Redirection

The three file descriptors

FD Name Purpose

0

stdin

input to the command

1

stdout

normal output (valid results)

2

stderr

error messages

Split stdout and stderr into separate files

find / -name "*.conf" 1>results.txt 2>errors.txt

Suppress errors — 2>/dev/null

find / -name "*.conf" 2>/dev/null

Merge stderr into stdout — 2>&1

command 2>&1 | grep "pattern"

This sends both stdout and stderr through the pipe. Without 2>&1, only stdout reaches grep — errors print to the terminal and bypass the pipeline.

Heredoc patterns

multi-line input to a command
cat <<'EOF'
Line 1
Line 2
EOF
heredoc commit messages (quotes prevent variable expansion)
git commit -m "$(cat <<'EOF'
feat: add new feature

Multi-line description here.
EOF
)"

API & curl/jq

domus-api — Documentation System REST API

start the API server
cd ~/atelier/_projects/personal/domus-api && uv run uvicorn domus_api.main:app --host 0.0.0.0 --port 8080
health check
curl -s localhost:8080/ | jq
full-text search
curl -s 'localhost:8080/search?q=mandiant' | jq
search — extract path, title, match count
curl -s 'localhost:8080/search?q=mandiant' | jq '.results[] | {path, title, match_count}'
list pages by category
curl -s 'localhost:8080/pages?category=standards' | jq
all antora.yml attributes
curl -s localhost:8080/attributes | jq

GitHub API

cross-repo search via GitHub API
gh search code "vault seal" --owner EvanusModestus --json repository,path,textMatches |
  jq '.[] | {repo: .repository.full_name, file: .path, match: .textMatches[].fragment}'
count .adoc files in a repo via API
gh api 'repos/EvanusModestus/domus-captures/git/trees/main?recursive=1' |
  jq '[.tree[] | select(.path | endswith(".adoc"))] | length'

Domus Workflows

Read content from terminal (meeting-ready)

today’s worklog
bat docs/modules/ROOT/pages/2026/04/WRKLOG-$(date +%Y-%m-%d).adoc
current priorities
bat docs/modules/ROOT/partials/trackers/work/priorities/current.adoc
carryover backlog
bat docs/modules/ROOT/partials/trackers/work/adhoc/carryover.adoc
any project summary
bat docs/modules/ROOT/partials/projects/mandiant-remediation/summary.adoc

Search and discovery

find all files related to a topic
grep -rl "MSCHAPv2" docs/modules/ROOT/ --include="*.adoc" | sort
search codex entries
grep -rn "pattern" docs/modules/ROOT/partials/codex/ --include="*.adoc" -B1 -A3
list all worklogs for a month
ls -1 docs/modules/ROOT/pages/2026/04/WRKLOG-*.adoc

Tracker aging — calculate days from origin

how many days since a carryover item started
echo $(( ($(date +%s) - $(date -d "2026-03-09" +%s)) / 86400 ))

Encrypted data access (d001)

view encrypted file without disk write
age --decrypt -i ~/.secrets/.metadata/keys/master.age.key \
  data/d001/projects/mandiant-remediation/findings-status-2026-04-16.adoc.age \
  | bat --language asciidoc
project encryption dashboard
for d in data/d001/projects/*/; do
  total=$(find "$d" -type f | wc -l)
  plain=$(find "$d" -type f ! -name '*.age' ! -name 'README.adoc' ! -name '.gitkeep' ! -name '*.py' | wc -l)
  printf "%-25s %s files  %s plaintext\n" "$(basename "$d")" "$total" "$plain"
done

ISE & Network Ops

ISE ERS API — endpoint CRUD

set credentials (session)
export ISE_HOST="{ise-ip}" ISE_USER="admin" ISE_PASS="$(gopass show -o ise/admin)"
list identity groups
curl -sk "https://$ISE_HOST:{ise-ers-port}/ers/config/identitygroup" \
  -H "Accept: application/json" -u "$ISE_USER:$ISE_PASS" | jq '.SearchResult.resources[].name'
check if endpoint exists by MAC
curl -sk "https://$ISE_HOST:{ise-ers-port}/ers/config/endpoint?filter=mac.EQ.AA:BB:CC:DD:EE:FF" \
  -H "Accept: application/json" -u "$ISE_USER:$ISE_PASS" | jq '.SearchResult.total'

Certificate inspection

view EAP-TLS client cert from local store
openssl x509 -in {cert-dir}/client.pem -text -noout | head -30
check cert expiry
openssl x509 -in {cert-dir}/client.pem -enddate -noout

Network diagnostics

check listening ports
ss -tlnp | grep -E ':{port-https}|:{port-ssh}|:{port-ldaps}'
test ISE connectivity
nc -zv {ise-ip} {ise-ers-port}
DNS resolution
dig {ise-hostname} +short

PowerShell (from zsh)

All PowerShell commands run inside pwsh -NoLogo -Command '…​' from zsh. Running them bare fails — zsh interprets $, |, () as shell syntax.

Process management

top 5 processes by memory
pwsh -NoLogo -Command 'Get-Process | Sort-Object WorkingSet64 -Descending |
  Select-Object -First 5 ProcessName, Id,
    @{N="MB";E={[math]::Round($_.WorkingSet64/1MB)}} | Format-Table'
stop/start Teams
pwsh -NoLogo -Command 'Get-Process | Where-Object {$_.ProcessName -like "*teams*"} | Stop-Process'
pwsh -NoLogo -Command 'Start-Process "ms-teams"'

Export to JSON (pipe to jq)

always use -NoLogo when piping pwsh output to zsh tools
pwsh -NoLogo -Command 'Get-Process | Sort-Object WorkingSet64 -Descending |
  Select-Object -First 5 ProcessName, Id,
    @{N="MB";E={[math]::Round($_.WorkingSet64/1MB)}} | ConvertTo-Json' | jq '.'
Never pipe Format-Table into ConvertTo-Json — it produces layout metadata, not data. Select-Object first, then ConvertTo-Json.

Wi-Fi management (netsh)

force fresh network scan
netsh wlan disconnect interface="Wi-Fi"
netsh wlan show networks mode=bssid
netsh wlan connect name="CHLA-Remote" interface="Wi-Fi"

SSH from PowerShell

connect to homelab from Windows terminal
ssh evan@modestus-razer.inside.domusdigitalis.dev

Security & Encryption

View encrypted files without writing to disk

pipe age decrypt to bat — nothing touches the filesystem
age --decrypt -i ~/.secrets/.metadata/keys/master.age.key \
  data/d001/projects/mandiant-remediation/findings-status-2026-04-16.adoc.age \
  | bat --language asciidoc --file-name "findings-status-2026-04-16.adoc"

Batch re-encrypt — brace expansion + loop

re-encrypt multiple project files
for f in data/d001/projects/mandiant-remediation/{findings-status,guest-acl-update,siem-report}-2026-04-16.adoc; do
  rm -f "${f}.age" && echo y | encrypt-file "$f"
done
Always rm -f the .age first. If you skip it, encrypt-file prompts about overwrite and may only delete the plaintext without re-encrypting.

Detect stale plaintext — files needing re-encryption

find plaintext newer than its .age counterpart
for f in data/d001/projects/*/*.adoc; do
  age="${f}.age"
  if [ -f "$f" ] && [ -f "$age" ]; then
    pt_mod=$(/usr/bin/stat -c'%Y' "$f")
    age_mod=$(/usr/bin/stat -c'%Y' "$age")
    [ "$pt_mod" -gt "$age_mod" ] && echo "STALE: $f"
  fi
done

Secure delete — shred for sensitive plaintext

shred -u data/d001/projects/mandiant-remediation/man-report.txt
On SSD/NVMe, shred is less effective (wear leveling), but better than rm which only removes the directory entry.

Pre-push audit — find all unencrypted project files

find data/d001/projects -type f ! -name '*.age' ! -name 'README.adoc' ! -name '.gitkeep' ! -name '*.py' | sort

System & Infrastructure

PipeWire audio validation

wpctl status                                    # PipeWire status
pactl list sinks short                          # list audio sinks
pw-play /usr/share/sounds/freedesktop/stereo/bell.oga  # test default sink
journalctl -b --grep='sof|cs35l56' --no-pager | tail -20  # kernel audio firmware
cat /proc/asound/cards                          # ALSA sound cards

gopass — personal document management

gopass-personal-docs    # interactive entry creation
gopass-query bills      # list recurring bills with totals
gopass-query storage    # list storage units with gate codes
gopass-query export bills  # export category to JSON

Makefile — daily workflow

make new-day      # create today's worklog + update attributes
make serve        # build + local server (port 8000)
make              # build only
make sync-nav     # sync worklog nav entries
make update-index # rebuild monthly index

Per-project file dashboard

per-project summary — total files vs unencrypted plaintext
for d in data/d001/projects/*/; do
  total=$(find "$d" -type f | wc -l)
  plain=$(find "$d" -type f ! -name '*.age' ! -name 'README.adoc' ! -name '.gitkeep' ! -name '*.py' | wc -l)
  echo "$(basename "$d") | ${total} files | ${plain} plaintext"
done