1 /* tslint:disable:no-unused-expression */
5 import { flushAndRunMultipleServers, flushTests, killallServers, ServerInfo } from '../../utils'
6 import { HTTP_SIGNATURE } from '../../../initializers'
7 import { buildDigest, buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activitypub-http-utils'
8 import * as chai from 'chai'
9 import { setActorField } from '../../utils/miscs/sql'
10 import { activityPubContextify, buildSignedActivity } from '../../../helpers/activitypub'
11 import { makeFollowRequest, makePOSTAPRequest } from '../../utils/requests/activitypub'
13 const expect = chai.expect
15 function setKeysOfServer2 (serverNumber: number, publicKey: string, privateKey: string) {
17 setActorField(serverNumber, 'http://localhost:9002/accounts/peertube', 'publicKey', publicKey),
18 setActorField(serverNumber, 'http://localhost:9002/accounts/peertube', 'privateKey', privateKey)
22 function setKeysOfServer3 (serverNumber: number, publicKey: string, privateKey: string) {
24 setActorField(serverNumber, 'http://localhost:9003/accounts/peertube', 'publicKey', publicKey),
25 setActorField(serverNumber, 'http://localhost:9003/accounts/peertube', 'privateKey', privateKey)
29 describe('Test ActivityPub security', function () {
30 let servers: ServerInfo[]
33 const keys = require('./json/peertube/keys.json')
34 const invalidKeys = require('./json/peertube/invalid-keys.json')
35 const baseHttpSignature = {
36 algorithm: HTTP_SIGNATURE.ALGORITHM,
37 authorizationHeaderName: HTTP_SIGNATURE.HEADER_NAME,
38 keyId: 'acct:peertube@localhost:9002',
40 headers: HTTP_SIGNATURE.HEADERS_TO_SIGN
43 // ---------------------------------------------------------------
45 before(async function () {
48 servers = await flushAndRunMultipleServers(3)
50 url = servers[0].url + '/inbox'
52 await setKeysOfServer2(1, keys.publicKey, keys.privateKey)
54 const to = { url: 'http://localhost:9001/accounts/peertube' }
55 const by = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey }
56 await makeFollowRequest(to, by)
59 describe('When checking HTTP signature', function () {
61 it('Should fail with an invalid digest', async function () {
62 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
64 Digest: buildDigest({ hello: 'coucou' })
67 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers)
69 expect(response.statusCode).to.equal(403)
72 it('Should fail with an invalid date', async function () {
73 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
74 const headers = buildGlobalHeaders(body)
75 headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT'
77 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers)
79 expect(response.statusCode).to.equal(403)
82 it('Should fail with bad keys', async function () {
83 await setKeysOfServer2(1, invalidKeys.publicKey, invalidKeys.privateKey)
84 await setKeysOfServer2(2, invalidKeys.publicKey, invalidKeys.privateKey)
86 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
87 const headers = buildGlobalHeaders(body)
89 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers)
91 expect(response.statusCode).to.equal(403)
94 it('Should succeed with a valid HTTP signature', async function () {
95 await setKeysOfServer2(1, keys.publicKey, keys.privateKey)
96 await setKeysOfServer2(2, keys.publicKey, keys.privateKey)
98 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
99 const headers = buildGlobalHeaders(body)
101 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers)
103 expect(response.statusCode).to.equal(204)
107 describe('When checking Linked Data Signature', function () {
109 await setKeysOfServer3(3, keys.publicKey, keys.privateKey)
111 const to = { url: 'http://localhost:9001/accounts/peertube' }
112 const by = { url: 'http://localhost:9003/accounts/peertube', privateKey: keys.privateKey }
113 await makeFollowRequest(to, by)
116 it('Should fail with bad keys', async function () {
119 await setKeysOfServer3(1, invalidKeys.publicKey, invalidKeys.privateKey)
120 await setKeysOfServer3(3, invalidKeys.publicKey, invalidKeys.privateKey)
122 const body = require('./json/peertube/announce-without-context.json')
123 body.actor = 'http://localhost:9003/accounts/peertube'
125 const signer: any = { privateKey: invalidKeys.privateKey, url: 'http://localhost:9003/accounts/peertube' }
126 const signedBody = await buildSignedActivity(signer, body)
128 const headers = buildGlobalHeaders(signedBody)
130 const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature, headers)
132 expect(response.statusCode).to.equal(403)
135 it('Should fail with an altered body', async function () {
138 await setKeysOfServer3(1, keys.publicKey, keys.privateKey)
139 await setKeysOfServer3(3, keys.publicKey, keys.privateKey)
141 const body = require('./json/peertube/announce-without-context.json')
142 body.actor = 'http://localhost:9003/accounts/peertube'
144 const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:9003/accounts/peertube' }
145 const signedBody = await buildSignedActivity(signer, body)
147 signedBody.actor = 'http://localhost:9003/account/peertube'
149 const headers = buildGlobalHeaders(signedBody)
151 const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature, headers)
153 expect(response.statusCode).to.equal(403)
156 it('Should succeed with a valid signature', async function () {
159 const body = require('./json/peertube/announce-without-context.json')
160 body.actor = 'http://localhost:9003/accounts/peertube'
162 const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:9003/accounts/peertube' }
163 const signedBody = await buildSignedActivity(signer, body)
165 const headers = buildGlobalHeaders(signedBody)
167 const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature, headers)
169 expect(response.statusCode).to.equal(204)
173 after(async function () {
174 killallServers(servers)
176 // Keep the logs if the test failed