Merge pull request #311 from sissl0/main

feat: added registry_url query param to /osm/api/registry-info endpoint
This commit is contained in:
Jessie Ho (j3ssie)
2026-08-08 13:56:28 +08:00
committed by GitHub
6 changed files with 100 additions and 4 deletions
+6
View File
@@ -1040,6 +1040,12 @@ const docTemplate = `{
"description": "Registry mode: direct-fetch or nix-build",
"name": "registry_mode",
"in": "query"
},
{
"type": "string",
"description": "Custom registry URL or local file path. In direct-fetch mode: source for the full binary list. In nix-build mode: metadata overlay (desc, tags, version).",
"name": "registry_url",
"in": "query"
}
],
"responses": {
+6
View File
@@ -1029,6 +1029,12 @@
"description": "Registry mode: direct-fetch or nix-build",
"name": "registry_mode",
"in": "query"
},
{
"type": "string",
"description": "Custom registry URL or local file path. In direct-fetch mode: source for the full binary list. In nix-build mode: metadata overlay (desc, tags, version).",
"name": "registry_url",
"in": "query"
}
],
"responses": {
+6
View File
@@ -1184,6 +1184,12 @@ paths:
in: query
name: registry_mode
type: string
- description: 'Custom registry URL or local file path. In direct-fetch mode:
source for the full binary list. In nix-build mode: metadata overlay (desc,
tags, version).'
in: query
name: registry_url
type: string
produces:
- application/json
responses:
+20
View File
@@ -16,6 +16,7 @@ Fetch binary registry metadata with installation status. Supports two modes:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `registry_mode` | string | `direct-fetch` | Registry mode: `direct-fetch` or `nix-build` |
| `registry_url` | string | _(embedded)_ | Custom registry URL or local file path. **Direct-fetch mode**: source for the full binary list. **Nix-build mode**: metadata overlay (desc, tags, version). Accepts HTTPS URLs or absolute file paths. |
---
@@ -28,6 +29,18 @@ curl http://localhost:8002/osm/api/registry-info \
-H "Authorization: Bearer $TOKEN"
```
**With a custom registry URL:**
```bash
curl "http://localhost:8002/osm/api/registry-info?registry_url=https://example.com/my-registry.json" \
-H "Authorization: Bearer $TOKEN"
```
**With a local file path:**
```bash
curl "http://localhost:8002/osm/api/registry-info?registry_url=/etc/osmedeus/registry.json" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
@@ -95,6 +108,12 @@ curl "http://localhost:8002/osm/api/registry-info?registry_mode=nix-build" \
-H "Authorization: Bearer $TOKEN"
```
**With a custom metadata registry:**
```bash
curl "http://localhost:8002/osm/api/registry-info?registry_mode=nix-build&registry_url=/etc/osmedeus/registry.json" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
@@ -144,6 +163,7 @@ curl "http://localhost:8002/osm/api/registry-info?registry_mode=nix-build" \
| Field | Type | Description |
|-------|------|-------------|
| `registry_mode` | string | Always `"nix-build"` |
| `registry_url` | string | Registry URL or file path used for metadata (empty string = embedded) |
| `nix_installed` | boolean | Whether Nix package manager is installed |
| `categories` | array | List of tool categories from flake.nix |
| `categories[].name` | string | Category name (e.g., "Subdomain", "Vuln") |
+13 -4
View File
@@ -16,6 +16,7 @@ import (
// @Tags Install
// @Produce json
// @Param registry_mode query string false "Registry mode: direct-fetch or nix-build" default(direct-fetch)
// @Param registry_url query string false "Custom registry URL or local file path. In direct-fetch mode: source for the full binary list. In nix-build mode: metadata overlay (desc, tags, version)."
// @Success 200 {object} map[string]interface{} "Registry data"
// @Failure 500 {object} map[string]interface{} "Failed to load registry"
// @Security BearerAuth
@@ -37,7 +38,8 @@ func GetRegistryInfo(cfg *config.Config) fiber.Handler {
// getDirectFetchRegistry returns the direct-fetch registry (existing behavior)
func getDirectFetchRegistry(c *fiber.Ctx) error {
registry, err := installer.LoadRegistry("", nil)
registryPathOrURL := c.Query("registry_url", "")
registry, err := installer.LoadRegistry(registryPathOrURL, nil)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": true,
@@ -45,6 +47,11 @@ func getDirectFetchRegistry(c *fiber.Ctx) error {
})
}
// Using installer.DefaultRegistryURL as default for query would break LoadRegistry logic
if registryPathOrURL == "" {
registryPathOrURL = installer.DefaultRegistryURL
}
// Build response with installation status for each binary
binariesWithStatus := make(map[string]BinaryStatusEntry)
for name, entry := range registry {
@@ -71,7 +78,7 @@ func getDirectFetchRegistry(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"registry_mode": "direct-fetch",
"registry_url": installer.DefaultRegistryURL,
"registry_url": registryPathOrURL,
"binaries": binariesWithStatus,
})
}
@@ -95,8 +102,9 @@ func getNixBuildRegistry(c *fiber.Ctx) error {
})
}
// Load registry for metadata (desc, tags)
registry, _ := installer.LoadRegistry("", nil)
// Load registry for metadata (desc, tags) - use custom registry_url if provided
registryPathOrURL := c.Query("registry_url", "")
registry, _ := installer.LoadRegistry(registryPathOrURL, nil)
// Build response with categories and tool metadata
categoriesData := make([]map[string]interface{}, 0)
@@ -138,6 +146,7 @@ func getNixBuildRegistry(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"registry_mode": "nix-build",
"registry_url": registryPathOrURL,
"nix_installed": installer.IsNixInstalled(),
"categories": categoriesData,
})
+49
View File
@@ -8,7 +8,10 @@ import (
"io"
"net"
"net/http"
"net/url"
"os/exec"
"path/filepath"
"runtime"
"testing"
"time"
@@ -469,16 +472,62 @@ func testScheduleEndpoints(t *testing.T, log *TestLogger) {
log.Success("Schedule endpoints OK")
}
// getPresetRegistryPath returns the absolute path to the bundled direct-fetch registry file
func getPresetRegistryPath(t *testing.T) string {
t.Helper()
_, filename, _, ok := runtime.Caller(0)
if !ok {
t.Fatal("Failed to get caller info")
}
return filepath.Join(filepath.Dir(filename), "..", "..", "public", "presets", "registry-metadata-direct-fetch.json")
}
// testRegistryEndpoint tests metadata registry endpoint
func testRegistryEndpoint(t *testing.T, log *TestLogger) {
log.Info("Testing registry endpoint")
presetRegistryPath := getPresetRegistryPath(t)
// Default: embedded registry, direct-fetch mode
log.Info("Testing default registry (embedded)")
resp := apiGet(t, "/osm/api/registry-info")
assert.Equal(t, 200, resp.StatusCode, "GET /osm/api/registry-info should return 200")
body := parseJSONResponse(t, resp)
assert.Equal(t, "direct-fetch", body["registry_mode"], "Default mode should be direct-fetch")
assert.Contains(t, body, "registry_url", "Should contain registry_url")
assert.Contains(t, body, "binaries", "Should contain binaries")
// direct-fetch with local preset registry file https://github.com/j3ssie/osmedeus/blob/d5aa39ba30545102a8c9717801f16879f8197736/public/presets/registry-metadata-direct-fetch.json
log.Info("Testing registry_url with preset file (direct-fetch)")
encodedPath := url.QueryEscape(presetRegistryPath)
resp = apiGet(t, "/osm/api/registry-info?registry_url="+encodedPath)
assert.Equal(t, 200, resp.StatusCode, "GET /osm/api/registry-info with preset file should return 200")
body = parseJSONResponse(t, resp)
assert.Equal(t, "direct-fetch", body["registry_mode"], "Mode should be direct-fetch")
assert.Equal(t, presetRegistryPath, body["registry_url"], "registry_url in response should match the path passed")
binaries, ok := body["binaries"].(map[string]interface{})
assert.True(t, ok, "Binaries should be a map")
assert.Contains(t, binaries, "amass", "Preset registry should contain amass")
assert.Contains(t, binaries, "nuclei", "Preset registry should contain nuclei")
// nix-build mode (may or may not have Nix; endpoint must respond regardless)
log.Info("Testing registry_mode=nix-build (no custom registry_url)")
resp = apiGet(t, "/osm/api/registry-info?registry_mode=nix-build")
assert.Equal(t, 200, resp.StatusCode, "GET /osm/api/registry-info?registry_mode=nix-build should return 200")
body = parseJSONResponse(t, resp)
assert.Equal(t, "nix-build", body["registry_mode"], "Mode should be nix-build")
assert.Contains(t, body, "nix_installed", "Should contain nix_installed field")
assert.Contains(t, body, "categories", "Should contain categories")
assert.Contains(t, body, "registry_url", "nix-build response should contain registry_url")
// nix-build mode with preset registry_url for metadata overlay
log.Info("Testing registry_mode=nix-build with preset registry_url for metadata")
resp = apiGet(t, "/osm/api/registry-info?registry_mode=nix-build&registry_url="+encodedPath)
assert.Equal(t, 200, resp.StatusCode, "GET /osm/api/registry-info nix-build+registry_url should return 200")
body = parseJSONResponse(t, resp)
assert.Equal(t, "nix-build", body["registry_mode"], "Mode should be nix-build")
assert.Equal(t, presetRegistryPath, body["registry_url"], "registry_url in nix-build response should match the path passed")
log.Success("Registry endpoint OK")
}