138 lines
6.0 KiB
Markdown
138 lines
6.0 KiB
Markdown
# Gmail OAuth / App Password Provisioning Guide
|
|
|
|
**TL;DR** — Mailroom automation provisioning guide and infrastructure artifacts. This file explains how to stand it up and who to contact; the machinery detail stays lower under Details.
|
|
|
|
|
|
## Scope
|
|
|
|
This guide documents how the CTO or Chairman provisions OAuth 2.0 or App Password access to the `jonathan@cloudinit.dev` Google Workspace Gmail account, so that the MAILROOM_AUTOMATION ingestion pipeline can fetch mail in a secure, auditable way.
|
|
|
|
## Decision Matrix
|
|
|
|
| Path | When to use | Scope | Rotation |
|
|
|------|-------------|-------|----------|
|
|
| OAuth 2.0 (recommended) | Production, long-lived automation | `gmail.readonly` only | Refresh token rotation on suspicion or schedule |
|
|
| App Password | Fallback / legacy IMAP systems | Full mailbox via IMAP | Revoke the App Password and generate a new one |
|
|
|
|
## OAuth 2.0 Flow (Recommended)
|
|
|
|
### 1. Register a Google Cloud project (or reuse an existing one)
|
|
- Console: https://console.cloud.google.com/
|
|
- Ensure the project belongs to the same Workspace org as `jonathan@cloudinit.dev`.
|
|
|
|
### 2. Enable the Gmail API
|
|
- APIs & Services → Library → Gmail API → Enable.
|
|
|
|
### 3. Configure the OAuth consent screen
|
|
- APIs & Services → OAuth consent screen → Internal (since this is a Workspace-hosted account).
|
|
- Add the following scope:
|
|
- `https://www.googleapis.com/auth/gmail.readonly` (least privilege).
|
|
|
|
### 4. Create OAuth 2.0 credentials
|
|
- APIs & Services → Credentials → Create Credentials → OAuth client ID.
|
|
- Application type: **Desktop app** (or “Other non-UI” if offered).
|
|
- Download the JSON client secrets file and place it in a secrets manager (do NOT commit it).
|
|
|
|
### 5. Obtain a refresh token
|
|
- Run the helper at `scripts/oauth_token_exchange.py` to start the OAuth consent flow.
|
|
- Authenticate as `jonathan@cloudinit.dev`.
|
|
- Authorize the `gmail.readonly` scope.
|
|
- The script outputs a `refresh_token`; store it as a runtime secret (e.g., Gitea secret / vault).
|
|
|
|
### 6. Token hygiene
|
|
- Rotate the refresh token quarterly or on any security alert.
|
|
- To revoke, delete the token in the Google Account security settings.
|
|
|
|
### 7. IMAP enablement
|
|
- The Gmail API path does **not** require IMAP to be enabled.
|
|
- If you also need legacy IMAP (for testing or a dual path), keep the App Password section in mind as a fallback.
|
|
|
|
## App Password Flow (Fallback / IMAP)
|
|
|
|
### 1. Enable 2-Step Verification
|
|
- https://myaccount.google.com/security → 2-Step Verification → On.
|
|
|
|
### 2. Generate an App Password
|
|
- https://myaccount.google.com/apppasswords
|
|
- Select app: **Mail** (or choose “Other” and name it `mailroom-automation-imap`).
|
|
- Copy the 16-character password and store it as a secret immediately. It will not be shown again.
|
|
|
|
### 3. IMAP configuration
|
|
- Gmail IMAP host: `imap.gmail.com`
|
|
- Port: `993`
|
|
- TLS/SSL: Required
|
|
- Username: `jonathan@cloudinit.dev`
|
|
- Password: the 16-character App Password
|
|
|
|
### 4. Validate connectivity
|
|
- Use `scripts/gmail_health_check.py --mode imap` to verify the connection without touching the actual ingestion pipeline.
|
|
|
|
### 5. Least privilege for IMAP
|
|
- App Passwords grant full mailbox IMAP access. Use this path **only** if the OAuth 2.0 Gmail API path is infeasible.
|
|
- Restrict by filtering folders in the mail fetcher rules after connection.
|
|
|
|
## Security & Compliance
|
|
|
|
- **Secrets**: Never commit `client_secret.json`, refresh tokens, or App Passwords in plain text.
|
|
- **Rotation plan**: Quarterly rotation for OAuth refresh tokens; on-demand for App Passwords.
|
|
- **Rollback**: Remove/revoke the OAuth client in Google Cloud Credentials or delete the App Password in Google Account settings. No code redeploy needed because credentials are injected at runtime.
|
|
- **Audit**: Log every token exchange attempt and every health check run (see script exit codes).
|
|
- **Access model**: Automation credentials should be tied to a service account or a delegated admin account, not a personal account, where possible. Discuss with Cybersecurity-Board-Member if a dedicated service account is preferred.
|
|
|
|
## Helper Scripts
|
|
|
|
### `scripts/oauth_token_exchange.py`
|
|
Performs the OAuth consent flow for a Desktop app client ID and saves the refresh token.
|
|
|
|
Usage:
|
|
```bash
|
|
export GMAIL_CLIENT_SECRET_PATH=/run/secrets/gmail_client_secret.json
|
|
python scripts/oauth_token_exchange.py
|
|
```
|
|
|
|
Exit codes:
|
|
- `0` — success, token written to stdout and optionally a file
|
|
- `1` — missing client secret
|
|
- `2` — network or Google API error
|
|
|
|
### `scripts/gmail_health_check.py`
|
|
Validates connectivity via Gmail API (OAuth) or IMAP (App Password).
|
|
|
|
Usage:
|
|
```bash
|
|
# OAuth mode
|
|
export GMAIL_REFRESH_TOKEN="1//..."
|
|
export GMAIL_CLIENT_SECRET_PATH=/run/secrets/gmail_client_secret.json
|
|
python scripts/gmail_health_check.py --mode oauth
|
|
|
|
# IMAP mode
|
|
export GMAIL_APP_PASSWORD="xxxx xxxx xxxx xxxx"
|
|
python scripts/gmail_health_check.py --mode imap --user jonathan@cloudinit.dev
|
|
```
|
|
|
|
Exit codes:
|
|
- `0` — connectivity verified, mailbox reachable
|
|
- `1` — credential or config missing/unreadable
|
|
- `2` — network or authentication failure
|
|
- `3` — mailbox accessible but unexpected folder structure (flag for review)
|
|
|
|
## Rollback Plan
|
|
|
|
| What changed | How to revert | Time to revert |
|
|
|--------------|---------------|----------------|
|
|
| OAuth client ID created | Delete client ID in Google Cloud Credentials | Immediate |
|
|
| Refresh token issued | Revoke token in Google Account → Third-party apps | Immediate |
|
|
| App Password created | Delete App Password in Google Account settings | Immediate |
|
|
| Gitea secret updated | Overwrite secret in Gitea with dummy value or delete | Immediate |
|
|
|
|
## Next Steps
|
|
|
|
1. Cybersecurity-Board-Member reviews this guide and confirms the chosen credential path.
|
|
2. The approved credential is stored in Gitea secrets or an external vault.
|
|
3. Ingestion pipeline references the secret via environment variable.
|
|
4. Onboarding test: run `gmail_health_check.py` in the target environment before enabling the full fetcher loop.
|
|
|
|
## Revision History
|
|
|
|
- `v1` — Initial guide (OAuth + App Password, helper scripts, security checklist)
|