Настройка сервиса

Реализация OSA Proxy

Эта страница относится к текущей реализации OSA Proxy. Архивная Java/Spring-реализация доступна в разделе Архивная Java/Spring-реализация.

Конфигурация OSA Proxy задается в файле osa-proxy.yml. Пример ниже показывает типовую рабочую конфигурацию с несколькими экосистемами, настройками CodeScoring, HTTP-клиента, Redis-кэша и логирования.

Совместимость с legacy Judge

Для CodeScoring версии ниже 2026.20.0 укажите codescoring.legacy-judge: true. В версиях до 2026.20.0 используется legacy API Judge, а OSA Proxy по умолчанию работает с текущим API Judge.

Пример конфигурации

codescoring:
  url: https://codescoring.example.com
  token: "<token>"
  work-mode: strict_wait
  osa-proxy-url: https://osa-proxy.example.com
  osa-proxy-url-from-forwarded-headers: false
  enable-status-line: true
  block-on-codescoring-errors: true
  block-message: "Component download blocked by security policy"
  append-block-url-to-message: true
  legacy-judge: false
  stage: proxy
  block-status-code: 403
  judge-concurrency: 16
  resilience:
    retry:
      max-attempts: 3
      wait-duration: 1s
      exponential-backoff-multiplier: 2
    circuit-breaker:
      failure-rate-threshold: 50
      minimum-number-of-calls: 10
      sliding-window-size: 20
      wait-duration-in-open-state: 30s
      permitted-number-of-calls-in-half-open-state: 5

http:
  server:
    read-timeout: 2m
    read-header-timeout: 5s
    idle-timeout: 120s
    shutdown-timeout: 10s
  client:
    connection-timeout: 10s
    response-timeout: 30s
    max-manifest-body-size: 200mb
    max-idle-conns: 100
    max-idle-conns-per-host: 10
    idle-conn-timeout: 90s

pypi:
  enabled: true
  repository:
    - name: pypi
      registry: https://pypi.org
      packages-registry: https://files.pythonhosted.org
      scan-manifest: true
      scan-package: true
      remove-blocked-versions: true
      work-mode: strict_wait
    - name: pytorch-pypi
      registry: https://download.pytorch.org
      packages-registry: https://download.pytorch.org
      additional-packages-registries:
        download.pytorch.org: https://download.pytorch.org
        download-r2.pytorch.org: https://download-r2.pytorch.org
        files.pythonhosted.org: https://files.pythonhosted.org
      scan-manifest: true
      scan-package: true
      remove-blocked-versions: true
      work-mode: strict_wait

maven:
  enabled: true
  repository:
    - name: maven
      registry: https://repo1.maven.org/maven2
      scan-manifest: true
      scan-package: true
      work-mode: strict_wait

nuget:
  enabled: true
  repository:
    - name: nuget
      registry: https://api.nuget.org
      scan-manifest: true
      scan-package: true
      remove-blocked-versions: true
      work-mode: strict_wait

npm:
  enabled: true
  repository:
    - name: npm
      registry: https://registry.npmjs.org
      scan-manifest: true
      scan-package: true
      remove-blocked-versions: true
      work-mode: strict_wait

composer:
  enabled: true
  repository:
    - name: composer
      registry: https://repo.packagist.org
      packages-registry: https://api.github.com
      additional-packages-registries:
        github.com: https://github.com
        gitlab.com: https://gitlab.com
      scan-manifest: true
      scan-package: true
      work-mode: strict_wait

ruby:
  enabled: true
  repository:
    - name: ruby
      registry: https://rubygems.org
      scan-manifest: true
      scan-package: true
      work-mode: strict_wait

go:
  enabled: true
  repository:
    - name: go
      registry: https://proxy.golang.org
      sumdb-registry: https://sum.golang.org
      scan-manifest: true
      scan-package: true
      work-mode: strict_wait

debian:
  enabled: true
  repository:
    - name: debian
      registry: https://deb.debian.org/debian
      distro: bookworm
      scan-package: true
      work-mode: strict_wait

alpine:
  enabled: true
  repository:
    - name: alpine
      registry: https://dl-cdn.alpinelinux.org/alpine
      scan-package: true
      work-mode: strict_wait

rpm:
  enabled: true
  repository:
    - name: rpm
      registry: https://mirror.stream.centos.org/10-stream/AppStream/x86_64/os
      scan-package: true
      work-mode: strict_wait

docker:
  enabled: true
  repository:
    - name: docker
      registry: https://registry-1.docker.io
      auth-token-url: https://auth.docker.io/token
      work-mode: strict_wait

cache:
  judge:
    enabled: false
    ttl: 24h
    refresh-after: 30m
    proactive-refresh-enabled: false
    proactive-refresh-interval: 2h
    proactive-refresh-workers: 10
    key-prefix: "cs:judge:"
  redis:
    address: redis:6379
    username: ""
    password: ""
    db: 0

logging:
  level: info

Секция codescoring

ПараметрНазначение
urlURL платформы CodeScoring.
tokenТокен доступа к CodeScoring.
work-modeГлобальный режим работы, если он не переопределен на уровне репозитория.
osa-proxy-urlВнешний URL OSA Proxy, который используется при формировании ссылок и ответов.
osa-proxy-url-from-forwarded-headersФормирует внешний URL из forwarded headers вместо статического значения.
enable-status-lineДобавляет причину блокировки в HTTP/1.1 status line, если клиент ее отображает.
block-on-codescoring-errorsБлокирует загрузку при ошибках CodeScoring или ошибках сканирования.
block-messageЗадает пользовательский текст ответа о блокировке. Если параметр не задан или пуст, используется стандартное сообщение OSA Proxy.
append-block-url-to-messageДобавляет к пользовательскому сообщению ссылку на причину блокировки.
block-status-codeHTTP-код для блокировки. По умолчанию используется 403.
judge-concurrencyКоличество параллельных запросов к Judge. Используется, чтобы ограничить нагрузку на Judge при проверке больших списков версий и фоновом обновлении кэша.
resilience.retryНастройки повторных запросов к CodeScoring.
resilience.circuit-breakerНастройки circuit breaker для временной деградации внешних вызовов.
Текст HTTP status line

HTTP/1.1 status line поддерживает только ASCII. Текст с кириллицей, например Загрузка компонента заблокирована политикой безопасности, не передается в status line. Если причина блокировки должна отображаться в status line Nexus или пакетного менеджера, используйте в block-message только ASCII-символы, например Component download blocked by security policy.

Формирование URL из forwarded headers

Параметр osa-proxy-url-from-forwarded-headers нужен, когда один инстанс OSA Proxy доступен по нескольким внешним URL, например из двух сетевых контуров:

codescoring:
  osa-proxy-url-from-forwarded-headers: true

Reverse proxy каждого контура передает свой X-Forwarded-Proto и X-Forwarded-Host. OSA Proxy использует их при формировании абсолютных ссылок на пакеты в metadata и манифестах, поэтому клиенты каждого контура получают ссылки через доступный им URL. Например, ответы на запросы через osa-proxy.internal.example.com содержат ссылки с этим host, а запросы через osa-proxy.dmz.example.com — ссылки с host DMZ.

Если заголовок X-Forwarded-Proto отсутствует, используется https; если отсутствует X-Forwarded-Host, используется обычный Host. Включайте этот режим только за доверенным reverse proxy, который перезаписывает forwarded headers, а не пропускает значения от клиента.

Секции пакетных менеджеров

Каждая экосистема содержит флаг enabled и список repository. Имя репозитория становится частью URL OSA Proxy:

npm:
  enabled: true
  repository:
    - name: company-npm
      registry: https://registry.npmjs.org
      scan-manifest: true
      scan-package: true
      work-mode: strict_wait
      url-encoded-config: true

Такой репозиторий будет доступен по адресу:

https://osa-proxy.example.com/company-npm/

Поля scan-manifest и scan-package включают проверку манифестов и скачиваемых артефактов. При scan-manifest: false metadata npm, NuGet и PyPI не проверяется, но ссылки в ответах по-прежнему переписываются на OSA Proxy. Поддержка режимов зависит от экосистемы; подробнее см. Поддерживаемые протоколы. Параметр work-mode на уровне репозитория переопределяет глобальный codescoring.work-mode.

Особенности экосистем

Для composer и pypi доступны packages-registry и additional-packages-registries, если артефакты загружаются с отдельных хостов. Для go указывается sumdb-registry, если нужно проксировать SumDB. Для Docker используется auth-token-url.

Интеграция с JFrog Artifactory

Для поддерживаемых экосистем доступны дополнительные варианты передачи в OSA Proxy контекста репозитория и пользователя JFrog Artifactory. Подходящий вариант зависит от версии и конфигурации Artifactory. Подробности по запросу предоставляет поддержка вендора.

Кэш вердиктов

По умолчанию Redis-кэш выключен:

cache:
  judge:
    enabled: false
  redis:
    address: redis:6379

Чтобы включить кэширование:

cache:
  judge:
    enabled: true
    ttl: 24h
    refresh-after: 30m
    proactive-refresh-enabled: false
    proactive-refresh-interval: 2h
    proactive-refresh-workers: 10
    key-prefix: "cs:judge:"
  redis:
    address: redis:6379
    password: ""
    db: 0

Логирование

Уровень логирования задается в logging.level. Поддерживаются значения debug, info, warn и error.

logging:
  level: info

Справочник параметров

Корневые секции

ПараметрНазначение
pypiНастройки PyPI-репозиториев.
mavenНастройки Maven-совместимых репозиториев для Maven и Gradle.
nugetНастройки NuGet-репозиториев.
npmНастройки npm-репозиториев.
composerНастройки Composer/Packagist-репозиториев.
rubyНастройки RubyGems-репозиториев.
conanНастройки Conan v2-репозиториев.
goНастройки Go module proxy.
debianНастройки Debian-репозиториев.
alpineНастройки Alpine APK-репозиториев.
rpmНастройки RPM/YUM/DNF-репозиториев.
dockerНастройки Docker Registry API v2.
codescoringПодключение к CodeScoring и поведение проверок.
httpТаймауты и лимиты HTTP-сервера и HTTP-клиента.
cacheRedis-кэш вердиктов Judge.
loggingУровень логирования сервиса.

Общие параметры секций пакетных менеджеров

ПараметрГде доступенНазначение
enabledВсе пакетные менеджерыВключает регистрацию маршрутов для экосистемы. Если false, репозитории этой секции не обслуживаются.
repositoryВсе пакетные менеджерыСписок upstream-репозиториев для экосистемы.
repository[*].nameВсе пакетные менеджерыИмя репозитория. Для non-Docker экосистем становится первым сегментом URL: /{name}/.... Должно быть уникальным среди включенных маршрутов.
repository[*].registryВсе пакетные менеджерыURL upstream-реестра, куда OSA Proxy проксирует запросы.
repository[*].work-modeВсе пакетные менеджерыРежим работы для конкретного репозитория. Если пустой, используется codescoring.work-mode.
repository[*].scan-manifestnpm, composer, maven, nuget, pypi, ruby, conan, goВключает проверку и модификацию манифестов/metadata.
repository[*].scan-packageВсе, кроме dockerВключает проверку скачиваемых файлов пакетов. Для docker сканирование образов включено логикой Docker Registry proxy.
repository[*].url-encoded-configВсе, кроме dockerВключает поддержку URL-safe Base64-контекста в пути для сценариев через Nexus/JFrog и применения политик к конкретному repository context.
repository[*].file-type-filterВсе, кроме dockerОграничивает, какие файлы отправляются на пакетное сканирование, по расширениям. Если параметр не задан или выключен, фильтрация не применяется.

Специфичные параметры репозиториев

ПараметрГде доступенНазначение
packages-registrypypi, composerБазовый URL отдельного хоста, с которого скачиваются файлы пакетов, если он отличается от metadata registry.
additional-packages-registriespypi, composerКарта дополнительных host -> registry для пакетов, которые публикуют артефакты на нескольких доменах. Нужна для корректной маршрутизации ссылок на внешние package hosts.
sumdb-registrygoURL Go checksum database, например https://sum.golang.org, если SumDB-запросы должны проходить через OSA Proxy.
remove-blocked-versionsnpm, nuget, pypiУдаляет заблокированные версии из metadata; значение по умолчанию — true. При false npm добавляет os/deprecated, NuGet помечает версию как delisted, а PyPI добавляет data-yanked.
distrodebian, alpineИмя дистрибутива или ветки репозитория, которое используется при обработке metadata и путей пакетов.
auth-token-urldockerПолный точный URL token endpoint. OSA Proxy не добавляет /token; для Docker Hub используйте https://auth.docker.io/token. Поле можно не задавать для registry без Bearer token service.

file-type-filter

ПараметрНазначение
additional-allowed-extensionsYAML-массив строк. Наличие этого поля включает фильтр: после этого проходят только расширения из встроенного preset и из additional-allowed-extensions, а остальные неизвестные расширения блокируются. Можно указывать с точкой или без точки; значения нормализуются к нижнему регистру и форме с точкой.
scanned-extensionsYAML-массив строк. Включает фильтр и заставляет handler рассматривать файлы с этими расширениями как package artifacts для сканирования и краткоживущего кэша результата сканирования. Можно указывать с точкой или без точки.

Фильтр работает только для репозиториев не-Docker экосистем. Если секция file-type-filter отсутствует или задана как {}, фильтр выключен: OSA Proxy работает как без фильтра, то есть запросы проходят по обычным правилам handler'а и совместимость с прежним поведением сохраняется. Чтобы включить фильтр, добавьте хотя бы одно из полей additional-allowed-extensions / scanned-extensions. Учитывается именно наличие ключа: например, additional-allowed-extensions: [] включает фильтр, но не добавляет расширений сверх встроенного preset.

При включенном фильтре OSA Proxy:

  • пропускает metadata/manifest-запросы без проверки расширения;
  • извлекает имя файла из URL path, декодирует URL-encoded символы и сравнивает расширение без учета регистра;
  • разрешает файл, если его расширение входит во встроенный preset экосистемы или в additional-allowed-extensions;
  • разрешает sidecar-файлы checksums и подписи (.metadata, .sha256, .sha512, .sha1, .asc, .md5), только если базовый артефакт тоже разрешен;
  • сразу блокирует все остальные package file-запросы до обращения к upstream и CodeScoring.

Встроенные presets:

ЭкосистемаРазрешенные расширения
npm.tgz
composer.zip, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz
pypi.whl, .tar.gz, .tar.bz2, .tar.xz, .zip, .egg
nuget.nupkg, .snupkg
ruby.gem
conan.py, .tgz
go.zip
alpine.apk
rpm.rpm, .drpm
debian.deb, .udeb, .dsc, .orig.tar.gz, .orig.tar.xz, .orig.tar.bz2, .debian.tar.gz, .debian.tar.xz, .debian.tar.bz2, .diff.gz
maven.pom, .jar, .war, .ear, .rar, .dar, .zip, .tar.gz, .aar, .apk, .aab, .nar, .hpi, .jpi, .kar, .eba, .sar, .par, .car, .mar, .har, .obr, .module

Для Debian также разрешаются source tarballs вида .orig-*.tar.gz, .orig-*.tar.xz и .orig-*.tar.bz2.

additional-allowed-extensions расширяет только allow-list фильтра. Само наличие этого поля переводит репозиторий в режим allow-list: OSA Proxy разрешает встроенные расширения экосистемы и расширения из additional-allowed-extensions, а все остальные неизвестные package file-расширения блокирует. Параметр нужен, когда в репозитории есть допустимые файлы с нестандартными расширениями и их не нужно блокировать самим фильтром. Он не заставляет handler отправлять такие файлы на package scan: если стандартная стратегия экосистемы не считает расширение сканируемым, запрос пройдет дальше как обычный passthrough. Чтобы новый тип файла также участвовал в package scan, добавьте это расширение в scanned-extensions.

scanned-extensions используется для второго поведения: файлы с этими расширениями считаются сканируемыми package artifacts, даже если стандартная стратегия экосистемы их не распознает. Для таких расширений включается кэш результата сканирования на короткое время, чтобы родственные файлы с одной базой имени могли использовать один вердикт. Например, для Maven можно указать scanned-extensions: [.jar, .pom], чтобы demo-1.0.0.jar и demo-1.0.0.pom группировались по базе demo-1.0.0.

Пример:

npm:
  enabled: true
  repository:
    - name: npm
      registry: https://registry.npmjs.org
      scan-package: true
      file-type-filter:
        additional-allowed-extensions: [tgz, license]
        scanned-extensions: [tgz]

В этом примере .tgz разрешается preset'ом npm и участвует в package scan, а .license дополнительно разрешается фильтром, но не становится сканируемым артефактом.

Пример поведения для npm

Без секции file-type-filter фильтр выключен. Npm handler работает по стандартной логике: package tarball left-pad-1.0.0.tgz отправляется на package scan, а остальные запросы обрабатываются как metadata или passthrough в зависимости от маршрута.

npm:
  enabled: true
  repository:
    - name: npm
      registry: https://registry.npmjs.org
      scan-package: true

Пустая секция также оставляет фильтр выключенным:

npm:
  enabled: true
  repository:
    - name: npm
      registry: https://registry.npmjs.org
      scan-package: true
      file-type-filter: {}

Чтобы включить фильтр без добавления новых расширений, можно задать пустой список. Тогда для npm разрешены только встроенный preset .tgz и sidecar-файлы к разрешенным артефактам. Запрос к left-pad-1.0.0.tgz пройдет и будет проверен, а запрос к left-pad-1.0.0.exe будет заблокирован до upstream и CodeScoring.

npm:
  enabled: true
  repository:
    - name: npm
      registry: https://registry.npmjs.org
      scan-package: true
      file-type-filter:
        additional-allowed-extensions: []

Если нужно разрешить нестандартный файл, но не отправлять его на package scan, добавьте расширение только в additional-allowed-extensions:

npm:
  enabled: true
  repository:
    - name: npm
      registry: https://registry.npmjs.org
      scan-package: true
      file-type-filter:
        additional-allowed-extensions: [license]

В такой конфигурации .tgz будет сканироваться как npm package, .license пройдет фильтр как допустимый файл, а .exe будет заблокирован фильтром.

codescoring

ПараметрЗначение по умолчаниюНазначение
urlОбязательный параметрURL платформы CodeScoring.
tokenОбязательный параметрТокен доступа к CodeScoring API.
work-modestrict_waitГлобальный режим работы: warmup, spectator, moderate, strict, strict_wait.
osa-proxy-urlОбязателен при выключенном forwarded-режимеАбсолютный HTTP(S) URL OSA Proxy. Используется при генерации ссылок и подмене URL в ответах.
osa-proxy-url-from-forwarded-headersfalseПри true формирует URL из X-Forwarded-Proto и X-Forwarded-Host. Используйте, когда один инстанс доступен по разным URL: ссылки на пакеты в metadata и манифестах будут соответствовать URL текущего контура. Fallback — https и обычный Host. Включайте только за доверенным reverse proxy.
enable-status-linefalseДобавляет причину блокировки в HTTP/1.1 status line. Не влияет на HTTP/2 и HTTP/3; Docker-клиенты читают JSON body.
block-on-codescoring-errorstrueБлокирует скачивание, если CodeScoring вернул ошибку или пакет не удалось проверить.
block-messageНе заданПользовательский текст ответа о блокировке. Если значение не задано или пустое, OSA Proxy использует стандартное сообщение, соответствующее причине блокировки.
append-block-url-to-messagetrueДобавляет ссылку на причину блокировки к пользовательскому сообщению, если ссылка получена от CodeScoring.
legacy-judgefalseВключает совместимость с версиями Judge до 2026.20.0. Используйте только для инсталляций CodeScoring со старой версией сервиса Judge.
stageproxyЗначение stage/context, передаваемое в проверки CodeScoring.
block-status-code403HTTP-код ответа при блокировке пакета.
judge-concurrency16Ограничивает количество параллельных обращений к Judge. Чем ниже значение, тем меньше одновременных запросов OSA Proxy отправляет в Judge при проверке больших списков версий и фоновом обновлении кэша.
resilienceСм. нижеНастройки устойчивости запросов к CodeScoring.

codescoring.resilience.retry

ПараметрЗначение по умолчаниюНазначение
max-attempts3Максимальное количество попыток запроса.
wait-duration1sПауза между попытками.
exponential-backoff-multiplier2Множитель exponential backoff для увеличения паузы между повторами.

codescoring.resilience.circuit-breaker

ПараметрЗначение по умолчаниюНазначение
failure-rate-threshold50Процент ошибок, после которого circuit breaker открывается.
minimum-number-of-calls10Минимальное число вызовов для расчета error rate.
sliding-window-size20Размер окна, по которому считается статистика ошибок.
wait-duration-in-open-state30sВремя ожидания перед переходом из open в half-open.
permitted-number-of-calls-in-half-open-state5Количество пробных запросов в half-open состоянии.

http.server

ПараметрЗначение по умолчаниюНазначение
read-timeout2mМаксимальное время чтения всего входящего запроса.
read-header-timeout5sМаксимальное время чтения HTTP-заголовков.
idle-timeout120sВремя удержания idle keep-alive соединения.
shutdown-timeout10sТаймаут graceful shutdown.

http.client

ПараметрЗначение по умолчаниюНазначение
connection-timeout10sТаймаут установки соединения с upstream-реестрами и CodeScoring.
response-timeout30sТаймаут ожидания ответа.
max-manifest-body-size200mbМаксимальный размер тела manifest/metadata, которое сервис готов обрабатывать. Поддерживаются значения вроде 200mb.
max-idle-conns100Максимальное количество idle HTTP-соединений.
max-idle-conns-per-host10Максимальное количество idle HTTP-соединений на один host.
idle-conn-timeout90sВремя жизни idle-соединения в HTTP-клиенте.

cache.judge

ПараметрЗначение по умолчаниюНазначение
enabledfalseВключает Redis-кэш результатов проверки Judge.
ttl24hВремя жизни записи кэша.
refresh-after30mВозраст записи, после которого ее можно обновлять в фоне.
proactive-refresh-enabledfalseВключает фоновое обновление устаревающих записей.
proactive-refresh-interval2hПериод запуска фонового обновления.
proactive-refresh-workers10Количество workers для фонового обновления.
key-prefixНе заданПрефикс Redis-ключей, например cs:judge:.

cache.redis

ПараметрНазначение
addressАдрес Redis в формате host:port.
usernameИмя пользователя Redis ACL.
passwordПароль Redis.
dbНомер Redis database.
sentinel.enabledВключает Redis Sentinel; при этом address можно не задавать.
sentinel.master-nameИмя master-группы Sentinel.
sentinel.addressesСписок Sentinel endpoints в формате host:port.
sentinel.usernameИмя пользователя Sentinel ACL.
sentinel.passwordОтдельный пароль Sentinel.

logging

ПараметрЗначение по умолчаниюНазначение
levelinfoУровень логирования: debug, info, warn, warning, error. Неизвестное значение трактуется как info.
Страница была полезна?