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 возвращает записанную квитанцию и не отправляет запрос снова.
Перед началом
- Сохраните каждую учётную запись в Хранилище секретов.
- Запишите ID хранилища, ключ и положительный номер версии секрета.
- Задайте точный allowlist цели: схему, хост, порт, префикс пути и, если применимо, ресурс провайдера.
- Выберите 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, поэтому повторно использовать отозванную ревизию нечему.
- Отзыв подключения не удаляет связанные секреты. При необходимости ротируйте или удаляйте их отдельно.