← Cloudflare Workers / workers / platform
Привязка развёртываний (временные учётные записи)
Временные аккаунты предпросмотра позволяют разворачивать и тестировать Workers прежде чем вы аутентифицируетесь в Cloudflare. После этого вы можете подтвердить права на аккаунт, чтобы сохранить его развёртывания и поддерживаемые ресурсы.
Cloudflare Drop ↗ демонстрирует этот жизненный цикл предварительного просмотра и подтверждения для статических сайтов. Платформы могут использовать REST API, чтобы предложить аналогичный процесс для сгенерированных приложений.
Контекст дизайна см. в Временные аккаунты Cloudflare для ИИ-агентов ↗.
Выберите интеграцию
Выберите интеграцию в зависимости от того, кто управляет предоставлением учётных записей:
| Интеграция | Когда использовать | Поведение при выделении ресурсов |
|---|---|---|
Wrangler с wrangler deploy --temporary |
ИИ-агент или инструмент запускает Wrangler | Wrangler создаёт новый аккаунт или использует существующий и выводит claim URL |
REST API по адресу api.cloudflare.com/client/v4/provisioning/previews |
Бэкенд вашей платформы управляет процессом развёртывания | Ваш бэкенд получает временные учётные данные и claim URL |
Для продакшена и непрерывной интеграции и доставки (CI/CD) используйте постоянную учётную запись Cloudflare. Аутентифицируйтесь с помощью wrangler login или API-токен Cloudflare.
Развертывание с помощью Wrangler
Используйте Wrangler, когда команды развёртывания выполняет ИИ-агент или инструмент. Wrangler берёт на себя задачу proof-of-work, учётные данные и URL для подтверждения.
Начиная с версии 4.102.0, Wrangler выводит подсказку о повторном запуске неавторизованных развёртываний с --temporary.
-
Установите или обновите Wrangler до версии 4.102.0 или новее.
Инструкции по установке см. в Установка и обновление.
-
Задайте своему ИИ-агенту промпт для развёртывания.
Например:
Make a very simple Hello World Cloudflare Worker in TypeScript and deploy it using the Wrangler CLI. Do not ask me questions. -
Разрешите агенту запустить
wrangler deploy.В неаутентифицированной неинтерактивной сессии Wrangler выводит примерно следующее:
To continue without logging in, rerun this command with `--temporary`. Wrangler will use a temporary account and print a claim URL.Этот вывод указывает агенту повторно выполнить команду с
--temporary. -
Перезапустите развёртывание с помощью
--temporary.npx wrangler deploy --temporaryWrangler выводит примерно следующее:
Continuing means you accept Cloudflare's Terms of Service (https://www.cloudflare.com/terms/) and Privacy Policy (https://www.cloudflare.com/privacypolicy/). Temporary account ready: Account: example-name (created) Claim within: 60 minutes Claim URL: https://dash.cloudflare.com/claim-preview?claimToken=<CLAIM_TOKEN> Uploaded example-worker Deployed example-worker triggers https://example-worker.example-name.workers.dev -
(Необязательно) Разверните изменения повторно, прежде чем подтвердить права на аккаунт.
Wrangler кэширует аккаунт и повторно использует его, пока действительны его учётные данные и claim URL. В выводе указывается, создал ли Wrangler новый аккаунт или использовал существующий.
Wrangler очищает кэшированный аккаунт при выполнении
wrangler loginилиwrangler logout.Wrangler хранит эти временные значения в глобальном каталоге конфигурации текущего пользователя операционной системы. Не используйте этот каталог совместно с другими пользователями платформы.
Интеграция с REST API
Используйте REST API, если развёртываниями управляет бэкенд вашей платформы. Бэкенд создаёт аккаунт ещё до аутентификации пользователя, а затем развёртывает поддерживаемые ресурсы.
Выполняйте все вызовы предоставления ресурсов и развёртывания со своего бэкенда. Ответ на запрос предоставления ресурсов содержит конфиденциальные учётные данные и URL для подтверждения.
На следующей диаграмме показано, как платформа хранит временные учётные данные на бэкенде, пока пользователь просматривает и подтверждает деплой:
flowchart LR
accTitle: Platform preview and claim architecture
accDescr: A user accepts Cloudflare's policies and requests a preview in the platform UI. The trusted platform backend creates a temporary account, keeps account.apiToken private, deploys the Worker, and returns only the preview and claim URLs to the UI. The claim URL is a bearer credential shown only to the intended user. The user claims the account in the Cloudflare dashboard. Future platform deployments require a separate OAuth flow.
USER((User))
subgraph PLATFORM["Platform"]
direction TB
UI["Platform UI<br/>No temporary API token"]
BACKEND["Trusted platform backend<br/>Stores account.apiToken"]
UI -->|"2. Request preview"| BACKEND
BACKEND -->|"10. Preview URL and bearer claim URL only"| UI
end
subgraph CLOUDFLARE["Cloudflare"]
direction TB
API["Cloudflare API"]
DASHBOARD["Cloudflare dashboard<br/>Claims the account"]
end
USER -->|"1. Accept policies and generate application"| UI
BACKEND -->|"3. Request challenge"| API
API -->|"4. Challenge parameters"| BACKEND
BACKEND -->|"5. Solve challenge locally"| BACKEND
BACKEND -->|"6. Create temporary account with solution"| API
API -->|"7. Account ID, API token, and claim URL"| BACKEND
BACKEND -->|"8. Deploy Worker and request subdomain"| API
API -->|"9. workers.dev subdomain"| BACKEND
UI -->|"11. Show live preview and intended-user-only claim link"| USER
USER -->|"12. Sign in and complete claim"| DASHBOARD
DASHBOARD -.->|"Optional after claim"| OAUTH["Separate OAuth flow<br/>for future platform deployments"]
Запросить вызов
Перед созданием временной учётной записи запросите вызов proof-of-work:
curl "https://api.cloudflare.com/client/v4/provisioning/previews/challenge" \
-X POST \
-H "Content-Type: application/json" \
--data '{}'Ответ включает challenge-токен, seed и параметры сложности:
{
"success": true,
"result": {
"challengeToken": "<CHALLENGE_TOKEN>",
"seed": "<BASE64URL_32_BYTE_SEED>",
"k": 8000,
"g": 2000
},
"errors": [],
"messages": []
}Решите proof of work
Решите задачу, вычислив последовательную цепочку контрольных точек SHA-256:
- Декодировать
seedкак Base64URL. При декодировании должно получаться 32 байта. - Вычисления
checkpoint[0] = SHA-256(seed). - Для каждого сегмента из
0кk - 1, вычислитеgпоследовательные хеши SHA-256 от предыдущей контрольной точки, а затем добавляет результат. - Объединить все
k + 1контрольных точек. Каждая контрольная точка занимает 32 байта. - Закодируйте объединённые байты с помощью стандартного Base64. Отправьте это значение как
solution.checkpoints.
Перед решением challenge подключите k и g быть положительными целыми числами. Отклоните проверку, если seed не декодируется в 32 байта или если k * g превышает 64,000,000.
Следующий пример на Node.js применяет эти границы и возвращает объект, необходимый для запроса создания:
import { createHash } from "node:crypto";
function sha256(value) {
return createHash("sha256").update(value).digest();
}
export function solvePreviewChallenge({ challengeToken, seed, k, g }) {
const seedBytes = Buffer.from(seed, "base64url");
if (seedBytes.length !== 32) {
throw new Error("seed must decode to 32 bytes");
}
if (!Number.isInteger(k) || k <= 0) {
throw new Error("k must be a positive integer");
}
if (!Number.isInteger(g) || g <= 0) {
throw new Error("g must be a positive integer");
}
if (k * g > 64_000_000) {
throw new Error("k * g must not exceed 64,000,000");
}
const checkpoints = [];
let hash = sha256(seedBytes);
checkpoints.push(hash);
for (let segment = 0; segment < k; segment++) {
for (let iteration = 0; iteration < g; iteration++) {
hash = sha256(hash);
}
checkpoints.push(hash);
}
return {
challengeToken,
solution: {
checkpoints: Buffer.concat(checkpoints).toString("base64"),
},
};
}import { createHash } from "node:crypto";
type PreviewChallenge = {
challengeToken: string;
seed: string;
k: number;
g: number;
};
function sha256(value: Uint8Array): Buffer {
return createHash("sha256").update(value).digest();
}
export function solvePreviewChallenge({
challengeToken,
seed,
k,
g,
}: PreviewChallenge) {
const seedBytes = Buffer.from(seed, "base64url");
if (seedBytes.length !== 32) {
throw new Error("seed must decode to 32 bytes");
}
if (!Number.isInteger(k) || k <= 0) {
throw new Error("k must be a positive integer");
}
if (!Number.isInteger(g) || g <= 0) {
throw new Error("g must be a positive integer");
}
if (k * g > 64_000_000) {
throw new Error("k * g must not exceed 64,000,000");
}
const checkpoints: Buffer[] = [];
let hash = sha256(seedBytes);
checkpoints.push(hash);
for (let segment = 0; segment < k; segment++) {
for (let iteration = 0; iteration < g; iteration++) {
hash = sha256(hash);
}
checkpoints.push(hash);
}
return {
challengeToken,
solution: {
checkpoints: Buffer.concat(checkpoints).toString("base64"),
},
};
}Создайте временный аккаунт
Требовать, чтобы пользователь принял Cloudflare Terms of Service ↗ и Политика конфиденциальности ↗ до создания аккаунта. Установите acceptTermsOfService к "yes" только после того, как пользователь примет оба условия.
Затем отправьте решение proof-of-work вместе с обязательными полями политики:
curl "https://api.cloudflare.com/client/v4/provisioning/previews" \
-X POST \
-H "Content-Type: application/json" \
--data '{
"termsOfService": "https://www.cloudflare.com/terms/",
"privacyPolicy": "https://www.cloudflare.com/privacypolicy/",
"acceptTermsOfService": "yes",
"challengeToken": "<CHALLENGE_TOKEN>",
"solution": {
"checkpoints": "<BASE64_CHECKPOINTS>"
}
}'Ответ содержит временные учётные данные и URL для подтверждения:
{
"success": true,
"result": {
"account": {
"id": "<TEMPORARY_ACCOUNT_ID>",
"name": "<TEMPORARY_ACCOUNT_NAME>",
"type": "standard",
"apiToken": "<TEMPORARY_ACCOUNT_API_TOKEN>",
"tokenId": "<TEMPORARY_TOKEN_ID>",
"expiresAt": "<ACCOUNT_EXPIRES_AT>"
},
"claim": {
"token": "<CLAIM_TOKEN>",
"url": "https://dash.cloudflare.com/claim-preview?claimToken=<CLAIM_TOKEN>",
"expiresAt": "<CLAIM_EXPIRES_AT>"
}
},
"errors": [],
"messages": []
}Прежде чем использовать ответ, убедитесь, что success это true. Убедитесь, что account.id, account.apiToken, account.expiresAt, claim.url, а также claim.expiresAt присутствуют.
Развертывание поддерживаемых ресурсов
Используйте account.id и account.apiToken с поддерживаемыми конечными точками Cloudflare API. Используйте временные значения только с поддерживаемыми операциями над ресурсами.
Токены временных аккаунтов не предоставляют все права доступа API, доступные постоянным аккаунтам. При попытке выполнить неподдерживаемую операцию возвращается ошибка авторизации.
В следующих примерах Worker загружается и разворачивается с Workers Script Upload API, затем получите workers.dev поддомен.
curl "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers/scripts/$SCRIPT_NAME" \
-X PUT \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-F 'metadata={"main_module":"worker.mjs","compatibility_date":"<YYYY-MM-DD>"};type=application/json' \
-F '[email protected];type=application/javascript+module'Вызовите Эндпоинт получения поддомена с временными учетными данными:
curl "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers/subdomain" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"Для скрипта, доступного на workers.dev, объедините result.subdomain с именем скрипта, чтобы создать URL развертывания: https://<SCRIPT_NAME>.<SUBDOMAIN>.workers.dev.
Используйте Cloudflare TypeScript SDK ↗ с поддерживаемыми операциями над ресурсами после подготовки временной учётной записи:
import Cloudflare from "cloudflare";
export async function deployWorker(
accountId: string,
apiToken: string,
scriptName: string,
compatibilityDate: string,
scriptContent: string,
) {
const client = new Cloudflare({ apiToken });
const workerModule = new File([scriptContent], "worker.mjs", {
type: "application/javascript+module",
});
await client.workers.scripts.update(scriptName, {
account_id: accountId,
metadata: {
main_module: "worker.mjs",
compatibility_date: compatibilityDate,
},
files: [workerModule],
});
const { subdomain } = await client.workers.subdomains.get({
account_id: accountId,
});
return `https://${scriptName}.${subdomain}.workers.dev`;
}Укажите URL развёртывания и claim.url предполагаемому пользователю.
Привязать учётную запись
Пользователь должен успеть выполнить claim в течение 60 минут. Одного перехода по claim URL до истечения срока недостаточно.
Они открывают URL-адрес, входят в Cloudflare или создают учётную запись, а затем выполняют шаги, предложенные в панели управления.
Если пользователь не завершает claim, Cloudflare удаляет аккаунт и его ресурсы.
С помощью Wrangler повторно запустите wrangler deploy --temporary если срок действия временных учётных данных или claim URL истёк. Wrangler создаёт новый аккаунт и выводит новый claim URL.
Для REST-интеграций запрашивайте новый challenge и account, если account.expiresAt или claim.expiresAt проходит до истечения срока действия claim.
После claim Worker и связанные с ним ресурсы остаются в аккаунте, который его выполнил.
Чтобы продолжить работу с Wrangler, выполните wrangler login, затем разверните без --temporary. Claim не даёт платформе постоянного доступа к аккаунту.
При последующих развёртываниях подключайте зарегистрированную учётную запись через обычный аутентифицированный процесс, например через OAuth-клиент Cloudflare.
Поддерживаемые ресурсы
В следующей таблице приведена сводка поддерживаемых возможностей и ограничений. Временные учётные данные не дают прав на все операции с этими ресурсами.
| Поддерживаемый продукт или ресурс | Поддерживаемая возможность или ограничение |
|---|---|
| Workers | Развертывания на workers.dev |
| Workers Static Assets | До 1 000 файлов, каждый ресурс до 5 MiB |
| Workers KV | Создание, просмотр списка, переименование и удаление пространств имен; добавление, получение, просмотр списка и удаление ключей; массовое добавление, получение и удаление |
| D1 | Одна база данных, до 100 MB на базу данных и 100 MB всего |
| Durable Objects | Развертывание Workers с привязками Durable Object и миграциями |
| Hyperdrive | До двух конфигураций баз данных и 10 подключений |
| Queues | До 10 очередей |
| mTLS и CA-сертификаты | wrangler cert операции загрузки, получения списка и удаления |
Безопасность и ограничения
Защита временных значений
account.apiTokenавторизует поддерживаемые операции с ресурсами. Никогда не раскрывайте его в ответах браузера или в клиентском коде.- Обрабатывать
claim.urlкак bearer-токен. Любой, у кого есть эта ссылка, может завладеть временной учётной записью. - Храните оба значения только в хранилище на стороне сервера или в серверном хранилище сессий, привязанном к нужному пользователю. Передавайте
claim.urlтолько этому пользователю. - Исключите оба значения из логов, аналитики и телеметрии поддержки. Удаляйте сохранённые копии, когда они больше не нужны, но не позднее возвращённого времени истечения срока действия.
Лимиты
- Перед созданием учётной записи Cloudflare требует прохождения проверки proof-of-work. Wrangler выполняет эту проверку самостоятельно, а интеграциям через REST необходимо отправить решение.
- Cloudflare ограничивает частоту создания временных учётных записей. Подождите перед повторной попыткой или выполните аутентификацию с постоянной учётной записью.
--temporaryподдерживает только неаутентифицированное использование. Существующие учётные данные OAuth, API-токена или глобального API-ключа вызывают ошибку.--temporaryне является глобальным флагом. Он есть только у команд, поддерживающих временные учетные данные.- Создание временных аккаунтов доступно только через стандартную публичную конечную точку API. Через конечную точку FedRAMP High API эта функция недоступна.
- Cloudflare может отклонять запросы, которые не проходят дополнительные проверки на предотвращение злоупотреблений.