@meshxdata/fops 0.1.45 → 0.1.46

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 (33) hide show
  1. package/CHANGELOG.md +16 -18
  2. package/package.json +1 -1
  3. package/src/commands/lifecycle.js +81 -5
  4. package/src/commands/setup.js +45 -4
  5. package/src/plugins/bundled/fops-plugin-azure/index.js +29 -0
  6. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-core.js +1185 -0
  7. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-flux.js +1180 -0
  8. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-ingress.js +393 -0
  9. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-naming.js +104 -0
  10. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-network.js +296 -0
  11. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-postgres.js +768 -0
  12. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-reconcilers.js +538 -0
  13. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-secrets.js +849 -0
  14. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-stacks.js +643 -0
  15. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-state.js +145 -0
  16. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-storage.js +496 -0
  17. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-terraform.js +1032 -0
  18. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks.js +155 -4245
  19. package/src/plugins/bundled/fops-plugin-azure/lib/azure-keyvault.js +186 -0
  20. package/src/plugins/bundled/fops-plugin-azure/lib/azure-results.js +5 -0
  21. package/src/plugins/bundled/fops-plugin-azure/lib/commands/infra-cmds.js +758 -0
  22. package/src/plugins/bundled/fops-plugin-azure/lib/commands/registry-cmds.js +250 -0
  23. package/src/plugins/bundled/fops-plugin-azure/lib/commands/test-cmds.js +2 -1
  24. package/src/plugins/bundled/fops-plugin-foundation/lib/apply.js +3 -2
  25. package/src/plugins/bundled/fops-plugin-foundation/lib/helpers.js +21 -0
  26. package/src/plugins/bundled/fops-plugin-foundation/lib/tools-read.js +3 -5
  27. package/src/ui/tui/App.js +13 -13
  28. package/src/web/dist/assets/index-NXC8Hvnp.css +1 -0
  29. package/src/web/dist/assets/index-QH1N4ejK.js +112 -0
  30. package/src/web/dist/index.html +2 -2
  31. package/src/web/server.js +4 -4
  32. package/src/web/dist/assets/index-BphVaAUd.css +0 -1
  33. package/src/web/dist/assets/index-CSckLzuG.js +0 -129
@@ -1253,6 +1253,192 @@ export async function keyvaultSetup(opts = {}) {
1253
1253
  console.log(chalk.bold.green(`\n Setup complete! Run: fops azure keyvault sync\n`));
1254
1254
  }
1255
1255
 
1256
+ // ═══════════════════════════════════════════════════════════════════════════
1257
+ // Network configuration (VNet integration, service endpoints)
1258
+ // ═══════════════════════════════════════════════════════════════════════════
1259
+
1260
+ export async function networkShow(opts = {}) {
1261
+ const execa = await lazyExeca();
1262
+ const sub = opts.profile;
1263
+ await ensureAzCli(execa);
1264
+ await ensureAzAuth(execa, { subscription: sub });
1265
+
1266
+ const vault = await resolveVault(execa, opts.vault, sub);
1267
+
1268
+ const { stdout } = await execa("az", [
1269
+ "keyvault", "show", "--name", vault, "--output", "json", ...subArgs(sub),
1270
+ ], { timeout: 30000 });
1271
+
1272
+ const v = JSON.parse(stdout);
1273
+ const props = v.properties || {};
1274
+ const networkRules = props.networkAcls || {};
1275
+
1276
+ banner(`Network Config — "${vault}"`);
1277
+ kvLine("Public Access", props.publicNetworkAccess === "Disabled" ? OK("disabled") : WARN("enabled"));
1278
+ kvLine("Default Action", networkRules.defaultAction === "Deny" ? OK("Deny") : WARN(networkRules.defaultAction || "Allow"));
1279
+ kvLine("Bypass", DIM(networkRules.bypass || "AzureServices"));
1280
+
1281
+ const ipRules = networkRules.ipRules || [];
1282
+ const vnetRules = networkRules.virtualNetworkRules || [];
1283
+
1284
+ console.log("");
1285
+ if (ipRules.length > 0) {
1286
+ console.log(ACCENT(" IP Rules"));
1287
+ for (const r of ipRules) {
1288
+ console.log(` ${DIM("•")} ${r.value}`);
1289
+ }
1290
+ } else {
1291
+ kvLine("IP Rules", DIM("none"));
1292
+ }
1293
+
1294
+ if (vnetRules.length > 0) {
1295
+ console.log(ACCENT(" VNet Rules"));
1296
+ for (const r of vnetRules) {
1297
+ const subnetId = r.id || "";
1298
+ const parts = subnetId.split("/");
1299
+ const vnet = parts[parts.indexOf("virtualNetworks") + 1] || "";
1300
+ const subnet = parts[parts.indexOf("subnets") + 1] || "";
1301
+ console.log(` ${DIM("•")} ${vnet}/${subnet}`);
1302
+ }
1303
+ } else {
1304
+ kvLine("VNet Rules", DIM("none"));
1305
+ }
1306
+
1307
+ console.log("");
1308
+ hint("Add VNet: fops azure keyvault network add-vnet --vault <name> --vnet <vnet> --subnet <subnet>");
1309
+ hint("Private: fops azure keyvault network private --vault <name>\n");
1310
+ }
1311
+
1312
+ export async function networkAddVnet(opts = {}) {
1313
+ const execa = await lazyExeca();
1314
+ const sub = opts.profile;
1315
+ await ensureAzCli(execa);
1316
+ await ensureAzAuth(execa, { subscription: sub });
1317
+
1318
+ const vault = await resolveVault(execa, opts.vault, sub);
1319
+
1320
+ if (!opts.vnet || !opts.subnet) {
1321
+ console.error(chalk.red("\n --vnet and --subnet are required.\n"));
1322
+ process.exit(1);
1323
+ }
1324
+
1325
+ const rg = opts.resourceGroup || opts.vnetResourceGroup;
1326
+
1327
+ // 1. Add service endpoint to subnet if not present
1328
+ hint(`Adding Microsoft.KeyVault service endpoint to ${opts.vnet}/${opts.subnet}...`);
1329
+
1330
+ const subnetArgs = [
1331
+ "network", "vnet", "subnet", "update",
1332
+ "--vnet-name", opts.vnet,
1333
+ "-n", opts.subnet,
1334
+ "--service-endpoints", "Microsoft.KeyVault",
1335
+ "--output", "none",
1336
+ ...subArgs(sub),
1337
+ ];
1338
+ if (rg) subnetArgs.push("-g", rg);
1339
+
1340
+ const { exitCode: seCode, stderr: seErr } = await execa("az", subnetArgs, { timeout: 120000, reject: false });
1341
+ if (seCode !== 0) {
1342
+ console.log(WARN(` ⚠ Service endpoint: ${(seErr || "").split("\n")[0]}`));
1343
+ } else {
1344
+ console.log(OK(" ✓ Service endpoint added"));
1345
+ }
1346
+
1347
+ // 2. Get subnet resource ID
1348
+ const subnetShowArgs = [
1349
+ "network", "vnet", "subnet", "show",
1350
+ "--vnet-name", opts.vnet,
1351
+ "-n", opts.subnet,
1352
+ "--query", "id", "-o", "tsv",
1353
+ ...subArgs(sub),
1354
+ ];
1355
+ if (rg) subnetShowArgs.push("-g", rg);
1356
+
1357
+ const { stdout: subnetId, exitCode: sidCode, stderr: sidErr } = await execa("az", subnetShowArgs, { timeout: 30000, reject: false });
1358
+ if (sidCode !== 0 || !subnetId?.trim()) {
1359
+ console.error(chalk.red(`\n ✗ Could not find subnet: ${(sidErr || "").split("\n")[0]}\n`));
1360
+ process.exit(1);
1361
+ }
1362
+
1363
+ // 3. Add VNet rule to Key Vault
1364
+ hint(`Adding VNet rule to Key Vault "${vault}"...`);
1365
+
1366
+ const { exitCode, stderr } = await execa("az", [
1367
+ "keyvault", "network-rule", "add",
1368
+ "--name", vault,
1369
+ "--subnet", subnetId.trim(),
1370
+ "--output", "none",
1371
+ ...subArgs(sub),
1372
+ ], { timeout: 60000, reject: false });
1373
+
1374
+ if (exitCode !== 0) {
1375
+ console.error(chalk.red(`\n ✗ ${(stderr || "").split("\n")[0]}\n`));
1376
+ process.exit(1);
1377
+ }
1378
+
1379
+ console.log(OK(` ✓ VNet rule added: ${opts.vnet}/${opts.subnet}`));
1380
+ hint(`\nSet to private: fops azure keyvault network private --vault ${vault}\n`);
1381
+ }
1382
+
1383
+ export async function networkPrivate(opts = {}) {
1384
+ const execa = await lazyExeca();
1385
+ const sub = opts.profile;
1386
+ await ensureAzCli(execa);
1387
+ await ensureAzAuth(execa, { subscription: sub });
1388
+
1389
+ const vault = await resolveVault(execa, opts.vault, sub);
1390
+
1391
+ hint(`Setting "${vault}" to private (deny public access)...`);
1392
+
1393
+ const { exitCode, stderr } = await execa("az", [
1394
+ "keyvault", "update",
1395
+ "--name", vault,
1396
+ "--default-action", "Deny",
1397
+ "--bypass", "AzureServices",
1398
+ "--output", "none",
1399
+ ...subArgs(sub),
1400
+ ], { timeout: 60000, reject: false });
1401
+
1402
+ if (exitCode !== 0) {
1403
+ console.error(chalk.red(`\n ✗ ${(stderr || "").split("\n")[0]}\n`));
1404
+ process.exit(1);
1405
+ }
1406
+
1407
+ console.log(OK(` ✓ Key Vault "${vault}" is now private`));
1408
+ console.log(DIM(" Default action: Deny"));
1409
+ console.log(DIM(" Bypass: AzureServices"));
1410
+ hint("\nAccess limited to allowed VNets/IPs and Azure services.\n");
1411
+ }
1412
+
1413
+ export async function networkPublic(opts = {}) {
1414
+ const execa = await lazyExeca();
1415
+ const sub = opts.profile;
1416
+ await ensureAzCli(execa);
1417
+ await ensureAzAuth(execa, { subscription: sub });
1418
+
1419
+ const vault = await resolveVault(execa, opts.vault, sub);
1420
+
1421
+ const { resolveCliSrc } = await import("./azure-helpers.js");
1422
+ const { confirm } = await import(resolveCliSrc("ui/confirm.js"));
1423
+ const yes = await confirm(` Make Key Vault "${vault}" publicly accessible?`);
1424
+ if (!yes) { console.log(DIM("\n Cancelled.\n")); return; }
1425
+
1426
+ const { exitCode, stderr } = await execa("az", [
1427
+ "keyvault", "update",
1428
+ "--name", vault,
1429
+ "--default-action", "Allow",
1430
+ "--output", "none",
1431
+ ...subArgs(sub),
1432
+ ], { timeout: 60000, reject: false });
1433
+
1434
+ if (exitCode !== 0) {
1435
+ console.error(chalk.red(`\n ✗ ${(stderr || "").split("\n")[0]}\n`));
1436
+ process.exit(1);
1437
+ }
1438
+
1439
+ console.log(WARN(` ⚠ Key Vault "${vault}" is now public`));
1440
+ }
1441
+
1256
1442
  // ── Config helpers ──────────────────────────────────────────────────────────
1257
1443
 
1258
1444
  function readFopsConfig() {
@@ -421,6 +421,11 @@ export async function resultsShow(opts = {}) {
421
421
  process.exit(1);
422
422
  }
423
423
 
424
+ if (opts.json) {
425
+ console.log(JSON.stringify(result, null, 2));
426
+ return;
427
+ }
428
+
424
429
  banner(`Test Result: ${target}`);
425
430
  kvLine("Passed", result.passed ? OK("yes") : ERR("no"));
426
431
  kvLine("Exit code", String(result.exitCode ?? "–"));