@lamalibre/create-lamaste 4.0.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/LICENSE.md +118 -0
- package/README.md +114 -0
- package/bin/create-lamaste.js +15 -0
- package/package.json +54 -0
- package/scripts/bundle-vendor.js +110 -0
- package/scripts/lamaste-cert-info +62 -0
- package/scripts/lamaste-certbot +96 -0
- package/scripts/lamaste-priv +693 -0
- package/src/index.js +646 -0
- package/src/lib/accounts.js +86 -0
- package/src/lib/binaries.js +137 -0
- package/src/lib/cert-help-page.js +160 -0
- package/src/lib/env.js +132 -0
- package/src/lib/http-redirect.js +38 -0
- package/src/lib/ownership.js +231 -0
- package/src/lib/relay-services.js +103 -0
- package/src/lib/secrets.js +19 -0
- package/src/lib/service-config.js +311 -0
- package/src/lib/summary.js +131 -0
- package/src/lib/wrappers.js +63 -0
- package/src/tasks/gatekeeper.js +233 -0
- package/src/tasks/harden.js +293 -0
- package/src/tasks/mtls.js +193 -0
- package/src/tasks/nginx.js +265 -0
- package/src/tasks/node.js +110 -0
- package/src/tasks/panel.js +408 -0
- package/src/tasks/redeploy.js +438 -0
- package/vendor/docs/00-introduction/how-it-works.md +447 -0
- package/vendor/docs/00-introduction/quickstart.md +472 -0
- package/vendor/docs/00-introduction/what-is-lamaste.md +112 -0
- package/vendor/docs/01-concepts/authentication.md +464 -0
- package/vendor/docs/01-concepts/authorization.md +242 -0
- package/vendor/docs/01-concepts/certificates.md +452 -0
- package/vendor/docs/01-concepts/dns-and-domains.md +343 -0
- package/vendor/docs/01-concepts/mtls.md +490 -0
- package/vendor/docs/01-concepts/nginx-reverse-proxy.md +540 -0
- package/vendor/docs/01-concepts/security-model.md +600 -0
- package/vendor/docs/01-concepts/tickets.md +414 -0
- package/vendor/docs/01-concepts/tunneling.md +367 -0
- package/vendor/docs/02-guides/agent-setup.md +194 -0
- package/vendor/docs/02-guides/certificate-management.md +341 -0
- package/vendor/docs/02-guides/cloud-provisioning.md +406 -0
- package/vendor/docs/02-guides/desktop-app-setup.md +226 -0
- package/vendor/docs/02-guides/disaster-recovery.md +464 -0
- package/vendor/docs/02-guides/first-tunnel.md +230 -0
- package/vendor/docs/02-guides/installation.md +393 -0
- package/vendor/docs/02-guides/managing-users.md +255 -0
- package/vendor/docs/02-guides/onboarding.md +244 -0
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +375 -0
- package/vendor/docs/02-guides/static-sites.md +364 -0
- package/vendor/docs/03-architecture/e2e-three-vm-sequences.md +457 -0
- package/vendor/docs/03-architecture/installer-flow.md +151 -0
- package/vendor/docs/03-architecture/installer.md +445 -0
- package/vendor/docs/03-architecture/management-flow.md +288 -0
- package/vendor/docs/03-architecture/nginx-configuration.md +830 -0
- package/vendor/docs/03-architecture/onboarding-flow.md +164 -0
- package/vendor/docs/03-architecture/overview.md +541 -0
- package/vendor/docs/03-architecture/panel-client.md +416 -0
- package/vendor/docs/03-architecture/panel-server.md +695 -0
- package/vendor/docs/03-architecture/state-management.md +529 -0
- package/vendor/docs/03-architecture/system-overview.md +167 -0
- package/vendor/docs/04-api-reference/certificates.md +1141 -0
- package/vendor/docs/04-api-reference/gatekeeper.md +592 -0
- package/vendor/docs/04-api-reference/onboarding.md +473 -0
- package/vendor/docs/04-api-reference/overview.md +404 -0
- package/vendor/docs/04-api-reference/services.md +267 -0
- package/vendor/docs/04-api-reference/settings.md +343 -0
- package/vendor/docs/04-api-reference/sites.md +716 -0
- package/vendor/docs/04-api-reference/system.md +268 -0
- package/vendor/docs/04-api-reference/tickets.md +618 -0
- package/vendor/docs/04-api-reference/tunnels.md +417 -0
- package/vendor/docs/04-api-reference/users.md +333 -0
- package/vendor/docs/05-operations/backup-and-restore.md +342 -0
- package/vendor/docs/05-operations/monitoring.md +285 -0
- package/vendor/docs/05-operations/uninstalling.md +344 -0
- package/vendor/docs/05-operations/upgrades.md +270 -0
- package/vendor/docs/06-reference/config-files.md +1080 -0
- package/vendor/docs/06-reference/glossary.md +528 -0
- package/vendor/docs/06-reference/installer-flags.md +260 -0
- package/vendor/docs/06-reference/ports-and-services.md +244 -0
- package/vendor/docs/06-reference/troubleshooting.md +665 -0
- package/vendor/docs/_index.json +233 -0
- package/vendor/docs/gatekeeper-design.md +953 -0
- package/vendor/docs/package.json +15 -0
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +641 -0
- package/vendor/gatekeeper/dist/boot.d.ts +1 -0
- package/vendor/gatekeeper/dist/boot.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/boot.js +17 -0
- package/vendor/gatekeeper/dist/boot.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js +33 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js +110 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js +98 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts +3 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.js +45 -0
- package/vendor/gatekeeper/dist/cli/index.js.map +1 -0
- package/vendor/gatekeeper/dist/index.d.ts +9 -0
- package/vendor/gatekeeper/dist/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/index.js +13 -0
- package/vendor/gatekeeper/dist/index.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.js +42 -0
- package/vendor/gatekeeper/dist/lib/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts +15 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js +19 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts +82 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.js +79 -0
- package/vendor/gatekeeper/dist/lib/constants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts +32 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.js +314 -0
- package/vendor/gatekeeper/dist/lib/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts +10 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.js +247 -0
- package/vendor/gatekeeper/dist/lib/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts +17 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.js +79 -0
- package/vendor/gatekeeper/dist/lib/migration.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/state-db.js +154 -0
- package/vendor/gatekeeper/dist/lib/state-db.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts +21 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.js +151 -0
- package/vendor/gatekeeper/dist/lib/templates.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts +178 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.js +2 -0
- package/vendor/gatekeeper/dist/lib/types.js.map +1 -0
- package/vendor/gatekeeper/dist/server/index.d.ts +15 -0
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/index.js +251 -0
- package/vendor/gatekeeper/dist/server/index.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts +7 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js +17 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js +279 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts +13 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js +249 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js +112 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js +139 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js.map +1 -0
- package/vendor/gatekeeper/package.json +49 -0
- package/vendor/server/bin/lamaste-server.js +204 -0
- package/vendor/server/package.json +31 -0
- package/vendor/server/src/commands/certs.js +224 -0
- package/vendor/server/src/commands/chisel.js +132 -0
- package/vendor/server/src/commands/logs.js +49 -0
- package/vendor/server/src/commands/plugins.js +321 -0
- package/vendor/server/src/commands/reset-admin.js +478 -0
- package/vendor/server/src/commands/restart.js +94 -0
- package/vendor/server/src/commands/sites.js +257 -0
- package/vendor/server/src/commands/status.js +158 -0
- package/vendor/server/src/commands/tunnels.js +365 -0
- package/vendor/server/src/commands/uninstall.js +326 -0
- package/vendor/server/src/config.js +38 -0
- package/vendor/server/src/exec.js +26 -0
- package/vendor/server/src/logger.js +39 -0
- package/vendor/server/src/ndjson.js +56 -0
- package/vendor/server/src/panel-api.js +85 -0
- package/vendor/server/src/state.js +45 -0
- package/vendor/server-ui/dist/assets/index-B0nWuUyL.js +257 -0
- package/vendor/server-ui/dist/assets/index-BqWWFlTU.css +1 -0
- package/vendor/server-ui/dist/index.html +13 -0
- package/vendor/serverd/package.json +44 -0
- package/vendor/serverd/src/boot.js +13 -0
- package/vendor/serverd/src/index.js +191 -0
- package/vendor/serverd/src/lib/app-error.js +14 -0
- package/vendor/serverd/src/lib/authelia.js +85 -0
- package/vendor/serverd/src/lib/certbot.js +74 -0
- package/vendor/serverd/src/lib/chisel-args.js +6 -0
- package/vendor/serverd/src/lib/chisel-reconcile.js +232 -0
- package/vendor/serverd/src/lib/chisel-runtime.js +46 -0
- package/vendor/serverd/src/lib/chisel-users.js +109 -0
- package/vendor/serverd/src/lib/chisel.js +81 -0
- package/vendor/serverd/src/lib/config.js +190 -0
- package/vendor/serverd/src/lib/constants.js +8 -0
- package/vendor/serverd/src/lib/csr-signing.js +331 -0
- package/vendor/serverd/src/lib/enrollment.js +302 -0
- package/vendor/serverd/src/lib/files.js +19 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +135 -0
- package/vendor/serverd/src/lib/invite-page.js +281 -0
- package/vendor/serverd/src/lib/ip-utils.js +79 -0
- package/vendor/serverd/src/lib/migrations/state/0001_enrollment_tokens.sql +17 -0
- package/vendor/serverd/src/lib/migrations/state/0002_tickets.sql +70 -0
- package/vendor/serverd/src/lib/migrations/state/0003_plugins.sql +15 -0
- package/vendor/serverd/src/lib/migrations/state/0004_agents.sql +19 -0
- package/vendor/serverd/src/lib/mtls.js +795 -0
- package/vendor/serverd/src/lib/nginx.js +1090 -0
- package/vendor/serverd/src/lib/pki-paths.js +41 -0
- package/vendor/serverd/src/lib/pki-sign.js +103 -0
- package/vendor/serverd/src/lib/plugins.js +538 -0
- package/vendor/serverd/src/lib/push-install.js +390 -0
- package/vendor/serverd/src/lib/revocation.js +112 -0
- package/vendor/serverd/src/lib/services.js +131 -0
- package/vendor/serverd/src/lib/session.js +151 -0
- package/vendor/serverd/src/lib/state-db.js +130 -0
- package/vendor/serverd/src/lib/state.js +140 -0
- package/vendor/serverd/src/lib/storage.js +63 -0
- package/vendor/serverd/src/lib/system-stats.js +58 -0
- package/vendor/serverd/src/lib/tickets.js +1556 -0
- package/vendor/serverd/src/lib/totp.js +76 -0
- package/vendor/serverd/src/lib/tunnel-deps.js +41 -0
- package/vendor/serverd/src/lib/user-access-session.js +142 -0
- package/vendor/serverd/src/lib/user-access.js +52 -0
- package/vendor/serverd/src/middleware/errors.js +63 -0
- package/vendor/serverd/src/middleware/mtls.js +120 -0
- package/vendor/serverd/src/middleware/onboarding-guard.js +30 -0
- package/vendor/serverd/src/middleware/role-guard.js +58 -0
- package/vendor/serverd/src/middleware/twofa-session.js +65 -0
- package/vendor/serverd/src/middleware/user-access-session.js +52 -0
- package/vendor/serverd/src/routes/enrollment.js +120 -0
- package/vendor/serverd/src/routes/health.js +22 -0
- package/vendor/serverd/src/routes/invite.js +163 -0
- package/vendor/serverd/src/routes/management/agents.js +182 -0
- package/vendor/serverd/src/routes/management/certs.js +911 -0
- package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +160 -0
- package/vendor/serverd/src/routes/management/identity.js +107 -0
- package/vendor/serverd/src/routes/management/invitations.js +166 -0
- package/vendor/serverd/src/routes/management/logs.js +218 -0
- package/vendor/serverd/src/routes/management/plugins.js +560 -0
- package/vendor/serverd/src/routes/management/services.js +63 -0
- package/vendor/serverd/src/routes/management/settings.js +325 -0
- package/vendor/serverd/src/routes/management/sites.js +522 -0
- package/vendor/serverd/src/routes/management/storage.js +192 -0
- package/vendor/serverd/src/routes/management/system.js +201 -0
- package/vendor/serverd/src/routes/management/tickets.js +457 -0
- package/vendor/serverd/src/routes/management/tunnels.js +709 -0
- package/vendor/serverd/src/routes/management/users.js +377 -0
- package/vendor/serverd/src/routes/management.js +36 -0
- package/vendor/serverd/src/routes/onboarding/dns.js +101 -0
- package/vendor/serverd/src/routes/onboarding/domain.js +42 -0
- package/vendor/serverd/src/routes/onboarding/index.js +18 -0
- package/vendor/serverd/src/routes/onboarding/provision.js +327 -0
- package/vendor/serverd/src/routes/onboarding/status.js +12 -0
- package/vendor/serverd/src/routes/plugin-router.js +79 -0
- package/vendor/serverd/src/routes/user-access.js +389 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate pre-filled message templates for requesting access to a resource.
|
|
3
|
+
*
|
|
4
|
+
* @param username - The authenticated user's username
|
|
5
|
+
* @param resourceName - Human-readable resource name (e.g., FQDN or plugin name)
|
|
6
|
+
* @param options - Optional admin contact info and domain
|
|
7
|
+
* @returns Templates for email, Slack, Teams, WhatsApp, and generic
|
|
8
|
+
*/
|
|
9
|
+
export function getAccessRequestTemplates(username, resourceName, options) {
|
|
10
|
+
const adminName = options?.adminName ?? 'Administrator';
|
|
11
|
+
const adminContact = options?.adminContact ?? '';
|
|
12
|
+
const contactLine = adminContact ? `\nAdmin contact: ${adminContact}` : '';
|
|
13
|
+
return {
|
|
14
|
+
email: {
|
|
15
|
+
subject: `Access request for ${resourceName}`,
|
|
16
|
+
body: `Hi ${adminName},\n\n` +
|
|
17
|
+
`I'd like to request access to ${resourceName}.\n` +
|
|
18
|
+
`My username is: ${username}\n\n` +
|
|
19
|
+
`Thank you.`,
|
|
20
|
+
},
|
|
21
|
+
slack: `Hi, could I get access to \`${resourceName}\`? My username is \`${username}\`.`,
|
|
22
|
+
teams: `Hi, could I get access to **${resourceName}**? My username is **${username}**.`,
|
|
23
|
+
whatsapp: `Hi, I need access to ${resourceName} (username: ${username}). Thanks!`,
|
|
24
|
+
generic: `Access request for ${resourceName}\n` + `Username: ${username}${contactLine}`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build an HTML page for the access-request denial page.
|
|
29
|
+
* Server-rendered with inline CSS, no external dependencies.
|
|
30
|
+
*
|
|
31
|
+
* @param username - The authenticated user's username
|
|
32
|
+
* @param resourceFqdn - The tunnel FQDN the user tried to access
|
|
33
|
+
* @param options - Optional admin contact info
|
|
34
|
+
* @returns Full HTML page string
|
|
35
|
+
*/
|
|
36
|
+
export function buildAccessRequestPage(username, resourceFqdn, options) {
|
|
37
|
+
const templates = getAccessRequestTemplates(username, resourceFqdn, options);
|
|
38
|
+
const adminContact = options?.adminContact ?? '';
|
|
39
|
+
const adminName = options?.adminName ?? 'your administrator';
|
|
40
|
+
return `<!DOCTYPE html>
|
|
41
|
+
<html lang="en">
|
|
42
|
+
<head>
|
|
43
|
+
<meta charset="utf-8">
|
|
44
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
45
|
+
<title>Access Required — ${escapeHtml(resourceFqdn)}</title>
|
|
46
|
+
<style>
|
|
47
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
48
|
+
body {
|
|
49
|
+
font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospace;
|
|
50
|
+
background: #09090b; color: #e4e4e7;
|
|
51
|
+
min-height: 100vh; display: flex; align-items: center; justify-content: center;
|
|
52
|
+
padding: 1rem;
|
|
53
|
+
}
|
|
54
|
+
.card {
|
|
55
|
+
background: #18181b; border: 1px solid #27272a; border-radius: 0.75rem;
|
|
56
|
+
max-width: 560px; width: 100%; padding: 2rem;
|
|
57
|
+
}
|
|
58
|
+
.icon { font-size: 2.5rem; margin-bottom: 1rem; }
|
|
59
|
+
h1 { font-size: 1.25rem; color: #f4f4f5; margin-bottom: 0.5rem; }
|
|
60
|
+
.fqdn { color: #22d3ee; }
|
|
61
|
+
.subtitle { color: #a1a1aa; font-size: 0.875rem; margin-bottom: 1.5rem; }
|
|
62
|
+
.section-label {
|
|
63
|
+
color: #71717a; font-size: 0.75rem; text-transform: uppercase;
|
|
64
|
+
letter-spacing: 0.05em; margin-bottom: 0.5rem; margin-top: 1.25rem;
|
|
65
|
+
}
|
|
66
|
+
.template-box {
|
|
67
|
+
background: #0f0f12; border: 1px solid #27272a; border-radius: 0.5rem;
|
|
68
|
+
padding: 0.75rem 1rem; margin-bottom: 0.5rem; position: relative;
|
|
69
|
+
font-size: 0.8125rem; line-height: 1.5; white-space: pre-wrap;
|
|
70
|
+
word-break: break-word; color: #d4d4d8;
|
|
71
|
+
}
|
|
72
|
+
.copy-btn {
|
|
73
|
+
position: absolute; top: 0.5rem; right: 0.5rem;
|
|
74
|
+
background: #27272a; border: 1px solid #3f3f46; border-radius: 0.375rem;
|
|
75
|
+
color: #a1a1aa; font-size: 0.6875rem; padding: 0.25rem 0.5rem;
|
|
76
|
+
cursor: pointer; font-family: inherit;
|
|
77
|
+
transition: background 0.15s, color 0.15s;
|
|
78
|
+
}
|
|
79
|
+
.copy-btn:hover { background: #3f3f46; color: #e4e4e7; }
|
|
80
|
+
.copy-btn.copied { background: #065f46; color: #6ee7b7; border-color: #065f46; }
|
|
81
|
+
.contact { color: #a1a1aa; font-size: 0.8125rem; margin-top: 1.5rem; }
|
|
82
|
+
.contact a { color: #22d3ee; text-decoration: none; }
|
|
83
|
+
.contact a:hover { text-decoration: underline; }
|
|
84
|
+
.user-badge {
|
|
85
|
+
display: inline-block; background: #27272a; border-radius: 0.25rem;
|
|
86
|
+
padding: 0.125rem 0.375rem; font-size: 0.75rem; color: #22d3ee;
|
|
87
|
+
}
|
|
88
|
+
</style>
|
|
89
|
+
</head>
|
|
90
|
+
<body>
|
|
91
|
+
<div class="card">
|
|
92
|
+
<div class="icon">🔒</div>
|
|
93
|
+
<h1>Access Required</h1>
|
|
94
|
+
<p class="subtitle">
|
|
95
|
+
You don't have access to <span class="fqdn">${escapeHtml(resourceFqdn)}</span>
|
|
96
|
+
</p>
|
|
97
|
+
<p class="subtitle">
|
|
98
|
+
Signed in as <span class="user-badge">${escapeHtml(username)}</span>
|
|
99
|
+
</p>
|
|
100
|
+
<p class="subtitle">
|
|
101
|
+
Contact ${escapeHtml(adminName)} to request access. Copy a message template below:
|
|
102
|
+
</p>
|
|
103
|
+
|
|
104
|
+
<div class="section-label">Email</div>
|
|
105
|
+
<div class="template-box" id="tpl-email">Subject: ${escapeHtml(templates.email.subject)}
|
|
106
|
+
|
|
107
|
+
${escapeHtml(templates.email.body)}<button class="copy-btn" onclick="copyTemplate('tpl-email', this)">Copy</button></div>
|
|
108
|
+
|
|
109
|
+
<div class="section-label">Slack / Teams</div>
|
|
110
|
+
<div class="template-box" id="tpl-slack">${escapeHtml(templates.slack)}<button class="copy-btn" onclick="copyTemplate('tpl-slack', this)">Copy</button></div>
|
|
111
|
+
|
|
112
|
+
<div class="section-label">WhatsApp</div>
|
|
113
|
+
<div class="template-box" id="tpl-whatsapp">${escapeHtml(templates.whatsapp)}<button class="copy-btn" onclick="copyTemplate('tpl-whatsapp', this)">Copy</button></div>
|
|
114
|
+
|
|
115
|
+
${adminContact ? `<p class="contact">Admin: <a href="mailto:${escapeAttr(adminContact)}">${escapeHtml(adminContact)}</a></p>` : ''}
|
|
116
|
+
</div>
|
|
117
|
+
<script>
|
|
118
|
+
function copyTemplate(id, btn) {
|
|
119
|
+
var el = document.getElementById(id);
|
|
120
|
+
if (!el) return;
|
|
121
|
+
var text = el.textContent.replace(/Copy$/, '').trim();
|
|
122
|
+
navigator.clipboard.writeText(text).then(function() {
|
|
123
|
+
btn.textContent = 'Copied';
|
|
124
|
+
btn.classList.add('copied');
|
|
125
|
+
setTimeout(function() {
|
|
126
|
+
btn.textContent = 'Copy';
|
|
127
|
+
btn.classList.remove('copied');
|
|
128
|
+
}, 2000);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
</script>
|
|
132
|
+
</body>
|
|
133
|
+
</html>`;
|
|
134
|
+
}
|
|
135
|
+
function escapeHtml(str) {
|
|
136
|
+
return str
|
|
137
|
+
.replace(/&/g, '&')
|
|
138
|
+
.replace(/</g, '<')
|
|
139
|
+
.replace(/>/g, '>')
|
|
140
|
+
.replace(/"/g, '"')
|
|
141
|
+
.replace(/'/g, ''');
|
|
142
|
+
}
|
|
143
|
+
function escapeAttr(str) {
|
|
144
|
+
return str
|
|
145
|
+
.replace(/&/g, '&')
|
|
146
|
+
.replace(/</g, '<')
|
|
147
|
+
.replace(/>/g, '>')
|
|
148
|
+
.replace(/"/g, '"')
|
|
149
|
+
.replace(/'/g, ''');
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAAgB,EAChB,YAAoB,EACpB,OAAyB;IAEzB,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,eAAe,CAAC;IACxD,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,EAAE,CAAC;IACjD,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,oBAAoB,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAE3E,OAAO;QACL,KAAK,EAAE;YACL,OAAO,EAAE,sBAAsB,YAAY,EAAE;YAC7C,IAAI,EACF,MAAM,SAAS,OAAO;gBACtB,iCAAiC,YAAY,KAAK;gBAClD,mBAAmB,QAAQ,MAAM;gBACjC,YAAY;SACf;QACD,KAAK,EAAE,+BAA+B,YAAY,wBAAwB,QAAQ,KAAK;QACvF,KAAK,EAAE,+BAA+B,YAAY,wBAAwB,QAAQ,KAAK;QACvF,QAAQ,EAAE,wBAAwB,YAAY,eAAe,QAAQ,YAAY;QACjF,OAAO,EAAE,sBAAsB,YAAY,IAAI,GAAG,aAAa,QAAQ,GAAG,WAAW,EAAE;KACxF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAgB,EAChB,YAAoB,EACpB,OAAyB;IAEzB,MAAM,SAAS,GAAG,yBAAyB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAC7E,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,oBAAoB,CAAC;IAE7D,OAAO;;;;;6BAKoB,UAAU,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDAkDD,UAAU,CAAC,YAAY,CAAC;;;8CAG9B,UAAU,CAAC,QAAQ,CAAC;;;gBAGlD,UAAU,CAAC,SAAS,CAAC;;;;wDAImB,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;;EAEzF,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;;;+CAGa,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;;;kDAGxB,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;;MAE1E,YAAY,CAAC,CAAC,CAAC,6CAA6C,UAAU,CAAC,YAAY,CAAC,KAAK,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;QAkB9H,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { PrincipalType, AccessMode } from './constants.js';
|
|
2
|
+
/**
|
|
3
|
+
* A Lamaste access control group.
|
|
4
|
+
*/
|
|
5
|
+
export interface Group {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly description: string;
|
|
8
|
+
readonly members: readonly string[];
|
|
9
|
+
readonly createdAt: string;
|
|
10
|
+
readonly createdBy: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Mutable group state (internal).
|
|
14
|
+
*/
|
|
15
|
+
export interface GroupState {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
members: string[];
|
|
19
|
+
createdAt: string;
|
|
20
|
+
createdBy: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Options for creating a group.
|
|
24
|
+
*/
|
|
25
|
+
export interface CreateGroupOptions {
|
|
26
|
+
readonly description?: string | undefined;
|
|
27
|
+
readonly createdBy?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Options for updating a group.
|
|
31
|
+
*/
|
|
32
|
+
export interface UpdateGroupOptions {
|
|
33
|
+
readonly name?: string | undefined;
|
|
34
|
+
readonly description?: string | undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result of deleting a group.
|
|
38
|
+
*/
|
|
39
|
+
export interface DeleteGroupResult {
|
|
40
|
+
readonly deletedGrants: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A generic access grant binding a principal to a resource.
|
|
44
|
+
*/
|
|
45
|
+
export interface Grant {
|
|
46
|
+
readonly grantId: string;
|
|
47
|
+
readonly principalType: PrincipalType;
|
|
48
|
+
readonly principalId: string;
|
|
49
|
+
readonly resourceType: string;
|
|
50
|
+
readonly resourceId: string;
|
|
51
|
+
readonly context: Record<string, unknown>;
|
|
52
|
+
readonly used: boolean;
|
|
53
|
+
readonly createdAt: string;
|
|
54
|
+
readonly usedAt: string | null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Mutable grant state (internal).
|
|
58
|
+
*/
|
|
59
|
+
export interface GrantState {
|
|
60
|
+
grantId: string;
|
|
61
|
+
principalType: PrincipalType;
|
|
62
|
+
principalId: string;
|
|
63
|
+
resourceType: string;
|
|
64
|
+
resourceId: string;
|
|
65
|
+
context: Record<string, unknown>;
|
|
66
|
+
used: boolean;
|
|
67
|
+
createdAt: string;
|
|
68
|
+
usedAt: string | null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Options for creating a grant.
|
|
72
|
+
*/
|
|
73
|
+
export interface CreateGrantOptions {
|
|
74
|
+
readonly principalType: PrincipalType;
|
|
75
|
+
readonly principalId: string;
|
|
76
|
+
readonly resourceType: string;
|
|
77
|
+
readonly resourceId: string;
|
|
78
|
+
readonly context?: Record<string, unknown>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Filter for listing grants.
|
|
82
|
+
*/
|
|
83
|
+
export interface GrantFilter {
|
|
84
|
+
readonly principalType?: PrincipalType | undefined;
|
|
85
|
+
readonly principalId?: string | undefined;
|
|
86
|
+
readonly resourceType?: string | undefined;
|
|
87
|
+
readonly resourceId?: string | undefined;
|
|
88
|
+
readonly used?: boolean | undefined;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Result of an access check.
|
|
92
|
+
*/
|
|
93
|
+
export interface AccessAllowed {
|
|
94
|
+
readonly allowed: true;
|
|
95
|
+
}
|
|
96
|
+
export interface AccessDenied {
|
|
97
|
+
readonly allowed: false;
|
|
98
|
+
readonly resource: {
|
|
99
|
+
readonly type: string;
|
|
100
|
+
readonly id: string;
|
|
101
|
+
};
|
|
102
|
+
readonly templates: AccessRequestTemplates;
|
|
103
|
+
}
|
|
104
|
+
export type AccessResult = AccessAllowed | AccessDenied;
|
|
105
|
+
/**
|
|
106
|
+
* Pre-filled message templates for access requests.
|
|
107
|
+
*/
|
|
108
|
+
export interface AccessRequestTemplates {
|
|
109
|
+
readonly email: {
|
|
110
|
+
readonly subject: string;
|
|
111
|
+
readonly body: string;
|
|
112
|
+
};
|
|
113
|
+
readonly slack: string;
|
|
114
|
+
readonly teams: string;
|
|
115
|
+
readonly whatsapp: string;
|
|
116
|
+
readonly generic: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Options for generating access request templates.
|
|
120
|
+
*/
|
|
121
|
+
export interface TemplateOptions {
|
|
122
|
+
readonly adminContact?: string | undefined;
|
|
123
|
+
readonly adminName?: string | undefined;
|
|
124
|
+
readonly domain?: string | undefined;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Gatekeeper service settings.
|
|
128
|
+
*/
|
|
129
|
+
export interface GatekeeperSettings {
|
|
130
|
+
readonly adminEmail?: string | undefined;
|
|
131
|
+
readonly adminName?: string | undefined;
|
|
132
|
+
readonly slackChannel?: string | undefined;
|
|
133
|
+
readonly teamsChannel?: string | undefined;
|
|
134
|
+
readonly sessionCacheTtlMs?: number | undefined;
|
|
135
|
+
readonly accessLoggingEnabled?: boolean | undefined;
|
|
136
|
+
readonly accessLogRetentionDays?: number | undefined;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* An entry in the access request log.
|
|
140
|
+
*/
|
|
141
|
+
export interface AccessRequestEntry {
|
|
142
|
+
readonly timestamp: string;
|
|
143
|
+
readonly username: string;
|
|
144
|
+
readonly resourceType: string;
|
|
145
|
+
readonly resourceId: string;
|
|
146
|
+
readonly resourceFqdn: string;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Tunnel info used by the authz check endpoint.
|
|
150
|
+
*/
|
|
151
|
+
export interface TunnelInfo {
|
|
152
|
+
readonly id: string;
|
|
153
|
+
readonly fqdn: string;
|
|
154
|
+
readonly accessMode: AccessMode;
|
|
155
|
+
readonly enabled: boolean;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Cached Authelia session data.
|
|
159
|
+
*/
|
|
160
|
+
export interface AutheliaSession {
|
|
161
|
+
readonly username: string;
|
|
162
|
+
readonly groups: string;
|
|
163
|
+
readonly displayName: string;
|
|
164
|
+
readonly email: string;
|
|
165
|
+
readonly expiresAt: number;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Logger interface (compatible with Fastify logger).
|
|
169
|
+
*/
|
|
170
|
+
export interface GatekeeperLogger {
|
|
171
|
+
info(msg: string): void;
|
|
172
|
+
info(obj: Record<string, unknown>, msg: string): void;
|
|
173
|
+
warn(msg: string): void;
|
|
174
|
+
warn(obj: Record<string, unknown>, msg: string): void;
|
|
175
|
+
error(msg: string): void;
|
|
176
|
+
error(obj: Record<string, unknown>, msg: string): void;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import '../boot.js';
|
|
2
|
+
import Fastify from 'fastify';
|
|
3
|
+
import type { TunnelInfo, GatekeeperSettings, AutheliaSession } from '../lib/types.js';
|
|
4
|
+
export declare function createServer(): Promise<ReturnType<typeof Fastify>>;
|
|
5
|
+
declare module 'fastify' {
|
|
6
|
+
interface FastifyInstance {
|
|
7
|
+
getTunnels(): TunnelInfo[];
|
|
8
|
+
getSettings(): GatekeeperSettings;
|
|
9
|
+
getSessionCache(): Map<string, AutheliaSession>;
|
|
10
|
+
getCacheVersion(): number;
|
|
11
|
+
bustCache(): void;
|
|
12
|
+
updateSettings(s: GatekeeperSettings): void;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,CAAC;AAEpB,OAAO,OAAO,MAAM,SAAS,CAAC;AAc9B,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAoHvF,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC,CA6IxE;AAkCD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,eAAe;QACvB,UAAU,IAAI,UAAU,EAAE,CAAC;QAC3B,WAAW,IAAI,kBAAkB,CAAC;QAClC,eAAe,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAChD,eAAe,IAAI,MAAM,CAAC;QAC1B,SAAS,IAAI,IAAI,CAAC;QAClB,cAAc,CAAC,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;KAC7C;CACF"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import '../boot.js';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import Fastify from 'fastify';
|
|
4
|
+
import rateLimit from '@fastify/rate-limit';
|
|
5
|
+
import { watch } from 'node:fs';
|
|
6
|
+
import { readFile } from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { atomicWriteJSON } from '@lamalibre/lamaste';
|
|
9
|
+
import { DEFAULT_DATA_DIR, GROUPS_FILE, GRANTS_FILE, SETTINGS_FILE, GATEKEEPER_PORT, SESSION_CACHE_TTL_MS, } from '../lib/constants.js';
|
|
10
|
+
import { registerCacheInvalidator } from '../lib/cache-bust.js';
|
|
11
|
+
import { authzRoutes } from './routes/authz.js';
|
|
12
|
+
import { groupRoutes } from './routes/groups.js';
|
|
13
|
+
import { grantRoutes } from './routes/grants.js';
|
|
14
|
+
import { diagnosticRoutes } from './routes/diagnostic.js';
|
|
15
|
+
import { accessRequestRoutes } from './routes/access-request.js';
|
|
16
|
+
const dataDir = process.env.LAMALIBRE_LAMASTE_DATA_DIR ?? DEFAULT_DATA_DIR;
|
|
17
|
+
const tunnelsPath = path.join(dataDir, 'tunnels.json');
|
|
18
|
+
const settingsPath = path.join(dataDir, SETTINGS_FILE);
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// In-memory caches (refreshed by file watch + TTL)
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
/** Tunnel info cache (refreshed on file change) */
|
|
23
|
+
let tunnelsCache = [];
|
|
24
|
+
/** Gatekeeper settings cache */
|
|
25
|
+
let settingsCache = {};
|
|
26
|
+
/** Authelia session cache: cookie hash → session data */
|
|
27
|
+
const sessionCache = new Map();
|
|
28
|
+
/** Cache version counter — incremented on cache bust */
|
|
29
|
+
let cacheVersion = 0;
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// File loaders
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
async function loadTunnels() {
|
|
34
|
+
try {
|
|
35
|
+
const raw = await readFile(tunnelsPath, 'utf-8');
|
|
36
|
+
const parsed = JSON.parse(raw);
|
|
37
|
+
if (!Array.isArray(parsed))
|
|
38
|
+
return [];
|
|
39
|
+
return parsed.map((t) => ({
|
|
40
|
+
id: String(t.id ?? ''),
|
|
41
|
+
fqdn: String(t.fqdn ?? ''),
|
|
42
|
+
accessMode: t.accessMode ?? 'restricted',
|
|
43
|
+
enabled: t.enabled !== false,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function loadSettings() {
|
|
51
|
+
try {
|
|
52
|
+
const raw = await readFile(settingsPath, 'utf-8');
|
|
53
|
+
return JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// File watcher with debounce
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
/**
|
|
63
|
+
* One directory watcher per parent directory, multiplexed by filename.
|
|
64
|
+
*
|
|
65
|
+
* We watch the parent directory rather than the file itself because all of our
|
|
66
|
+
* state files (tunnels.json, grants.json, groups.json, gatekeeper.json) are
|
|
67
|
+
* updated via atomic rename (temp → fsync → rename). A direct `fs.watch` on
|
|
68
|
+
* the file is pinned to the original inode, and the rename swaps that inode
|
|
69
|
+
* out — leaving the watcher silently attached to a file that no longer has a
|
|
70
|
+
* name. Watching the directory survives renames: we receive a `rename` event
|
|
71
|
+
* for the target filename each time a write lands, and re-run the reloader.
|
|
72
|
+
*/
|
|
73
|
+
const dirWatchers = new Map();
|
|
74
|
+
function watchFile(filePath, reload, logger) {
|
|
75
|
+
const dir = path.dirname(filePath);
|
|
76
|
+
const base = path.basename(filePath);
|
|
77
|
+
let debounceTimer = null;
|
|
78
|
+
const handler = () => {
|
|
79
|
+
if (debounceTimer)
|
|
80
|
+
clearTimeout(debounceTimer);
|
|
81
|
+
debounceTimer = setTimeout(() => {
|
|
82
|
+
reload().catch(() => {
|
|
83
|
+
// Reload errors are non-fatal — keep using cached data
|
|
84
|
+
});
|
|
85
|
+
logger.info(`Reloaded ${base}`);
|
|
86
|
+
}, 200);
|
|
87
|
+
};
|
|
88
|
+
let handlers = dirWatchers.get(dir);
|
|
89
|
+
if (!handlers) {
|
|
90
|
+
handlers = new Map();
|
|
91
|
+
dirWatchers.set(dir, handlers);
|
|
92
|
+
try {
|
|
93
|
+
watch(dir, (_eventType, filename) => {
|
|
94
|
+
if (!filename)
|
|
95
|
+
return;
|
|
96
|
+
const cb = handlers.get(filename);
|
|
97
|
+
if (cb)
|
|
98
|
+
cb();
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Parent directory doesn't exist yet — watcher not set up.
|
|
103
|
+
dirWatchers.delete(dir);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
handlers.set(base, handler);
|
|
108
|
+
}
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// Server startup
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
export async function createServer() {
|
|
113
|
+
const server = Fastify({
|
|
114
|
+
logger: true,
|
|
115
|
+
trustProxy: 1,
|
|
116
|
+
});
|
|
117
|
+
// Global rate limit. The gatekeeper binds to 127.0.0.1 and is reached
|
|
118
|
+
// exclusively by nginx auth_request and the panel proxy — both are
|
|
119
|
+
// local services. Because every caller arrives from 127.0.0.1, a
|
|
120
|
+
// per-IP limiter would collapse them into a single bucket and either
|
|
121
|
+
// be useless or punish legitimate nginx traffic. We collapse the key
|
|
122
|
+
// explicitly to one shared bucket and set a high ceiling; the hot
|
|
123
|
+
// /authz/check route then overrides this with its own ceiling that
|
|
124
|
+
// makes the "nginx-only" assumption explicit.
|
|
125
|
+
await server.register(rateLimit, {
|
|
126
|
+
max: 1000,
|
|
127
|
+
timeWindow: '1 minute',
|
|
128
|
+
keyGenerator: () => 'gatekeeper-internal',
|
|
129
|
+
});
|
|
130
|
+
// Load initial state
|
|
131
|
+
tunnelsCache = await loadTunnels();
|
|
132
|
+
settingsCache = await loadSettings();
|
|
133
|
+
// Decorate server with shared state accessors
|
|
134
|
+
server.decorate('getTunnels', () => tunnelsCache);
|
|
135
|
+
server.decorate('getSettings', () => settingsCache);
|
|
136
|
+
server.decorate('getSessionCache', () => sessionCache);
|
|
137
|
+
server.decorate('getCacheVersion', () => cacheVersion);
|
|
138
|
+
const bustCache = () => {
|
|
139
|
+
cacheVersion++;
|
|
140
|
+
sessionCache.clear();
|
|
141
|
+
};
|
|
142
|
+
server.decorate('bustCache', bustCache);
|
|
143
|
+
registerCacheInvalidator(bustCache);
|
|
144
|
+
server.decorate('updateSettings', (s) => {
|
|
145
|
+
settingsCache = s;
|
|
146
|
+
});
|
|
147
|
+
// Watch state files for changes
|
|
148
|
+
watchFile(tunnelsPath, async () => {
|
|
149
|
+
tunnelsCache = await loadTunnels();
|
|
150
|
+
}, server.log);
|
|
151
|
+
// TODO(sqlite-step-4): groups.json and access-grants.json are now
|
|
152
|
+
// .migrated stubs after first SQLite open. These watch registrations stay
|
|
153
|
+
// attached to the old paths so they never fire — every authz read goes
|
|
154
|
+
// through the DB and is always current, but admin grant/group changes do
|
|
155
|
+
// not invalidate the in-memory session cache without a daemon restart.
|
|
156
|
+
// Replace with a DB-modtime sentinel that the writer touches on commit
|
|
157
|
+
// (or polled `PRAGMA data_version`) once Step 4 (rodeo) is green.
|
|
158
|
+
watchFile(path.join(dataDir, GROUPS_FILE), async () => {
|
|
159
|
+
// Groups are read from SQLite on each call,
|
|
160
|
+
// but clearing session cache ensures authz re-evaluates group membership
|
|
161
|
+
sessionCache.clear();
|
|
162
|
+
}, server.log);
|
|
163
|
+
watchFile(path.join(dataDir, GRANTS_FILE), async () => {
|
|
164
|
+
// Same — clear session cache so authz picks up grant changes
|
|
165
|
+
sessionCache.clear();
|
|
166
|
+
}, server.log);
|
|
167
|
+
watchFile(settingsPath, async () => {
|
|
168
|
+
settingsCache = await loadSettings();
|
|
169
|
+
}, server.log);
|
|
170
|
+
// Load or generate API secret for localhost management auth.
|
|
171
|
+
// The secret is wrapped in a JSON envelope and written atomically so a
|
|
172
|
+
// crash during initial generation never leaves a half-written file
|
|
173
|
+
// (which the next start would treat as "no secret yet" and rotate, breaking
|
|
174
|
+
// any external client holding the previous value).
|
|
175
|
+
const secretPath = path.join(dataDir, 'gatekeeper-secret.json');
|
|
176
|
+
const legacySecretPath = path.join(dataDir, 'gatekeeper-secret');
|
|
177
|
+
let apiSecret;
|
|
178
|
+
try {
|
|
179
|
+
const raw = await readFile(secretPath, 'utf-8');
|
|
180
|
+
const parsed = JSON.parse(raw);
|
|
181
|
+
if (typeof parsed.secret !== 'string' || parsed.secret.length === 0) {
|
|
182
|
+
throw new Error('gatekeeper-secret.json is missing the "secret" field');
|
|
183
|
+
}
|
|
184
|
+
apiSecret = parsed.secret;
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
if (err.code !== 'ENOENT') {
|
|
188
|
+
// Existing file is corrupt — refuse to rotate silently. An operator must
|
|
189
|
+
// resolve this so external callers do not lose their pinned secret.
|
|
190
|
+
throw err;
|
|
191
|
+
}
|
|
192
|
+
// First-run path: try migrating the legacy plaintext file before generating.
|
|
193
|
+
try {
|
|
194
|
+
const legacy = (await readFile(legacySecretPath, 'utf-8')).trim();
|
|
195
|
+
if (legacy.length > 0) {
|
|
196
|
+
apiSecret = legacy;
|
|
197
|
+
await atomicWriteJSON(secretPath, { secret: apiSecret }, { mkdirp: true });
|
|
198
|
+
server.log.info('Migrated legacy gatekeeper-secret file to JSON envelope');
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
throw new Error('legacy gatekeeper-secret was empty');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
apiSecret = crypto.randomBytes(32).toString('hex');
|
|
206
|
+
await atomicWriteJSON(secretPath, { secret: apiSecret }, { mkdirp: true });
|
|
207
|
+
server.log.info('Generated new gatekeeper API secret');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Register routes — authz, access-request, and health are public (nginx subrequests)
|
|
211
|
+
await server.register(authzRoutes);
|
|
212
|
+
await server.register(accessRequestRoutes);
|
|
213
|
+
// Management /api/* routes require the shared secret
|
|
214
|
+
await server.register(async (scope) => {
|
|
215
|
+
scope.addHook('onRequest', async (request, reply) => {
|
|
216
|
+
const auth = request.headers['x-gatekeeper-secret'];
|
|
217
|
+
if (auth !== apiSecret) {
|
|
218
|
+
return reply.code(401).send({ error: 'Unauthorized' });
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
await scope.register(groupRoutes, { prefix: '/api' });
|
|
222
|
+
await scope.register(grantRoutes, { prefix: '/api' });
|
|
223
|
+
await scope.register(diagnosticRoutes, { prefix: '/api' });
|
|
224
|
+
});
|
|
225
|
+
// Health endpoint
|
|
226
|
+
server.get('/health', async () => ({ status: 'ok' }));
|
|
227
|
+
return server;
|
|
228
|
+
}
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
// Entry point
|
|
231
|
+
// ---------------------------------------------------------------------------
|
|
232
|
+
async function start() {
|
|
233
|
+
const server = await createServer();
|
|
234
|
+
await server.listen({
|
|
235
|
+
host: '127.0.0.1',
|
|
236
|
+
port: GATEKEEPER_PORT,
|
|
237
|
+
});
|
|
238
|
+
// Graceful shutdown
|
|
239
|
+
const shutdown = async (signal) => {
|
|
240
|
+
server.log.info({ signal }, 'Received signal, shutting down gracefully');
|
|
241
|
+
await server.close();
|
|
242
|
+
process.exit(0);
|
|
243
|
+
};
|
|
244
|
+
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
|
245
|
+
process.on('SIGINT', () => void shutdown('SIGINT'));
|
|
246
|
+
}
|
|
247
|
+
start().catch((err) => {
|
|
248
|
+
console.error('Failed to start gatekeeper:', err);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
});
|
|
251
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
|
+
/**
|
|
3
|
+
* Standalone access-request page route.
|
|
4
|
+
* Used as a fallback when the inline 403 body approach isn't available.
|
|
5
|
+
*/
|
|
6
|
+
export declare function accessRequestRoutes(fastify: FastifyInstance): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=access-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-request.d.ts","sourceRoot":"","sources":["../../../src/server/routes/access-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAG7E;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAYjF"}
|