Документация Полномочия подключений

Connection Authority

Connection Authority позволяет администратору указать, куда интеграция может обращаться и что делать. Например, раннеру можно разрешить проверить один проект GitLab, не выдавая доступ ко всем проектам. В записи подключения хранится ссылка на секрет из Хранилища секретов, а не сам пароль или токен.

Каждое сохранённое изменение создаёт новую ревизию. В ней указаны разрешённая цель, операции и версии секретов. При проверке, изменении или отзыве подключения указывайте текущую ревизию: тогда старый запрос не перезапишет новую настройку.

Что умеет подключение

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

Подключение хранит разрешённые операции и может проверить целевую систему:

  • Хранит и версионирует полномочие. Каждый advance — неизменяемая ревизия с дайджестом; предыдущая перестаёт быть текущей.
  • Выдаёт ссылки без учётных данных. Когда задача плагина допускается к исполнению, раннер получает точные ревизии секретов и подключений, которые этой задаче разрешены, — и никогда исходный текст; граница раннера перепроверяет это полномочие на обоих путях диспетчеризации. Задача, полномочие которой не подтверждается, отклоняется.
  • Отвечает на разрешение точно. Чтение текущей ревизии возвращает её, а после отзыва — ничего.
  • Выполняет проверку (probe). Операция вида <адаптер>.probe (например, gitlab.probe) спрашивает у HTTP- или HTTPS-цели внутри targetPolicy подключения, отвечает ли она и принимает ли учётные данные подключения. Mockarty использует секрет на стороне сервера и возвращает только итог — succeeded или failed, если цель отвергла учётные данные, ответила ошибкой или недоступна. Проверка ничего не меняет у цели, а секрет в ответ не попадает.
  • Отправляет запросы от имени учётной записи подключения. <адаптер>.target_read отправляет один запрос GET, HEAD или OPTIONS, а <адаптер>.target_write — один POST, PUT, PATCH или DELETE в собственную цель подключения; учётные данные подставляет сервер. Вы выбираете путь (внутри pathPrefixes), метод (из списка methods), параметры запроса, дополнительные заголовки и тело; хост, порт и схема всегда берутся из политики цели. Ответ — статус, безопасные заголовки и до 64 КиБ тела — возвращается один раз. Всё, что в нём совпадает с учётными данными, заменяется на [redacted]; Set-Cookie не возвращается никогда. Так автономная миссия тестирует от имени ограниченной учётной записи.

ID операции имеет вид <адаптер>.<класс>. Допустимые классы: probe, target_read, target_write, issue_ephemeral_token, rotate и revoke. Выполнить можно probe, target_read и target_write. Попытка выполнить issue_ephemeral_token, rotate или revoke вернёт 422 и ничего не изменит. Эти имена могут быть в описании подключения, но само перечисление не включает их выполнение.

Что записывает запрос к цели

Каждая выполненная операция оставляет квитанцию с итогом. Для запросов к цели квитанция ещё и называет причину отказа — в result.evidence:

Ответ цели result.status result.evidence
2xx succeeded verified
401 failed authentication_rejected — учётные данные не приняты
403 failed permission_denied — этой учётной записи действие запрещено
другие 4xx, перенаправление failed provider_rejected
5xx на чтение, нет ответа на чтение failed provider_unavailable
5xx на запись или обрыв после отправки записи outcome_unknown запись могла примениться; проверьте цель, прежде чем повторять

Запись с неизвестным итогом никогда не объявляется «не применённой». Повтор с тем же idempotencyKey возвращает записанную квитанцию и не отправляет запрос снова.

Перед началом

  1. Сохраните каждую учётную запись в Хранилище секретов.
  2. Запишите ID хранилища, ключ и положительный номер версии секрета.
  3. Задайте точный allowlist цели: схему, хост, порт, префикс пути и, если применимо, ресурс провайдера.
  4. Выберите ID операций, разрешённых этому подключению, в виде <адаптер>.<класс> (например, gitlab.probe). Для запросов к цели перечислите также разрешённые HTTP-методы в methods политики цели.

Owner или Admin может создавать, переводить на следующую ревизию и отзывать descriptor. User и Viewer могут его просматривать, но не изменять полномочия подключения.

Пример descriptor

Сохраните содержимое как gitlab-connection.json. При создании сервер назначает пространство имён и ревизию; не помещайте исходные учётные данные в этот файл.

{
  "contractVersion": "mockarty.connection/v1",
  "id": "gitlab-prod",
  "kind": "gitlab",
  "endpoint": "https://gitlab.example.com/api/v4",
  "residency": "customer_contour",
  "configuredBindings": {
    "project": "payments/service"
  },
  "targetPolicy": {
    "schemes": ["https"],
    "hosts": ["gitlab.example.com"],
    "ports": [443],
    "pathPrefixes": ["/api/v4"],
    "projects": ["payments/service"]
  },
  "secretRefs": [
    {"storeId": "team-vault", "key": "gitlab-token", "version": 3}
  ],
  "allowedOperationIds": ["gitlab.probe"],
  "dataClasses": ["source_code"],
  "settingsSchema": {"type": "object"}
}

В ответе приходит полный descriptor, его ревизия и digest. Сохраните номер ревизии для следующего advance или revoke.

Панель администратора

Откройте Администрирование → Интеграции → Connection Authority. Выберите конкретное пространство имён, вставьте descriptor без учётных данных и используйте Create, Load, Advance, Проверить или Revoke. Для advance, проверки и revoke нужна точная текущая ревизия; устаревшая ревизия отклоняется и не перезаписывает параллельное изменение. Проверить берёт первую операцию <адаптер>.probe из descriptor и направляет её на его endpoint.

Не каждый неуспешный probe означает запрет полномочий: HTTP 401 означает, что цель не приняла аутентификацию — нужно проверить учётные данные и срок их действия; HTTP 403 означает отказ в запрошенном чтении, а HTTP 5xx — сбой цели. Перенаправление тоже завершает probe неуспехом: оно не доказывает приём учётных данных; Mockarty не переходит по нему и не пересылает учётные данные. Эти ответы сами по себе не доказывают, что цель опознала конкретного пользователя или запретила операцию записи. Probe выполняет только GET или HEAD.

REST API

Метод Путь Назначение
POST /api/v1/namespaces/{namespace}/connections Создать ревизию 1
GET /api/v1/namespaces/{namespace}/connections/{id} Прочитать текущую ревизию
PUT /api/v1/namespaces/{namespace}/connections/{id}?expectedRevision=N Опубликовать ревизию N+1
DELETE /api/v1/namespaces/{namespace}/connections/{id}?revision=N Отозвать точную ревизию N
POST /api/v1/namespaces/{namespace}/connections/{id}/execute Выполнить разрешённую операцию (probe, target_read, target_write)
curl -X POST "$MOCKARTY_URL/api/v1/namespaces/payments/connections" \
  -H "X-API-Key: $MOCKARTY_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @gitlab-connection.json

curl -H "X-API-Key: $MOCKARTY_API_TOKEN" \
  "$MOCKARTY_URL/api/v1/namespaces/payments/connections/gitlab-prod"

curl -X PUT "$MOCKARTY_URL/api/v1/namespaces/payments/connections/gitlab-prod?expectedRevision=1" \
  -H "X-API-Key: $MOCKARTY_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @gitlab-connection.json

curl -X DELETE \
  -H "X-API-Key: $MOCKARTY_API_TOKEN" \
  "$MOCKARTY_URL/api/v1/namespaces/payments/connections/gitlab-prod?revision=2"

Проверка ревизии 2 подключения. Цель должна лежать внутри его targetPolicy; повторите idempotencyKey, чтобы повтор вернул записанный итог, а не проверял заново:

curl -X POST "$MOCKARTY_URL/api/v1/namespaces/payments/connections/gitlab-prod/execute" \
  -H "X-API-Key: $MOCKARTY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"revision":2,"operationId":"gitlab.probe","idempotencyKey":"probe-2026-09-26",
       "target":{"scheme":"https","host":"gitlab.example.com","port":443,"path":"/api/v4"}}'

В ответе — result.status (succeeded или failed) и receiptId; учётных данных в нём нет никогда. Токен GitLab передаётся заголовком PRIVATE-TOKEN, если в descriptor задано "configuredBindings": {"probe.header_style": "gitlab"}; по умолчанию используется Authorization: Bearer, а "api-gateway" отправляет X-API-Key. Та же настройка действует для запросов к цели.

Создайте запись от имени учётной записи подключения. Детали запроса передаются в arguments:

curl -X POST "$MOCKARTY_URL/api/v1/namespaces/payments/connections/shop-reader/execute" \
  -H "X-API-Key: $MOCKARTY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"revision":1,"operationId":"shop.target_write",
       "target":{"scheme":"https","host":"shop.example.com","port":443,"path":"/api/items","method":"POST"},
       "arguments":{"body":"{\"name\":\"test item\"}","headers":{"Accept":"application/json"}}}'

Учётная запись только для чтения получит result.evidence: "permission_denied", а в response — собственный ответ цели (statusCode: 403 и её сообщение). response есть только в том вызове, который действительно отправил запрос.

SDK

Go

descriptor := mockarty.ConnectionDescriptor{
    ContractVersion: "mockarty.connection/v1",
    Namespace: "payments", ID: "gitlab-prod", Kind: "gitlab",
    Endpoint: "https://gitlab.example.com/api/v4",
    TargetPolicy: mockarty.ConnectionTargetPolicy{
        Schemes: []string{"https"}, Hosts: []string{"gitlab.example.com"},
        Ports: []uint16{443}, PathPrefixes: []string{"/api/v4"},
        Projects: []string{"payments/service"},
    },
    SecretRefs: []mockarty.ConnectionSecretRef{{StoreID: "team-vault", Key: "gitlab-token", Version: 3}},
    AllowedOperationIDs: []string{"gitlab.probe"},
}
snapshot, err := client.Connections().Create(ctx, descriptor)

Остальные операции lifecycle доступны как GetCurrent, Advance и Revoke в client.Connections().

Python

descriptor = {
    "namespace": "payments",
    "contractVersion": "mockarty.connection/v1",
    "id": "gitlab-prod",
    "kind": "gitlab",
    "endpoint": "https://gitlab.example.com/api/v4",
    "targetPolicy": {"schemes": ["https"], "hosts": ["gitlab.example.com"], "ports": [443], "pathPrefixes": ["/api/v4"]},
    "secretRefs": [{"storeId": "team-vault", "key": "gitlab-token", "version": 3}],
    "allowedOperationIds": ["gitlab.probe"],
}
snapshot = client.connections.create(descriptor)

Остальные методы — get_current, advance и revoke в client.connections. Асинхронный клиент предоставляет те же методы.

Java

ObjectNode descriptor = mapper.createObjectNode();
descriptor.put("namespace", "payments");
descriptor.put("contractVersion", "mockarty.connection/v1");
descriptor.put("id", "gitlab-prod");
descriptor.put("kind", "gitlab");
descriptor.put("endpoint", "https://gitlab.example.com/api/v4");
// Перед публикацией добавьте targetPolicy, точные secretRefs и allowedOperationIds.
JsonNode snapshot = client.connections().create(descriptor);

Остальные методы — getCurrent, advance и revoke в client.connections().

CLI и MCP

mockarty-cli --namespace payments connections create --file gitlab-connection.json
mockarty-cli --namespace payments connections get gitlab-prod
mockarty-cli --namespace payments connections advance gitlab-prod --revision 1 --file gitlab-connection.json
mockarty-cli --namespace payments connections revoke gitlab-prod --revision 2

Встроенный MCP-сервер предоставляет connection_create, connection_get_current, connection_advance, connection_execute (выполняет проверку или запрос к цели) и connection_revoke. В descriptor принимаются только точные ссылки на секреты. Не вставляйте учётные данные в prompt агента или descriptor.

Ротация и отзыв

  • Advance создаёт новую неизменяемую ревизию, а не редактирует прежнюю.
  • Каждый advance и revoke защищён точным номером текущей ревизии.
  • Повтор уже состоявшегося advance безопасен, пока эта ревизия остаётся текущей: тот же descriptor с тем же expectedRevision возвращает её, не создавая новую. Другой descriptor отклоняется как конфликт. После появления более новой текущей ревизии даже совпадающий повтор старого запроса возвращает 409; перед следующим изменением прочитайте текущую ревизию.
  • После advance предыдущая ревизия перестаёт быть текущей.
  • После revoke чтение текущей ревизии возвращает not found, поэтому повторно использовать отозванную ревизию нечему.
  • Отзыв подключения не удаляет связанные секреты. При необходимости ротируйте или удаляйте их отдельно.