- добавлен shared config presets, custom transforms и allowlist hosts - реализованы Backend endpoints для assets, presets и variants - добавлена orchestration через PostgreSQL, RabbitMQ, S3 и worker - обновлён Gateway read-through flow с L1 cache и корректным Vary: Accept - добавлена миграция resize_mode для variants lookup - обновлены dev scripts, env template, lockfile и документация
2.0 KiB
2.0 KiB
Контракт с imgproxy
imgproxy всегда внешний сервис для image-platform.
Env
IMGPROXY_UPSTREAM=http://external-imgproxy.internal:8080
IMGPROXY_SIGNING_ENABLED=false
IMGPROXY_KEY=
IMGPROXY_SALT=
Dev режим
В dev можно использовать unsigned /unsafe URL, если внешний imgproxy запущен без key/salt.
Пример path:
/unsafe/resize:fit:800:0:0/q:80/plain/https://storage.yandexcloud.net/shared1318/img/1.jpg
Prod режим
В prod нужно перейти на signed URLs и закрыть /unsafe.
Path для подписи строится без /unsafe:
/resize:fit:800:0:0/q:80/plain/https://storage.yandexcloud.net/shared1318/img/1.jpg
Signature:
HMAC-SHA256(binary_key, binary_salt + path_bytes)
base64url without padding
Node implementation reference:
import crypto from "node:crypto"
export function signImgproxyPath(keyHex: string, saltHex: string, path: string) {
const key = Buffer.from(keyHex, "hex")
const salt = Buffer.from(saltHex, "hex")
const hmac = crypto.createHmac("sha256", key)
hmac.update(Buffer.concat([salt, Buffer.from(path)]))
return hmac.digest("base64url")
}
Final signed URL:
{IMGPROXY_UPSTREAM}/{signature}{path}
Security rules
- Не отдавать
IMGPROXY_KEYиIMGPROXY_SALTв браузер. - Source URL валидировать в Backend/worker.
- Разрешать только
httpиhttps. - Запрещать localhost, private IP, loopback, link-local.
- Source host должен быть разрешён mock allowlist
SOURCE_ALLOWED_HOSTS; таблицаallowed_image_hostsостаётся для будущего CRUD. - Не давать клиенту произвольные imgproxy options без
IMAGE_ALLOW_CUSTOM_TRANSFORMS=true. - Использовать static presets/custom normalization и deterministic
variantHash.