aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api/activitypub/security.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests/api/activitypub/security.ts')
-rw-r--r--server/tests/api/activitypub/security.ts180
1 files changed, 180 insertions, 0 deletions
diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts
new file mode 100644
index 000000000..c5428abbb
--- /dev/null
+++ b/server/tests/api/activitypub/security.ts
@@ -0,0 +1,180 @@
1/* tslint:disable:no-unused-expression */
2
3import 'mocha'
4
5import { flushAndRunMultipleServers, flushTests, killallServers, makeAPRequest, makeFollowRequest, ServerInfo } from '../../utils'
6import { HTTP_SIGNATURE } from '../../../initializers'
7import { buildDigest, buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activitypub-http-utils'
8import * as chai from 'chai'
9import { setActorField } from '../../utils/miscs/sql'
10import { activityPubContextify, buildSignedActivity } from '../../../helpers/activitypub'
11
12const expect = chai.expect
13
14function setKeysOfServer2 (serverNumber: number, publicKey: string, privateKey: string) {
15 return Promise.all([
16 setActorField(serverNumber, 'http://localhost:9002/accounts/peertube', 'publicKey', publicKey),
17 setActorField(serverNumber, 'http://localhost:9002/accounts/peertube', 'privateKey', privateKey)
18 ])
19}
20
21function setKeysOfServer3 (serverNumber: number, publicKey: string, privateKey: string) {
22 return Promise.all([
23 setActorField(serverNumber, 'http://localhost:9003/accounts/peertube', 'publicKey', publicKey),
24 setActorField(serverNumber, 'http://localhost:9003/accounts/peertube', 'privateKey', privateKey)
25 ])
26}
27
28describe('Test ActivityPub security', function () {
29 let servers: ServerInfo[]
30 let url: string
31
32 const keys = require('./json/peertube/keys.json')
33 const invalidKeys = require('./json/peertube/invalid-keys.json')
34 const baseHttpSignature = {
35 algorithm: HTTP_SIGNATURE.ALGORITHM,
36 authorizationHeaderName: HTTP_SIGNATURE.HEADER_NAME,
37 keyId: 'acct:peertube@localhost:9002',
38 key: keys.privateKey,
39 headers: HTTP_SIGNATURE.HEADERS_TO_SIGN
40 }
41
42 // ---------------------------------------------------------------
43
44 before(async function () {
45 this.timeout(60000)
46
47 servers = await flushAndRunMultipleServers(3)
48
49 url = servers[0].url + '/inbox'
50
51 await setKeysOfServer2(1, keys.publicKey, keys.privateKey)
52
53 const to = { url: 'http://localhost:9001/accounts/peertube' }
54 const by = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey }
55 await makeFollowRequest(to, by)
56 })
57
58 describe('When checking HTTP signature', function () {
59
60 it('Should fail with an invalid digest', async function () {
61 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
62 const headers = {
63 Digest: buildDigest({ hello: 'coucou' })
64 }
65
66 const { response } = await makeAPRequest(url, body, baseHttpSignature, headers)
67
68 expect(response.statusCode).to.equal(403)
69 })
70
71 it('Should fail with an invalid date', async function () {
72 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
73 const headers = buildGlobalHeaders(body)
74 headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT'
75
76 const { response } = await makeAPRequest(url, body, baseHttpSignature, headers)
77
78 expect(response.statusCode).to.equal(403)
79 })
80
81 it('Should fail with bad keys', async function () {
82 await setKeysOfServer2(1, invalidKeys.publicKey, invalidKeys.privateKey)
83 await setKeysOfServer2(2, invalidKeys.publicKey, invalidKeys.privateKey)
84
85 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
86 const headers = buildGlobalHeaders(body)
87
88 const { response } = await makeAPRequest(url, body, baseHttpSignature, headers)
89
90 expect(response.statusCode).to.equal(403)
91 })
92
93 it('Should succeed with a valid HTTP signature', async function () {
94 await setKeysOfServer2(1, keys.publicKey, keys.privateKey)
95 await setKeysOfServer2(2, keys.publicKey, keys.privateKey)
96
97 const body = activityPubContextify(require('./json/peertube/announce-without-context.json'))
98 const headers = buildGlobalHeaders(body)
99
100 const { response } = await makeAPRequest(url, body, baseHttpSignature, headers)
101
102 expect(response.statusCode).to.equal(204)
103 })
104 })
105
106 describe('When checking Linked Data Signature', function () {
107 before(async () => {
108 await setKeysOfServer3(3, keys.publicKey, keys.privateKey)
109
110 const to = { url: 'http://localhost:9001/accounts/peertube' }
111 const by = { url: 'http://localhost:9003/accounts/peertube', privateKey: keys.privateKey }
112 await makeFollowRequest(to, by)
113 })
114
115 it('Should fail with bad keys', async function () {
116 this.timeout(10000)
117
118 await setKeysOfServer3(1, invalidKeys.publicKey, invalidKeys.privateKey)
119 await setKeysOfServer3(3, invalidKeys.publicKey, invalidKeys.privateKey)
120
121 const body = require('./json/peertube/announce-without-context.json')
122 body.actor = 'http://localhost:9003/accounts/peertube'
123
124 const signer: any = { privateKey: invalidKeys.privateKey, url: 'http://localhost:9003/accounts/peertube' }
125 const signedBody = await buildSignedActivity(signer, body)
126
127 const headers = buildGlobalHeaders(signedBody)
128
129 const { response } = await makeAPRequest(url, signedBody, baseHttpSignature, headers)
130
131 expect(response.statusCode).to.equal(403)
132 })
133
134 it('Should fail with an altered body', async function () {
135 this.timeout(10000)
136
137 await setKeysOfServer3(1, keys.publicKey, keys.privateKey)
138 await setKeysOfServer3(3, keys.publicKey, keys.privateKey)
139
140 const body = require('./json/peertube/announce-without-context.json')
141 body.actor = 'http://localhost:9003/accounts/peertube'
142
143 const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:9003/accounts/peertube' }
144 const signedBody = await buildSignedActivity(signer, body)
145
146 signedBody.actor = 'http://localhost:9003/account/peertube'
147
148 const headers = buildGlobalHeaders(signedBody)
149
150 const { response } = await makeAPRequest(url, signedBody, baseHttpSignature, headers)
151
152 expect(response.statusCode).to.equal(403)
153 })
154
155 it('Should succeed with a valid signature', async function () {
156 this.timeout(10000)
157
158 const body = require('./json/peertube/announce-without-context.json')
159 body.actor = 'http://localhost:9003/accounts/peertube'
160
161 const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:9003/accounts/peertube' }
162 const signedBody = await buildSignedActivity(signer, body)
163
164 const headers = buildGlobalHeaders(signedBody)
165
166 const { response } = await makeAPRequest(url, signedBody, baseHttpSignature, headers)
167
168 expect(response.statusCode).to.equal(204)
169 })
170 })
171
172 after(async function () {
173 killallServers(servers)
174
175 // Keep the logs if the test failed
176 if (this['ok']) {
177 await flushTests()
178 }
179 })
180})