From e25bc218b5213c969411e828d99b6c780e18fc74 Mon Sep 17 00:00:00 2001 From: Jonas Kaninda Date: Sun, 10 Nov 2024 21:05:19 +0100 Subject: [PATCH] refactor: update test, configuration deployment examples --- examples/configMap.yaml | 73 +++++++++++++++++++++++++------ examples/goma.yml | 29 ++++++++----- internal/middleware_test.go | 86 ++++++++++++++++++++++++++++--------- internal/server_test.go | 26 ++++++++++- 4 files changed, 169 insertions(+), 45 deletions(-) diff --git a/examples/configMap.yaml b/examples/configMap.yaml index f005ce5..eb00446 100644 --- a/examples/configMap.yaml +++ b/examples/configMap.yaml @@ -4,7 +4,7 @@ metadata: name: goma-config data: goma.yml: | - # Goma Gateway configurations + # Goma Gateway configurations version: 1.0 gateway: # Proxy write timeout @@ -19,6 +19,7 @@ data: sslKeyFile: ''#key.pem # Proxy rate limit, it's In-Memory IP based rateLimit: 0 + logLevel: info # debug, trace accessLog: "/dev/Stdout" errorLog: "/dev/stderr" ## Enable, disable routes health check @@ -50,10 +51,10 @@ data: ##### Define routes routes: # Example of a route | 1 - - name: Public # Name is optional + - path: / + name: Public # Name is optional # host Domain/host based request routing - host: "" # Host is optional - path: /public + hosts: [] # Hosts are optional ## Rewrite a request path # e.g rewrite: /store to / rewrite: / @@ -64,8 +65,6 @@ data: # [X-Forwarded-Host, X-Forwarded-For, Host, Scheme ] # It will not match the backend route, by default, it's disabled disableHeaderXForward: false - # Internal health check - healthCheck: '' #/internal/health/ready # Route Cors, global cors will be overridden by route cors: # Route Origins Cors, route will override global cors origins @@ -85,17 +84,27 @@ data: middlewares: - api-forbidden-paths # Example of a route | 2 - - name: Basic auth - path: /protected + - path: /protected + name: Basic auth rewrite: / - destination: https://example.com - methods: [] + destination: '' + backends: + - https://example.com + - https://example2.com + methods: + - GET + # Route healthcheck healthCheck: + path: /health/live + interval: 30 + timeout: 10 + healthyStatuses: + - 200 + - 404 cors: {} middlewares: - api-forbidden-paths - basic-auth - #Defines proxy middlewares # middleware name must be unique middlewares: @@ -147,4 +156,44 @@ data: - /v2/swagger-ui/* - /api-docs/* - /internal/* - - /actuator/* \ No newline at end of file + - /actuator/* + - name: oauth-google + type: oauth + paths: + - /protected + - /example-of-oauth + rule: + clientId: xxx + clientSecret: xxx + provider: google + endpoint: + userInfoUrl: "" + redirectUrl: http://localhost:8080/callback + redirectPath: "" + cookiePath: "" + scopes: + - https://www.googleapis.com/auth/userinfo.email + - https://www.googleapis.com/auth/userinfo.profile + state: randomStateString + jwtSecret: your-strong-jwt-secret | It's optional + - name: oauth-authentik + type: oauth + paths: + - /protected + - /example-of-oauth + rule: + clientId: xxx + clientSecret: xxx + provider: custom + endpoint: + authUrl: https://authentik.example.com/application/o/authorize/ + tokenUrl: https://authentik.example.com/application/o/token/ + userInfoUrl: https://authentik.example.com/application/o/userinfo/ + redirectUrl: http://localhost:8080/callback + redirectPath: "" + cookiePath: "" + scopes: + - email + - openid + state: randomStateString + jwtSecret: your-strong-jwt-secret | It's optional \ No newline at end of file diff --git a/examples/goma.yml b/examples/goma.yml index fc2b68e..3bc23c2 100644 --- a/examples/goma.yml +++ b/examples/goma.yml @@ -13,6 +13,7 @@ gateway: sslKeyFile: ''#key.pem # Proxy rate limit, it's In-Memory IP based rateLimit: 0 + logLevel: info # debug, trace accessLog: "/dev/Stdout" errorLog: "/dev/stderr" ## Enable, disable routes health check @@ -44,10 +45,10 @@ gateway: ##### Define routes routes: # Example of a route | 1 - - name: Public # Name is optional + - path: / + name: Public # Name is optional # host Domain/host based request routing - host: "" # Host is optional - path: /public + hosts: [] # Hosts are optional ## Rewrite a request path # e.g rewrite: /store to / rewrite: / @@ -58,8 +59,6 @@ gateway: # [X-Forwarded-Host, X-Forwarded-For, Host, Scheme ] # It will not match the backend route, by default, it's disabled disableHeaderXForward: false - # Internal health check - healthCheck: '' #/internal/health/ready # Route Cors, global cors will be overridden by route cors: # Route Origins Cors, route will override global cors origins @@ -79,17 +78,27 @@ gateway: middlewares: - api-forbidden-paths # Example of a route | 2 - - name: Basic auth - path: /protected + - path: /protected + name: Basic auth rewrite: / - destination: https://example.com - methods: [] + destination: '' + backends: + - https://example.com + - https://example2.com + methods: + - GET + # Route healthcheck healthCheck: + path: /health/live + interval: 30 + timeout: 10 + healthyStatuses: + - 200 + - 404 cors: {} middlewares: - api-forbidden-paths - basic-auth - #Defines proxy middlewares # middleware name must be unique middlewares: diff --git a/internal/middleware_test.go b/internal/middleware_test.go index 4799cba..316d370 100644 --- a/internal/middleware_test.go +++ b/internal/middleware_test.go @@ -32,7 +32,7 @@ func TestMiddleware(t *testing.T) { middlewares := []Middleware{ { Name: "basic-auth", - Type: "basic", + Type: BasicAuth, Paths: []string{"/", "/admin"}, Rule: BasicRuleMiddleware{ Username: "goma", @@ -41,7 +41,7 @@ func TestMiddleware(t *testing.T) { }, { Name: "forbidden path access", - Type: "access", + Type: AccessMiddleware, Paths: []string{"/", "/admin"}, Rule: BasicRuleMiddleware{ Username: "goma", @@ -51,7 +51,7 @@ func TestMiddleware(t *testing.T) { { Name: "jwt", - Type: "jwt", + Type: JWTAuth, Paths: []string{"/", "/admin"}, Rule: JWTRuleMiddleware{ URL: "https://www.googleapis.com/auth/userinfo.email", @@ -59,6 +59,35 @@ func TestMiddleware(t *testing.T) { Params: map[string]string{}, }, }, + { + Name: "oauth-google", + Type: OAuth, + Paths: []string{ + "/protected", + "/example-of-oauth", + }, + Rule: OauthRulerMiddleware{ + ClientID: "xxx", + ClientSecret: "xxx", + Provider: "google", + JWTSecret: "your-strong-jwt-secret | It's optional", + RedirectURL: "http://localhost:8080/callback", + Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", + "https://www.googleapis.com/auth/userinfo.profile"}, + Endpoint: OauthEndpoint{}, + State: "randomStateString", + }, + }, + { + Name: "api-forbidden-paths", + Type: AccessMiddleware, + Paths: []string{ + "/swagger-ui/*", + "/v2/swagger-ui/*", + "/api-docs/*", + "/actuator/*", + }, + }, } yamlData, err := yaml.Marshal(&middlewares) if err != nil { @@ -74,28 +103,43 @@ func TestMiddleware(t *testing.T) { func TestReadMiddleware(t *testing.T) { TestMiddleware(t) middlewares := getMiddlewares(t) - middleware, err := getMiddleware(rules, middlewares) + m, err := getMiddleware(rules, middlewares) if err != nil { t.Fatalf("Error searching middleware %s", err.Error()) } - switch middleware.Type { - case "basic": - log.Println("Basic auth") - basicAuth, err := getBasicAuthMiddleware(middleware.Rule) - if err != nil { - log.Fatalln("error:", err) - } - log.Printf("Username: %s and password: %s\n", basicAuth.Username, basicAuth.Password) - case "jwt": - log.Println("JWT auth") - jwt, err := getJWTMiddleware(middleware.Rule) - if err != nil { - log.Fatalln("error:", err) - } - log.Printf("JWT authentification URL is %s\n", jwt.URL) - default: - t.Errorf("Unknown middleware type %s", middleware.Type) + log.Printf("Middleware: %v\n", m) + for _, middleware := range middlewares { + + switch middleware.Type { + case BasicAuth: + log.Println("Basic auth") + basicAuth, err := getBasicAuthMiddleware(middleware.Rule) + if err != nil { + log.Fatalln("error:", err) + } + log.Printf("Username: %s and password: %s\n", basicAuth.Username, basicAuth.Password) + case JWTAuth: + log.Println("JWT auth") + jwt, err := getJWTMiddleware(middleware.Rule) + if err != nil { + log.Fatalln("error:", err) + } + log.Printf("JWT authentification URL is %s\n", jwt.URL) + case OAuth: + log.Println("OAuth auth") + oauth, err := oAuthMiddleware(middleware.Rule) + if err != nil { + log.Fatalln("error:", err) + } + log.Printf("OAuth authentification: provider %s\n", oauth.Provider) + case AccessMiddleware: + log.Println("Access middleware") + log.Printf("Access middleware: paths: [%s]\n", middleware.Paths) + default: + t.Errorf("Unknown middleware type %s", middleware.Type) + + } } } diff --git a/internal/server_test.go b/internal/server_test.go index d40048e..424042d 100644 --- a/internal/server_test.go +++ b/internal/server_test.go @@ -1,6 +1,8 @@ package pkg import ( + "context" + "log" "net/http" "net/http/httptest" "os" @@ -19,6 +21,16 @@ func TestInit(t *testing.T) { } } +func TestCheckConfig(t *testing.T) { + TestInit(t) + initConfig(configFile) + err := CheckConfig(configFile) + if err != nil { + t.Error(err) + } + log.Println("Goma Gateway configuration file checked successfully") +} + func TestStart(t *testing.T) { TestInit(t) initConfig(configFile) @@ -28,7 +40,8 @@ func TestStart(t *testing.T) { t.Error(err) } route := gatewayServer.Initialize() - route.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { + + route.HandleFunc("/test", func(rw http.ResponseWriter, r *http.Request) { _, err := rw.Write([]byte("Hello Goma Proxy")) if err != nil { t.Fatalf("Failed writing HTTP response: %v", err) @@ -43,10 +56,19 @@ func TestStart(t *testing.T) { t.Fatalf("expected a status code of 200, got %v", resp.StatusCode) } } + ctx := context.Background() + go func() { + err = gatewayServer.Start(ctx) + if err != nil { + t.Error(err) + return + } + }() + t.Run("httpServer", func(t *testing.T) { s := httptest.NewServer(route) defer s.Close() assertResponseBody(t, s, "Hello Goma Proxy") }) - + ctx.Done() }