Skip to content

Commit

Permalink
Add service registration to API gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
tomekstrzeszkowski committed Dec 30, 2024
1 parent 2781ffb commit bebdbb8
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 63 deletions.
77 changes: 77 additions & 0 deletions gateway/api_gateway.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gateway

import (
"errors"
"fmt"
"net/http"
"net/http/httputil"
Expand Down Expand Up @@ -93,3 +94,79 @@ func (gw *APIGateway) UpdateRouter(r *gin.Engine) {
route.Ready = true
}
}

func (gw *APIGateway) RegisterEchoServiceWithRoutes(c *gin.Context) error {
echoService, _ := NewService("echo", "echo-server:80", nil, nil)
err := gw.AddServiceWithRoutes(echoService, &[]*Route{
&Route{
Path: "/echo",
ServiceName: echoService.Name,
Methods: []string{"GET", "POST"},
},
})
if err != nil {
gw.logger.Error(fmt.Sprintf("%v", err))
c.Abort()
}
return err
}

func (gw *APIGateway) RegisterCertServiceWithRoutes(c *gin.Context) error {
cert := "/secr/cert.pem"
skipVerify := false
certService, _ := NewService("cert", "cert-server:8001", &cert, &skipVerify)
err := gw.AddServiceWithRoutes(certService, &[]*Route{&Route{
Path: "/cert",
ServiceName: certService.Name,
Methods: []string{"POST"},
}})
if err != nil {
gw.logger.Error(fmt.Sprintf("%v", err))
c.Abort()
}
return err
}

func (gw *APIGateway) RegisterE2eServiceWithRoutes(c *gin.Context, router *gin.Engine) error {
privateKey := "/secr/gateway/private.key"
publicKey := "/secr/public.pem"
encryptedService, _ := NewE2eEncryptedService(
"encrypted", "encrypted-server:8011", &privateKey, &publicKey, nil, nil,
)
route := Route{
Path: "/e2e",
ServiceName: encryptedService.Name,
Methods: []string{"POST"},
}
err := gw.AddServiceWithRoutes(encryptedService, &[]*Route{&route})
if err != nil {
gw.logger.Error(fmt.Sprintf("%v", err))
c.Abort()
} else {
router.GET(
fmt.Sprintf("/rsa-public%s", route.Path),
encryptedService.SecurityManager.EndpointExposePublicKey(),
)
}

return err
}

func (gw *APIGateway) AddServiceWithRoutes(service *ServiceConfig, routes *[]*Route) error {
if service == nil {
gw.logger.Sugar().Fatalf("Service adding error")
return errors.New("Service adding error")
}
if err := gw.AddService(service); err != nil {
gw.logger.Sugar().Fatalf("Service adding error %v", err)
return fmt.Errorf("Service `%s` adding error %v", service.Name, err)
}
for _, route := range *routes {
err := gw.AddRoute(route)
if err != nil {
gw.logger.Sugar().Fatalf("Route adding error %v", err)
return fmt.Errorf("Route `%s` adding error %v", route.Path, err)
}
}
return nil
}
55 changes: 7 additions & 48 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"log"
"net/http"

"example.com/m/v2/gateway"
Expand All @@ -21,61 +20,21 @@ func main() {
defer cancel()
go resourceMonitor.StartPeriodicMonitoring(ctx)
router := api.InitializeRouter(securityManager)
// expose rsa public key just for learning purposes,
// it's recommended to remove this endpint for any other use
router.GET("/rsa-public", func(c *gin.Context) {
publicKey, _ := securityManager.ExportPublicKey()
c.JSON(http.StatusOK, gin.H{
"public": string(publicKey),
})
})
router.GET("/rsa-public", securityManager.EndpointExposePublicKey())
// dynamic service registration
router.POST("/register-services/all", func(c *gin.Context) {
// basic echo service
echoService, err := gateway.NewService("echo", "echo-server:80", nil, nil)
if err != nil {
log.Fatalf("Service adding error %v", err)
}
if err := api.AddService(echoService); err != nil {
log.Fatalf("Service adding error %v", err)
if err := api.RegisterEchoServiceWithRoutes(c); err != nil {
return
}
api.AddRoute(&gateway.Route{
Path: "/echo",
ServiceName: echoService.Name,
Methods: []string{"GET", "POST"},
})
// SSL
cert := "/secr/cert.pem"
skipVerify := false
certService, err := gateway.NewService("cert", "cert-server:8001", &cert, &skipVerify)
if err != nil {
log.Fatalf("Service adding error %v", err)
if err := api.RegisterCertServiceWithRoutes(c); err != nil {
return
}
if err := api.AddService(certService); err != nil {
log.Fatalf("Service adding error %v", err)
}
api.AddRoute(&gateway.Route{
Path: "/cert",
ServiceName: certService.Name,
Methods: []string{"POST"},
})
// Custom E2E encryption
privateKey := "/secr/gateway/private.key"
publicKey := "/secr/public.pem"
encryptedService, err := gateway.NewE2eEncryptedService(
"encrypted", "encrypted-server:8011", &privateKey, &publicKey, nil, nil,
)
if err != nil {
log.Fatalf("Service adding error %v", err)
}
if err := api.AddService(encryptedService); err != nil {
log.Fatalf("Service adding error %v", err)
if err := api.RegisterE2eServiceWithRoutes(c, router); err != nil {
return
}
api.AddRoute(&gateway.Route{
Path: "/e2e",
ServiceName: encryptedService.Name,
Methods: []string{"POST"},
})
api.UpdateRouter(router)
c.Status(http.StatusOK)
})
Expand Down
39 changes: 24 additions & 15 deletions security/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,21 +212,6 @@ func (sm *SecurityManager) ExportPublicKey() ([]byte, error) {
return publicPEM, nil
}

func (sm *SecurityManager) MiddlewareEncryption() gin.HandlerFunc {
return func(c *gin.Context) {
if encryptedHeader := c.GetHeader("X-Encrypted-Request"); encryptedHeader != "" {
secretMessage, err := sm.DecryptRSA(encryptedHeader)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Decryption error"})
c.Abort()
return
}
fmt.Print(secretMessage)
}
c.Next()
}
}

func (sm *SecurityManager) GetTlsConfig() *tls.Config {
skipVerify := false
if sm.skipCertificateVerify != nil {
Expand All @@ -245,3 +230,27 @@ func (sm *SecurityManager) GetTlsConfig() *tls.Config {
InsecureSkipVerify: skipVerify,
}
}

func (sm *SecurityManager) MiddlewareEncryption() gin.HandlerFunc {
return func(c *gin.Context) {
if encryptedHeader := c.GetHeader("X-Encrypted-Request"); encryptedHeader != "" {
secretMessage, err := sm.DecryptRSA(encryptedHeader)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Decryption error"})
c.Abort()
return
}
fmt.Print(secretMessage)
}
c.Next()
}
}

func (sm *SecurityManager) EndpointExposePublicKey() gin.HandlerFunc {
return func(c *gin.Context) {
publicKey, _ := sm.ExportPublicKey()
c.JSON(http.StatusOK, gin.H{
"public": string(publicKey),
})
}
}

0 comments on commit bebdbb8

Please sign in to comment.