@lamalibre/portlama-agent 1.0.23 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/lib/panel-server.js +33 -3
package/package.json
CHANGED
package/src/lib/panel-server.js
CHANGED
|
@@ -70,10 +70,11 @@ export async function startPanelServer(label, { port = 9393 } = {}) {
|
|
|
70
70
|
// Plugin bundles are intentionally public (loaded via <script> tag)
|
|
71
71
|
if (request.url.startsWith('/plugin-bundles/')) return;
|
|
72
72
|
|
|
73
|
-
// Auth is required for /api/* routes AND plugin
|
|
74
|
-
//
|
|
73
|
+
// Auth is required for /api/* management routes AND all plugin routes
|
|
74
|
+
// (/<pluginName>/..., including non-/api/ sub-paths). Static assets (SPA
|
|
75
|
+
// files served by fastify-static from root) don't need auth.
|
|
75
76
|
const needsAuth = request.url.startsWith('/api') ||
|
|
76
|
-
/^\/[a-z0-9-]
|
|
77
|
+
/^\/[a-z0-9-]+\//.test(request.url);
|
|
77
78
|
if (!needsAuth) return;
|
|
78
79
|
|
|
79
80
|
const verify = request.headers['x-ssl-client-verify'];
|
|
@@ -91,6 +92,35 @@ export async function startPanelServer(label, { port = 9393 } = {}) {
|
|
|
91
92
|
request.certRole = 'agent';
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
95
|
+
|
|
96
|
+
// Authelia-authenticated user (plugin tunnel access).
|
|
97
|
+
// When nginx routes through an Authelia-protected plugin vhost,
|
|
98
|
+
// Remote-User is set after successful Authelia forward auth. The header
|
|
99
|
+
// is cleared then re-injected by nginx — cannot be forged from outside.
|
|
100
|
+
// Port 9393 binds 127.0.0.1, so external traffic only arrives via nginx.
|
|
101
|
+
//
|
|
102
|
+
// Authelia users are restricted to plugin routes only (/{pluginName}/...).
|
|
103
|
+
// They must NOT access agent management API (/api/*) — those require
|
|
104
|
+
// mTLS (admin/agent cert) or localhost origin (desktop app).
|
|
105
|
+
const remoteUser = request.headers['remote-user'];
|
|
106
|
+
if (remoteUser) {
|
|
107
|
+
// Validate username format (defense-in-depth against header injection)
|
|
108
|
+
if (!/^[a-z0-9_.-]+$/i.test(remoteUser)) {
|
|
109
|
+
return reply.code(403).send({ error: 'Invalid user identity' });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Block access to /api/* management endpoints — Authelia users
|
|
113
|
+
// may only access plugin routes (/{pluginName}/api/...)
|
|
114
|
+
if (request.url.startsWith('/api')) {
|
|
115
|
+
return reply.code(403).send({ error: 'Management API requires certificate authentication' });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
request.certCN = `user:${remoteUser}`;
|
|
119
|
+
request.certRole = 'user';
|
|
120
|
+
request.autheliaUser = remoteUser;
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
94
124
|
return reply.code(403).send({ error: 'Valid mTLS certificate required' });
|
|
95
125
|
}
|
|
96
126
|
|