@lelu-auth/lelu 0.1.4 → 0.1.6

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/scripts/lelu.js CHANGED
@@ -3,18 +3,12 @@
3
3
  /*
4
4
  * Lelu CLI
5
5
  *
6
- * Provides a one-command local dashboard bootstrap for SDK users.
6
+ * Provides audit log viewing and other utilities for SDK users.
7
7
  */
8
8
 
9
9
  const { spawnSync } = require("node:child_process");
10
- const fs = require("node:fs");
11
- const os = require("node:os");
12
10
  const path = require("node:path");
13
11
 
14
- const REPO_URL = "https://github.com/lelu-auth/lelu.git";
15
- const STACK_DIR = path.join(os.homedir(), ".lelu-stack");
16
- const DASHBOARD_URL = "http://localhost:3002/audit";
17
-
18
12
  function run(cmd, args, options = {}) {
19
13
  const result = spawnSync(cmd, args, {
20
14
  stdio: "inherit",
@@ -30,40 +24,15 @@ function run(cmd, args, options = {}) {
30
24
  }
31
25
  }
32
26
 
33
- function checkTool(command, name) {
34
- const check = spawnSync(command, ["--version"], { stdio: "ignore", shell: false });
35
- if (check.error || check.status !== 0) {
36
- console.error(`\n${name} is required but was not found in PATH.`);
37
- process.exit(1);
38
- }
27
+ function showAuditLog() {
28
+ const auditScript = path.join(__dirname, "audit-log.js");
29
+ run("node", [auditScript]);
39
30
  }
40
31
 
41
- function ensureRepo() {
42
- if (!fs.existsSync(STACK_DIR)) {
43
- console.log(`\nCloning Lelu stack into ${STACK_DIR} ...`);
44
- run("git", ["clone", "--depth", "1", REPO_URL, STACK_DIR]);
45
- return;
46
- }
47
-
48
- console.log("\nUpdating local Lelu stack...");
49
- run("git", ["-C", STACK_DIR, "checkout", "main"]);
50
- run("git", ["-C", STACK_DIR, "pull", "--ff-only", "origin", "main"]);
51
- }
52
-
53
- function startDashboard() {
54
- checkTool("git", "Git");
55
- checkTool("docker", "Docker");
56
-
57
- ensureRepo();
58
-
59
- console.log("\nStarting local Lelu dashboard stack (this may take a few minutes)...");
60
- run("docker", ["compose", "up", "-d", "--build"], { cwd: STACK_DIR });
61
-
62
- console.log("\nLelu dashboard is ready:");
63
- console.log(` ${DASHBOARD_URL}`);
64
- console.log("\nTo stop later:");
65
- console.log(` cd ${STACK_DIR}`);
66
- console.log(" docker compose down");
32
+ function showPolicies() {
33
+ const policiesScript = path.join(__dirname, "policies.js");
34
+ const args = process.argv.slice(3); // Pass remaining args to policies script
35
+ run("node", [policiesScript, ...args]);
67
36
  }
68
37
 
69
38
  function printHelp() {
@@ -71,16 +40,42 @@ function printHelp() {
71
40
  Lelu CLI
72
41
 
73
42
  Usage:
74
- lelu dashboard Start local dashboard stack and print URL
75
- lelu help Show this help
43
+ lelu audit-log View recent audit events from the platform
44
+ lelu policies Manage authorization policies
45
+ lelu help Show this help
46
+
47
+ Commands:
48
+ audit-log View audit trail and authorization events
49
+ policies list List all policies
50
+ policies get <name> Get a specific policy
51
+ policies set <name> <file> Create or update a policy from file
52
+ policies delete <name> Delete a policy
53
+
54
+ Environment Variables:
55
+ LELU_PLATFORM_URL Platform API URL (default: http://localhost:9091)
56
+ LELU_PLATFORM_API_KEY Platform API key (default: platform-dev-key)
57
+ LELU_TENANT_ID Tenant ID (default: default)
58
+ LELU_AUDIT_LIMIT Number of events to fetch (default: 20)
59
+
60
+ Examples:
61
+ lelu audit-log # View recent audit events
62
+ lelu policies list # List all policies
63
+ lelu policies get auth # View the "auth" policy
64
+ lelu policies set auth ./auth.rego # Create/update policy from file
65
+ LELU_TENANT_ID=prod lelu policies list # Use different tenant
76
66
  `);
77
67
  }
78
68
 
79
69
  function main() {
80
- const command = process.argv[2] || "dashboard";
70
+ const command = process.argv[2] || "help";
71
+
72
+ if (command === "audit-log") {
73
+ showAuditLog();
74
+ return;
75
+ }
81
76
 
82
- if (command === "dashboard") {
83
- startDashboard();
77
+ if (command === "policies") {
78
+ showPolicies();
84
79
  return;
85
80
  }
86
81
 
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Lelu Policies CLI
4
+ async function main() {
5
+ try {
6
+ // Dynamic import to handle ESM module
7
+ const { createClient } = await import('@lelu-auth/lelu');
8
+
9
+ const baseUrl = process.env.LELU_PLATFORM_URL || 'http://localhost:9091';
10
+ const apiKey = process.env.LELU_PLATFORM_API_KEY || 'platform-dev-key';
11
+ const tenantId = process.env.LELU_TENANT_ID || 'default';
12
+
13
+ const command = process.argv[2] || 'list';
14
+ const policyName = process.argv[3];
15
+ const filePath = process.argv[4];
16
+
17
+ const lelu = createClient({ baseUrl, apiKey });
18
+
19
+ // First check if the service is reachable
20
+ try {
21
+ const healthResponse = await fetch(`${baseUrl}/healthz`, {
22
+ method: 'GET',
23
+ signal: AbortSignal.timeout(3000)
24
+ });
25
+ if (!healthResponse.ok) {
26
+ throw new Error('Service not healthy');
27
+ }
28
+ } catch (healthError) {
29
+ console.log('❌ Lelu platform service is not running or not reachable');
30
+ console.log('');
31
+ console.log('To manage policies, you need the Lelu platform service running.');
32
+ console.log('');
33
+ console.log('🚀 Quick start with Docker:');
34
+ console.log(' git clone https://github.com/lelu-auth/lelu.git');
35
+ console.log(' cd lelu');
36
+ console.log(' docker compose up -d');
37
+ console.log(' lelu policies list # Try again');
38
+ console.log('');
39
+ console.log('🌐 Or set LELU_PLATFORM_URL to point to your hosted instance:');
40
+ console.log(' LELU_PLATFORM_URL=https://your-lelu-platform.com lelu policies list');
41
+ console.log('');
42
+ console.log(`💡 Currently trying to connect to: ${baseUrl}`);
43
+ process.exit(1);
44
+ }
45
+
46
+ switch (command) {
47
+ case 'list':
48
+ await listPolicies(lelu, tenantId);
49
+ break;
50
+ case 'get':
51
+ if (!policyName) {
52
+ console.log('❌ Policy name is required');
53
+ console.log('Usage: lelu policies get <policy-name>');
54
+ process.exit(1);
55
+ }
56
+ await getPolicy(lelu, policyName, tenantId);
57
+ break;
58
+ case 'set':
59
+ if (!policyName || !filePath) {
60
+ console.log('❌ Policy name and file path are required');
61
+ console.log('Usage: lelu policies set <policy-name> <file-path>');
62
+ process.exit(1);
63
+ }
64
+ await setPolicy(lelu, policyName, filePath, tenantId);
65
+ break;
66
+ case 'delete':
67
+ if (!policyName) {
68
+ console.log('❌ Policy name is required');
69
+ console.log('Usage: lelu policies delete <policy-name>');
70
+ process.exit(1);
71
+ }
72
+ await deletePolicy(lelu, policyName, tenantId);
73
+ break;
74
+ case 'help':
75
+ case '--help':
76
+ case '-h':
77
+ showHelp();
78
+ break;
79
+ default:
80
+ console.log(`❌ Unknown command: ${command}`);
81
+ showHelp();
82
+ process.exit(1);
83
+ }
84
+
85
+ } catch (err) {
86
+ // Handle other types of errors
87
+ if (err.message && (err.message.includes('ECONNREFUSED') || err.message.includes('fetch failed'))) {
88
+ console.log('❌ Connection failed to Lelu platform service');
89
+ console.log('');
90
+ console.log('🔧 Troubleshooting steps:');
91
+ console.log('1. Ensure the Lelu platform service is running');
92
+ console.log('2. Check the platform URL is correct');
93
+ console.log('3. Verify your network connection');
94
+ console.log('4. Check if firewall is blocking the connection');
95
+ } else {
96
+ console.error('❌ Error:', err.message || err);
97
+ }
98
+ process.exit(1);
99
+ }
100
+ }
101
+
102
+ async function listPolicies(lelu, tenantId) {
103
+ console.log(`Fetching policies from ${lelu.baseUrl}...`);
104
+
105
+ const result = await lelu.listPolicies({ tenantId });
106
+
107
+ if (!result.policies.length) {
108
+ console.log('📋 No policies found.');
109
+ console.log('');
110
+ console.log('This could mean:');
111
+ console.log('- No policies have been created yet');
112
+ console.log('- You are looking at the wrong tenant');
113
+ console.log('- The policies are stored elsewhere');
114
+ return;
115
+ }
116
+
117
+ console.log(`\n📊 Policies (${result.count} total)`);
118
+ console.log('─'.repeat(80));
119
+
120
+ for (const policy of result.policies) {
121
+ const createdAt = new Date(policy.createdAt).toLocaleString();
122
+ const updatedAt = new Date(policy.updatedAt).toLocaleString();
123
+
124
+ console.log(`📄 ${policy.name} (v${policy.version})`);
125
+ console.log(` ID: ${policy.id}`);
126
+ console.log(` Created: ${createdAt}`);
127
+ console.log(` Updated: ${updatedAt}`);
128
+ console.log(` Content: ${policy.content.length} characters`);
129
+ console.log('');
130
+ }
131
+ }
132
+
133
+ async function getPolicy(lelu, name, tenantId) {
134
+ console.log(`Fetching policy "${name}"...`);
135
+
136
+ try {
137
+ const policy = await lelu.getPolicy({ name, tenantId });
138
+
139
+ console.log(`\n📄 Policy: ${policy.name} (v${policy.version})`);
140
+ console.log('─'.repeat(80));
141
+ console.log(`ID: ${policy.id}`);
142
+ console.log(`Tenant: ${policy.tenantId}`);
143
+ console.log(`Created: ${new Date(policy.createdAt).toLocaleString()}`);
144
+ console.log(`Updated: ${new Date(policy.updatedAt).toLocaleString()}`);
145
+ console.log(`HMAC: ${policy.hmacSha256}`);
146
+ console.log('');
147
+ console.log('Content:');
148
+ console.log('─'.repeat(40));
149
+ console.log(policy.content);
150
+
151
+ } catch (err) {
152
+ if (err.status === 404) {
153
+ console.log(`❌ Policy "${name}" not found`);
154
+ console.log('');
155
+ console.log('💡 Use "lelu policies list" to see available policies');
156
+ } else {
157
+ throw err;
158
+ }
159
+ }
160
+ }
161
+
162
+ async function setPolicy(lelu, name, filePath, tenantId) {
163
+ const fs = await import('fs/promises');
164
+
165
+ try {
166
+ const content = await fs.readFile(filePath, 'utf8');
167
+
168
+ console.log(`Setting policy "${name}" from ${filePath}...`);
169
+
170
+ const policy = await lelu.upsertPolicy({
171
+ name,
172
+ content,
173
+ tenantId
174
+ });
175
+
176
+ console.log(`✅ Policy "${name}" saved successfully`);
177
+ console.log(` ID: ${policy.id}`);
178
+ console.log(` Version: ${policy.version}`);
179
+ console.log(` Updated: ${new Date(policy.updatedAt).toLocaleString()}`);
180
+ console.log(` Content: ${content.length} characters`);
181
+
182
+ } catch (err) {
183
+ if (err.code === 'ENOENT') {
184
+ console.log(`❌ File not found: ${filePath}`);
185
+ } else if (err.code === 'EACCES') {
186
+ console.log(`❌ Permission denied reading file: ${filePath}`);
187
+ } else {
188
+ throw err;
189
+ }
190
+ }
191
+ }
192
+
193
+ async function deletePolicy(lelu, name, tenantId) {
194
+ console.log(`Deleting policy "${name}"...`);
195
+
196
+ try {
197
+ const result = await lelu.deletePolicy({ name, tenantId });
198
+
199
+ if (result.deleted) {
200
+ console.log(`✅ Policy "${name}" deleted successfully`);
201
+ } else {
202
+ console.log(`❌ Failed to delete policy "${name}"`);
203
+ }
204
+
205
+ } catch (err) {
206
+ if (err.status === 404) {
207
+ console.log(`❌ Policy "${name}" not found`);
208
+ console.log('');
209
+ console.log('💡 Use "lelu policies list" to see available policies');
210
+ } else {
211
+ throw err;
212
+ }
213
+ }
214
+ }
215
+
216
+ function showHelp() {
217
+ console.log(`
218
+ Lelu Policies CLI
219
+
220
+ Usage:
221
+ lelu policies list List all policies
222
+ lelu policies get <name> Get a specific policy
223
+ lelu policies set <name> <file> Create or update a policy from file
224
+ lelu policies delete <name> Delete a policy
225
+ lelu policies help Show this help
226
+
227
+ Environment Variables:
228
+ LELU_PLATFORM_URL Platform API URL (default: http://localhost:9091)
229
+ LELU_PLATFORM_API_KEY Platform API key (default: platform-dev-key)
230
+ LELU_TENANT_ID Tenant ID (default: default)
231
+
232
+ Examples:
233
+ lelu policies list # List all policies
234
+ lelu policies get auth # View the "auth" policy
235
+ lelu policies set auth ./auth.rego # Create/update auth policy from file
236
+ lelu policies delete old-policy # Delete a policy
237
+ LELU_TENANT_ID=prod lelu policies list # List policies for prod tenant
238
+ `);
239
+ }
240
+
241
+ main();