Skip to content

Описание сервиса Security

Общее описание

Сервис предназначен для проверки загружаемых файлов в NextBox. Каждый файл при загрузке помещается в карантин и проверяется внешними системами. После чего и принимается одно из решений:

  • файл опасен
  • файл безопасен

В первом случае файл остается в карантине и находится там указанный в конфиг срок. Во втором случае файл перемещается в хранилище.

Пока файл находится в карантине и проверяется, в хранилище он отображается как недоступный со статусом На проверке. Заблокированные файлы, непрошедшие проверку, остаются со статусом Заблокировано.

img.png

Включение безопасной загрузки

После установки сервиса в настройках системы появляется раздел Безопасная загрузка в котором можно включить карантин и проверку файлов, а так же указать срок хранения файлов в карантине.

img.png

Поддерживаемые 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