@lamalibre/create-lamaste 4.0.0 → 4.2.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.
Files changed (66) hide show
  1. package/package.json +2 -2
  2. package/scripts/lamaste-priv +21 -2
  3. package/src/lib/oidc-issuer-key.js +124 -0
  4. package/src/lib/relay-services.js +4 -0
  5. package/src/lib/service-config.js +16 -0
  6. package/vendor/docs/00-introduction/how-it-works.md +2 -2
  7. package/vendor/docs/00-introduction/quickstart.md +5 -5
  8. package/vendor/docs/00-introduction/what-is-lamaste.md +5 -5
  9. package/vendor/docs/01-concepts/authentication.md +45 -1
  10. package/vendor/docs/01-concepts/certificates.md +3 -3
  11. package/vendor/docs/01-concepts/mtls.md +2 -2
  12. package/vendor/docs/01-concepts/security-model.md +1 -1
  13. package/vendor/docs/01-concepts/tickets.md +2 -2
  14. package/vendor/docs/01-concepts/tunneling.md +4 -4
  15. package/vendor/docs/02-guides/agent-setup.md +3 -3
  16. package/vendor/docs/02-guides/certificate-management.md +2 -2
  17. package/vendor/docs/02-guides/cloud-provisioning.md +3 -3
  18. package/vendor/docs/02-guides/desktop-app-setup.md +10 -10
  19. package/vendor/docs/02-guides/installation.md +3 -3
  20. package/vendor/docs/02-guides/onboarding.md +2 -2
  21. package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +2 -2
  22. package/vendor/docs/03-architecture/installer-flow.md +2 -2
  23. package/vendor/docs/03-architecture/installer.md +6 -5
  24. package/vendor/docs/03-architecture/management-flow.md +1 -1
  25. package/vendor/docs/03-architecture/overview.md +5 -5
  26. package/vendor/docs/03-architecture/panel-client.md +6 -6
  27. package/vendor/docs/03-architecture/panel-server.md +2 -2
  28. package/vendor/docs/03-architecture/state-management.md +2 -2
  29. package/vendor/docs/03-architecture/system-overview.md +1 -1
  30. package/vendor/docs/04-api-reference/onboarding.md +1 -1
  31. package/vendor/docs/04-api-reference/overview.md +111 -105
  32. package/vendor/docs/04-api-reference/registry-and-oidc.md +207 -0
  33. package/vendor/docs/05-operations/backup-and-restore.md +1 -1
  34. package/vendor/docs/05-operations/uninstalling.md +1 -1
  35. package/vendor/docs/05-operations/upgrades.md +6 -5
  36. package/vendor/docs/06-reference/config-files.md +103 -45
  37. package/vendor/docs/06-reference/glossary.md +3 -3
  38. package/vendor/docs/06-reference/installer-flags.md +13 -13
  39. package/vendor/docs/06-reference/ports-and-services.md +1 -1
  40. package/vendor/docs/06-reference/troubleshooting.md +8 -8
  41. package/vendor/docs/_index.json +5 -0
  42. package/vendor/docs/gatekeeper-design.md +8 -8
  43. package/vendor/docs/identity-directory-design.md +443 -0
  44. package/vendor/docs/package.json +1 -1
  45. package/vendor/docs/todo/lib-cli-desktop-refactor.md +27 -27
  46. package/vendor/gatekeeper/package.json +1 -1
  47. package/vendor/server/bin/lamaste-server.js +10 -1
  48. package/vendor/server/package.json +4 -3
  49. package/vendor/server/src/commands/plugins.js +200 -158
  50. package/vendor/server/src/commands/registry-credential.js +142 -0
  51. package/vendor/server/src/panel-api.js +86 -39
  52. package/vendor/server-ui/dist/assets/{index-B0nWuUyL.js → index-B5Wp8lu-.js} +26 -26
  53. package/vendor/server-ui/dist/index.html +1 -1
  54. package/vendor/serverd/package.json +5 -2
  55. package/vendor/serverd/src/index.js +11 -0
  56. package/vendor/serverd/src/lib/authelia.js +11 -0
  57. package/vendor/serverd/src/lib/migrations/state/0005_plugin_hosting.sql +3 -0
  58. package/vendor/serverd/src/lib/plugin-oidc.js +233 -0
  59. package/vendor/serverd/src/lib/plugins.js +37 -5
  60. package/vendor/serverd/src/lib/registry-credential.js +145 -0
  61. package/vendor/serverd/src/routes/management/agents.js +81 -0
  62. package/vendor/serverd/src/routes/management/plugins.js +65 -2
  63. package/vendor/serverd/src/routes/management/registry-credential.js +170 -0
  64. package/vendor/serverd/src/routes/management/storage.js +10 -2
  65. package/vendor/serverd/src/routes/management/users.js +31 -0
  66. package/vendor/serverd/src/routes/management.js +2 -0
@@ -13,18 +13,95 @@ import { PKI_DIR } from './config.js';
13
13
 
14
14
  const PANEL_URL = 'https://127.0.0.1:9292';
15
15
 
16
+ /**
17
+ * The curl argument vector for one panel request. Pure, exported for tests.
18
+ *
19
+ * The JSON content type and the body travel together: a `Content-Type:
20
+ * application/json` header on a body-less DELETE made Fastify answer 400
21
+ * ("Body cannot be empty when content-type is set"), so `registry-credential
22
+ * clear`, `tunnels delete` and `sites delete` never reached their routes.
23
+ *
24
+ * @param {{ method: string, path: string, body?: Record<string, unknown> | null, p12Path: string, configPath: string }} request
25
+ * @returns {string[]}
26
+ */
27
+ export function buildPanelCurlArgs({ method, path, body = null, p12Path, configPath }) {
28
+ const args = [
29
+ '-K',
30
+ configPath,
31
+ '--cert-type',
32
+ 'P12',
33
+ '--cert',
34
+ p12Path,
35
+ '-k', // Server uses self-signed cert on localhost
36
+ '-s', // Silent
37
+ '-S', // Show errors
38
+ '-X',
39
+ method,
40
+ '-H',
41
+ 'Accept: application/json',
42
+ ];
43
+ if (body !== null && body !== undefined) {
44
+ args.push('-H', 'Content-Type: application/json', '-d', JSON.stringify(body));
45
+ }
46
+ // Append the HTTP status on its own line so an error response is not
47
+ // mistaken for a result — the panel answers errors with a JSON body.
48
+ args.push('-w', '\n%{http_code}', `${PANEL_URL}${path}`);
49
+ return args;
50
+ }
51
+
52
+ /**
53
+ * Split curl's output (`<payload>\n<status>`) and turn a non-2xx status
54
+ * into an error carrying the panel's `error` (and `details`). Pure,
55
+ * exported for tests.
56
+ *
57
+ * @param {string} stdout
58
+ * @param {string} method
59
+ * @param {string} path
60
+ * @returns {Record<string, unknown>}
61
+ */
62
+ export function parsePanelResponse(stdout, method, path) {
63
+ const split = stdout.lastIndexOf('\n');
64
+ const payload = stdout.slice(0, split).trim();
65
+ const status = Number(stdout.slice(split + 1).trim());
66
+ let parsed = {};
67
+ if (payload) {
68
+ try {
69
+ parsed = JSON.parse(payload);
70
+ } catch {
71
+ parsed = { error: payload };
72
+ }
73
+ }
74
+
75
+ // Anything but a 2xx is an error: 4xx/5xx from the panel, a 3xx curl did
76
+ // not follow, or 0 when curl reported no status at all.
77
+ if (!Number.isInteger(status) || status < 200 || status >= 300) {
78
+ const reason = [parsed.error, parsed.details].filter(Boolean).join(': ');
79
+ const err = new Error(
80
+ `${method} ${path} failed (HTTP ${status})${reason ? `: ${reason}` : ''}`,
81
+ );
82
+ err.statusCode = status;
83
+ throw err;
84
+ }
85
+
86
+ return parsed;
87
+ }
88
+
16
89
  /**
17
90
  * Make an authenticated API request to the local panel server.
18
91
  *
19
92
  * Uses curl with the admin client certificate (mTLS) and a temporary
20
- * config file for the P12 password (never in process args).
93
+ * config file for the P12 password (never in process args). Resolves with
94
+ * the JSON body; rejects with an Error (`statusCode`, the panel's `error`
95
+ * in the message) for any non-2xx answer.
21
96
  *
22
97
  * @param {string} method
23
98
  * @param {string} path e.g. '/api/tunnels'
24
- * @param {Record<string, unknown> | null} [body]
99
+ * @param {Record<string, unknown> | null} [body] sent as JSON when given
100
+ * @param {{ timeoutMs?: number }} [options] `timeoutMs` for calls the panel
101
+ * needs longer to answer (a plugin install runs npm); default 30 s
25
102
  * @returns {Promise<Record<string, unknown>>}
26
103
  */
27
- export async function panelRequest(method, path, body = null) {
104
+ export async function panelRequest(method, path, body = null, { timeoutMs = 30000 } = {}) {
28
105
  const p12Path = `${PKI_DIR}/client.p12`;
29
106
 
30
107
  // Read p12 password from the stored file
@@ -42,43 +119,13 @@ export async function panelRequest(method, path, body = null) {
42
119
  try {
43
120
  await writeFile(tmpConfigPath, `--pass "${p12Password}"\n`, { mode: 0o600 });
44
121
 
45
- const curlArgs = [
46
- '-K',
47
- tmpConfigPath,
48
- '--cert-type',
49
- 'P12',
50
- '--cert',
51
- p12Path,
52
- '-k', // Server uses self-signed cert on localhost
53
- '-s', // Silent
54
- '-S', // Show errors
55
- '-X',
56
- method,
57
- '-H',
58
- 'Content-Type: application/json',
59
- ];
60
-
61
- if (body) {
62
- curlArgs.push('-d', JSON.stringify(body));
63
- }
64
-
65
- // Append the HTTP status on its own line so an error response is not
66
- // mistaken for a result — the panel answers errors with a JSON body.
67
- curlArgs.push('-w', '\n%{http_code}', `${PANEL_URL}${path}`);
68
-
69
- const { stdout } = await execa('curl', curlArgs, { timeout: 30000 });
70
-
71
- const split = stdout.lastIndexOf('\n');
72
- const payload = stdout.slice(0, split).trim();
73
- const status = Number(stdout.slice(split + 1).trim());
74
- const parsed = payload ? JSON.parse(payload) : {};
75
-
76
- if (!Number.isInteger(status) || status >= 400) {
77
- const reason = [parsed.error, parsed.details].filter(Boolean).join(': ');
78
- throw new Error(`${method} ${path} failed (HTTP ${status})${reason ? `: ${reason}` : ''}`);
79
- }
122
+ const { stdout } = await execa(
123
+ 'curl',
124
+ buildPanelCurlArgs({ method, path, body, p12Path, configPath: tmpConfigPath }),
125
+ { timeout: timeoutMs },
126
+ );
80
127
 
81
- return parsed;
128
+ return parsePanelResponse(stdout, method, path);
82
129
  } finally {
83
130
  await unlink(tmpConfigPath).catch(() => {});
84
131
  }