# Azure Functions

> Deploy Centinel Analytica using Azure Functions for request validation.

Source: https://docs.centinelanalytica.com/platforms/application/azure-functions

## Overview

This guide deploys Centinel as an Azure Function that validates incoming requests. Two modes are available:

* **Validation-only mode**: Function validates and returns allow/block decisions. Use as a standalone validation endpoint.
* **Reverse proxy mode**: Function validates and proxies allowed traffic to your backend.

Deployment takes 5-10 minutes.

## Prerequisites

* Centinel secret key
* Azure subscription with permissions to create Function Apps
* Backend application URL (your existing app)
* Azure CLI installed (optional, for CLI deployment)

## Install

1. **Download the function package**

   1. Download [`centinel-azure-functions.zip`](https://docs.centinelanalytica.com/downloads/centinel-azure-functions.zip).
   2. Extract to review contents:
      * `host.json` - Azure Functions host configuration
      * `package.json` - Node.js package metadata
      * `centinel/index.js` - Main function code
      * `centinel/function.json` - HTTP trigger bindings

2. **Create the Function App**

   1. Go to the [Azure Portal](https://portal.azure.com).
   2. Click **Create a resource** → search for **Function App** → **Create**.
   3. Configure:
      * **Subscription**: Select your subscription
      * **Resource Group**: Create new or select existing
      * **Function App name**: Pick a unique name (e.g. `centinel-middleware`)
      * **Runtime stack**: Node.js
      * **Version**: 18 or 20
      * **Region**: Pick the region closest to your backend
   4. Click **Review + create** → **Create**.
   5. Wait for deployment.

3. **Deploy the function code**

   1. In your Function App, go to **Deployment** → **Deployment Center**.
   2. For quick deployment, use **Local Git** or **Zip Deploy**:
      * **Zip Deploy**: Go to **Advanced Tools** → **Go** → **Debug console** → **CMD**
      * Navigate to `site/wwwroot`
      * Drag and drop the extracted zip contents (or use the zip file directly)
   3. Or deploy via Azure CLI (see the Configure section below).

## Configure

1. **Configure app settings**

   1. Open your Function App in the Azure Portal.
   2. Go to **Settings** → **Environment variables**.
   3. Add:

   | Name                   | Required | Value                                                                               |
   | ---------------------- | -------- | ----------------------------------------------------------------------------------- |
   | `CENTINEL_SECRET_KEY`  | Yes      | Your Centinel secret key                                                            |
   | `CENTINEL_BACKEND_URL` | No       | Your backend URL for reverse proxy mode (e.g. `https://your-app.azurewebsites.net`) |

   > **Deployment modes:** **Validation-only mode** (no `CENTINEL_BACKEND_URL`): Function returns JSON with `X-Centinel-Decision` header.
   >
   > * Allowed: `200 OK` with `{"success": true, "decision": "allow"}`
   > * Blocked: Interstitial page or block page with `429` or `403` status
   >
   > **Reverse proxy mode** (with `CENTINEL_BACKEND_URL`): Function validates and proxies allowed traffic to your backend.

   4. (Optional) Add:

   | Name                       | Default | Description                        |
   | -------------------------- | ------- | ---------------------------------- |
   | `CENTINEL_TIMEOUT`         | `100`   | Validator timeout in milliseconds  |
   | `CENTINEL_LOG_ENABLED`     | `true`  | Enable detailed logging            |
   | `CENTINEL_REDIRECT_STATUS` | `429`   | HTTP status for interstitial pages |
   | `CENTINEL_BLOCK_STATUS`    | `403`   | HTTP status for blocked requests   |

   5. Click **Apply** to save.

2. **Configure Azure Front Door (optional)**

   For CDN capabilities, put Azure Front Door in front of your function:

   1. Go to **Create a resource** → **Front Door and CDN profiles**.
   2. Select **Azure Front Door** → **Quick create** or **Custom create**.
   3. Configure the origin:
      * **Origin type**: App services
      * **Origin host name**: Your Function App (`centinel-middleware.azurewebsites.net`)
   4. Create a route that forwards all traffic (`/*`) to the function origin.
   5. Wait for deployment (5-10 minutes for global propagation).

### Path protection

Edit `centinel/index.js` to customize path protection (lines 50-86):

```javascript
// Protect specific paths only (empty array = protect all paths)
var CENTINEL_PROTECTED_PATHS = [
    '/admin/*',
    '/api/*',
    '/login'
];

// Skip validation for static assets (default includes common extensions)
var CENTINEL_UNPROTECTED_PATHS = [
    '*.js', '*.css', '*.png', '*.jpg', '*.gif',
    '*.woff', '*.woff2', '*.ico', '*.svg'
];
```

**Pattern examples:**

* `/admin/*` - Protects `/admin/dashboard`, `/admin/users`, etc.
* `/api/*` - Protects all API routes
* `*.js` - Excludes all JavaScript files at any path depth

Redeploy after editing.

### Deploy via Azure CLI

Deploy with Azure CLI for automation:

```bash
# Login to Azure
az login

# Create resource group
az group create --name centinel-rg --location eastus

# Create storage account (required for Functions)
az storage account create \
  --name centinelstorage \
  --resource-group centinel-rg \
  --location eastus \
  --sku Standard_LRS

# Create Function App
az functionapp create \
  --name centinel-middleware \
  --resource-group centinel-rg \
  --storage-account centinelstorage \
  --consumption-plan-location eastus \
  --runtime node \
  --runtime-version 18 \
  --functions-version 4

# Configure settings (validation-only mode)
az functionapp config appsettings set \
  --name centinel-middleware \
  --resource-group centinel-rg \
  --settings \
    CENTINEL_SECRET_KEY="sk_live_your_key_here"

# For reverse proxy mode, also add:
# CENTINEL_BACKEND_URL="https://your-backend.azurewebsites.net"

# Deploy code (from extracted zip directory)
cd centinel-azure-functions
zip -r deploy.zip .
az functionapp deployment source config-zip \
  --name centinel-middleware \
  --resource-group centinel-rg \
  --src deploy.zip
```

## Verify

* Test the function URL directly: `https://your-function.azurewebsites.net/`
* If using Front Door, test: `https://your-frontdoor.azurefd.net/`
* Check logs in **Monitor** → **Log stream** for entries prefixed with `[Centinel]`.
* Verify requests appear in your Centinel dashboard.

## Troubleshooting

### Monitoring and logs

**Application Insights:**

Enable Application Insights for detailed monitoring:

1. In your Function App, go to **Settings** → **Application Insights**.
2. Click **Turn on Application Insights**.
3. Query logs with:

```kusto
traces
| where message startswith "[Centinel]"
| order by timestamp desc
```

**Real-time logs:**

```bash
# Stream logs via Azure CLI
az functionapp log tail --name centinel-middleware --resource-group centinel-rg
```

**Log entries to look for:**

* `[Centinel] Processing request` - Request received
* `[Centinel] Validator response received` - Validation completed with timing
* `[Centinel] Allowing request` / `[Centinel] Blocking request` - Decision applied
* `[Centinel] Validation-only mode: request allowed` - Request allowed (validation-only mode)

## Changelog

* **v1.0.0** — Initial release
