#!/usr/bin/env bash # Simple script to set allowed email addresses for Cloudflare Access # Usage: ./set-access-emails.sh email1@example.com email2@example.com ... set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TUNNELS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; } log_error() { echo -e "${RED}[✗]${NC} $1"; } # Load .env if [ -f "$TUNNELS_DIR/../../.env" ]; then source "$TUNNELS_DIR/../../.env" 2>/dev/null || true fi if [[ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ]] || [[ -z "${CLOUDFLARE_API_KEY:-}" ]] || [[ -z "${CLOUDFLARE_EMAIL:-}" ]]; then log_error "Cloudflare credentials not found in .env" exit 1 fi # Get emails from command line ALLOWED_EMAILS=("$@") if [ ${#ALLOWED_EMAILS[@]} -eq 0 ]; then log_error "Usage: $0 email1@example.com email2@example.com ..." echo "" log_info "Example:" echo " $0 admin@example.com user1@example.com user2@example.com" exit 1 fi log_info "Configuring Access policies for: ${ALLOWED_EMAILS[*]}" echo "" # App IDs (from earlier creation) declare -A APP_IDS=( ["ml110-01.d-bis.org"]="ebc7cafa-11dc-4bfa-8347-4e6c229f4d3b" ["r630-01.d-bis.org"]="967625a2-0199-490a-9f4f-2de5c8d49243" ["r630-02.d-bis.org"]="618ab003-37bf-413e-b0fa-13963c2186c5" ) # Function to make API request cf_api_request() { local method="$1" local endpoint="$2" local data="${3:-}" local url="https://api.cloudflare.com/client/v4${endpoint}" local temp_file=$(mktemp) local http_code if [[ -n "$data" ]]; then http_code=$(curl -s -o "$temp_file" -w "%{http_code}" \ -X "$method" "$url" \ -H "X-Auth-Email: ${CLOUDFLARE_EMAIL}" \ -H "X-Auth-Key: ${CLOUDFLARE_API_KEY}" \ -H "Content-Type: application/json" \ -d "$data" 2>/dev/null) else http_code=$(curl -s -o "$temp_file" -w "%{http_code}" \ -X "$method" "$url" \ -H "X-Auth-Email: ${CLOUDFLARE_EMAIL}" \ -H "X-Auth-Key: ${CLOUDFLARE_API_KEY}" \ -H "Content-Type: application/json" 2>/dev/null) fi local response=$(cat "$temp_file" 2>/dev/null || echo "") rm -f "$temp_file" if [[ "$http_code" != "200" ]] && [[ "$http_code" != "201" ]]; then return 1 fi echo "$response" } # Build email includes EMAIL_INCLUDES=$(printf '%s\n' "${ALLOWED_EMAILS[@]}" | jq -R . | jq -s . | jq 'map({email: {email: .}})') # Configure each app for hostname in "${!APP_IDS[@]}"; do app_id="${APP_IDS[$hostname]}" log_info "Configuring $hostname..." # Get existing policies POLICIES=$(cf_api_request "GET" "/accounts/${CLOUDFLARE_ACCOUNT_ID}/access/apps/${app_id}/policies" 2>&1) || POLICIES="{}" EXISTING_ID=$(echo "$POLICIES" | jq -r '.result[]? | select(.name == "Allow Team Access") | .id' 2>/dev/null || echo "") # Build policy (require field removed - email verification is default) POLICY_DATA=$(jq -n \ --argjson emails "$EMAIL_INCLUDES" \ '{ name: "Allow Team Access", decision: "allow", include: $emails }') if [[ -n "$EXISTING_ID" ]] && [[ "$EXISTING_ID" != "null" ]]; then # Update response=$(cf_api_request "PUT" "/accounts/${CLOUDFLARE_ACCOUNT_ID}/access/apps/${app_id}/policies/${EXISTING_ID}" "$POLICY_DATA" 2>&1) else # Create response=$(cf_api_request "POST" "/accounts/${CLOUDFLARE_ACCOUNT_ID}/access/apps/${app_id}/policies" "$POLICY_DATA" 2>&1) fi if echo "$response" | jq -e '.success' >/dev/null 2>&1; then log_success " ✓ $hostname configured" else log_error " ✗ Failed for $hostname" echo "$response" | jq -r '.errors[0].message // "Unknown error"' 2>/dev/null || echo "$response" | head -3 fi done echo "" log_success "=== Access Policies Configured ===" log_info "Allowed emails:" for email in "${ALLOWED_EMAILS[@]}"; do echo " - $email" done