SKILL.md
Add Access User Skill
Grant users access to Cloudflare Access protected services by updating authentication policies.
Quick Start
To add a new user:
Add [email protected] to Cloudflare Access
The skill will:
- Add the email to ACCESSALLOWEDEMAIL in .env
- Update the update-access-emails.sh script with new email list
- Run the script to sync policies to Cloudflare
- Verify policies updated for all 6 protected services
- Provide test instructions for the new user
Table of Contents
- [When to Use This Skill](#1-when-to-use-this-skill)
- [What This Skill Does](#2-what-this-skill-does)
- [Instructions](#3-instructions)
- [Supporting Files](#4-supporting-files)
- [Expected Outcomes](#5-expected-outcomes)
- [Requirements](#6-requirements)
- [Red Flags to Avoid](#7-red-flags-to-avoid)
When to Use This Skill
Explicit Triggers:
- "Add [email] to Cloudflare Access"
- "Grant access to [email]"
- "Allow [email] to authenticate"
- "Share service access with [email]"
- "Update access users"
Implicit Triggers:
- User mentions sharing network access with family/colleagues
- User wants to grant remote access to services
- User asks about multi-user authentication
Debugging Triggers:
- "User [email] can't log in"
- "Access denied for [email]"
- "How do I add another user?"
What This Skill Does
- Validates Email - Ensures valid email format
- Checks Duplicates - Prevents adding existing users
- Updates .env - Adds email to ACCESSALLOWEDEMAIL
- Updates Script - Modifies update-access-emails.sh with new email list
- Syncs Policies - Runs script to update Cloudflare Access policies
- Verifies - Confirms all 6 services updated successfully
- Provides Test Steps - Instructions for new user to verify access
Instructions
3.1 Gather Email Address
Ask user for the email address(es) to add. Accept:
- Single email:
[email protected] - Multiple emails:
[email protected], [email protected]
3.2 Validate Email Format
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email.strip()))
3.3 Read Current Configuration
Read current ACCESSALLOWEDEMAIL from .env:
grep -E "^ACCESS_ALLOWED_EMAIL" /home/dawiddutoit/projects/network/.env
Current format: ACCESSALLOWEDEMAIL="email1,email2,email3"
3.4 Check for Duplicates
Before adding, verify email is not already in the list.
3.5 Update .env File
Edit /home/dawiddutoit/projects/network/.env:
Before:
ACCESS_ALLOWED_EMAIL="[email protected],[email protected]"
After (adding [email protected]):
ACCESS_ALLOWED_EMAIL="[email protected],[email protected],[email protected]"
3.6 Update update-access-emails.sh Script
The script at /home/dawiddutoit/projects/network/scripts/update-access-emails.sh has hardcoded email addresses in the policy JSON. Update the include array to match all emails:
Location in script (around line 48-52):
"include": [
{"email": {"email": "[email protected]"}},
{"email": {"email": "[email protected]"}},
{"email": {"email": "[email protected]"}},
{"email": {"email": "NEW_EMAIL_HERE"}}
]
3.7 Run Update Script
cd /home/dawiddutoit/projects/network && ./scripts/update-access-emails.sh
Expected output:
Updating policies for all services to include all three emails...
Processing app: 56de3246-c9ed-4877-8af1-dc360ac49584
Updating policy: <policy-id>
[checkmark] Policy updated successfully
Processing app: 9f1e8109-3f3f-456e-94f5-093bfc9e1c1e
...
[checkmark] Policy updated successfully
All policies updated!
3.8 Verify Policies Updated
All 6 protected services should show success:
- Services Dashboard (temet.ai)
- Home Assistant (ha.temet.ai)
- Sprinkler System (sprinkler.temet.ai)
- Langfuse Monitoring (langfuse.temet.ai)
- Jaeger Tracing (jaeger.temet.ai)
- Pi-hole Admin (pihole.temet.ai)
3.9 Provide Test Instructions
Give the new user these steps:
ACCESS GRANTED FOR: [email]
To test your access:
1. Open an incognito/private browser window
2. Navigate to: https://pihole.temet.ai
3. Click "Google" to authenticate
4. Sign in with your Google account: [email]
5. After successful authentication, you should see Pi-hole admin
All accessible services:
- https://pihole.temet.ai (Pi-hole DNS admin)
- https://jaeger.temet.ai (Jaeger tracing)
- https://langfuse.temet.ai (Langfuse monitoring)
- https://sprinkler.temet.ai (Sprinkler system)
- https://ha.temet.ai (Home Assistant)
- https://temet.ai (Services dashboard)
Supporting Files
| File | Purpose |
|---|---|
references/reference.md |
Technical details, API structure, troubleshooting |
examples/examples.md |
Common scenarios and edge cases |
Expected Outcomes
Success:
- Email added to ACCESSALLOWEDEMAIL in .env
- Script updated with new email in include array
- All 6 Cloudflare Access policies updated
- New user can authenticate via Google OAuth
Partial Success:
- .env updated but script needs manual sync
- Some policies failed (rare - API rate limiting)
Failure Indicators:
- "Policy update failed" in script output
- Email validation error
- Duplicate email detected
- API token expired or missing permissions
Requirements
Environment:
- Valid
.envwith CLOUDFLAREACCESSAPI_TOKEN - CLOUDFLAREACCOUNTID set correctly
- Network connectivity to Cloudflare API
For non-workspace Gmail accounts: If adding personal Gmail (not @temet.ai), Google OAuth consent screen must be set to "External":
- Go to: https://console.cloud.google.com/apis/credentials/consent
- Change User Type from "Internal" to "External"
- Save changes
Tools needed:
- Read (check current .env)
- Edit (update .env and script)
- Bash (run update script)
- Grep (check for duplicates)
Red Flags to Avoid
- Do not add invalid email format
- Do not add duplicate emails (check first)
- Do not forget to update BOTH .env AND the script
- Do not skip running update-access-emails.sh after editing
- Do not skip verification of all 6 services
- Do not assume non-workspace emails will work without OAuth consent change
- Do not modify the bypass policy for webhook.temet.ai
- Do not run cf-access-setup.sh (that's for initial setup, not adding users)
Notes
- The script has hardcoded app IDs for the 6 protected services
- Webhook (webhook.temet.ai) has bypass policy and is NOT affected
- Session duration is 24 hours - users must re-authenticate daily
- Access logs available at: https://one.dash.cloudflare.com -> Logs -> Access
- Google OAuth requires the email to match exactly (case-insensitive)
- Multiple emails are comma-separated with no spaces after commas