Преминете към основното съдържание

Протокол на конектора на Matrix

Конекторът на Matrix използва същия плик (envelope), hello, сигнал за активност и жизнен цикъл на задачите като агентите и конекторите на Axis (Протокол на агента и конектора) и добавя съобщенията и задачите за управление на защитни стени. Go типовете в entrosity-shared-go/proto/matrix (и JobProgress.Detail в proto/jobs.go) са единственият източник на истина; тази страница описва предназначението и поведението.

Както и останалата част от протокола, тези типове само растат: полета се добавят, никога не се преименуват и не получават ново предназначение, така че конекторите на терен продължават да работят.

Транспорт​

  • WebSocket: wss://hub.entrosity.com/matrix/api/connector/v1/ws с Authorization: Bearer <connector key>. JSON текстови рамки, по един плик в рамка.
  • Първото съобщение трябва да е hello (capabilities: ["firewall"], плюс "sites" от версиите, които управляват разрешени сайтове, "update" от версиите, които инсталират подписани издания, и pending_job_ids); сървърът отговаря с hello.ack, доставя чакащите задачи и може да предложи обновяване.
  • Конекторът изпраща heartbeat всяка минута. Той е онлайн от своя hello, докато сокетът не се затвори, или до 3 минути без съобщение. Минаването офлайн прави залите на защитните му стени неактуални.
  • Задачите следват job.assign → job.ack → job.progress → job.result. Задача, изпратена без job.ack, се изпраща отново; задача, незавършена преди изтичането си, се маркира от сървъра като изтекла (Резултати).

HTTP крайни точки (/api/connector/v1)​

Метод и пътПредназначение
POST /enroll{enrollment_token, hostname, domain, version} → {connector_id, connector_key, ws_url}. Токенът трябва да е токен за конектор на Matrix на активен тенант. Ограничение за IP (MATRIX_ENROLL_RATE_PER_MINUTE).
GET /wsWebSocket.
POST /heartbeatHTTP резервен вариант на heartbeat.
GET /jobs/pending, POST /jobs/{id}/ack, …/progress, …/resultHTTP резервен вариант с периодично запитване за жизнения цикъл на задачите.
POST /jobs/{id}/authorizeРазрешаване в момента на записа (по-долу).
POST /reportHTTP резервен вариант на matrix.report (същата обработка; приема се gzip). 204.
GET /firewalls/{firewallID}/credentialsAPI ключът на защитната стена (Идентификационни данни).
GET /releases/{releaseID}/msi?t=…MSI на издание за самообновяване; токенът във връзката го разрешава (без ключа на конектора).

Всички освен /enroll и изтеглянето на издание изискват ключа на конектора. Всичко, което прави конекторът, е ограничено до неговия тенант и до собствените му защитни стени.

Съобщения​

Конектор → сървър: matrix.report​

Report е {firewalls: [FirewallReport]} (най-много 50). Всеки FirewallReport:

ПолеЗначение
firewall_idЗащитната стена.
statusonline, unreachable, auth_failed, version_mismatch, direction_invalid или error, с error и error_code.
fortios_versionКакто я отчита FortiGate.
guard_stateaccepted, pending или mismatch.
rooms_fetched_at, roomsRoom {policy_id, name, room, building, status} на всяко правило на зала (най-много 2000).
groups_hash, groups_fetched_at, groupsАдресните групи (AddressGroup с members); groups се пропуска, когато не са се променили от последния отчет със същия groups_hash. Най-много 500 групи с по 2000 члена.
sites_hash, sites_fetched_at, sitesСамо от конектори с sites. sites е списък от SitesList (Разрешени сайтове): винаги общият списък (exists: false, когато групата му липсва) и списъкът на всяка текуща зала, чиято група съществува; пропуска се, когато не се е променил от последния отчет със същия sites_hash. (services, групата на премахнатите услуги на Entrosity, още се изпраща от по-старите конектори и се пренебрегва.)

Изпраща се според интервала за отчет на всяка защитна стена, веднага след всеки запис, а с групите (и сайтовете) – на всеки 5 минути, след обновяване на адресите и след записи на адреси или сайтове.

Какво прави сървърът: записва или обновява залите (present, last_seen_at); залите, липсващи в успешен отчет, стават present = false; съхранява моментната снимка на групите, когато е включена, както и сайтовете, когато са включени (отчет без sites_hash, от по-стар конектор, ги изчиства); обновява състоянието, версията, състоянието на защитата и last_report_at на защитната стена; уведомява уеб приложенията (matrix.rooms, matrix.addresses, matrix.sites). Невалиден отчет се отказва (invalid_message).

Задачи​

ТипДанниРезултатТаймаут / изтичане
matrix.firewall.applyFirewallApplyJob {firewall: FirewallRef, credentials_version}FirewallApplyResult {guard_state}1 мин / 24 ч
matrix.firewall.remove{firewall_id}–1 мин / 24 ч
matrix.firewall.check{firewall_id, credentials_version?}CheckResult60 с / 2 мин
matrix.refresh{firewall_id, scope: rooms|addresses|all}FirewallReport30 с / 1 мин
matrix.policy.setPolicySetJob {firewall_id, policy_id, room, desired, change_id}PolicySetResult30 с / 60 с
matrix.address.updateAddressOpJob с expected_ipAddressOpResult2 мин / 2 мин
matrix.address.createAddressOpJob без expected_ipAddressOpResult2 мин / 2 мин
matrix.sites.setSitesSetJob {firewall_id, list, room, domains, list_version, change_id}SitesSetResult2 мин / 2 мин
update_agentUpdateJob, компонент matrix-connectorUpdateResult30 мин
  • FirewallRef е конфигурацията на защитната стена: firewall_id, driver (fortigate или simulator), host, port, vdom, source_interface, destination_interface, policy_pattern, hostname_suffix, marker_prefix, verify_tls, ca_pem, expected_version, report_interval_seconds, writes_enabled, address_writes_enabled, site_writes_enabled. Никога не съдържа ключа. Превключвателите не са част от обхвата. (services_enabled и service_domains на премахнатите услуги на Entrosity вече не се изпращат; конекторите ги пренебрегват.) Неговият обхват (хост, порт, VDOM, двата интерфейса, шаблон, окончание, маркер) е това, което фиксира локалната защита.
  • Прилагането съхранява конфигурацията; първото прилагане записва защитната стена в защитата като очакваща, а променен обхват – като несъответстващ. Когато credentials_version е по-нова от съхранената, конекторът взима ключа.
  • CheckResult: version, direction_ok, rooms, groups, members, warnings (на английски, със стабилни представки като later_accept_policy:), guard_state, policy_names (всяко правило със зададеното направление, най-много 2000), а от конектори със sites: sites (списъците, както в отчета). Предупрежденията за разрешените сайтове използват представките sites_not_set_up:, sites_policy_missing:, sites_policy_disabled:, sites_policy_not_covering:, sites_group_read_only: и sites_wildcard_dns:. Правило, на което всеки dstaddr е група за разрешени сайтове (или старата група Matrix Entrosity services), не се отчита като later_accept_policy. Само за четене.
  • PolicySetResult: policy_id, room, name, previous, status, wrote (изпратен е запис), confirmed (прочетен обратно).
  • AddressOpJob: operation_id (UUID, същият при повторните опити), firewall_id, policy_id, group, name, ip, expected_ip (промяна), group_version (64 шестнадесетични знака) и resume (отбелязаното в журнала AddressOpState на прекъснат опит, при изричен повторен опит; етап update_sent, create_sent, created или member_sent).
  • AddressOpResult: operation_id, state {stage, address_uuid, original_members, previous_ip}, member.

Неуспешна задача за запис също носи своя PolicySetResult / AddressOpResult / SitesSetResult в job.result.result, така че сървърът знае дали нещо е било записано.

Разрешени сайтове​

Домейни, които компютрите на една зала достигат и когато правилото на залата е изключено. Всеки списък е адресна група във FortiGate с фиксирано име, която администраторът създава еднократно заедно с ACCEPT правило (същото направление като залите, групата на списъка като dstaddr, групата (групите) на залата като srcaddr):

Списък (list)Адресна група
shared (всички зали)Matrix allowed sites
код на зала, напр. SB1-102Matrix allowed sites SB1-102
  • SitesList: list, room (празно за shared), group, exists, policy (SitesPolicy {policy_id, name, status, covers}: първото включено ACCEPT правило с точното направление на защитната стена и групата в dstaddr; covers, когато неговият srcaddr съдържа източника на всяко правило на зала – или на тази зала при собствен списък – или all), version (64 шестнадесетични знака, отпечатък на групата и обектите на членовете ѝ), editable, reason, domains (SiteEntry {domain, object, owned, editable, reason}; вграденият член none не се изброява).
  • Обекти, притежавани от Matrix: адресни обекти type fqdn с име matrix-site:<domain> (при по-дълги имена: първите 58 знака на домейна, ~ и 8 шестнадесетични цифри от неговия SHA-256; най-много 79), чийто коментар е <marker prefix> site и чийто fqdn е точно домейнът. Само те се премахват или изтриват; всеки друг член се показва само за преглед (Not created by Matrix; change it on the FortiGate.) и се запазва.
  • Домейни (matrix.ValidSiteDomain): малки букви, два или повече етикета от a-z 0-9 - (punycode за международните имена), по избор *. в началото, най-много 253 знака, не IP адрес; най-много 200 в списък.
  • matrix.sites.set: domains е пълното желано множество от домейни, притежавани от Matrix (канонични, сортирани). Конекторът прочита всичко отново; списъкът трябва да е настроен (група и правило, иначе sites_not_set_up), да може да се редактира (да не се използва като източник или в друга група, без вложени групи) и да е във версия list_version (иначе conflict); собствени списъци само за текущи зали. Той създава липсващите обекти (като използва повторно свой обект за същия домейн от друг списък), задава членовете на групата като запазените членове плюс новите обекти (none, когато не остава нищо), изтрива своите обекти на премахнатите домейни, които вече никоя група или правило не използва (доколкото може), и потвърждава с ново прочитане. Домейн, който вече се осигурява от член, който не е на Matrix, не се добавя повторно.
  • Услуги на Entrosity (премахнати): matrix.services.sync (ServicesSyncJob), стъпката за разрешаване services.sync, списъкът services и ServicesState остават в proto/matrix само като остарели (deprecated) типове на протокола. Сървърите никога не изпращат задачата и отказват стъпката (services_removed); конекторите завършват задачата неуспешно като неподдържан тип задача.
  • SitesSetResult: list, domains (притежаваните от Matrix след задачата), added, removed, stage, wrote, confirmed. Неуспех след какъвто и да е запис се отчита като unconfirmed.

Задача за сайтове заема едно място от лимита на записи на минута на конектора; следващите ѝ записи проверяват отново изтичането на задачата и локалната защита.

Подробности за напредъка на задачата​

job.progress има специфично за продукта поле detail (JobProgress.Detail). Задачите за адреси изпращат AddressOpProgress {operation_id, state} преди всяка стъпка на запис, след като са я отбелязали в локалния журнал:

ЕтапИзпраща се преди
update_sentPUT firewall/address/<name> (новата подмрежа)
create_sentPOST firewall/address (новият обект)
created– (обектът е прочетен обратно; следва членството)
member_sentPUT firewall/addrgrp/<group> (членовете)
done– (потвърдено)

Сървърът пази етапа в операцията с адреса, така че при прекъсване се вижда докъде е стигнала, а повторният опит може да продължи.

Задачите за сайтове изпращат SitesSetProgress {list, stage, object} преди всяка стъпка на запис: create_sent (преди POST firewall/address на FQDN обект), created (прочетен обратно), member_sent (преди PUT firewall/addrgrp/<group>), delete_sent (преди DELETE firewall/address/<object> на неизползван обект на Matrix).

Разрешаване в момента на записа​

Точно преди всеки запис конекторът изпраща POST /jobs/{jobID}/authorize с AuthorizeRequest:

ПолеЗа
steppolicy.status (превключване на зала), address.update, address.create, address.member, sites.set
policy_id, roomСтъпките за зали и адреси (room и при sites.set на собствен списък)
list, domains_hashsites.set (списъкът на задачата, SitesDomainsHash на домейните ѝ)
previous, desiredpolicy.status
object_name, groupСтъпките за адреси

Отговорът е {allowed: true} или {allowed: false, reason}. При съмнение конекторът отказва: всеки друг отговор, грешка или липса на отговор до 5 секунди блокира записа (unauthorized).

Сървърът разрешава само ако са изпълнени всички условия:

  • задачата принадлежи на този конектор, е acked или running и не е изтекла;
  • стъпката съответства на типа задача (matrix.policy.set ↔ policy.status; address.update ↔ address.update; address.create ↔ address.create или address.member; matrix.sites.set ↔ sites.set), а стойностите са равни на данните на задачата; задача matrix.services.sync винаги се отказва (services_removed);
  • за sites.set: site_writes_enabled на защитната стена е включено и авторът все още може да променя списъка (общия списък: администратор на тенанта; списък на зала: администратор на тенанта или учител с право за залата);
  • защитната стена е в употреба и writes_enabled (стъпки за зали) или address_writes_enabled (стъпки за адреси) е включено;
  • авторът на задачата все още е активен потребител на тенанта, чиято сесия в Hub не е прекратена, и все още е администратор на тенанта (или глобален администратор), или, при превключване на зали, учител с право за залата; системна задача (без автор, автоматично повторно включване) трябва да принадлежи на график, който е firing.

Причини: invalid_request, unknown_job, job_not_live, expired, step_mismatch, values_mismatch, firewall_disabled, writes_disabled, user_inactive, session_ended, not_permitted, room_not_granted, schedule_not_firing, services_removed (задача matrix.services.sync на премахнатите услуги на Entrosity), not_recorded. Всяко извикване се записва като стъпка на промяната (metadata.steps); ако не може да бъде записано, записът се отказва.

Идентификационни данни​

GET /firewalls/{firewallID}/credentials → {token, version} (Cache-Control: no-store), само за защитна стена, зададена на питащия конектор; 404 no_credentials, когато няма съхранен ключ. Конекторът го взима, когато прилагане или проверка носи по-нова credentials_version, и го пази защитен с DPAPI във firewalls.json. Всяко взимане се записва в одитния журнал на тенанта като firewall.credentials_fetch, без ключа. Ключовете никога не се появяват в данните на задачите, резултатите, отчетите, събитията или журналите.

Кодове на грешки при задачи​

Докладват се в job.result.error_code:

КодЗначениеРезултат
forbidden_policyНе е правило на зала, което може да се управлява.отказано
policy_changedПроменено между прочитанията или непотвърдено без запис.отказано
room_mismatchПравилото вече не е тази зала.отказано
unconfirmedИзпратен е запис, но не е потвърден.непотвърдено
conflictВерсията на групата или очакваният IP адрес се различават.отказано
duplicate_ip, duplicate_nameДруг управляван компютър има този IP адрес; съществува обект с това име.отказано
shared_objectИзползва се извън залата: само за четене.отказано
invalid_inputИмето или IP адресът са отхвърлени.отказано
sites_not_set_upГрупата за разрешени сайтове или нейното ACCEPT правило липсва.отказано
unauthorizedРазрешаването в момента на записа от сървъра е отказало.отказано
guard_pending, guard_mismatchЛокалната защита не е приета или обхватът е променен.отказано
writes_disabledЗаписите са изключени (от превключвател в сървъра или от защитата).отказано
busyИзпълнява се друг запис на същия обект.отказано
not_foundОбектът не е намерен във FortiGate.отказано
rate_limitedЛокалният лимит на записи на конектора.отказано
expiredЗадачата е пристигнала твърде късно за запис.грешка
unreachable, tls, auth_failedНяма връзка; сертификатът не е проверен успешно; HTTP 401/403.грешка
version_mismatch, direction_invalid, invalid_responseВерсията на FortiOS се различава от фиксираната; интерфейсите или зоните не са намерени; непоследователни данни от FortiGate.грешка
unknown_firewall, unknown_driverКонекторът не познава защитната стена или няма такъв драйвер.грешка
interruptedКонекторът е рестартиран преди какъвто и да е запис.грешка

Кодовете при самообновяване (update_unsigned, signature_invalid, download_failed, hash_mismatch, exec_failed) са същите като при другите конектори (Кодове на грешки).

Резултати​

Как сървърът съпоставя задача за запис с резултата на промяната:

ЗадачаРезултат на промяната
Успешна (и, за залите, confirmed)success
Неуспешна с wrote: true, код unconfirmed, етап на адрес след prepared или етап на сайтове (create_sent, created, member_sent, delete_sent)unconfirmed
Неуспешна без запис, с код за отказ (редовете с отказано по-горе)denied
Неуспешна без запис, с всеки друг кодerror
Изтекла, след като конекторът я е потвърдил или стартиралunconfirmed
Изтекла, без изобщо да е потвърденаerror

Сървърът никога не създава отново задача за запис сам; непотвърдена промяна чака човек (нова промяна или изричен повторен опит за адреса).

Ограничения​

ОграничениеСтойност
Защитни стени в отчет50
Зали на защитна стена2000
Адресни групи на защитна стена, членове на група500, 2000
Списъци с разрешени сайтове на защитна стена, домейни в списък2001, 200
Шаблон за имената на правилата500 знака, RE2, една (?P<room>…)
Интервал за отчет15–300 с (по подразбиране 30)
Локални записи на защитна стена за минута1–600 (по подразбиране 60)
Ключ512 знака, без интервали