From 9ab330b90decf4edf152ff8e1d2948c065766b2c Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 19 Oct 2022 10:43:53 +0200 Subject: Use private ACL for private videos in s3 --- server/middlewares/validators/shared/videos.ts | 6 +-- server/middlewares/validators/static.ts | 72 ++++++++++++++++++++------ 2 files changed, 58 insertions(+), 20 deletions(-) (limited to 'server/middlewares') diff --git a/server/middlewares/validators/shared/videos.ts b/server/middlewares/validators/shared/videos.ts index c29751eca..ebbfc0a0a 100644 --- a/server/middlewares/validators/shared/videos.ts +++ b/server/middlewares/validators/shared/videos.ts @@ -111,7 +111,7 @@ async function checkCanSeeVideo (options: { }) { const { req, res, video, paramId } = options - if (video.requiresAuth(paramId)) { + if (video.requiresAuth({ urlParamId: paramId, checkBlacklist: true })) { return checkCanSeeAuthVideo(req, res, video) } @@ -174,13 +174,13 @@ async function checkCanAccessVideoStaticFiles (options: { res: Response paramId: string }) { - const { video, req, res, paramId } = options + const { video, req, res } = options if (res.locals.oauth?.token.User) { return checkCanSeeVideo(options) } - if (!video.requiresAuth(paramId)) return true + if (!video.hasPrivateStaticPath()) return true const videoFileToken = req.query.videoFileToken if (!videoFileToken) { diff --git a/server/middlewares/validators/static.ts b/server/middlewares/validators/static.ts index ff9e6ae6e..13fde6dd1 100644 --- a/server/middlewares/validators/static.ts +++ b/server/middlewares/validators/static.ts @@ -7,10 +7,17 @@ import { logger } from '@server/helpers/logger' import { LRU_CACHE } from '@server/initializers/constants' import { VideoModel } from '@server/models/video/video' import { VideoFileModel } from '@server/models/video/video-file' +import { MStreamingPlaylist, MVideoFile, MVideoThumbnail } from '@server/types/models' import { HttpStatusCode } from '@shared/models' import { areValidationErrors, checkCanAccessVideoStaticFiles } from './shared' -const staticFileTokenBypass = new LRUCache({ +type LRUValue = { + allowed: boolean + video?: MVideoThumbnail + file?: MVideoFile + playlist?: MStreamingPlaylist } + +const staticFileTokenBypass = new LRUCache({ max: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.MAX_SIZE, ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL }) @@ -27,18 +34,26 @@ const ensureCanAccessVideoPrivateWebTorrentFiles = [ const cacheKey = token + '-' + req.originalUrl if (staticFileTokenBypass.has(cacheKey)) { - const allowedFromCache = staticFileTokenBypass.get(cacheKey) + const { allowed, file, video } = staticFileTokenBypass.get(cacheKey) + + if (allowed === true) { + res.locals.onlyVideo = video + res.locals.videoFile = file - if (allowedFromCache === true) return next() + return next() + } return res.sendStatus(HttpStatusCode.FORBIDDEN_403) } - const allowed = await isWebTorrentAllowed(req, res) + const result = await isWebTorrentAllowed(req, res) + + staticFileTokenBypass.set(cacheKey, result) - staticFileTokenBypass.set(cacheKey, allowed) + if (result.allowed !== true) return - if (allowed !== true) return + res.locals.onlyVideo = result.video + res.locals.videoFile = result.file return next() } @@ -64,18 +79,28 @@ const ensureCanAccessPrivateVideoHLSFiles = [ const cacheKey = token + '-' + videoUUID if (staticFileTokenBypass.has(cacheKey)) { - const allowedFromCache = staticFileTokenBypass.get(cacheKey) + const { allowed, file, playlist, video } = staticFileTokenBypass.get(cacheKey) - if (allowedFromCache === true) return next() + if (allowed === true) { + res.locals.onlyVideo = video + res.locals.videoFile = file + res.locals.videoStreamingPlaylist = playlist + + return next() + } return res.sendStatus(HttpStatusCode.FORBIDDEN_403) } - const allowed = await isHLSAllowed(req, res, videoUUID) + const result = await isHLSAllowed(req, res, videoUUID) + + staticFileTokenBypass.set(cacheKey, result) - staticFileTokenBypass.set(cacheKey, allowed) + if (result.allowed !== true) return - if (allowed !== true) return + res.locals.onlyVideo = result.video + res.locals.videoFile = result.file + res.locals.videoStreamingPlaylist = result.playlist return next() } @@ -96,25 +121,38 @@ async function isWebTorrentAllowed (req: express.Request, res: express.Response) logger.debug('Unknown static file %s to serve', req.originalUrl, { filename }) res.sendStatus(HttpStatusCode.FORBIDDEN_403) - return false + return { allowed: false } } - const video = file.getVideo() + const video = await VideoModel.load(file.getVideo().id) - return checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid }) + return { + file, + video, + allowed: await checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid }) + } } async function isHLSAllowed (req: express.Request, res: express.Response, videoUUID: string) { - const video = await VideoModel.load(videoUUID) + const filename = basename(req.path) + + const video = await VideoModel.loadWithFiles(videoUUID) if (!video) { logger.debug('Unknown static file %s to serve', req.originalUrl, { videoUUID }) res.sendStatus(HttpStatusCode.FORBIDDEN_403) - return false + return { allowed: false } } - return checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid }) + const file = await VideoFileModel.loadByFilename(filename) + + return { + file, + video, + playlist: video.getHLSPlaylist(), + allowed: await checkCanAccessVideoStaticFiles({ req, res, video, paramId: video.uuid }) + } } function extractTokenOrDie (req: express.Request, res: express.Response) { -- cgit v1.2.3