Skip to content

pkg/connectors: GetKeycloakURL panics on malformed Keycloak config response #395

@hazelmayank

Description

@hazelmayank

Describe the bug

GetKeycloakURL in pkg/connectors/microcks_client.go parses the response from /api/keycloak/config using direct, single-value type assertions:

// pkg/connectors/microcks_client.go:240-242
enabled := configResp["enabled"].(bool)
authServerURL := configResp["auth-server-url"].(string)
realmName := configResp["realm"].(string)

If the response is missing any of these fields, or if a field has an unexpected type, the assertion panics rather than producing the error value the function's signature already promises. The CLI then crashes with a Go stack trace.


Expected behavior

A malformed or unexpected response from /api/keycloak/config should cause GetKeycloakURL to return a descriptive error. Valid responses (Keycloak enabled or Keycloak disabled) should continue to work exactly as today.


Actual behavior

The CLI panics with an interface-conversion error similar to:

panic: interface conversion: interface {} is nil, not bool

goroutine 1 [running]:
github.com/microcks/microcks-cli/pkg/connectors.(*microcksClient).GetKeycloakURL(...)
        pkg/connectors/microcks_client.go:240

The process exits via panic instead of via the (string, error) return path the function already declares.


How to Reproduce?

Minimal Go reproducer using httptest:

package main

import (
    "net/http"
    "net/http/httptest"

    "github.com/microcks/microcks-cli/pkg/connectors"
)

func main() {
    s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        w.Write([]byte(`{}`)) // missing 'enabled', 'auth-server-url', 'realm'
    }))
    defer s.Close()

    c := connectors.NewMicrocksClient(s.URL)
    _, _ = c.GetKeycloakURL() // panics here
}

Run with:

go run main.go

Observe the panic instead of a clean error.


Microcks version or git rev

master


Install method (docker-compose, helm chart, operator, docker-desktop extension,...)

go run .


Additional information

Why this matters. GetKeycloakURL sits in the connector/API layer used by every authenticated CLI command (login, import, test, ...). A Microcks server upgrade, a stub/mock server during local development, or a transient gateway returning HTML can crash the CLI instead of producing a clean error message. The function already returns (string, error); the panic path is inconsistent with its own signature.

Root cause. Three single-value type assertions on a map[string]interface{} parsed from the response body:

enabled := configResp["enabled"].(bool)
authServerURL := configResp["auth-server-url"].(string)
realmName := configResp["realm"].(string)

A single-value type assertion panics if the asserted type does not match. The two-value (comma-ok) form returns (value, false) instead, which lets the function surface the problem as an error.

Proposed fix. Switch to the comma-ok form on each assertion and return a descriptive error when a field is missing or wrong-typed. The early return "null", nil for the Keycloak-disabled case is preserved:

enabled, ok := configResp["enabled"].(bool)
if !ok {
    return "", fmt.Errorf("Microcks /api/keycloak/config response missing or invalid 'enabled' field")
}
if !enabled {
    return "null", nil
}
authServerURL, ok := configResp["auth-server-url"].(string)
if !ok {
    return "", fmt.Errorf("Microcks /api/keycloak/config response missing or invalid 'auth-server-url' field")
}
realmName, ok := configResp["realm"].(string)
if !ok {
    return "", fmt.Errorf("Microcks /api/keycloak/config response missing or invalid 'realm' field")
}
return authServerURL + "/realms/" + realmName + "/", nil

This preserves both currently-working cases (enabled and disabled Keycloak) and replaces the panic with the same error-return contract the function already advertises.

Test plan. Extend pkg/connectors/microcks_client_test.go using the existing httptest.NewServer pattern already used by TestDownloadArtifactReturnsResponseBody:

  1. Valid Keycloak-enabled response — server returns {"enabled": true, "auth-server-url": "https://kc", "realm": "microcks"} → expect "https://kc/realms/microcks/" and nil error.
  2. Keycloak-disabled response — server returns {"enabled": false} → expect "null" and nil error.
  3. Malformed response — server returns {} → expect a non-nil error and no panic.

A similar single-value-assertion pattern exists in pkg/connectors/keycloak_client.go (e.g. ConnectAndGetToken). I am intentionally calling it out here but leaving it to a separate follow-up PR to keep this issue's scope tight.

I would like to send a small PR for this if the maintainers agree on the approach.

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

No response

Microcks version or git rev

No response

Install method (docker-compose, helm chart, operator, docker-desktop extension,...)

No response

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions