Secure API Automation with Cloudflare Zero Trust (Part 3)

Part 3: Script explained – Use Cloudflare with Secure API Calls

Building on Part 2, where we discussed technical automation for BookStack, this part dives into code that can be used for lookup and creation of entries for a BookStack via Cloudflare.

The challenge with automating behind a Zero Trust perimeter is ensuring your scripts can authenticate without manual intervention. Below, we break down a robust Bash script that handles authentication, prevents duplicates, and manages relationships between books and shelves.

The Full Script

For the complete, production-ready version of this script, check out the GitHub Gist: Bash script


1. Authentication: The Dual-Layer Header

The core of this automation lies in the api_call function. It must satisfy both Cloudflare’s gateway and BookStack’s internal API security.

Bash

api_call() {
    local endpoint="$1"
    local method="$2"
    local data="$3"

    curl -s -w "\n%{http_code}" -X "$method" "$BOOKSTACK_URL$endpoint" \
        -H "CF-Access-Client-Id: $CF_ACCESS_ID" \
        -H "CF-Access-Client-Secret: $CF_ACCESS_SECRET" \
        -H "Authorization: Token $BOOKSTACK_API_ID:$BOOKSTACK_API_SECRET" \
        -H "Content-Type: application/json" \
        --data "$data"
}
  • CF-Access Headers: These bypass the Cloudflare login screen by providing a Service Token.
  • Authorization Header: This provides the application-level permissions within BookStack.

2. Ensuring Idempotency: The “Lookup First” Strategy

A common mistake in automation is creating duplicate entries every time a script runs. This script avoids that by building a local map of existing books before attempting any creation.

Bash

# Create a mapping of book names to IDs to check for existence
temp_book_map=$(mktemp)
echo "$ALL_BOOKS_BODY" | jq -r '.data[] | "\(.name)|\(.id)"' > "$temp_book_map"

By checking the temp_book_map, the script determines if it should POST a new book or simply reuse the existing ID.

3. Managing Relationships (Shelves & Books)

In BookStack, a book is assigned to a shelf by updating the shelf’s properties. Our script handles this by:

  1. Fetching the current list of books on a shelf.
  2. Merging them with the newly created (or identified) book IDs using jq.
  3. Ensuring no duplicates are sent back to the API.

Bash

# Combine current books with new books and remove duplicates
FULL_BOOK_IDS=$(echo "$CURRENT_BOOKS_JSON" | jq --argjson new_books "$BOOKS_TO_ADD_IDS_JSON" '. + ($new_books | map({"id": .})) | unique_by(.id) | map(.id)')

Summary

By using a combination of curl for transport and jq for data processing, sophisticated, state-aware automation can be achieved.
This script allows you to manage your documentation as code, even when it is locked behind a world-class security perimeter like Cloudflare Zero Trust.