2ff6e05ffc
Permit integration - part 1 * WIP permit integration * slim down build * Merge branch 'main' of bitbucket.org:aarete/query-orchestration into feature/permit-integration-1 * omit swagger from auth * clean build * comment * part 1 completed this is the initial permitio parts and tests without integration. Also testing.md since we have a new test target `task test:permitio` * feature flag for no jwt validation * permit integration * fix ci unit tests * ci fix * build fix * fix home handler * fix redirect * test fix * update docs for auth
108 lines
3.7 KiB
Go
108 lines
3.7 KiB
Go
package cognitoauth
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ValidatePermitIOConfiguration validates both PDP connectivity and API key at startup
|
|
// This function should be called during application startup to ensure configuration is correct
|
|
// before processing any real authorization requests.
|
|
//
|
|
// It performs two checks:
|
|
// 1. PDP Health Check: Tests connectivity to the PDP URL using the /healthy endpoint
|
|
// 2. API Key Validation: Makes a dummy permission check to verify the API key is valid
|
|
//
|
|
// If DISABLE_AUTH=true, validation is skipped and function returns success.
|
|
// Returns an error if either check fails, which should cause the application to halt startup.
|
|
func ValidatePermitIOConfiguration() error {
|
|
// Skip validation if auth is disabled
|
|
disableAuth := os.Getenv("DISABLE_AUTH")
|
|
if strings.ToLower(disableAuth) == "true" {
|
|
fmt.Println("✓ Permit.io validation skipped (DISABLE_AUTH=true)")
|
|
return nil
|
|
}
|
|
|
|
pdpURL := os.Getenv("PERMIT_IO_PDP_URL")
|
|
apiKey := os.Getenv("PERMIT_IO_API_KEY")
|
|
|
|
// Apply default for PDP URL if not set
|
|
if pdpURL == "" {
|
|
pdpURL = "http://localhost:7766"
|
|
}
|
|
|
|
if apiKey == "" {
|
|
return fmt.Errorf("PERMIT_IO_API_KEY environment variable must be set")
|
|
}
|
|
|
|
// 1. Test PDP connectivity with /healthy endpoint
|
|
client := &http.Client{Timeout: 10 * time.Second}
|
|
healthURL := strings.TrimSuffix(pdpURL, "/") + "/healthy"
|
|
|
|
req, err := http.NewRequest("GET", healthURL, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create health check request: %v", err)
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return fmt.Errorf("Permit.io PDP connectivity failed with PDP_URL=%s: %v", pdpURL, err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != 200 {
|
|
return fmt.Errorf("Permit.io PDP health check failed with PDP_URL=%s: HTTP %d", pdpURL, resp.StatusCode)
|
|
}
|
|
|
|
// 2. Test API key validity with a dummy permission check
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelWarn}))
|
|
permitClient := NewPermitIOClient(apiKey, pdpURL, logger)
|
|
|
|
// Use dummy test data that will likely be denied but should work with valid API key
|
|
testUser := "startup-validation-user-12345"
|
|
testAction := "read"
|
|
testResource := "startup-validation-resource"
|
|
|
|
_, err = permitClient.CheckPermission(testUser, testAction, testResource)
|
|
if err != nil {
|
|
// Check for specific error patterns to distinguish error types
|
|
errStr := err.Error()
|
|
|
|
if strings.Contains(errStr, "UnexpectedError") && (strings.Contains(errStr, "connection refused") || strings.Contains(errStr, "no such host")) {
|
|
return fmt.Errorf("Permit.io PDP connectivity failed with PDP_URL=%s: %v", pdpURL, err)
|
|
}
|
|
|
|
if strings.Contains(errStr, "Unauthorized") || strings.Contains(errStr, "Invalid PDP token") || strings.Contains(errStr, "api_error") {
|
|
return fmt.Errorf("Permit.io API key validation failed with API_KEY=%s and PDP_URL=%s: %v",
|
|
maskAPIKey(apiKey), pdpURL, err)
|
|
}
|
|
|
|
if strings.Contains(errStr, "UnprocessableEntityError") {
|
|
return fmt.Errorf("Permit.io API configuration error with API_KEY=%s and PDP_URL=%s: %v",
|
|
maskAPIKey(apiKey), pdpURL, err)
|
|
}
|
|
|
|
// Any other error is also a configuration problem
|
|
return fmt.Errorf("Permit.io validation failed with API_KEY=%s and PDP_URL=%s: %v",
|
|
maskAPIKey(apiKey), pdpURL, err)
|
|
}
|
|
|
|
// Success - both PDP connectivity and API key are valid
|
|
fmt.Printf("✓ Permit.io configuration validated successfully (PDP_URL=%s, API_KEY=%s)\n",
|
|
pdpURL, maskAPIKey(apiKey))
|
|
|
|
return nil
|
|
}
|
|
|
|
// maskAPIKey masks the API key for logging, showing only the first 8 characters
|
|
func maskAPIKey(apiKey string) string {
|
|
if len(apiKey) <= 8 {
|
|
return "***masked***"
|
|
}
|
|
return apiKey[:8] + "..."
|
|
}
|