Skip to content

Commit cebc138

Browse files
committed
Added user access control to all builtin apps
1 parent dfbec91 commit cebc138

File tree

9 files changed

+70
-43
lines changed

9 files changed

+70
-43
lines changed

agent/apps/ztm/proxy/api.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ export default function ({ app, mesh }) {
3030
path: `/api/config`,
3131
},
3232
JSON.encode(config)
33-
))
33+
)).then(res => {
34+
var status = res?.head?.status
35+
if (!(200 <= status && status <= 299)) throw res.head.statusText
36+
})
3437
}
3538
}
3639

agent/apps/ztm/proxy/main.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export default function ({ app, mesh, utils }) {
1010
var gui = new http.Directory(os.path.join(app.root, 'gui'))
1111
var response = utils.createResponse
1212
var responder = utils.createResponder
13+
var responderOwnerOnly = (f) => responder((params, req) => (
14+
$ctx.peer.username === app.username ? f(params, req) : Promise.resolve(response(403))
15+
))
1316

1417
var serveUser = utils.createServer({
1518
'/cli': {
@@ -55,7 +58,7 @@ export default function ({ app, mesh, utils }) {
5558
ret => ret ? response(200, ret) : response(404)
5659
)),
5760

58-
'POST': responder((_, req) => {
61+
'POST': responderOwnerOnly((_, req) => {
5962
var config = JSON.decode(req.body)
6063
return api.setEndpointConfig(app.endpoint.id, config).then(response(201))
6164
}),

agent/apps/ztm/script/api.js

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default function ({ app, mesh }) {
55

66
var scripts = {}
77

8+
var $ctx
89
var $ep
910
var $hash
1011
var $command
@@ -24,27 +25,34 @@ export default function ({ app, mesh }) {
2425
)
2526

2627
var executeScriptLocal = pipeline($=>$
27-
.replaceMessage(req => {
28-
var url = new URL(req.head.path)
29-
var argv = JSON.parse(URL.decodeComponent(url.searchParams.get('argv') || '[]'))
30-
var exe = app.executable
31-
var program = exe.endsWith('pipy') || exe.endsWith('pipy.exe') ? [exe] : [exe, '--pipy']
32-
$hash = addScript(req.body)
33-
$command = [
34-
...program,
35-
'--no-reload',
36-
'--log-level=error',
37-
`${app.url}/api/scripts/${$hash}`,
38-
'--args', ...argv
39-
]
40-
return new Data
41-
})
42-
.exec(() => $command, { stderr: true })
43-
.replaceStreamStart(evt => [new MessageStart, evt])
44-
.replaceStreamEnd(() => {
45-
delete scripts[$hash]
46-
return new MessageEnd
28+
.onStart(c => { $ctx = c })
29+
.pipe(() => $ctx.peer.username === app.username ? 'exec' : 'deny', {
30+
'exec': ($=>$
31+
.replaceMessage(req => {
32+
var url = new URL(req.head.path)
33+
var argv = JSON.parse(URL.decodeComponent(url.searchParams.get('argv') || '[]'))
34+
var exe = app.executable
35+
var program = exe.endsWith('pipy') || exe.endsWith('pipy.exe') ? [exe] : [exe, '--pipy']
36+
$hash = addScript(req.body)
37+
$command = [
38+
...program,
39+
'--no-reload',
40+
'--log-level=error',
41+
`${app.url}/api/scripts/${$hash}`,
42+
'--args', ...argv
43+
]
44+
return new Data
45+
})
46+
.exec(() => $command, { stderr: true })
47+
.replaceStreamStart(evt => [new MessageStart, evt])
48+
.replaceStreamEnd(() => {
49+
delete scripts[$hash]
50+
return new MessageEnd
51+
})
52+
),
53+
'deny': $=>$.replaceMessage(new Message({ status: 403 }, 'Forbidden'))
4754
})
55+
4856
)
4957

5058
function addScript(script) {

agent/apps/ztm/script/cli.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export default function ({ app, api, utils }) {
2424
}
2525

2626
try {
27-
println(argv)
2827
return utils.parseArgv(argv, {
2928
help: text => Promise.resolve(output(text + '\n')),
3029
commands: [

agent/apps/ztm/script/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export default function ({ app, mesh, utils }) {
5555

5656
var servePeer = utils.createServer({
5757
'/api/script': {
58-
'POST': api.executeScriptLocal,
58+
'POST': pipeline($=>$.pipe(api.executeScriptLocal, () => $ctx)),
5959
},
6060
})
6161

agent/apps/ztm/terminal/api.js

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export default function ({ app, mesh }) {
2+
var $ctx
23
var $shell
34

45
function allEndpoints() {
@@ -14,7 +15,11 @@ export default function ({ app, mesh }) {
1415
method: 'GET',
1516
path: `/api/config`,
1617
}
17-
)).then(res => res ? JSON.decode(res.body) : null)
18+
)).then(res => {
19+
var status = res?.head?.status
20+
if (!(200 <= status && status <= 299)) throw res.head.statusText
21+
return JSON.decode(res.body)
22+
})
1823
}
1924
}
2025

@@ -49,18 +54,24 @@ export default function ({ app, mesh }) {
4954
}
5055

5156
var serveTerminal = pipeline($=>$
52-
.acceptHTTPTunnel(() => new Message({ status: 200 })).to($=>$
53-
.onStart(() => getLocalConfig().then(config => {
54-
$shell = config.shell || os.env['SHELL'] || 'sh'
55-
return new Data
56-
}))
57-
.exec(
58-
() => $shell, {
59-
pty: true,
60-
onExit: () => new StreamEnd
61-
}
62-
)
63-
)
57+
.onStart(c => { $ctx = c })
58+
.pipe(() => $ctx.peer.username === app.username ? 'exec' : 'deny', {
59+
'exec': ($=>$
60+
.acceptHTTPTunnel(() => new Message({ status: 200 })).to($=>$
61+
.onStart(() => getLocalConfig().then(config => {
62+
$shell = config.shell || os.env['SHELL'] || 'sh'
63+
return new Data
64+
}))
65+
.exec(
66+
() => $shell, {
67+
pty: true,
68+
onExit: () => new StreamEnd
69+
}
70+
)
71+
)
72+
),
73+
'deny': $=>$.replaceMessage(new Message({ status: 403 }))
74+
})
6475
)
6576

6677
function getLocalConfig() {

agent/apps/ztm/terminal/main.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default function ({ app, mesh, utils }) {
99

1010
var response = utils.createResponse
1111
var responder = utils.createResponder
12+
var responderOwnerOnly = (f) => responder((params, req) => (
13+
$ctx.peer.username === app.username ? f(params, req) : Promise.resolve(response(403))
14+
))
1215

1316
var serveUser = utils.createServer({
1417
'/cli': {
@@ -44,18 +47,18 @@ export default function ({ app, mesh, utils }) {
4447

4548
var servePeer = utils.createServer({
4649
'/api/config': {
47-
'GET': responder(() => api.getEndpointConfig(app.endpoint.id).then(
50+
'GET': responderOwnerOnly(() => api.getEndpointConfig(app.endpoint.id).then(
4851
ret => ret ? response(200, ret) : response(404)
4952
)),
5053

51-
'POST': responder((_, req) => {
54+
'POST': responderOwnerOnly((_, req) => {
5255
var config = JSON.decode(req.body)
5356
return api.setEndpointConfig(app.endpoint.id, config).then(response(201))
5457
}),
5558
},
5659

5760
'/api/shell': {
58-
'CONNECT': api.serveTerminal,
61+
'CONNECT': pipeline($=>$.pipe(api.serveTerminal, () => $ctx)),
5962
},
6063
})
6164

agent/apps/ztm/tunnel/api.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ export default function ({ app, mesh }) {
327327

328328
var matchApiOutbound = new http.Match('/api/outbound/{proto}/{name}')
329329
var response200 = new Message({ status: 200 })
330-
var response401 = new Message({ status: 401 })
330+
var response403 = new Message({ status: 403 })
331331
var response404 = new Message({ status: 404 })
332332

333333
var $ctx
@@ -356,7 +356,7 @@ export default function ({ app, mesh }) {
356356
return response200
357357
} else {
358358
app.log(`Rejected inbound from ${peer.id} (user = ${peer.username}) for ${key}`)
359-
return response401
359+
return response403
360360
}
361361
}
362362
app.log(`No target found for ${key}`)

agent/apps/ztm/tunnel/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default function ({ app, mesh, utils }) {
1111
var response = utils.createResponse
1212
var responder = utils.createResponder
1313
var responderOwnerOnly = (f) => responder((params, req) => (
14-
$ctx.peer.username === app.username ? f(params, req) : Promise.resolve(response(401))
14+
$ctx.peer.username === app.username ? f(params, req) : Promise.resolve(response(403))
1515
))
1616

1717
var serveUser = utils.createServer({

0 commit comments

Comments
 (0)