Services: Admin-Compliance, Backend-Compliance, AI-Compliance-SDK, Consent-SDK, Developer-Portal, PCA-Platform, DSMS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
189 lines
5.1 KiB
Go
189 lines
5.1 KiB
Go
// BreakPilot Compliance SDK - API Gateway
|
|
//
|
|
// Main entry point for the API Gateway service.
|
|
// Handles authentication, rate limiting, and request routing.
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/breakpilot/compliance-sdk/services/api-gateway/internal/api"
|
|
"github.com/breakpilot/compliance-sdk/services/api-gateway/internal/config"
|
|
"github.com/breakpilot/compliance-sdk/services/api-gateway/internal/middleware"
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func main() {
|
|
// Initialize logger
|
|
logger, _ := zap.NewProduction()
|
|
defer logger.Sync()
|
|
|
|
// Load configuration
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
logger.Fatal("Failed to load configuration", zap.Error(err))
|
|
}
|
|
|
|
// Set Gin mode
|
|
if cfg.Environment == "production" {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
}
|
|
|
|
// Initialize router
|
|
router := gin.New()
|
|
|
|
// Global middleware
|
|
router.Use(gin.Recovery())
|
|
router.Use(middleware.Logger(logger))
|
|
router.Use(middleware.CORS())
|
|
router.Use(middleware.RequestID())
|
|
|
|
// Health check (no auth required)
|
|
router.GET("/health", func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"status": "healthy",
|
|
"service": "api-gateway",
|
|
"version": cfg.Version,
|
|
})
|
|
})
|
|
|
|
// API v1 routes
|
|
v1 := router.Group("/api/v1")
|
|
{
|
|
// Public routes (rate limited)
|
|
v1.Use(middleware.RateLimiter(cfg.RateLimit))
|
|
|
|
// Auth routes
|
|
auth := v1.Group("/auth")
|
|
{
|
|
auth.POST("/token", api.GetToken)
|
|
auth.POST("/refresh", api.RefreshToken)
|
|
}
|
|
|
|
// Protected routes
|
|
protected := v1.Group("")
|
|
protected.Use(middleware.Auth(cfg.JWTSecret))
|
|
protected.Use(middleware.TenantIsolation())
|
|
{
|
|
// State management
|
|
protected.GET("/state/:tenantId", api.GetState)
|
|
protected.POST("/state/save", api.SaveState)
|
|
protected.POST("/state/reset", api.ResetState)
|
|
|
|
// DSGVO
|
|
dsgvo := protected.Group("/dsgvo")
|
|
{
|
|
dsgvo.POST("/consent", api.RecordConsent)
|
|
dsgvo.GET("/consent/:userId", api.GetConsents)
|
|
dsgvo.DELETE("/consent/:consentId", api.RevokeConsent)
|
|
|
|
dsgvo.POST("/dsr", api.SubmitDSR)
|
|
dsgvo.GET("/dsr", api.ListDSRRequests)
|
|
dsgvo.PUT("/dsr/:requestId", api.UpdateDSRStatus)
|
|
|
|
dsgvo.GET("/vvt", api.GetProcessingActivities)
|
|
dsgvo.POST("/vvt", api.CreateProcessingActivity)
|
|
dsgvo.PUT("/vvt/:activityId", api.UpdateProcessingActivity)
|
|
dsgvo.DELETE("/vvt/:activityId", api.DeleteProcessingActivity)
|
|
|
|
dsgvo.GET("/tom", api.GetTOMs)
|
|
dsgvo.POST("/tom", api.CreateTOM)
|
|
dsgvo.PUT("/tom/:tomId", api.UpdateTOM)
|
|
dsgvo.DELETE("/tom/:tomId", api.DeleteTOM)
|
|
|
|
dsgvo.GET("/dsfa", api.GetDSFAs)
|
|
dsgvo.POST("/dsfa", api.CreateDSFA)
|
|
dsgvo.PUT("/dsfa/:dsfaId", api.UpdateDSFA)
|
|
|
|
dsgvo.GET("/retention", api.GetRetentionPolicies)
|
|
dsgvo.POST("/retention", api.CreateRetentionPolicy)
|
|
dsgvo.PUT("/retention/:policyId", api.UpdateRetentionPolicy)
|
|
dsgvo.DELETE("/retention/:policyId", api.DeleteRetentionPolicy)
|
|
}
|
|
|
|
// Compliance
|
|
compliance := protected.Group("/compliance")
|
|
{
|
|
compliance.GET("/controls", api.GetControls)
|
|
compliance.POST("/controls", api.CreateControl)
|
|
compliance.PUT("/controls/:controlId", api.UpdateControl)
|
|
compliance.DELETE("/controls/:controlId", api.DeleteControl)
|
|
|
|
compliance.GET("/evidence", api.GetEvidence)
|
|
compliance.POST("/evidence", api.UploadEvidence)
|
|
compliance.PUT("/evidence/:evidenceId", api.UpdateEvidence)
|
|
compliance.DELETE("/evidence/:evidenceId", api.DeleteEvidence)
|
|
|
|
compliance.GET("/obligations", api.GetObligations)
|
|
compliance.POST("/assessment", api.RunAssessment)
|
|
|
|
compliance.GET("/export/pdf", api.ExportPDF)
|
|
compliance.GET("/export/docx", api.ExportDOCX)
|
|
}
|
|
|
|
// RAG
|
|
rag := protected.Group("/rag")
|
|
{
|
|
rag.POST("/search", api.SearchRAG)
|
|
rag.POST("/ask", api.AskRAG)
|
|
rag.GET("/regulations", api.GetRegulations)
|
|
rag.POST("/documents", api.UploadDocument)
|
|
}
|
|
|
|
// SBOM & Security
|
|
security := protected.Group("/security")
|
|
{
|
|
security.POST("/sbom/generate", api.GenerateSBOM)
|
|
security.GET("/sbom/components", api.GetSBOMComponents)
|
|
security.GET("/sbom/export/:format", api.ExportSBOM)
|
|
|
|
security.POST("/scan", api.StartSecurityScan)
|
|
security.GET("/findings", api.GetSecurityFindings)
|
|
security.GET("/recommendations", api.GetRecommendations)
|
|
security.GET("/reports", api.GetSecurityReports)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create HTTP server
|
|
srv := &http.Server{
|
|
Addr: ":" + cfg.Port,
|
|
Handler: router,
|
|
ReadTimeout: 15 * time.Second,
|
|
WriteTimeout: 15 * time.Second,
|
|
IdleTimeout: 60 * time.Second,
|
|
}
|
|
|
|
// Start server in goroutine
|
|
go func() {
|
|
logger.Info("Starting API Gateway", zap.String("port", cfg.Port))
|
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
logger.Fatal("Failed to start server", zap.Error(err))
|
|
}
|
|
}()
|
|
|
|
// Graceful shutdown
|
|
quit := make(chan os.Signal, 1)
|
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
<-quit
|
|
|
|
logger.Info("Shutting down server...")
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
if err := srv.Shutdown(ctx); err != nil {
|
|
logger.Fatal("Server forced to shutdown", zap.Error(err))
|
|
}
|
|
|
|
logger.Info("Server exited")
|
|
}
|