Appearance
Описание сервиса Security
Общее описание
Сервис предназначен для проверки загружаемых файлов в NextBox. Каждый файл при загрузке помещается в карантин и проверяется внешними системами. После чего и принимается одно из решений:
- файл опасен
- файл безопасен
В первом случае файл остается в карантине и находится там указанный в конфиг срок. Во втором случае файл перемещается в хранилище.
Пока файл находится в карантине и проверяется, в хранилище он отображается как недоступный со статусом На проверке
. Заблокированные файлы, непрошедшие проверку, остаются со статусом Заблокировано
.
Включение безопасной загрузки
После установки сервиса в настройках системы появляется раздел Безопасная загрузка
в котором можно включить карантин и проверку файлов, а так же указать срок хранения файлов в карантине.
Поддерживаемые 3rd party сервисы проверок
Вместе с сервисом security устанавливаются два сервиса интеграции:
- kesl
- infowatch
Первый сервис интегрируется с Kaspersky Endpoint Security 12.1 для Linux
. Подробнее про продукт по ссылке. Инструкция развертывания по ссылке.
Второй сервис интегрируется с Infowatch Traffic Monitor 7.8
. Подробнее про продукт по ссылке.
Ручное добавление сторонних сервисов проверок
Для проверки файлов можно добавлять дополнительные сервисы проверок, через кастомные интеграционные сервисы.
Каждый из этих сервисов должен уметь принимать запросы по http endpoint указанному в конфиге у сервиса security. На вход будет отправляться json, имеющий следующую структуру:
json
{
"bucket_id": "<string>",
"file_id": "<string>"
}
В заголовке Authorization
будет добавлен сервисный токен для проверки валидности запроса. Пример: Authorization: Service qwerty1234567890
С помощью полученных bucket_id
и file_id
можно запросить информацию о файле как и сам файл у сервиса security.
Пример кода на golang запрашивающего информацию о файле:
go
type GetInfoResponse struct {
UserInfo struct {
Id uint64 `json:"id"`
CreateDate string `json:"create_date"`
UpdateDate string `json:"update_date"`
FirstName string `json:"first_name"`
MiddleName string `json:"middle_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
Login string `json:"login"`
LastLoginDate time.Time `json:"last_login_date"`
IsDeleted bool `json:"is_deleted"`
Role string `json:"role"`
RoleId *uint64 `json:"role_id"`
AvatarPath string `json:"avatar_path" example:"alkdsf23124.png"`
HomePath string `json:"home_path" example:"/storage/qwe"`
Type string `json:"type" example:"user"`
AuthType string `json:"auth_type" example:"ldap"`
} `json:"user_info,omitempty"`
FileStorageInfo struct {
FileContainerId uuid.UUID `json:"file_container_id"`
FullPath string `json:"full_path" example:"/ML/ML.docx"`
Path string `json:"path" example:"/ML"`
Name string `json:"name" example:"ML.docx"`
FileNameExt *string `json:"file_name_ext,omitempty" example:".docx"`
ContentType string `json:"content_type" example:"any"`
Type string `json:"type" example:"file"`
UpdateDate string `json:"update_date" swaggertype:"string" example:"2023-03-06T13:52:01.700527Z"`
CreateDate string `json:"create_date" swaggertype:"string" example:"2023-03-06T13:52:01.700527Z"`
DelGroupId *int64 `json:"del_group_id,omitempty" example:"1"`
WithPreview bool `json:"with_preview" example:"true"`
Shared bool `json:"shared" example:"false"`
IsFavorite bool `json:"is_favorite" example:"true"`
InstanceNumber int64 `json:"instance_number"`
OwnerId int64 `json:"owner_id"`
IsDeleted bool `json:"is_deleted"`
CreatedByExtension *string `json:"created_by_extension,omitempty"`
LastUsedExtension *string `json:"last_used_extension"`
} `json:"file_storage_info,omitempty"`
}
func getFileInfo(
serviceToken string,
securityUrl string,
httpClient *http.Client,
bucketId uuid.UUID,
fileId uuid.UUID,
) (res GetInfoResponse, err error) {
fileUrl, err := url.Parse(securityUrl)
if err != nil {
return
}
fileUrl.Path = fmt.Sprintf("/api/v1/security/files/%s/%s/info", bucketId.String(), fileId.String())
q := fileUrl.Query()
q.Set("with_user_info", "true")
q.Set("with_file_info", "true")
fileUrl.RawQuery = q.Encode()
request, err := http.NewRequest("GET", fileUrl.String(), nil)
if err != nil {
return
}
request.Header.Set("Authorization", "Service "+serviceToken)
response, err := httpClient.Do(request)
if err != nil {
return
}
defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&res)
return
}
Пример кода на golang запрашивающего файл:
go
func getFile(
serviceToken string,
securityUrl string,
httpClient *http.Client,
bucketId uuid.UUID,
fileId uuid.UUID,
) (io.ReadCloser, error) {
fileUrl, err := url.Parse(securityUrl)
if err != nil {
return nil, err
}
fileUrl.Path = fmt.Sprintf("/api/v1/security/files/%s/%s", bucketId.String(), fileId.String())
req := &http.Request{
Method: "GET",
Header: map[string][]string{
"Authorization": {fmt.Sprintf("Service %s", serviceToken)},
},
URL: fileUrl,
}
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("fail to download file, code: %d", res.StatusCode)
}
return res.Body, nil
}
В обоих случаях используется security_token
для проверки валидности запросов. Этот токен указывается в конфиге у каждого сервиса NextBox.
После проверки файла, необходимо вернуть ответ в сервис Security
. Ответ должен быть 200 OK и { "status": "Allowed" }
для успеха. Иные ответы будут расцениваться как неудача.
Описание дополнительных возможностей конфигурации
- storage_duration или в настройках веб интерфейса задается срок хранения заблокированных файлов в реестре, заблокированные файлы хранятся указанное время в часах, после чего удаляются
- security_rabbit_mq_num_workers: Количество потоков параллельной обработки и проверки из очереди загруженных файлов
- strict_secure_upload: Строгий режим, который требует обязательного включения и доступности сервиса Security для загрузки файлов, конфигурация задаётся в сервисе File_storage_router
Конфигурационный файл /etc/nextbox/config.yml
Сервис поддерживает загрузку настроек из файла конфигурации (mount в контейнер по пути /etc/nextbox/config.yml
).
Ключ верхнего уровня — security
.
Хранилище: папка заданная security.file_system.path
должна быть на устойчивом диске. Рекомендуется выделить отдельный volume.
Пример конфиг файла сервиса security
Для указания интеграционных сервисов в конфиг файле необходимо задать адрес, куда слать запрос проверки.
Ниже конфигурационный файл для двух встроенных сервисов kesl и infowatch для установки docker-compose:
yaml
security:
database:
dsn: postgres://admin:admin@postgresql:5432/security
service:
token: qwe123
back_url: http://security:8080
discovery:
url: http://discovery:8080
file_system:
path: "/repo"
tmp: "/repo/tmp"
settings:
path: "/var/nextbox/security/settings.json"
integrations:
service:
- name: Kesl
method: POST
callback: http://kesl/security/check
- name: Infowatch
method: POST
callback: http://infowatch/security/check
security:
enabled: true
storage_duration: 720