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