Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ microcks login http://localhost:8080 --sso --sso-launch-browser=false
os.Exit(1)
}
//Perform login and retrive tokens
authToken, refreshToken = passwordLogin(keycloakUrl, clientID, clientSecret, username, password)
var loginErr error
authToken, refreshToken, loginErr = passwordLogin(keycloakUrl, clientID, clientSecret, username, password)
if loginErr != nil {
log.Fatal(loginErr)
}
authCfg.ClientId = clientID
authCfg.ClientSecret = clientSecret
} else {
Expand Down Expand Up @@ -308,17 +312,16 @@ func ssoAuthFlow(url string, ssoLaunchBrowser bool) {
}
}

func passwordLogin(keycloakURL, clientId, clientSecret, Username, Password string) (string, string) {
func passwordLogin(keycloakURL, clientId, clientSecret, Username, Password string) (string, string, error) {
kc := connectors.NewKeycloakClient(keycloakURL, clientId, clientSecret)
username, password := promptCredentials(Username, Password)

authToken, refreshToken, err := kc.ConnectAndGetTokenAndRefreshToken(username, password)

if err != nil {
panic(err)
return "", "", err
}

return authToken, refreshToken
return authToken, refreshToken, nil
}

func promptCredentials(username, password string) (string, string) {
Expand Down
45 changes: 33 additions & 12 deletions pkg/connectors/keycloak_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,23 @@ func (c *keycloakClient) ConnectAndGetToken() (string, error) {

body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
return "", fmt.Errorf("failed to read response body: %w", err)
}

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("keycloak returned HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}

var openIDResp map[string]interface{}
if err := json.Unmarshal(body, &openIDResp); err != nil {
panic(err)
return "", fmt.Errorf("failed to parse token response: %w", err)
}

accessToken := openIDResp["access_token"].(string)
return accessToken, err
accessToken, ok := openIDResp["access_token"].(string)
if !ok || accessToken == "" {
return "", fmt.Errorf("keycloak response missing 'access_token'")
}
return accessToken, nil
}

func (c *keycloakClient) GetOIDCConfig() (*oauth2.Config, error) {
Expand All @@ -127,16 +134,23 @@ func (c *keycloakClient) GetOIDCConfig() (*oauth2.Config, error) {

body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
return nil, fmt.Errorf("failed to read response body: %w", err)
}

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("keycloak returned HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}

var openIDResp map[string]interface{}
if err := json.Unmarshal(body, &openIDResp); err != nil {
panic(err)
return nil, fmt.Errorf("failed to parse OIDC config response: %w", err)
}

authURL := openIDResp["authorization_endpoint"].(string)
tokenURL := openIDResp["token_endpoint"].(string)
authURL, ok1 := openIDResp["authorization_endpoint"].(string)
tokenURL, ok2 := openIDResp["token_endpoint"].(string)
if !ok1 || !ok2 {
return nil, fmt.Errorf("OIDC config response missing 'authorization_endpoint' or 'token_endpoint'")
}

return &oauth2.Config{
Endpoint: oauth2.Endpoint{
Expand Down Expand Up @@ -174,16 +188,23 @@ func (c *keycloakClient) ConnectAndGetTokenAndRefreshToken(username, password st

body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
return "", "", fmt.Errorf("failed to read response body: %w", err)
}

if resp.StatusCode != http.StatusOK {
return "", "", fmt.Errorf("keycloak returned HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}

var openIDResp map[string]interface{}
if err := json.Unmarshal(body, &openIDResp); err != nil {
panic(err)
return "", "", fmt.Errorf("failed to parse token response: %w", err)
}

authToken := openIDResp["access_token"].(string)
refreshToken := openIDResp["refresh_token"].(string)
authToken, ok1 := openIDResp["access_token"].(string)
refreshToken, ok2 := openIDResp["refresh_token"].(string)
if !ok1 || !ok2 {
return "", "", fmt.Errorf("keycloak response missing 'access_token' or 'refresh_token'")
}

return authToken, refreshToken, nil
}
29 changes: 19 additions & 10 deletions pkg/connectors/microcks_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,21 +239,26 @@ func (c *microcksClient) GetKeycloakURL() (string, error) {

body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
return "", fmt.Errorf("failed to read response body: %w", err)
}

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("microcks returned HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}

var configResp map[string]interface{}
if err := json.Unmarshal(body, &configResp); err != nil {
panic(err)
return "", fmt.Errorf("failed to parse keycloak config response (is the server URL correct?): %w", err)
}

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

// Return a proper URL or 'null' if Keycloak is disables.
enabled, _ := configResp["enabled"].(bool)
if enabled {
authServerURL, ok1 := configResp["auth-server-url"].(string)
realmName, ok2 := configResp["realm"].(string)
if !ok1 || !ok2 {
return "", fmt.Errorf("invalid keycloak config response (missing 'auth-server-url' or 'realm')")
}
return authServerURL + "/realms/" + realmName + "/", nil
}
return "null", nil
Expand Down Expand Up @@ -425,7 +430,11 @@ func (c *microcksClient) GetTestResult(testResultID string) (*TestResultSummary,

body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
return nil, fmt.Errorf("failed to read response body: %w", err)
}

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("microcks returned HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}

result := TestResultSummary{}
Expand Down Expand Up @@ -558,15 +567,15 @@ func (c *microcksClient) DownloadArtifact(artifactURL string, mainArtifact bool,

respBody, err := io.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
return "", fmt.Errorf("failed to read response body: %w", err)
}

// Raise exception if not created.
if resp.StatusCode != 201 {
return "", errs.New(string(respBody))
}

return string(respBody), err
return string(respBody), nil
}

func ensureValidOperationsList(filteredOperations string) bool {
Expand Down
35 changes: 35 additions & 0 deletions pkg/connectors/microcks_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,38 @@ func TestDownloadArtifactReturnsResponseBody(t *testing.T) {
t.Fatalf("expected response body %q, got %q", expectedBody, msg)
}
}

func TestUnexpectedServerResponseHandling(t *testing.T) {
// Create a test server that returns HTML / Bad Gateway
const htmlError = `<html><body>502 Bad Gateway</body></html>`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadGateway)
_, _ = w.Write([]byte(htmlError))
}))
defer server.Close()

client := NewMicrocksClient(server.URL)

// Test GetKeycloakURL
_, err := client.GetKeycloakURL()
if err == nil {
t.Error("expected GetKeycloakURL to return error on Bad Gateway response, got nil")
} else if !strings.Contains(err.Error(), "502") {
t.Errorf("expected error message to contain HTTP status code '502', got: %v", err)
}

// Test GetTestResult
_, err = client.GetTestResult("some-id")
if err == nil {
t.Error("expected GetTestResult to return error on Bad Gateway response, got nil")
} else if !strings.Contains(err.Error(), "502") {
t.Errorf("expected error message to contain HTTP status code '502', got: %v", err)
}

// Test DownloadArtifact
_, err = client.DownloadArtifact("https://example.com/openapi.yaml", true, "")
if err == nil {
t.Error("expected DownloadArtifact to return error on Bad Gateway response, got nil")
}
}

Loading