X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Ftests%2Fapi%2Fobject-storage%2Fvideo-static-file-privacy.ts;h=930c88543ba680a1e26273be084d226732e16103;hb=05a60d85997c108d39bcfb14f1ffd4c74f8b1e93;hp=c6d7a1a2cc8847a5d1004fc208e59c9d0c1c6f94;hpb=508c1b1e9f3b26752a961e945b7fa59b72b30827;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/tests/api/object-storage/video-static-file-privacy.ts b/server/tests/api/object-storage/video-static-file-privacy.ts index c6d7a1a2c..930c88543 100644 --- a/server/tests/api/object-storage/video-static-file-privacy.ts +++ b/server/tests/api/object-storage/video-static-file-privacy.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import { basename } from 'path' -import { expectStartWith } from '@server/tests/shared' +import { checkVideoFileTokenReinjection, expectStartWith } from '@server/tests/shared' import { areScalewayObjectStorageTestsDisabled, getAllFiles, getHLS } from '@shared/core-utils' import { HttpStatusCode, LiveVideo, VideoDetails, VideoPrivacy } from '@shared/models' import { @@ -19,6 +19,12 @@ import { waitJobs } from '@shared/server-commands' +function extractFilenameFromUrl (url: string) { + const parts = basename(url).split(':') + + return parts[parts.length - 1] +} + describe('Object storage for video static file privacy', function () { // We need real world object storage to check ACL if (areScalewayObjectStorageTestsDisabled()) return @@ -26,75 +32,81 @@ describe('Object storage for video static file privacy', function () { let server: PeerTubeServer let userToken: string - before(async function () { - this.timeout(120000) + // --------------------------------------------------------------------------- - server = await createSingleServer(1, ObjectStorageCommand.getDefaultScalewayConfig(1)) - await setAccessTokensToServers([ server ]) - await setDefaultVideoChannel([ server ]) + async function checkPrivateVODFiles (uuid: string) { + const video = await server.videos.getWithToken({ id: uuid }) - await server.config.enableMinimumTranscoding() + for (const file of video.files) { + expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/webseed/private/') - userToken = await server.users.generateUserAndToken('user1') - }) + await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) + } - describe('VOD', function () { - let privateVideoUUID: string - let publicVideoUUID: string - let userPrivateVideoUUID: string + for (const file of getAllFiles(video)) { + const internalFileUrl = await server.sql.getInternalFileUrl(file.id) + expectStartWith(internalFileUrl, ObjectStorageCommand.getScalewayBaseUrl()) + await makeRawRequest({ url: internalFileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) + } - async function checkPrivateFiles (uuid: string) { - const video = await server.videos.getWithToken({ id: uuid }) + const hls = getHLS(video) - for (const file of video.files) { - expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/webseed/private/') + if (hls) { + for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) { + expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/') + } + + await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) + await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) + + for (const file of hls.files) { + expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/streaming-playlists/hls/private/') await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) } + } + } - for (const file of getAllFiles(video)) { - const internalFileUrl = await server.sql.getInternalFileUrl(file.id) - expectStartWith(internalFileUrl, ObjectStorageCommand.getScalewayBaseUrl()) - await makeRawRequest({ url: internalFileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) - } + async function checkPublicVODFiles (uuid: string) { + const video = await server.videos.getWithToken({ id: uuid }) - const hls = getHLS(video) + for (const file of getAllFiles(video)) { + expectStartWith(file.fileUrl, ObjectStorageCommand.getScalewayBaseUrl()) - if (hls) { - for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) { - expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/') - } + await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) + } - await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) - await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) + const hls = getHLS(video) - for (const file of hls.files) { - expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/streaming-playlists/hls/private/') + if (hls) { + expectStartWith(hls.playlistUrl, ObjectStorageCommand.getScalewayBaseUrl()) + expectStartWith(hls.segmentsSha256Url, ObjectStorageCommand.getScalewayBaseUrl()) - await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) - } - } + await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) + await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) } + } - async function checkPublicFiles (uuid: string) { - const video = await server.videos.getWithToken({ id: uuid }) + // --------------------------------------------------------------------------- - for (const file of getAllFiles(video)) { - expectStartWith(file.fileUrl, ObjectStorageCommand.getScalewayBaseUrl()) + before(async function () { + this.timeout(120000) - await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) - } + server = await createSingleServer(1, ObjectStorageCommand.getDefaultScalewayConfig({ serverNumber: 1 })) + await setAccessTokensToServers([ server ]) + await setDefaultVideoChannel([ server ]) - const hls = getHLS(video) + await server.config.enableMinimumTranscoding() - if (hls) { - expectStartWith(hls.playlistUrl, ObjectStorageCommand.getScalewayBaseUrl()) - expectStartWith(hls.segmentsSha256Url, ObjectStorageCommand.getScalewayBaseUrl()) + userToken = await server.users.generateUserAndToken('user1') + }) - await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) - await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) - } - } + describe('VOD', function () { + let privateVideoUUID: string + let publicVideoUUID: string + let userPrivateVideoUUID: string + + // --------------------------------------------------------------------------- async function getSampleFileUrls (videoId: string) { const video = await server.videos.getWithToken({ id: videoId }) @@ -105,8 +117,10 @@ describe('Object storage for video static file privacy', function () { } } + // --------------------------------------------------------------------------- + it('Should upload a private video and have appropriate object storage ACL', async function () { - this.timeout(60000) + this.timeout(120000) { const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) @@ -120,18 +134,18 @@ describe('Object storage for video static file privacy', function () { await waitJobs([ server ]) - await checkPrivateFiles(privateVideoUUID) + await checkPrivateVODFiles(privateVideoUUID) }) it('Should upload a public video and have appropriate object storage ACL', async function () { - this.timeout(60000) + this.timeout(120000) const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.UNLISTED }) await waitJobs([ server ]) publicVideoUUID = uuid - await checkPublicFiles(publicVideoUUID) + await checkPublicVODFiles(publicVideoUUID) }) it('Should not get files without appropriate OAuth token', async function () { @@ -177,12 +191,26 @@ describe('Object storage for video static file privacy', function () { } }) + it('Should reinject video file token', async function () { + this.timeout(120000) + + const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: privateVideoUUID }) + + await checkVideoFileTokenReinjection({ + server, + videoUUID: privateVideoUUID, + videoFileToken, + resolutions: [ 240, 720 ], + isLive: false + }) + }) + it('Should update public video to private', async function () { this.timeout(60000) await server.videos.update({ id: publicVideoUUID, attributes: { privacy: VideoPrivacy.INTERNAL } }) - await checkPrivateFiles(publicVideoUUID) + await checkPrivateVODFiles(publicVideoUUID) }) it('Should update private video to public', async function () { @@ -190,7 +218,7 @@ describe('Object storage for video static file privacy', function () { await server.videos.update({ id: publicVideoUUID, attributes: { privacy: VideoPrivacy.PUBLIC } }) - await checkPublicFiles(publicVideoUUID) + await checkPublicVODFiles(publicVideoUUID) }) }) @@ -203,6 +231,8 @@ describe('Object storage for video static file privacy', function () { let unrelatedFileToken: string + // --------------------------------------------------------------------------- + async function checkLiveFiles (live: LiveVideo, liveId: string) { const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey }) await server.live.waitUntilPublished({ videoId: liveId }) @@ -260,6 +290,8 @@ describe('Object storage for video static file privacy', function () { } } + // --------------------------------------------------------------------------- + before(async function () { await server.config.enableMinimumTranscoding() @@ -273,13 +305,21 @@ describe('Object storage for video static file privacy', function () { }) { - const { video, live } = await server.live.quickCreate({ saveReplay: true, permanentLive: false, privacy: VideoPrivacy.PRIVATE }) + const { video, live } = await server.live.quickCreate({ + saveReplay: true, + permanentLive: false, + privacy: VideoPrivacy.PRIVATE + }) normalLiveId = video.uuid normalLive = live } { - const { video, live } = await server.live.quickCreate({ saveReplay: true, permanentLive: true, privacy: VideoPrivacy.PRIVATE }) + const { video, live } = await server.live.quickCreate({ + saveReplay: true, + permanentLive: true, + privacy: VideoPrivacy.PRIVATE + }) permanentLiveId = video.uuid permanentLive = live } @@ -297,6 +337,26 @@ describe('Object storage for video static file privacy', function () { await checkLiveFiles(permanentLive, permanentLiveId) }) + it('Should reinject video file token in permanent live', async function () { + this.timeout(240000) + + const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: permanentLive.rtmpUrl, streamKey: permanentLive.streamKey }) + await server.live.waitUntilPublished({ videoId: permanentLiveId }) + + const video = await server.videos.getWithToken({ id: permanentLiveId }) + const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid }) + + await checkVideoFileTokenReinjection({ + server, + videoUUID: permanentLiveId, + videoFileToken, + resolutions: [ 720 ], + isLive: true + }) + + await stopFfmpeg(ffmpegCommand) + }) + it('Should have created a replay of the normal live with a private static path', async function () { this.timeout(240000) @@ -320,8 +380,54 @@ describe('Object storage for video static file privacy', function () { }) }) + describe('With private files proxy disabled and public ACL for private files', function () { + let videoUUID: string + + before(async function () { + this.timeout(240000) + + await server.kill() + + const config = ObjectStorageCommand.getDefaultScalewayConfig({ + serverNumber: 1, + enablePrivateProxy: false, + privateACL: 'public-read' + }) + await server.run(config) + + const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) + videoUUID = uuid + + await waitJobs([ server ]) + }) + + it('Should display object storage path for a private video and be able to access them', async function () { + this.timeout(60000) + + await checkPublicVODFiles(videoUUID) + }) + + it('Should not be able to access object storage proxy', async function () { + const privateVideo = await server.videos.getWithToken({ id: videoUUID }) + const webtorrentFilename = extractFilenameFromUrl(privateVideo.files[0].fileUrl) + const hlsFilename = extractFilenameFromUrl(getHLS(privateVideo).files[0].fileUrl) + + await makeRawRequest({ + url: server.url + '/object-storage-proxy/webseed/private/' + webtorrentFilename, + token: server.accessToken, + expectedStatus: HttpStatusCode.BAD_REQUEST_400 + }) + + await makeRawRequest({ + url: server.url + '/object-storage-proxy/streaming-playlists/hls/private/' + videoUUID + '/' + hlsFilename, + token: server.accessToken, + expectedStatus: HttpStatusCode.BAD_REQUEST_400 + }) + }) + }) + after(async function () { - this.timeout(60000) + this.timeout(240000) const { data } = await server.videos.listAllForAdmin() @@ -330,7 +436,7 @@ describe('Object storage for video static file privacy', function () { } for (const v of data) { - await server.servers.waitUntilLog('Removed files of video ' + v.url, 1, true) + await server.servers.waitUntilLog('Removed files of video ' + v.url) } await cleanupTests([ server ])