{{define "style"}}{{end}} {{define "logo"}}{{end}} {{define "head"}}{{.Title}} · лицензии Bridge&Join{{template "style"}}
{{template "logo"}}Bridge&Joinлицензии
{{if .Me}}{{if .Me.Name}}{{.Me.Name}}{{else}}{{.Me.Login}}{{end}}
{{end}}
{{if .OK}}
{{.OK}}
{{end}} {{if .Err}}
{{.Err}}
{{end}} {{end}} {{define "foot"}}
{{end}} {{define "login"}}Вход · лицензии Bridge&Join{{template "style"}}
{{template "logo"}}Bridge&Join

Сервер лицензирования: вход администратора

{{if .Err}}
{{.Err}}
{{end}}
{{end}} {{define "login2fa"}}Подтверждение входа · лицензии Bridge&Join{{template "style"}}
{{template "logo"}}Bridge&Join

Подтвердите вход

Запрос отправлен в приложение «ЗЕТИТ Ключ» ({{.Data.Email}}). Подтвердите вход на телефоне — страница продолжит сама.

{{.Data.Left}}

{{if .Err}}
{{.Err}}
{{end}}

Отмена

{{end}} {{define "evtable"}}
{{range .}}{{else}}{{end}}
КогдаСобытиеКлиентКтоIP
{{dt .At}} {{.Text}}{{if .InstallID}} {{short .InstallID}}{{end}} {{if .LicenseID}}{{if .TenantName}}{{.TenantName}}{{else}}{{short .LicenseID}}{{end}}{{else}}{{end}} {{.Actor}}{{.IP}}
Событий пока нет
{{end}} {{define "dashboard"}}{{template "head" .}}

Обзор

{{.Data.Tenants}}клиентов
{{.Data.Active}}действующих лицензий
{{.Data.Revoked}}отозвано
{{.Data.Installs}}установок всего
{{.Data.Online}}на связи за 48 ч
{{if .Data.Expiring}}

Требуют внимания

{{range .Data.Expiring}}{{end}}
КлиентПланДоговор доСтатус
{{.TenantName}}{{plan .Plan}}{{d .ContractUntil}}{{.Status}}
{{end}}

Последние события

{{template "evtable" .Data.Events}}

Весь журнал →

{{template "foot" .}}{{end}} {{define "tenants"}}{{template "head" .}}

Клиенты

{{range .Data}} {{else}}{{end}}
КлиентИННКонтактЛицензийУстановокДобавлен
{{.Name}}{{.INN}}{{.Contact}}{{.Licenses}}{{.Installs}}{{d .CreatedAt}}
Клиентов пока нет. Добавьте первого ниже.

Новый клиент

{{template "foot" .}}{{end}} {{define "tenant"}}{{template "head" .}}

← Клиенты

{{.Data.Tenant.Name}}

Лицензии

Выпустить лицензию
{{range .Data.Licenses}} {{else}}{{end}}
ЛицензияПланУстановокДоговор доСтатус
{{.Code}}{{plan .Plan}}{{.Active}} из {{if .MaxNodes}}{{.MaxNodes}}{{else}}∞{{end}}{{d .ContractUntil}}{{.Status}}
Лицензий нет

Реквизиты

добавлен {{dt .Data.Tenant.CreatedAt}}
{{template "foot" .}}{{end}} {{define "terms"}}
{{$f := .Features}}{{range $.All}}{{end}}
{{end}} {{define "licenses"}}{{template "head" .}}

Лицензии

{{range .Data.Rows}}{{else}}{{end}}
КлиентКод активацииПланМодулиУстановокДоговор доСтатус
{{.TenantName}}{{.Code}}{{plan .Plan}} {{range .Features}}{{feature .}}{{else}}{{end}} {{.Active}} из {{if .MaxNodes}}{{.MaxNodes}}{{else}}∞{{end}}{{d .ContractUntil}}{{.Status}}
Лицензий пока нет.

Выпустить лицензию

{{if .Data.Tenants}}
{{template "terms" (dict2 .Plans .Features)}}
{{else}}

Сначала добавьте клиента.

{{end}}
{{template "foot" .}}{{end}} {{define "license"}}{{template "head" .}}{{$row := .Data.Row}}{{$csrf := .CSRF}}

← Лицензии · {{$row.TenantName}}

{{$row.TenantName}} {{$row.Status}}

{{if .Data.OfflineToken}}

Офлайн-ключ выпущен

Ключ показывается один раз. Вставьте его в bj: Настройка → Лицензия. Действует до {{d $row.ContractUntil}} без связи с сервером; отзыв на него не распространяется.

{{.Data.OfflineToken}}
{{end}}

Код активации

{{$row.Code}}

Клиент вводит код в bj (Настройка → Лицензия → «Активировать»). Одним кодом активируется до {{if $row.MaxNodes}}{{$row.MaxNodes}}{{else}}любого числа{{end}} установок; сейчас активных {{$row.Active}}.

Сводка

План
{{plan $row.Plan}}
Модули
{{range $row.Features}}{{feature .}}{{else}}{{end}}
Договор до
{{d $row.ContractUntil}}{{if not $row.Revoked}} (осталось {{daysLeft $row.ContractUntil}} дн.){{end}}
Выпущена
{{dt $row.CreatedAt}}{{if $row.CreatedBy}} · {{$row.CreatedBy}}{{end}}
ID
{{$row.ID}}
{{if $row.Revoked}}
Отозвана
{{dt $row.RevokedAt}}: {{$row.RevokeReason}}
{{end}}

Установки

{{range .Data.Installs}}{{else}}{{end}}
СерверВерсияIPПервая активацияПоследнее продлениеТокен до
{{if .Hostname}}{{.Hostname}}{{else}}{{end}}
{{.InstallID}}
{{if .Blocked}}заблокирована {{.BlockReason}}{{else if .Stale}}нет связи{{end}}
{{.Version}}{{.IP}}{{dt .FirstSeen}} {{dt .LastSeen}}
{{ago .LastSeen}}
{{d .TokenExpires}} {{if .Blocked}}
{{else}}
Заблокировать
{{end}}
Установок ещё нет: они появятся после активации кодом.

Условия

{{template "terms" (dict3 .Plans .Features $row.License)}}
установки получат их при следующем продлении

Офлайн-ключ

Для закрытого контура без доступа к серверу: ключ без привязки к установке, действует до окончания договора. Отозвать его нельзя.

{{if $row.Revoked}}Восстановление{{else}}Отзыв{{end}}

{{if $row.Revoked}}
{{else}}

Продления прекращаются; выданные токены доживают свой срок (до 60 дней).

{{end}}

Журнал лицензии

{{template "evtable" .Data.Events}}
{{template "foot" .}}{{end}} {{define "installs"}}{{template "head" .}}{{$csrf := .CSRF}}

Установки

{{range .Data.Installs}}{{else}}{{end}}
КлиентСерверВерсияIPПоследнее продлениеТокен доСтатус
{{if .TenantName}}{{.TenantName}}{{else}}{{short .LicenseID}}{{end}} {{if .Hostname}}{{.Hostname}}{{else}}{{end}}
{{short .InstallID}}
{{.Version}}{{.IP}}{{dt .LastSeen}}
{{ago .LastSeen}}
{{d .TokenExpires}} {{if .Blocked}}заблокирована{{else if .Stale}}нет связи{{else}}на связи{{end}}
Установок пока нет.

Доверенные IP (fail2ban)

Адрес попадает сюда после успешной активации или продления лицензии. fail2ban не блокирует его за ошибки API (неверный код, испорченный токен). На вход в кабинет и SSH доверие не распространяется. При отзыве лицензии или блокировке установки адрес исключается автоматически.

{{range .Data.Trusted}}{{else}}{{end}}
IPКлиентСерверДобавленПоследнее обращение
{{.IP}} {{if .TenantName}}{{.TenantName}}{{else}}{{short .LicenseID}}{{end}} {{if .Hostname}}{{.Hostname}}{{else}}{{end}}
{{short .InstallID}}
{{dt .AddedAt}}{{dt .LastSeen}}
{{ago .LastSeen}}
Доверенных адресов пока нет: они появятся после первой активации или продления.
{{template "foot" .}}{{end}} {{define "security"}}{{template "head" .}}{{$csrf := .CSRF}}{{$d := .Data}}

Защита

Доступ к кабинету

Адрес кабинета

https://{{$d.Host}}{{$d.AdminBase}}/ {{if $d.AdminDefault}}стандартный{{else}}свой{{end}}

{{if not $d.AdminDefault}}
{{end}}

При своём адресе /admin и главная страница отвечают «не найдено», и боты не находят форму входа. Сохраните адрес в закладки и не пересылайте. Узнать по SSH: /opt/bj-license/bj-license-server admin-info

Только из белого списка

{{if and $d.AdminAllowOnly $d.AdminOpen}}открыт аварийно по SSH Ограничение включено, но сейчас не действует.{{else if $d.AdminAllowOnly}}включено Кабинет и страница входа видны только адресам белого списка администраторов, остальным — «не найдено».{{else}}выключено Страница входа открывается с любого адреса.{{end}}

{{if and $d.AdminAllowOnly (not $d.AdminOpen)}}
{{else}}
{{end}}

API активации и продления это не затрагивает. Ваш адрес {{$d.MyIP}} {{if $d.MyIPCovered}}в белом списке{{else}}добавится в белый список при включении{{end}}. Аварийно открыть кабинет по SSH: /opt/bj-license/bj-license-server fw-apply -off

Второй фактор

{{if eq $d.TwoFA $d.Admins}}у всех{{else}}{{$d.TwoFA}} из {{$d.Admins}}{{end}} администраторов входят с кодом из приложения.

Даже зная пароль, без телефона войти нельзя. Потерянный телефон: второй фактор сбрасывает другой администратор или по SSH admin-config -reset-2fa логин при остановленном сервере.

ЗЕТИТ Ключ

{{if $d.ZKEnabled}}включён После пароля вход подтверждается push-уведомлением в приложении «ЗЕТИТ Ключ» или кодом из него. Действует для администраторов с указанным e-mail ({{$d.ZKWithEmail}} из {{$d.Admins}}).{{else}}выключен Второй фактор через приложение «ЗЕТИТ Ключ», как при входе в ZETIT Connect.{{end}}

E-mail администраторов задаётся на странице «Администраторы» и должен совпадать с учётной записью в ЗЕТИТ Ключ. Включить можно, только если ваш e-mail найден в Ключе с привязанным приложением. У администраторов без e-mail действует пароль и код приложения-аутентификатора, если он подключён. Если Ключ недоступен, вход с e-mail невозможен — аварийно выключить по SSH при остановленном сервере: bj-license-server admin-config -zetit-key off

{{if not $d.StatusFresh}}
Помощник защиты не отвечает

{{if $d.Status.At.IsZero}}Статуса ещё нет.{{else}}Последний отчёт {{dt $d.Status.At}} ({{ago $d.Status.At}}).{{end}} Команды из этого раздела не применяются. На сервере: systemctl status bj-license-fw.timer bj-license-fw.path

{{end}}

Режим обороны

{{if $d.Status.Lockdown}}Оборона включена На сайт и API пускаются только адреса из белого списка ({{$d.Status.AllowCount}}){{if not $d.Status.Until.IsZero}}, автоматически выключится {{dt $d.Status.Until}}{{end}}. {{else if $d.Status.Emergency}}Оборона выключена аварийно по SSH Включить снова можно кнопкой ниже. {{else}}Обычный режим Доступ открыт всем, fail2ban блокирует адреса, которые перебирают пароли и коды.{{end}}

{{if $d.WantedActive}}
{{else}}
{{end}}

Для атаки на сервер: все, кроме белого списка, получают отказ на уровне файрвола (порты 80 и 443). В белом списке — доверенные IP установок ({{$d.TrustedCount}}, Установки) и адреса администраторов ниже. Ваш адрес {{$d.MyIP}} {{if $d.MyIPCovered}}уже в белом списке{{else}}добавится в белый список автоматически при включении{{end}}. SSH не затрагивается. Пока оборона включена, Let's Encrypt не сможет продлить сертификат. Аварийно выключить по SSH: /opt/bj-license/bj-license-server fw-apply -off

{{if $d.Status.Errors}}
{{range $d.Status.Errors}}
{{.}}
{{end}}
{{end}}

Белый список администраторов

Адреса офиса и администраторов. Они не блокируются fail2ban (ни за вход в кабинет, ни за API) и пропускаются в режиме обороны.

{{range $d.Allow}} {{else}}{{end}}
IP или сетьКомментарийДобавил
{{.Net}}{{.Comment}}{{.AddedBy}}
{{dt .AddedAt}}
Пока пусто.

Параметры блокировок

Сколько неудачных попыток за период приводят к блокировке адреса и на какой срок. Долгие блокировки сохраняются и после перезапуска fail2ban. Белый список и доверенные установки не блокируются.

{{range $d.Limits}}{{$row := .}} {{end}}
Что защищаемПопытокЗа периодБлокировать на
{{.Title}}{{if .HasEffective}}
{{.Effective}}
{{end}}
Вход в кабинет (приложение)
срабатывает раньше fail2ban: после N неудачных попыток форма входа отказывает этому адресу и логину
за срок блокировки

fail2ban

{{range $d.Status.Jails}}{{$jail := .Name}} {{else}}{{end}}
JailОшибок сейчас / всегоЗаблокировано сейчас / всегоЗаблокированные адреса
{{.Name}}
{{if eq .Name "bj-license-api"}}коды активации и токены{{else if eq .Name "bj-license-admin"}}вход в кабинет{{else if eq .Name "sshd"}}SSH{{end}}
{{.CurrentlyFailed}} / {{.TotalFailed}}{{.CurrentlyBanned}} / {{.TotalBanned}} {{range .Banned}}
{{.}}
{{else}}нет{{end}}
Данных пока нет.
{{if $d.Pending}}

Ожидают применения: {{range $d.Pending}}{{.Op}} {{.IP}} ({{.Jail}}) {{end}}

{{end}}

Ручная блокировка действует срок блокировки jail из «Параметров блокировок». Статус обновляется раз в 30 секунд{{if not $d.Status.At.IsZero}}, последний — {{dt $d.Status.At}}{{end}}.

{{template "foot" .}}{{end}} {{define "totp"}}{{template "head" .}}{{$csrf := .CSRF}}{{$d := .Data}}

Второй фактор входа

{{if $d.Enabled}}

Подключён При входе в кабинет, кроме пароля, нужен шестизначный код из приложения.

{{else}}

Установите на телефон приложение для одноразовых кодов: Яндекс Ключ, Google Authenticator, Microsoft Authenticator или любое с поддержкой TOTP.

1. Добавьте ключ в приложение

{{if $d.QR}}
{{$d.QR}}
{{end}}

Отсканируйте QR-код или введите ключ вручную: {{$d.SecretGrouped}}. Если открыли кабинет на телефоне — добавить в приложение.

2. Подтвердите кодом

Ключ показывается только на этой странице. Если телефон потеряется, второй фактор сбросит другой администратор на странице «Администраторы».

{{end}}
{{template "foot" .}}{{end}} {{define "events"}}{{template "head" .}}

Журнал

{{template "evtable" .Data}}

Последние 500 событий.

{{template "foot" .}}{{end}} {{define "users"}}{{template "head" .}}{{$csrf := .CSRF}}{{$me := .Me}}

Администраторы

{{range .Data}}{{end}}
ЛогинИмяE-mail (ЗЕТИТ Ключ)Последний входСтатусВторой факторСменить пароль
{{.Login}}{{.Name}}
{{dt .LastLogin}} {{if .Disabled}}отключён{{else}}активен{{end}} {{if .HasTOTP}}подключён{{if ne .Login $me.Login}}
{{end}}{{else}}нет{{end}}{{if eq .Login $me.Login}}{{end}}
{{if ne .Login $me.Login}}
{{end}}

Новый администратор

Мой пароль

{{template "foot" .}}{{end}}