INTEGRITY Документация

Отправка атрибутов SSO на защищённые Access источники с помощью Workers

В этом руководстве вы шаг за шагом расширите возможности единого входа (SSO) Cloudflare Access с нашей платформой бессерверных вычислений, Cloudflare Workers. В частности, в этом руководстве показано, как изменить запросы, отправляемые на защищенный источник, чтобы включить в них дополнительную информацию о событии аутентификации Cloudflare Access.

Время выполнения: 45 минут

Поток аутентификации

Cloudflare Access это прокси аутентификации, отвечающий за проверку личности пользователя перед подключением к вашему приложению. Как показано на схеме ниже, Access вставляет JWT в запрос, который затем можно подтверждено исходным сервером.

Стандартный поток аутентификации для запроса к приложению Access

Эту функциональность можно расширить с помощью Cloudflare Worker, который добавляет в запрос дополнительные HTTP-заголовки. В этом примере мы добавим атрибуты состояния устройства firewall_activated и disk_encrypted, но вы можете включить любые атрибуты, которые Cloudflare Access собирает из события аутентификации.

Расширенный процесс аутентификации использует Worker для передачи дополнительных заголовков запроса на origin-сервер

Преимущества

Этот подход позволяет вам:

Перед началом работы

1. Создайте Worker

  1. Создайте новый проект Workers:

    npm create cloudflare@latest -- device-posture-worker

    Для настройки выберите следующие параметры:

    • Для С чего вы хотите начать?, выберите Hello World example.
    • Для Какой шаблон вы хотите использовать?, выберите Worker only.
    • Для Какой язык вы хотите использовать?, выберите JavaScript.
    • Для Хотите использовать git для контроля версий?, выберите Yes.
    • Для Хотите развернуть приложение?, выберите No (мы внесём некоторые изменения перед развёртыванием).
  2. Перейдите в каталог проекта:

    $ cd device-posture-worker
  3. Скопируйте и вставьте следующий код в src/index.js. Обязательно замените <your-team-name> с вашим Zero Trust название команды.

    index.js
    import { parse } from "cookie";
    export default {
    	async fetch(request, env, ctx) {
    		// The name of the cookie
    		const COOKIE_NAME = "CF_Authorization";
    		const CF_GET_IDENTITY =
    			"https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/get-identity";
    		const cookie = parse(request.headers.get("Cookie") || "");
    		if (cookie[COOKIE_NAME] != null) {
    			try {
    				let id = await (await fetch(CF_GET_IDENTITY, request)).json();
    				let diskEncryptionStatus = false;
    				let firewallStatus = false;
    
    				for (const checkId in id.devicePosture) {
    					const check = id.devicePosture[checkId];
    					if (check.type === "disk_encryption") {
    						console.log(check.type);
    						diskEncryptionStatus = check.success;
    					}
    					if (check.type === "firewall") {
    						console.log(check.type);
    						firewallStatus = check.success;
    						break;
    					}
    				}
    				//clone request (immutable otherwise) and insert posture values in new header set
    				let newRequest = await new Request(request);
    				newRequest.headers.set(
    					"Cf-Access-Firewall-Activated",
    					firewallStatus,
    				);
    				newRequest.headers.set("Cf-Access-Disk-Encrypted", firewallStatus);
    
    				//sent modified request to origin
    				return await fetch(newRequest);
    			} catch (e) {
    				console.log(e);
    				return await fetch(request);
    			}
    		}
    		return await fetch(request);
    	},
    };

2. Просмотрите идентификационные данные пользователя

Скрипт в index.js использует get-identity конечную точку, чтобы получить полную информацию о личности пользователя из события аутентификации Cloudflare Access. Чтобы увидеть список доступных полей данных, войдите в приложение Access и добавьте /cdn-cgi/access/get-identity к URL. Например, если www.example.com находится за Access, перейдите в https://www.example.com/cdn-cgi/access/get-identity.

Ниже приведен пример идентификатора пользователя, который включает disk_encryption и firewall проверки состояния устройства. Worker добавляет результаты проверки состояния устройства в заголовки запроса Cf-Access-Firewall-Activated и Cf-Access-Disk-Encrypted.

Пример идентификации пользователя
{
  "id": "P51Tuu01fWHMBjIBvrCK1lK-eUDWs2aQMv03WDqT5oY",
  "name": "John Doe",
  "email": "[email protected]",
  "amr": [
    "pwd"
  ],
  "oidc_fields": {
    "principalName": "XXXXXX_cloudflare.com#EXT#@XXXXXXcloudflare.onmicrosoft.com"
  },
  "groups": [
    {
      "id": "fdaedb59-e9be-4ab7-8001-3e069da54185",
      "name": "XXXXX"
    }
  ],
  "idp": {
    "id": "b9f4d68e-dac1-48b0-b728-ae05a5f0d4b2",
    "type": "azureAD"
  },
  "geo": {
    "country": "FR"
  },
  "user_uuid": "ce40d564-c72f-475f-a9b8-f395f19ad986",
  "account_id": "121287a0c6e6260ec930655e6b39a3a8",
  "iat": 1724056537,
  "devicePosture": {
    "f6f9391e-6776-4878-9c60-0cc807dc7dc8": {
      "id": "f6f9391e-6776-4878-9c60-0cc807dc7dc8",
      "schedule": "5m",
      "timestamp": "2024-08-19T08:31:59.274Z",
      "description": "",
      "type": "disk_encryption",
      "check": {
        "drives": {
          "C": {
            "encrypted": true
          }
        }
      },
      "success": false,
      "rule_name": "Disk Encryption - Windows",
      "input": {
        "requireAll": true,
        "checkDisks": []
    },
    "a0a8e83d-be75-4aa6-bfa0-5791da6e9186": {
      "id": "a0a8e83d-be75-4aa6-bfa0-5791da6e9186",
      "schedule": "5m",
      "timestamp": "2024-08-19T08:31:59.274Z",
      "description": "",
      "type": "firewall",
      "check": {
        "firewall": false
      },
      "success": false,
      "rule_name": "Local Firewall Check - Windows",
      "input": {
        "enabled": true
      }
    }
    ...
  }

3. Направьте Worker к своему приложению

В конфигурационный файл Wrangler, настройте маршрут который сопоставляет Worker с доменом вашего приложения Access:

{
	"route": {
		"pattern": "app.example.com/*",
		"zone_name": "example.com"
	}
}
[route]
pattern = "app.example.com/*"
zone_name = "example.com"

4. Разверните Worker

npx wrangler deploy

Теперь Worker будет добавлять Cf-Access-Firewall-Activated и Cf-Access-Disk-Encrypted заголовки в запросы, которые проходят политики Access вашего приложения.

Примеры заголовков запроса
{
	"headers": {
		"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
		"Accept-Encoding": "gzip",
		"Accept-Language": "en-US,en;q=0.9,fr-FR;q=0.8,fr;q=0.7,en-GB;q=0.6",
		"Cf-Access-Authenticated-User-Email": "[email protected]",
		"Cf-Access-Disk-Encrypted": "false",
		"Cf-Access-Firewall-Activated": "false",
		"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
	}
}

Можно убедиться, что эти заголовки получены исходным сервером.