# Session Log — Cascades Tucson: EOP Access Test & Alma Montt Mailbox Investigation
**Date:** 2026-05-20
**Channel:** #alma.montt-at-cascades-reports-not-receiving-email

## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-BEAST-ROG (Discord bot session)
- **Role:** admin

---

## Session Summary

The session began with testing the EOP access remediation skill for Cascades Tucson at the request of Mike Swanson via Discord. The vault was confirmed accessible at `C:/Users/guru/vault`, and credentials were retrieved for both the Cascades Tucson M365 tenant and the ComputerGuru Security Investigator MSP app. An investigator-exo token was successfully acquired for the Cascades tenant. Graph API access was verified as working, and the EXO `adminapi/beta/InvokeCommand` endpoint was tested, returning 401 Unauthorized.

The root cause was identified: the Security Investigator app had `full_access_as_app` (EWS, role ID `dc890d15`) granted on Exchange Online, but the InvokeCommand REST endpoint requires `Exchange.ManageAsApp` (role ID `dc50a0fb`). Mike granted admin consent via URL, but consent only covered the existing permission set since `Exchange.ManageAsApp` had not yet been added to the app registration. The app registration was updated via PATCH using a tenant-admin Graph token in the MSP tenant, and the role was directly granted in the Cascades tenant via POST. After clearing the token cache, the new token contained both roles and InvokeCommand returned 200 OK.

The investigation then pivoted to Alma Montt's mailbox, as she had reported not receiving email. The mailbox was confirmed active (she had logged in and interacted today at ~17:00 UTC). No forwarding, suspicious inbox rules, blocked senders, or transport rule blocks were found. MX records correctly point to EOP. Message trace returned zero results (likely a permissions gap with the reporting role rather than actual zero mail flow — her inbox had 29 items). Quarantine check returned Invalid Operation due to the same permissions gap. The most notable finding was `EmailAddressPolicyEnabled: False` and only one SMTP address on the mailbox — no onmicrosoft.com alias — suggesting manual provisioning that may have missed standard alias setup.

---

## Key Decisions

- **Added Exchange.ManageAsApp via Graph API rather than waiting for re-consent**: Mike had consented, but the permission wasn't in the app registration yet, so consent had no effect. PATCH to the app registration in the MSP tenant + POST grant in Cascades was cleaner and immediate.
- **Used tenant-admin tier for both the PATCH and the role grant**: Security Investigator app (investigator tier) doesn't have `AppRoleAssignment.ReadWrite.All`, so tenant-admin was required for the Cascades grant. MSP tenant-admin was required for the app registration PATCH.
- **Did not attempt to fix Alma's mailbox without a confirmed root cause**: Message trace and quarantine access failed due to permissions, leaving the specific missing email unidentified. Reported findings and left detailed EAC follow-up steps rather than guessing.
- **This fix needs to be applied to all other client tenants**: The app registration change is done (MSP tenant), but the `Exchange.ManageAsApp` app role grant must be done per-tenant. Other clients still only have `full_access_as_app`.

---

## Problems Encountered

- **EXO InvokeCommand returned 401**: App had `full_access_as_app` (EWS) but not `Exchange.ManageAsApp` (REST cmdlet API). Resolved by patching app registration and granting role directly via Graph.
- **Admin consent did not include Exchange.ManageAsApp**: Consent was granted before the permission was added to the app registration, so it had no effect. Resolved by programmatic grant using tenant-admin.
- **Get-MessageTraceV2 returned 0 results for all queries (including no-filter tenant-wide)**: Likely the SP lacks the `Compliance Management` or `View-Only Recipients` role needed for trace data access. Not resolved this session — flagged for follow-up.
- **Get-QuarantineMessage returned Invalid Operation**: Same permissions gap. Not resolved this session.

---

## Infrastructure & Credentials

### Cascades Tucson Tenant
- **Tenant ID:** `207fa277-e9d8-4eb7-ada1-1064d2221498`
- **Domain:** `cascadestucson.com`
- **MX:** `cascadestucson-com.mail.protection.outlook.com` (EOP, correct)
- **Vault:** `clients/cascades-tucson/m365-admin.sops.yaml`
- **Admin UPN:** `admin@cascadestucson.com`

### MSP App — Security Investigator (updated this session)
- **App ID:** `bfbc12a4-f0dd-4e12-b06d-997e7271e10c`
- **App Object ID (MSP tenant):** `2ca484d4-5b38-4fa5-b8f7-08a70304a54d`
- **SP Object ID in Cascades:** `c64ee5c1-a607-46cb-81b8-42de3de98d48`
- **Vault:** `msp-tools/computerguru-security-investigator.sops.yaml`
- **Auth method used:** client_secret (cert also available)

### Exchange Online SP in Cascades
- **SP Object ID:** `072df88c-1f1f-4910-a9b2-b27144fde653`
- **Display Name:** Office 365 Exchange Online

### App Role IDs (Exchange Online resource `00000002-0000-0ff1-ce00-000000000000`)
| Role | ID |
|---|---|
| `full_access_as_app` (EWS) | `dc890d15-9560-4a4c-9b7f-a736ec74ec40` |
| `Exchange.ManageAsApp` (REST cmdlets) | `dc50a0fb-09a3-484d-be87-e023b12c6440` |
| `Exchange.ManageAsAppV2` | `ea3d980d-ebc7-4be4-8298-a167e5b8797c` |

---

## Commands Run

### Token acquisition
```bash
bash "$SKILL_DIR/scripts/get-token.sh" "207fa277-e9d8-4eb7-ada1-1064d2221498" "investigator-exo"
# Result: success, token TTL 55 min, cached at /tmp/remediation-tool/{tenant-id}/investigator-exo.jwt
```

### Patch app registration (MSP tenant)
```
PATCH https://graph.microsoft.com/v1.0/applications/2ca484d4-5b38-4fa5-b8f7-08a70304a54d
Authorization: Bearer <tenant-admin token for MSP tenant ce61461e-81a0-4c84-bb4a-7b354a9a356d>
Body: requiredResourceAccess with Exchange.ManageAsApp (dc50a0fb) added alongside existing full_access_as_app
Result: 204 No Content
```

### Grant role in Cascades
```
POST https://graph.microsoft.com/v1.0/servicePrincipals/072df88c-1f1f-4910-a9b2-b27144fde653/appRoleAssignedTo
Authorization: Bearer <tenant-admin token for Cascades>
Body: { principalId: c64ee5c1, resourceId: 072df88c, appRoleId: dc50a0fb }
Result: 201 Created — ComputerGuru - Security Investigator / Office 365 Exchange Online
```

### Confirmed working
```
POST https://outlook.office365.com/adminapi/beta/207fa277-e9d8-4eb7-ada1-1064d2221498/InvokeCommand
Body: { CmdletInput: { CmdletName: "Get-AcceptedDomain" } }
Result: 200 OK — cascadestucson.com returned
```

---

## Alma Montt Mailbox Findings

| Property | Value |
|---|---|
| PrimarySmtpAddress | `Alma.Montt@cascadestucson.com` |
| RecipientType | UserMailbox |
| EmailAddressPolicyEnabled | **False** (manually provisioned) |
| Email addresses | Only `Alma.Montt@cascadestucson.com` — no onmicrosoft alias |
| DeliverToMailboxAndForward | False |
| ForwardingAddress | None |
| LitigationHoldEnabled | False |
| HiddenFromAddressLists | False |
| LastLogonTime | 2026-05-20 17:01 UTC (today) |
| LastInteractionTime | 2026-05-20 17:17 UTC (today) |
| ItemCount | 128 |
| TotalSize | ~5MB |
| Inbox items | 29 |
| Junk Email items | 0 |
| Inbox rules | 1 (built-in Junk E-mail Rule only, no custom rules) |
| Hidden inbox rules | None |
| Blocked senders | None |
| TrustedListsOnly | False |
| Transport rules blocking | None (only rule: Fax Forward BCC) |
| Quarantine | Not checked — Get-QuarantineMessage returned Invalid Operation |
| Message trace (7d) | 0 results — SP likely needs Compliance Management role for trace data |

### What's known
Mail is reaching the mailbox — she logged in today and has 29 inbox items. No obvious delivery block found at EOP level.

### Likely next step
The missing email is probably specific (a particular sender or domain). Check via Exchange Admin Center:
- `https://admin.exchange.microsoft.com/#/messagetrace` → filter by recipient `Alma.Montt@cascadestucson.com` and the expected sender
- Check quarantine at `https://security.microsoft.com/quarantine` for her address
- Consider adding onmicrosoft alias via `Set-Mailbox -EmailAddresses @{Add="SMTP:alma.montt@cascadestucson.onmicrosoft.com"}` if senders may be using the old routing address

---

## Pending / Follow-Up

- [ ] **Apply Exchange.ManageAsApp grant to all other client tenants** — app registration updated, but each tenant needs the role granted individually. Can be done via `onboard-tenant.sh` or direct Graph POST per tenant.
- [ ] **Investigate Alma's specific missing email** — need to know which sender/domain she's not receiving from. Run targeted message trace in EAC or give SP the Compliance Management role for trace access.
- [ ] **Add Compliance Management or View-Only Recipients role to Security Investigator SP** in client tenants so message trace works via InvokeCommand.
- [ ] **Add onmicrosoft alias to Alma's mailbox** if confirmed she should have it (`EmailAddressPolicyEnabled: False` is unusual).
- [ ] **Update vault permissions list** for Security Investigator — vault entry currently lists `full_access_as_app (EXO)` but app now also has `Exchange.ManageAsApp`.

---

## Vault Paths Accessed
- `clients/cascades-tucson/m365-admin.sops.yaml`
- `msp-tools/computerguru-security-investigator.sops.yaml`
- `msp-tools/computerguru-tenant-admin.sops.yaml`
