@lamalibre/create-lamaste 4.4.0 → 4.5.0
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 +2 -2
- package/scripts/lamaste-priv +200 -16
- package/src/index.js +1 -0
- package/src/lib/backend-cookie.js +65 -0
- package/src/lib/ip-panel-vhost.js +208 -0
- package/src/lib/service-config.js +5 -3
- package/src/tasks/nginx.js +18 -135
- package/src/tasks/redeploy.js +39 -1
- package/vendor/docs/00-introduction/how-it-works.md +2 -2
- package/vendor/docs/00-introduction/quickstart.md +5 -5
- package/vendor/docs/00-introduction/what-is-lamaste.md +5 -5
- package/vendor/docs/01-concepts/authentication.md +1 -1
- package/vendor/docs/01-concepts/authorization.md +66 -48
- package/vendor/docs/01-concepts/certificates.md +3 -3
- package/vendor/docs/01-concepts/mtls.md +2 -2
- package/vendor/docs/01-concepts/security-model.md +70 -33
- package/vendor/docs/01-concepts/tickets.md +2 -2
- package/vendor/docs/01-concepts/tunneling.md +4 -4
- package/vendor/docs/02-guides/agent-setup.md +5 -5
- package/vendor/docs/02-guides/certificate-management.md +2 -2
- package/vendor/docs/02-guides/cloud-provisioning.md +3 -3
- package/vendor/docs/02-guides/desktop-app-setup.md +10 -10
- package/vendor/docs/02-guides/installation.md +3 -3
- package/vendor/docs/02-guides/managing-users.md +113 -25
- package/vendor/docs/02-guides/onboarding.md +2 -2
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +2 -2
- package/vendor/docs/03-architecture/installer-flow.md +2 -2
- package/vendor/docs/03-architecture/installer.md +4 -4
- package/vendor/docs/03-architecture/management-flow.md +3 -1
- package/vendor/docs/03-architecture/nginx-configuration.md +165 -18
- package/vendor/docs/03-architecture/overview.md +13 -17
- package/vendor/docs/03-architecture/panel-client.md +6 -6
- package/vendor/docs/03-architecture/panel-server.md +3 -2
- package/vendor/docs/03-architecture/state-management.md +4 -8
- package/vendor/docs/03-architecture/system-overview.md +1 -1
- package/vendor/docs/04-api-reference/agent-hosted-plugins.md +292 -23
- package/vendor/docs/04-api-reference/app-host.md +3 -3
- package/vendor/docs/04-api-reference/gatekeeper.md +60 -5
- package/vendor/docs/04-api-reference/lifecycle-hooks.md +15 -13
- package/vendor/docs/04-api-reference/onboarding.md +1 -1
- package/vendor/docs/04-api-reference/registry-and-oidc.md +6 -4
- package/vendor/docs/04-api-reference/tunnels.md +67 -29
- package/vendor/docs/04-api-reference/users.md +241 -45
- package/vendor/docs/05-operations/backup-and-restore.md +35 -26
- package/vendor/docs/05-operations/monitoring.md +39 -0
- package/vendor/docs/05-operations/uninstalling.md +2 -1
- package/vendor/docs/05-operations/upgrades.md +15 -6
- package/vendor/docs/06-reference/config-files.md +83 -189
- package/vendor/docs/06-reference/glossary.md +3 -3
- package/vendor/docs/06-reference/installer-flags.md +13 -13
- package/vendor/docs/06-reference/ports-and-services.md +25 -26
- package/vendor/docs/06-reference/troubleshooting.md +8 -8
- package/vendor/docs/gatekeeper-design.md +10 -8
- package/vendor/docs/identity-directory-design.md +48 -14
- package/vendor/docs/package.json +1 -1
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +27 -27
- package/vendor/gatekeeper/dist/index.d.ts +2 -1
- package/vendor/gatekeeper/dist/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/index.js +2 -0
- package/vendor/gatekeeper/dist/index.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/grants.d.ts +6 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/grants.js +6 -1
- package/vendor/gatekeeper/dist/lib/grants.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/groups.d.ts +5 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/groups.js +5 -1
- package/vendor/gatekeeper/dist/lib/groups.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/principals.d.ts +29 -0
- package/vendor/gatekeeper/dist/lib/principals.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/principals.js +67 -0
- package/vendor/gatekeeper/dist/lib/principals.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/tunnels.d.ts +13 -0
- package/vendor/gatekeeper/dist/lib/tunnels.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/tunnels.js +68 -0
- package/vendor/gatekeeper/dist/lib/tunnels.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts +19 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.js +22 -48
- package/vendor/gatekeeper/dist/server/index.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts +15 -1
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.js +250 -103
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js +61 -4
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/principals.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/principals.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/principals.js +27 -0
- package/vendor/gatekeeper/dist/server/routes/principals.js.map +1 -0
- package/vendor/gatekeeper/package.json +2 -2
- package/vendor/server/bin/lamaste-server.js +15 -1
- package/vendor/server/package.json +2 -2
- package/vendor/server/src/commands/plugin-identity.js +335 -0
- package/vendor/server/src/commands/plugins.js +99 -11
- package/vendor/server/src/commands/registry-credential.js +2 -1
- package/vendor/server/src/commands/tunnels.js +102 -2
- package/vendor/server/src/commands/uninstall.js +3 -1
- package/vendor/server/src/commands/users.js +358 -0
- package/vendor/server/src/plugin-approval.js +107 -5
- package/vendor/server/src/plugin-identity.js +382 -0
- package/vendor/server-ui/dist/assets/index-D-fer5ef.css +1 -0
- package/vendor/server-ui/dist/assets/index-DSaDPJaw.js +84 -0
- package/vendor/server-ui/dist/index.html +2 -2
- package/vendor/serverd/package.json +2 -2
- package/vendor/serverd/src/index.js +25 -1
- package/vendor/serverd/src/lib/audience.js +576 -0
- package/vendor/serverd/src/lib/authelia.js +78 -7
- package/vendor/serverd/src/lib/config.js +68 -43
- package/vendor/serverd/src/lib/directory.js +1113 -0
- package/vendor/serverd/src/lib/entitlements.js +517 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +215 -10
- package/vendor/serverd/src/lib/hook-pipelines.js +13 -0
- package/vendor/serverd/src/lib/identity-sync.js +905 -0
- package/vendor/serverd/src/lib/migrations/state/0013_identity_directory.sql +158 -0
- package/vendor/serverd/src/lib/migrations/state/0014_identity_ledger.sql +20 -0
- package/vendor/serverd/src/lib/mtls.js +6 -2
- package/vendor/serverd/src/lib/nginx.js +279 -48
- package/vendor/serverd/src/lib/plugin-hooks.js +98 -45
- package/vendor/serverd/src/lib/plugin-hosting.js +33 -5
- package/vendor/serverd/src/lib/plugin-lifecycle.js +100 -9
- package/vendor/serverd/src/lib/plugin-packages.js +30 -22
- package/vendor/serverd/src/lib/plugins.js +94 -15
- package/vendor/serverd/src/lib/registry-credential.js +46 -6
- package/vendor/serverd/src/lib/request-logging.js +19 -0
- package/vendor/serverd/src/lib/retained-data.js +50 -4
- package/vendor/serverd/src/lib/state.js +18 -0
- package/vendor/serverd/src/lib/tunnel-hooks.js +4 -1
- package/vendor/serverd/src/lib/user-access-session.js +21 -11
- package/vendor/serverd/src/lib/user-caller.js +67 -0
- package/vendor/serverd/src/lib/user-surface.js +733 -0
- package/vendor/serverd/src/lib/vhost-reconcile.js +136 -34
- package/vendor/serverd/src/middleware/user-access-session.js +9 -0
- package/vendor/serverd/src/routes/agent-forwarder.js +4 -2
- package/vendor/serverd/src/routes/invite.js +53 -12
- package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +107 -16
- package/vendor/serverd/src/routes/management/identity-directory.js +79 -0
- package/vendor/serverd/src/routes/management/invitations.js +78 -68
- package/vendor/serverd/src/routes/management/plugin-identity.js +221 -0
- package/vendor/serverd/src/routes/management/registry-credential.js +1 -1
- package/vendor/serverd/src/routes/management/tunnels.js +98 -2
- package/vendor/serverd/src/routes/management/users.js +290 -208
- package/vendor/serverd/src/routes/management.js +4 -0
- package/vendor/serverd/src/routes/onboarding/provision.js +14 -1
- package/vendor/serverd/src/routes/user-access.js +17 -4
- package/vendor/serverd/src/routes/user-surface.js +69 -0
- package/vendor/server-ui/dist/assets/index-25wo_8av.css +0 -1
- package/vendor/server-ui/dist/assets/index-CESyyK8V.js +0 -84
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import { request as undiciRequest } from 'undici';
|
|
3
|
-
import { RELAY_ASSERTION_HEADER, signRelayAssertion } from '@lamalibre/lamaste';
|
|
3
|
+
import { AUTHELIA_SESSION_COOKIE, RELAY_ASSERTION_HEADER, RELAY_PANEL_AUDIENCE, RELAY_PANEL_PORT, autheliaSessionCookies, isUserSurfaceUrl, signRelayAssertion, } from '@lamalibre/lamaste';
|
|
4
4
|
import { AUTHELIA_VERIFY_URL, SESSION_CACHE_TTL_MS } from '../../lib/constants.js';
|
|
5
5
|
import { checkAccess } from '../../lib/authz.js';
|
|
6
6
|
import { buildAccessRequestPage } from '../../lib/templates.js';
|
|
@@ -17,35 +17,35 @@ const AUTHELIA_VERIFY_TIMEOUT_MS = 2_500;
|
|
|
17
17
|
* key and trigger collision-based attacks against cache-eviction logic.
|
|
18
18
|
*/
|
|
19
19
|
const COOKIE_HMAC_KEY = crypto.randomBytes(32);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
* future refactor caches negative results — let an unauthenticated request
|
|
29
|
-
* poison a downstream entry.
|
|
30
|
-
*/
|
|
31
|
-
function extractAutheliaCookie(cookie) {
|
|
32
|
-
const match = cookie.match(/(?:^|;\s*)authelia_session=([^;]*)/);
|
|
33
|
-
return match?.[1] ?? null;
|
|
20
|
+
function presentedSession(cookieHeader) {
|
|
21
|
+
// Every pair counts towards "more than one", an empty one too: a planted
|
|
22
|
+
// `authelia_session=` beside the real cookie is still a second cookie.
|
|
23
|
+
const values = autheliaSessionCookies(cookieHeader);
|
|
24
|
+
if (values.length > 1)
|
|
25
|
+
return { kind: 'many' };
|
|
26
|
+
const [value] = values;
|
|
27
|
+
return value ? { kind: 'one', value } : { kind: 'none' };
|
|
34
28
|
}
|
|
35
29
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
30
|
+
* The session cache key of a session cookie on one tunnel host —
|
|
31
|
+
* HMAC-SHA256 under a per-process random key, so keys are not predictable
|
|
32
|
+
* from cookie values, and nobody can probe or seed the cache. Keyed by the
|
|
33
|
+
* host too: Authelia decides per host (a site's or plugin tunnel's rules
|
|
34
|
+
* name users), so a session it accepted for one host proves nothing on
|
|
35
|
+
* another.
|
|
40
36
|
*/
|
|
41
|
-
function
|
|
42
|
-
return crypto
|
|
37
|
+
function sessionCacheKey(session, host) {
|
|
38
|
+
return crypto
|
|
39
|
+
.createHmac('sha256', COOKIE_HMAC_KEY)
|
|
40
|
+
.update(`${host.toLowerCase()}\n${session}`)
|
|
41
|
+
.digest('hex');
|
|
43
42
|
}
|
|
44
43
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* Ask Authelia's verify endpoint about one session cookie for one URL, and
|
|
45
|
+
* take the identity headers from its answer. Authelia is sent that cookie
|
|
46
|
+
* alone (`authelia_session=<value>`), never the browser's others.
|
|
47
47
|
*/
|
|
48
|
-
async function validateWithAuthelia(
|
|
48
|
+
async function validateWithAuthelia(session, originalUrl, requestId) {
|
|
49
49
|
try {
|
|
50
50
|
// Authelia's `/api/authz/auth-request` needs both the target URL and
|
|
51
51
|
// method — without `X-Original-Method` it assumes `GET`, which is fine
|
|
@@ -54,7 +54,7 @@ async function validateWithAuthelia(cookie, originalUrl, requestId) {
|
|
|
54
54
|
const { statusCode, headers } = await undiciRequest(AUTHELIA_VERIFY_URL, {
|
|
55
55
|
method: 'GET',
|
|
56
56
|
headers: {
|
|
57
|
-
Cookie:
|
|
57
|
+
Cookie: `${AUTHELIA_SESSION_COOKIE}=${session}`,
|
|
58
58
|
'X-Original-URL': originalUrl,
|
|
59
59
|
'X-Original-Method': 'GET',
|
|
60
60
|
'X-Forwarded-For': '127.0.0.1',
|
|
@@ -96,23 +96,47 @@ function findTunnelByFqdn(tunnels, fqdn) {
|
|
|
96
96
|
const wanted = fqdn.toLowerCase();
|
|
97
97
|
return tunnels.find((t) => t.fqdn.toLowerCase() === wanted);
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Why the hostnames a tunnel vhost writes into the subrequest's path,
|
|
101
|
+
* X-Original-URL and Host disagree, or null when they agree.
|
|
102
|
+
*/
|
|
103
|
+
function hostnameMismatch(request, fqdn, originalHost) {
|
|
104
|
+
const named = fqdn.toLowerCase();
|
|
105
|
+
const hostHeader = request.headers['host'] ?? '';
|
|
106
|
+
const hostOnly = hostHeader.split(':')[0]?.toLowerCase() ?? '';
|
|
107
|
+
if (originalHost.toLowerCase() === named && hostOnly === named)
|
|
108
|
+
return null;
|
|
109
|
+
return {
|
|
110
|
+
reason: hostOnly ? 'tunnel_name_mismatch' : 'missing_host_header',
|
|
111
|
+
originalHost,
|
|
112
|
+
hostHeader,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
99
115
|
/** A tunnel hostname as a vhost writes it into the subrequest's path. */
|
|
100
116
|
const TUNNEL_FQDN_RE = /^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$/;
|
|
101
117
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
118
|
+
* How many authorization subrequests one client may cause on one tunnel
|
|
119
|
+
* host per minute. nginx asks on every request a protected host serves — a
|
|
120
|
+
* page and its assets, an application's polling — so the bound is
|
|
121
|
+
* generous; what it stops is one client (a script hammering Authelia with
|
|
122
|
+
* made-up session cookies, each an Authelia round trip) starving the
|
|
123
|
+
* others.
|
|
108
124
|
*/
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
125
|
+
export const AUTHZ_RATE_LIMIT_PER_CLIENT = 6_000;
|
|
126
|
+
/**
|
|
127
|
+
* The bucket of an authorization subrequest: the client's address and the
|
|
128
|
+
* tunnel host. nginx is the only client of these routes (Gatekeeper binds
|
|
129
|
+
* 127.0.0.1) and sets `X-Forwarded-For` to `$remote_addr` on every
|
|
130
|
+
* subrequest; Gatekeeper trusts that header from 127.0.0.1 only
|
|
131
|
+
* (`trustProxy` in `server/index.ts`), so `request.ip` is the address nginx
|
|
132
|
+
* accepted the browser's connection from — never one the browser named.
|
|
133
|
+
* The host is the tunnel the vhost names in the path (or its `Host`).
|
|
134
|
+
*/
|
|
135
|
+
function authzRateLimitKey(request) {
|
|
136
|
+
const fqdn = request.params?.fqdn;
|
|
137
|
+
const host = typeof fqdn === 'string' ? fqdn : (request.headers['host'] ?? '');
|
|
138
|
+
return `${request.ip}|${host.toLowerCase()}`;
|
|
139
|
+
}
|
|
116
140
|
/**
|
|
117
141
|
* Parse an X-Original-URL header into its hostname and host components.
|
|
118
142
|
* Returns null when the value is not a parseable absolute URL.
|
|
@@ -129,7 +153,14 @@ function parseOriginalUrl(originalUrl) {
|
|
|
129
153
|
// ---------------------------------------------------------------------------
|
|
130
154
|
// Route plugin
|
|
131
155
|
// ---------------------------------------------------------------------------
|
|
132
|
-
export async function authzRoutes(fastify) {
|
|
156
|
+
export async function authzRoutes(fastify, opts = {}) {
|
|
157
|
+
const authzRateLimit = {
|
|
158
|
+
rateLimit: {
|
|
159
|
+
max: opts.rateLimitPerClient ?? AUTHZ_RATE_LIMIT_PER_CLIENT,
|
|
160
|
+
timeWindow: '1 minute',
|
|
161
|
+
keyGenerator: authzRateLimitKey,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
133
164
|
/**
|
|
134
165
|
* GET /authz/tunnel/:fqdn — the nginx auth_request target of a tunnel vhost
|
|
135
166
|
*
|
|
@@ -149,7 +180,33 @@ export async function authzRoutes(fastify) {
|
|
|
149
180
|
* On 403, the response body is the full access-request HTML page
|
|
150
181
|
* (nginx serves this inline on the tunnel's FQDN via error_page 403 =).
|
|
151
182
|
*/
|
|
152
|
-
fastify.get('/authz/tunnel/:fqdn', { config:
|
|
183
|
+
fastify.get('/authz/tunnel/:fqdn', { config: authzRateLimit }, async (request, reply) => authorizeTunnelRequest(fastify, request, reply, request.params.fqdn));
|
|
184
|
+
/**
|
|
185
|
+
* GET /authz/user-surface/:fqdn — the nginx auth_request target of a
|
|
186
|
+
* plugin's user surface: `/api/<route>/app` and everything under it, on
|
|
187
|
+
* the host of a tunnel bound to the plugin (`userSurface` in
|
|
188
|
+
* tunnels.json). The vhost names the tunnel as for `/authz/tunnel/:fqdn`.
|
|
189
|
+
*
|
|
190
|
+
* Gatekeeper authenticates the session — on a restricted tunnel it checks
|
|
191
|
+
* the user's grant too — and vouches for its user to the panel: a relay
|
|
192
|
+
* assertion for the panel's audience and port, naming the username alone
|
|
193
|
+
* and bound to the method and the raw request target, which must lie on
|
|
194
|
+
* the user surface of a route bound to this tunnel. The panel takes
|
|
195
|
+
* everything else about the user from its own directory.
|
|
196
|
+
*
|
|
197
|
+
* 200 with the assertion (never cacheable, no `Remote-*`), 401 without a
|
|
198
|
+
* session (nginx answers with `/authz/user-surface-unauthenticated`), 403
|
|
199
|
+
* for anything else refused — never the access-request page, never a
|
|
200
|
+
* redirect: the caller is an application's request. 503 while the relay
|
|
201
|
+
* signing key is unusable.
|
|
202
|
+
*/
|
|
203
|
+
fastify.get('/authz/user-surface/:fqdn', { config: authzRateLimit }, async (request, reply) => authorizeUserSurfaceRequest(fastify, request, reply, request.params.fqdn));
|
|
204
|
+
/**
|
|
205
|
+
* GET /authz/user-surface-unauthenticated — what a user-surface request
|
|
206
|
+
* without a session is answered with (nginx `error_page 401`): JSON, so
|
|
207
|
+
* the application can tell its user to sign in again; never a redirect.
|
|
208
|
+
*/
|
|
209
|
+
fastify.get('/authz/user-surface-unauthenticated', { config: authzRateLimit }, async (_request, reply) => reply.code(401).header('Cache-Control', 'no-store').send({ error: 'unauthenticated' }));
|
|
153
210
|
/**
|
|
154
211
|
* GET /authz/check — what tunnel vhosts written before 4.3 call. They name
|
|
155
212
|
* the tunnel by the client's Host header (`$http_host`), which an
|
|
@@ -158,7 +215,7 @@ export async function authzRoutes(fastify) {
|
|
|
158
215
|
* such a vhost (it does when it starts) its tunnel is closed, rather than
|
|
159
216
|
* open to the users of every other tunnel.
|
|
160
217
|
*/
|
|
161
|
-
fastify.get('/authz/check', { config:
|
|
218
|
+
fastify.get('/authz/check', { config: authzRateLimit }, async (request, reply) => {
|
|
162
219
|
request.log.error({
|
|
163
220
|
requestId: request.id,
|
|
164
221
|
reason: 'vhost_predates_host_binding',
|
|
@@ -171,6 +228,51 @@ export async function authzRoutes(fastify) {
|
|
|
171
228
|
.send('This tunnel is unavailable until the relay rewrites its configuration.\n');
|
|
172
229
|
});
|
|
173
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* The Authelia session behind the request's `authelia_session` cookie, or
|
|
233
|
+
* null: none, more than one (refused — see {@link presentedSession}), or
|
|
234
|
+
* Authelia refused it. The session cache — one shared by every route here
|
|
235
|
+
* — is keyed by that cookie's value and the tunnel host, so unrelated
|
|
236
|
+
* cookies (CSRF tokens, analytics) cannot pollute it, and a session Authelia
|
|
237
|
+
* accepted on one host is never taken for another.
|
|
238
|
+
*/
|
|
239
|
+
async function authenticatedSession(fastify, request, cookieHeader, originalUrl, hostname) {
|
|
240
|
+
const requestId = request.id;
|
|
241
|
+
const presented = presentedSession(cookieHeader);
|
|
242
|
+
if (presented.kind !== 'one') {
|
|
243
|
+
// Short-circuit before any cache work or the upstream Authelia /verify
|
|
244
|
+
// call: an unauthenticated request costs no Authelia round-trip.
|
|
245
|
+
request.log.info({
|
|
246
|
+
requestId,
|
|
247
|
+
reason: presented.kind === 'none' ? 'missing_authelia_cookie' : 'duplicate_authelia_cookie',
|
|
248
|
+
fqdn: hostname,
|
|
249
|
+
}, 'authz denied');
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
const cacheKey = sessionCacheKey(presented.value, hostname);
|
|
253
|
+
const sessionCache = fastify.getSessionCache();
|
|
254
|
+
const cached = sessionCache.get(cacheKey);
|
|
255
|
+
if (cached && cached.expiresAt > Date.now())
|
|
256
|
+
return cached;
|
|
257
|
+
if (cached) {
|
|
258
|
+
// Lazy TTL eviction — one stale entry pruned per request.
|
|
259
|
+
sessionCache.delete(cacheKey);
|
|
260
|
+
}
|
|
261
|
+
const validated = await validateWithAuthelia(presented.value, originalUrl, requestId);
|
|
262
|
+
if (!validated) {
|
|
263
|
+
request.log.info({ requestId, reason: 'authelia_rejected', fqdn: hostname }, 'authz denied');
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
// Opportunistic eviction — drop oldest (insertion-order head) when at cap.
|
|
267
|
+
while (sessionCache.size >= MAX_SESSION_CACHE_ENTRIES) {
|
|
268
|
+
const oldestKey = sessionCache.keys().next().value;
|
|
269
|
+
if (oldestKey === undefined)
|
|
270
|
+
break;
|
|
271
|
+
sessionCache.delete(oldestKey);
|
|
272
|
+
}
|
|
273
|
+
sessionCache.set(cacheKey, validated);
|
|
274
|
+
return validated;
|
|
275
|
+
}
|
|
174
276
|
/**
|
|
175
277
|
* Authorize one request on the tunnel named `fqdn` (see the
|
|
176
278
|
* `/authz/tunnel/:fqdn` route).
|
|
@@ -181,7 +283,7 @@ async function authorizeTunnelRequest(fastify, request, reply, fqdn) {
|
|
|
181
283
|
request.log.info({ requestId, reason: 'invalid_tunnel_name' }, 'authz denied');
|
|
182
284
|
return reply.code(401).send();
|
|
183
285
|
}
|
|
184
|
-
const cookie = request.headers['cookie']
|
|
286
|
+
const cookie = request.headers['cookie'];
|
|
185
287
|
const originalUrl = request.headers['x-original-url'] ?? '';
|
|
186
288
|
if (!cookie || !originalUrl) {
|
|
187
289
|
return reply.code(401).send();
|
|
@@ -191,20 +293,12 @@ async function authorizeTunnelRequest(fastify, request, reply, fqdn) {
|
|
|
191
293
|
request.log.info({ requestId, reason: 'invalid_original_url' }, 'authz denied');
|
|
192
294
|
return reply.code(401).send();
|
|
193
295
|
}
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (parsed.hostname.toLowerCase() !== named || hostOnly !== named) {
|
|
201
|
-
request.log.info({
|
|
202
|
-
requestId,
|
|
203
|
-
reason: hostOnly ? 'tunnel_name_mismatch' : 'missing_host_header',
|
|
204
|
-
tunnel: fqdn,
|
|
205
|
-
originalHost: parsed.hostname,
|
|
206
|
-
hostHeader,
|
|
207
|
-
}, 'authz denied');
|
|
296
|
+
// Disagreement means a request that did not come from a tunnel vhost of
|
|
297
|
+
// this version: refuse it before Authelia is asked anything.
|
|
298
|
+
const mismatch = hostnameMismatch(request, fqdn, parsed.hostname);
|
|
299
|
+
if (mismatch) {
|
|
300
|
+
const { reason, ...detail } = mismatch;
|
|
301
|
+
request.log.info({ requestId, reason, tunnel: fqdn, ...detail }, 'authz denied');
|
|
208
302
|
return reply.code(401).send();
|
|
209
303
|
}
|
|
210
304
|
const tunnels = fastify.getTunnels();
|
|
@@ -213,44 +307,9 @@ async function authorizeTunnelRequest(fastify, request, reply, fqdn) {
|
|
|
213
307
|
request.log.info({ requestId, reason: 'unknown_tunnel_fqdn', fqdn }, 'authz denied');
|
|
214
308
|
return reply.code(401).send();
|
|
215
309
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const autheliaCookie = extractAutheliaCookie(cookie);
|
|
219
|
-
if (!autheliaCookie) {
|
|
220
|
-
// No authelia_session — short-circuit before any cache work or the
|
|
221
|
-
// upstream Authelia /verify call. Without this, an unauthenticated
|
|
222
|
-
// request would still cost us an Authelia round-trip.
|
|
223
|
-
request.log.info({ requestId, reason: 'missing_authelia_cookie', fqdn: parsed.hostname }, 'authz denied');
|
|
310
|
+
const session = await authenticatedSession(fastify, request, cookie, originalUrl, parsed.hostname);
|
|
311
|
+
if (!session)
|
|
224
312
|
return reply.code(401).send();
|
|
225
|
-
}
|
|
226
|
-
const cacheKey = hashCookie(autheliaCookie);
|
|
227
|
-
const sessionCache = fastify.getSessionCache();
|
|
228
|
-
const cached = sessionCache.get(cacheKey);
|
|
229
|
-
const now = Date.now();
|
|
230
|
-
let session;
|
|
231
|
-
if (cached && cached.expiresAt > now) {
|
|
232
|
-
session = cached;
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
if (cached) {
|
|
236
|
-
// Lazy TTL eviction — one stale entry pruned per request.
|
|
237
|
-
sessionCache.delete(cacheKey);
|
|
238
|
-
}
|
|
239
|
-
const validated = await validateWithAuthelia(cookie, originalUrl, requestId);
|
|
240
|
-
if (!validated) {
|
|
241
|
-
request.log.info({ requestId, reason: 'authelia_rejected', fqdn: parsed.hostname }, 'authz denied');
|
|
242
|
-
return reply.code(401).send();
|
|
243
|
-
}
|
|
244
|
-
// Opportunistic eviction — drop oldest (insertion-order head) when at cap.
|
|
245
|
-
while (sessionCache.size >= MAX_SESSION_CACHE_ENTRIES) {
|
|
246
|
-
const oldestKey = sessionCache.keys().next().value;
|
|
247
|
-
if (oldestKey === undefined)
|
|
248
|
-
break;
|
|
249
|
-
sessionCache.delete(oldestKey);
|
|
250
|
-
}
|
|
251
|
-
sessionCache.set(cacheKey, validated);
|
|
252
|
-
session = validated;
|
|
253
|
-
}
|
|
254
313
|
// Check access mode
|
|
255
314
|
if (tunnel.accessMode === 'public' || tunnel.accessMode === 'authenticated') {
|
|
256
315
|
return allow(fastify, request, reply, tunnel, session);
|
|
@@ -263,14 +322,13 @@ async function authorizeTunnelRequest(fastify, request, reply, fqdn) {
|
|
|
263
322
|
if (result.allowed) {
|
|
264
323
|
return allow(fastify, request, reply, tunnel, session);
|
|
265
324
|
}
|
|
325
|
+
// The tunnel and the reason only — never who was refused.
|
|
266
326
|
request.log.info({
|
|
267
327
|
requestId,
|
|
268
328
|
reason: 'no_matching_grant',
|
|
269
|
-
|
|
329
|
+
tunnel: fqdn,
|
|
270
330
|
resourceType: 'tunnel',
|
|
271
331
|
resourceId: tunnel.id,
|
|
272
|
-
requiredGrant: `tunnel:${tunnel.id}`,
|
|
273
|
-
fqdn: parsed.hostname,
|
|
274
332
|
}, 'authz denied');
|
|
275
333
|
if (fastify.getSettings().accessLoggingEnabled) {
|
|
276
334
|
logAccessRequest({
|
|
@@ -294,6 +352,101 @@ async function authorizeTunnelRequest(fastify, request, reply, fqdn) {
|
|
|
294
352
|
.type('text/html; charset=utf-8')
|
|
295
353
|
.send(html);
|
|
296
354
|
}
|
|
355
|
+
/**
|
|
356
|
+
* Authorize one request on the user surface of the tunnel named `fqdn` (see
|
|
357
|
+
* the `/authz/user-surface/:fqdn` route).
|
|
358
|
+
*/
|
|
359
|
+
async function authorizeUserSurfaceRequest(fastify, request, reply, fqdn) {
|
|
360
|
+
const requestId = request.id;
|
|
361
|
+
// Single use: nothing of this answer may be cached, a refusal included.
|
|
362
|
+
reply.header('Cache-Control', 'no-store');
|
|
363
|
+
const refuse = (reason, extra = {}) => {
|
|
364
|
+
request.log.info({ requestId, reason, tunnel: fqdn, ...extra }, 'user-surface authz denied');
|
|
365
|
+
return reply.code(403).send();
|
|
366
|
+
};
|
|
367
|
+
if (!TUNNEL_FQDN_RE.test(fqdn))
|
|
368
|
+
return refuse('invalid_tunnel_name');
|
|
369
|
+
const originalUrl = request.headers['x-original-url'];
|
|
370
|
+
const originalMethod = request.headers['x-original-method'];
|
|
371
|
+
if (typeof originalUrl !== 'string' || typeof originalMethod !== 'string') {
|
|
372
|
+
return refuse('missing_original_request');
|
|
373
|
+
}
|
|
374
|
+
const parsed = parseOriginalUrl(originalUrl);
|
|
375
|
+
if (!parsed)
|
|
376
|
+
return refuse('invalid_original_url');
|
|
377
|
+
const mismatch = hostnameMismatch(request, fqdn, parsed.hostname);
|
|
378
|
+
if (mismatch) {
|
|
379
|
+
const { reason, ...detail } = mismatch;
|
|
380
|
+
return refuse(reason, detail);
|
|
381
|
+
}
|
|
382
|
+
const tunnel = findTunnelByFqdn(fastify.getTunnels(), fqdn);
|
|
383
|
+
if (!tunnel)
|
|
384
|
+
return refuse('unknown_tunnel_fqdn');
|
|
385
|
+
if (!tunnel.enabled)
|
|
386
|
+
return refuse('tunnel_disabled');
|
|
387
|
+
if (tunnel.accessMode === 'public' || !tunnel.userSurface)
|
|
388
|
+
return refuse('no_user_surface');
|
|
389
|
+
// The request target exactly as the browser sent it — what follows the
|
|
390
|
+
// hostname the vhost wrote — never re-encoded by a URL parser: the panel
|
|
391
|
+
// receives it unchanged and holds the assertion against it byte for byte.
|
|
392
|
+
const prefix = `https://${fqdn.toLowerCase()}`;
|
|
393
|
+
if (originalUrl.slice(0, prefix.length).toLowerCase() !== prefix) {
|
|
394
|
+
return refuse('invalid_original_url');
|
|
395
|
+
}
|
|
396
|
+
const target = originalUrl.slice(prefix.length);
|
|
397
|
+
const route = tunnel.userSurface.routes.find((r) => isUserSurfaceUrl(target, r));
|
|
398
|
+
if (!route)
|
|
399
|
+
return refuse('not_on_user_surface');
|
|
400
|
+
// Bound, but its plugin is not hosted by the agent carrying this tunnel
|
|
401
|
+
// (moved, revoked, hosted elsewhere): nothing of it is served here.
|
|
402
|
+
if (!tunnel.userSurface.served.includes(route))
|
|
403
|
+
return refuse('not_hosting_agent', { route });
|
|
404
|
+
const session = await authenticatedSession(fastify, request, request.headers['cookie'], originalUrl, parsed.hostname);
|
|
405
|
+
if (!session)
|
|
406
|
+
return reply.code(401).send();
|
|
407
|
+
if (tunnel.accessMode !== 'authenticated') {
|
|
408
|
+
// restricted — the user's grant for the tunnel, as on its other paths
|
|
409
|
+
const result = await checkAccess(session.username, 'tunnel', tunnel.id, {
|
|
410
|
+
adminContact: fastify.getSettings().adminEmail,
|
|
411
|
+
adminName: fastify.getSettings().adminName,
|
|
412
|
+
});
|
|
413
|
+
if (!result.allowed) {
|
|
414
|
+
// The tunnel and the reason only — never who was refused.
|
|
415
|
+
return refuse('no_matching_grant', { resourceType: 'tunnel', resourceId: tunnel.id });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
const key = await currentRelayKey(fastify, request);
|
|
419
|
+
if (!key) {
|
|
420
|
+
request.log.error({ requestId, reason: 'relay_signing_key_unavailable', tunnel: fqdn }, 'user-surface authz failed');
|
|
421
|
+
return reply.code(503).send();
|
|
422
|
+
}
|
|
423
|
+
let assertion;
|
|
424
|
+
try {
|
|
425
|
+
assertion = signRelayAssertion({
|
|
426
|
+
aud: RELAY_PANEL_AUDIENCE,
|
|
427
|
+
port: RELAY_PANEL_PORT,
|
|
428
|
+
caller: { type: 'user', username: session.username },
|
|
429
|
+
method: originalMethod,
|
|
430
|
+
target: { route, path: target },
|
|
431
|
+
}, key);
|
|
432
|
+
}
|
|
433
|
+
catch (err) {
|
|
434
|
+
// A username, method or target an assertion cannot carry.
|
|
435
|
+
return refuse('not_assertable', { detail: err instanceof Error ? err.message : String(err) });
|
|
436
|
+
}
|
|
437
|
+
reply.header(RELAY_ASSERTION_HEADER, assertion);
|
|
438
|
+
return reply.code(200).send();
|
|
439
|
+
}
|
|
440
|
+
/** The relay signing key, or null when there is none or it is unusable (logged). */
|
|
441
|
+
async function currentRelayKey(fastify, request) {
|
|
442
|
+
try {
|
|
443
|
+
return await fastify.getRelaySigner().current();
|
|
444
|
+
}
|
|
445
|
+
catch (err) {
|
|
446
|
+
request.log.error({ err: err instanceof Error ? err.message : String(err) }, 'Relay signing key unusable');
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
297
450
|
/**
|
|
298
451
|
* Answer an allowed request: the Authelia identity headers nginx forwards
|
|
299
452
|
* to the tunnel backend.
|
|
@@ -312,13 +465,7 @@ async function allow(fastify, request, reply, tunnel, session) {
|
|
|
312
465
|
return reply.code(200).send();
|
|
313
466
|
}
|
|
314
467
|
reply.header('Cache-Control', 'no-store');
|
|
315
|
-
|
|
316
|
-
try {
|
|
317
|
-
key = await fastify.getRelaySigner().current();
|
|
318
|
-
}
|
|
319
|
-
catch (err) {
|
|
320
|
-
request.log.error({ err: err instanceof Error ? err.message : String(err) }, 'Relay signing key unusable');
|
|
321
|
-
}
|
|
468
|
+
const key = await currentRelayKey(fastify, request);
|
|
322
469
|
if (!key) {
|
|
323
470
|
request.log.error({ requestId: request.id, reason: 'relay_signing_key_unavailable', fqdn: tunnel.fqdn }, 'authz failed');
|
|
324
471
|
return reply.code(503).send();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz.js","sourceRoot":"","sources":["../../../src/server/routes/authz.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"authz.js","sourceRoot":"","sources":["../../../src/server/routes/authz.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostic.d.ts","sourceRoot":"","sources":["../../../src/server/routes/diagnostic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAO7E,OAAO,KAAK,EAAsB,kBAAkB,EAAoB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnostic.d.ts","sourceRoot":"","sources":["../../../src/server/routes/diagnostic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAO7E,OAAO,KAAK,EAAsB,kBAAkB,EAAoB,MAAM,oBAAoB,CAAC;AAiNnG,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAyI9E;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAEhE"}
|
|
@@ -15,6 +15,20 @@ const DEFAULT_RETENTION_DAYS = 90;
|
|
|
15
15
|
// JSON-era rotation cadence loosely and is comfortably below any sensible
|
|
16
16
|
// retention setting.
|
|
17
17
|
const RETENTION_SWEEP_INTERVAL_MS = 60 * 60 * 1000;
|
|
18
|
+
/**
|
|
19
|
+
* `POST /api/access-log/purge { username, before? }`: the rows of one
|
|
20
|
+
* username, before a time when given. The username travels in the body —
|
|
21
|
+
* a URL is what request logs keep.
|
|
22
|
+
*/
|
|
23
|
+
const PurgeBodySchema = z
|
|
24
|
+
.object({
|
|
25
|
+
username: z.string().min(1).max(100),
|
|
26
|
+
before: z
|
|
27
|
+
.string()
|
|
28
|
+
.regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z$/, 'before is an ISO 8601 UTC time')
|
|
29
|
+
.optional(),
|
|
30
|
+
})
|
|
31
|
+
.strict();
|
|
18
32
|
const UpdateSettingsSchema = z.object({
|
|
19
33
|
adminEmail: z.string().email().max(200).optional(),
|
|
20
34
|
adminName: z.string().max(200).optional(),
|
|
@@ -41,6 +55,11 @@ async function getStmts() {
|
|
|
41
55
|
countAll: db.prepare('SELECT COUNT(*) AS n FROM access_request_log'),
|
|
42
56
|
deleteAll: db.prepare('DELETE FROM access_request_log'),
|
|
43
57
|
deleteOlderThan: db.prepare('DELETE FROM access_request_log WHERE timestamp < ?'),
|
|
58
|
+
// Erasing a removed user (the panel): their rows only — those logged
|
|
59
|
+
// before they were removed, when the panel says when that was (a later
|
|
60
|
+
// user may have the same username).
|
|
61
|
+
deleteByUsername: db.prepare('DELETE FROM access_request_log WHERE username = ?'),
|
|
62
|
+
deleteByUsernameBefore: db.prepare('DELETE FROM access_request_log WHERE username = ? AND timestamp < ?'),
|
|
44
63
|
begin: db.prepare('BEGIN IMMEDIATE'),
|
|
45
64
|
commit: db.prepare('COMMIT'),
|
|
46
65
|
rollback: db.prepare('ROLLBACK'),
|
|
@@ -223,12 +242,50 @@ export async function diagnosticRoutes(fastify) {
|
|
|
223
242
|
return reply.code(500).send({ error: err.message });
|
|
224
243
|
}
|
|
225
244
|
});
|
|
226
|
-
// DELETE /api/access-log — clear access request log
|
|
227
|
-
|
|
245
|
+
// DELETE /api/access-log — clear the whole access request log (and the
|
|
246
|
+
// entries still queued for it). It takes no query: a purge of one user's
|
|
247
|
+
// rows is POST /api/access-log/purge, and a query an older caller sent to
|
|
248
|
+
// narrow the purge must never clear everything instead. Answers how many
|
|
249
|
+
// rows went (`removed`).
|
|
250
|
+
fastify.delete('/access-log', async (request, reply) => {
|
|
251
|
+
if (Object.keys(request.query ?? {}).length > 0) {
|
|
252
|
+
return reply.code(400).send({
|
|
253
|
+
error: "DELETE clears the whole log and takes no query — purge one user's rows with POST /api/access-log/purge",
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
const s = await getStmts();
|
|
258
|
+
logQueue = [];
|
|
259
|
+
const result = s.deleteAll.run();
|
|
260
|
+
return { ok: true, removed: Number(result.changes) };
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
return reply.code(500).send({ error: err.message });
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
// POST /api/access-log/purge { username, before? } — one user's rows,
|
|
267
|
+
// logged before `before` when given (a later user may hold the username),
|
|
268
|
+
// and the matching entries still queued for the log, so none of them is
|
|
269
|
+
// written after the purge. Answers how many rows went (`removed`).
|
|
270
|
+
fastify.post('/access-log/purge', async (request, reply) => {
|
|
271
|
+
const parsed = PurgeBodySchema.safeParse(request.body ?? {});
|
|
272
|
+
if (!parsed.success) {
|
|
273
|
+
return reply.code(400).send({
|
|
274
|
+
error: 'Invalid body',
|
|
275
|
+
details: parsed.error.issues.map((i) => i.message),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
const { username, before } = parsed.data;
|
|
228
279
|
try {
|
|
229
280
|
const s = await getStmts();
|
|
230
|
-
|
|
231
|
-
|
|
281
|
+
const matches = (e) => e.username === username && (before === undefined || e.timestamp < before);
|
|
282
|
+
const kept = logQueue.filter((e) => !matches(e));
|
|
283
|
+
const queued = logQueue.length - kept.length;
|
|
284
|
+
logQueue = kept;
|
|
285
|
+
const result = before === undefined
|
|
286
|
+
? s.deleteByUsername.run(username)
|
|
287
|
+
: s.deleteByUsernameBefore.run(username, before);
|
|
288
|
+
return { ok: true, removed: Number(result.changes) + queued };
|
|
232
289
|
}
|
|
233
290
|
catch (err) {
|
|
234
291
|
return reply.code(500).send({ error: err.message });
|