Skip to content

Add DNS and CG endpoints to test server - #1074

Open
PaulJouvanceau wants to merge 1 commit into
opensvc:mainfrom
PaulJouvanceau:feat/dns-alias-cname-records
Open

Add DNS and CG endpoints to test server#1074
PaulJouvanceau wants to merge 1 commit into
opensvc:mainfrom
PaulJouvanceau:feat/dns-alias-cname-records

Conversation

@PaulJouvanceau

Copy link
Copy Markdown
Contributor
  • Extend util/sgcpserverfortest/main.go with handlers for the new SGCP DNS CNAME records API (list, create, get, update/patch, delete) and a basic CG endpoint.
  • Add util/sgcpserverfortest/users.yaml for test credentials.
  • Add util/sgcpserverfortest/qa.sh to test the server endpoints, covering auth token, filesystem, CG, and DNS alias lifecycle.

@PaulJouvanceau
PaulJouvanceau force-pushed the feat/dns-alias-cname-records branch from 8947ae2 to ae645d5 Compare August 25, 2026 07:07
@PaulJouvanceau PaulJouvanceau changed the title Add DNS and CG endpoints to test server and QA script Add DNS and CG endpoints to test server Aug 25, 2026
- Extend util/sgcpserverfortest/main.go with handlers for the new
  SGCP DNS CNAME records API (list, create, get, update/patch, delete)
  and a basic CG endpoint.
- Add util/sgcpserverfortest/users.yaml for test credentials.
@PaulJouvanceau
PaulJouvanceau force-pushed the feat/dns-alias-cname-records branch from ae645d5 to aaaaf5b Compare August 27, 2026 14:51
Comment on lines +341 to +345
ListDnsAliases = "GET /dns/zones/{zoneID}/cname-records"
CreateDnsAlias = "POST /dns/zones/{zoneID}/cname-records"
GetDnsAlias = "GET /dns/zones/{zoneID}/cname-records/{id}"
UpdateDnsAlias = "PATCH /dns/zones/{zoneID}/cname-records/{id}"
DeleteDnsAlias = "DELETE /dns/zones/{zoneID}/cname-records/{id}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium - DNS test server no longer serves the configured client paths

The server replaces the existing /dns/zone/{zoneID}/cname-entry handler with /dns/zones/{zoneID}/cname-records, but the SGCP client still constructs the former path from the repository's test configuration. Running the DNS client against this test server therefore receives a 404 for list/create/update/delete operations instead of exercising the new implementation, breaking the test-server integration.

Show fix

Either retain the existing /dns/zone/{zoneID}/cname-entry route (and add the new API routes), or update the client/configuration and all consumers in the same change so the configured DNS paths match the server routes. Add an end-to-end test that starts this server and verifies the URL generated by util/sgcp/dns.go reaches the handler.

More info - Reply on this comment to give feedback or ignore the issue.

func dnsCreateAlias(w http.ResponseWriter, r *http.Request) {
zoneID := r.PathValue("zoneID")
slog.Info(CreateDnsAlias, "zoneID", zoneID)
if !assertAuth(CreateDnsAlias, w, r, "account1:sgcp:dns:read", "account1:sgcp:dns:write") {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium - DNS write operations reject the scopes issued by the client

The new create, update, and delete handlers require both the DNS read and DNS write scope, while util/sgcp/dns.go requests only dns_write for each of those operations. With the repository test configuration mapping that request to only dns:write, valid write tokens receive 403 and none of the mutating DNS paths can be exercised.

Show fix

Require only the write scope for create, update, and delete handlers, matching the client calls, or change the client contract to request both scopes and update the token configuration consistently. Add integration coverage for each operation using the exact scopes emitted by DNSAPI.

More info - Reply on this comment to give feedback or ignore the issue.

return
}
// Use search by id
a, ok := dnsApi.DB.Search(zoneID, "", id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium - DNS alias IDs bypass the requested zone boundary

The new GET, PATCH, and DELETE handlers pass an empty name when looking up an alias by path ID, and the helper falls back to its global byId index whenever name is empty, ignoring the supplied zone ID. A caller who knows an alias UUID can therefore read it through another zone path or update/delete it while presenting that other zone, violating the zone/resource binding expected by these routes.

Show fix

Make ID lookups require both the UUID and zone ID, for example by validating the returned alias's ZoneID against the path before returning or mutating it, and make the helper's UUID index zone-aware. Add tests that create or seed an alias in zone A and assert that GET, PATCH, and DELETE through zone B return not found without changing the zone-A record.

More info - Reply on this comment to give feedback or ignore the issue.

func dnsCreateAlias(w http.ResponseWriter, r *http.Request) {
zoneID := r.PathValue("zoneID")
slog.Info(CreateDnsAlias, "zoneID", zoneID)
if !assertAuth(CreateDnsAlias, w, r, "account1:sgcp:dns:read", "account1:sgcp:dns:write") {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium - New DNS and CG routes accept forged Authorization headers

The new handlers rely on assertAuth, which only checks whether the raw Authorization header contains each scope string and never verifies a Bearer scheme, token issuance, signature, or client identity. Consequently, any caller who can reach this listener can invoke the new DNS mutations or CG endpoint by sending arbitrary text containing the required scope names, without obtaining credentials; this extends the pre-existing weak check to newly added privileged operations.

Show fix

Validate the authorization scheme and token against the token issued by postAuthToken (or use a real signed/opaque-token verifier), derive scopes from the validated principal rather than substring matching, and return 401/403 for invalid tokens. Add tests proving that arbitrary headers and tokens with similar-but-unissued text cannot access each new route.

More info - Reply on this comment to give feedback or ignore the issue.

if !assertAuth(ListDnsAliases, w, r, "account1:sgcp:dns:read") {
return
}
_, _, code, data, err := dnsApi.GetAliases(r.Context(), zoneID, name, id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium - Listing DNS aliases without filters always returns 404

The new list handler forwards empty name and id when the caller requests all aliases, but the helper's search function has no empty-filter case and reports no match. As a result, the endpoint returns 404 for a valid list-all request instead of a successful cnameRecords response, so clients cannot enumerate aliases when neither filter is supplied.

Show fix

Implement an explicit list-all path in the helper that returns all aliases in the requested zone, with a 200 response and an empty cnameRecords array when there are no matches. Preserve filtered lookup semantics separately and add tests for list-all on populated and empty zones.

More info - Reply on this comment to give feedback or ignore the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant