Files
query-orchestration/cmd/auth_related/permit_test/permit.harness/main.go
T
Jay Brown 6dccf494f8 Merged in feature/permit-policy-cleanup (pull request #210)
cleanup permit policies and correct documentation

* docs

* policy cleanup

* refactor

* Merge remote-tracking branch 'origin/feature/permit-policy-cleanup' into feature/permit-policy-cleanup

* docs and edits
2026-02-19 20:22:59 +00:00

219 lines
6.1 KiB
Go

package main
import (
"fmt"
"log"
"net/http"
"os"
"time"
"github.com/permitio/permit-golang/pkg/config"
"github.com/permitio/permit-golang/pkg/enforcement"
"github.com/permitio/permit-golang/pkg/permit"
)
const (
port = 4000
readTimeout = 10 * time.Second
writeTimeout = 30 * time.Second
idleTimeout = 120 * time.Second
// This is the subject value from our JWT once we have authenticated.
// Also found in the cognito user pool for the testuser.
testUserSubject = "e12bb510-30e1-7062-a69a-ca7f3f38d80e"
)
func main() {
// Get PDP URL from environment variable, default to local OPAL
pdpURL := os.Getenv("AUTH_PDP_URL")
if pdpURL == "" {
pdpURL = "http://localhost:7766"
}
// Get API key from environment variable (still needed for OPAL)
permitKey := os.Getenv("PERMIT_IO_KEY")
if permitKey == "" {
log.Fatal("PERMIT_IO_KEY environment variable is not set")
}
// Initialize the Permit.io SDK
permitClient := initPermitClient(permitKey, pdpURL)
// Set up routes
mux := setupRoutes(permitClient)
// Start server with timeout settings
startServer(port, mux)
}
// initPermitClient initializes and returns the Permit.io client
func initPermitClient(permitKey string, pdpURL string) *permit.Client {
return permit.NewPermit(
config.NewConfigBuilder(permitKey).
WithPdpUrl(pdpURL).
Build(),
)
}
// setupRoutes configures and returns the HTTP routes
func setupRoutes(permitClient *permit.Client) *http.ServeMux {
mux := http.NewServeMux()
// Register the endpoints
mux.HandleFunc("/query-endpoint", createPermissionHandler(permitClient, "query-endpoint"))
mux.HandleFunc("/admin-stuff", createPermissionHandler(permitClient, "admin-stuff"))
mux.HandleFunc("/", createHomeHandler())
return mux
}
// createHomeHandler returns the handler function for the root path
func createHomeHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "text/html")
_, err := w.Write([]byte(`
<!DOCTYPE html>
<html>
<head>
<title>Permit.io Test Harness</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
}
a {
display: block;
margin: 10px 0;
}
</style>
</head>
<body>
<h1>Permit.io Test Harness</h1>
<h2>Available endpoints:</h2>
<a href="/query-endpoint?action=read">Query Endpoint - Read Action</a>
<a href="/query-endpoint?action=write">Query Endpoint - Write Action</a>
<a href="/admin-stuff?action=read">Admin Stuff - Read Action</a>
<a href="/admin-stuff?action=write">Admin Stuff - Write Action</a>
</body>
</html>
`))
if err != nil {
log.Printf("Error writing response: %v", err)
}
}
}
// createPermissionHandler creates a handler function for permission checks
func createPermissionHandler(permitClient *permit.Client, resourceType string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Get and validate the action parameter
action, err := validateActionParam(r)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
_, writeErr := w.Write([]byte(err.Error()))
if writeErr != nil {
log.Printf("Error writing response: %v", writeErr)
}
return
}
// Check permission
permitted, err := checkPermission(permitClient, testUserSubject, action, resourceType)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, writeErr := w.Write([]byte(fmt.Sprintf("Error checking permissions: %v", err)))
if writeErr != nil {
log.Printf("Error writing response: %v", writeErr)
}
return
}
// Determine response status and color
status, httpStatus, backgroundColor := getResponseStatus(permitted)
// Render the HTML response
renderHTMLResponse(w, resourceType, action, status, httpStatus, backgroundColor)
}
}
// validateActionParam extracts and validates the action parameter from the request
func validateActionParam(r *http.Request) (string, error) {
action := r.URL.Query().Get("action")
if action == "" {
return "", fmt.Errorf("Missing 'action' parameter")
}
return action, nil
}
// checkPermission performs the permission check using the Permit.io client
func checkPermission(permitClient *permit.Client, userID string, action string, resourceType string) (bool, error) {
// Create user for permission check
user := enforcement.UserBuilder(userID).Build()
// Create resource based on the endpoint
resource := enforcement.ResourceBuilder(resourceType).Build()
// Check permission
return permitClient.Check(user, enforcement.Action(action), resource)
}
// getResponseStatus determines the response status based on permission result
func getResponseStatus(permitted bool) (string, int, string) {
if permitted {
return "PERMITTED *********** OK ", http.StatusOK, "#d4ffcc" // Light green
}
return "NOT PERMITTED", http.StatusForbidden, "#ffcccc" // Light red
}
// renderHTMLResponse generates and sends the HTML response
func renderHTMLResponse(w http.ResponseWriter, resourceType, action, status string, httpStatus int, backgroundColor string) {
w.WriteHeader(httpStatus)
w.Header().Set("Content-Type", "text/html")
html := fmt.Sprintf(`
<!DOCTYPE html>
<html>
<head>
<title>Permit.io Test Result</title>
<style>
body {
background-color: %s;
font-family: Arial, sans-serif;
padding: 20px;
}
</style>
</head>
<body>
<h1>Permission Check Result</h1>
<p>Action '%s' on endpoint '%s' was %s</p>
<p><a href="/">Back to home</a></p>
</body>
</html>
`, backgroundColor, action, resourceType, status)
_, err := w.Write([]byte(html))
if err != nil {
log.Printf("Error writing response: %v", err)
}
}
// startServer starts the HTTP server with proper timeout settings
func startServer(port int, handler http.Handler) {
// Create a server with timeout settings
server := &http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: handler,
ReadTimeout: readTimeout,
WriteTimeout: writeTimeout,
IdleTimeout: idleTimeout,
}
// Start the server
fmt.Printf("Listening on http://localhost:%d\n", port)
if err := server.ListenAndServe(); err != nil {
log.Fatalf("Server error: %v", err)
}
}