mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-10-24 06:48:09 +00:00
Add ability to set up allowed paths for proxying.
This commit is contained in:
@@ -30,6 +30,7 @@ I wanted to monitor the queries and responses of our graphql endpoint. Still, we
|
|||||||
| security | Blocking schema introspection |
|
| security | Blocking schema introspection |
|
||||||
| security | Rate limiting queries based on user role |
|
| security | Rate limiting queries based on user role |
|
||||||
| security | Blocking mutations in read-only mode |
|
| security | Blocking mutations in read-only mode |
|
||||||
|
| security | Allow access only to listed URLs |
|
||||||
|
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
@@ -49,6 +50,7 @@ I wanted to monitor the queries and responses of our graphql endpoint. Still, we
|
|||||||
| `BLOCK_SCHEMA_INTROSPECTION`| Blocks the schema introspection | `false` |
|
| `BLOCK_SCHEMA_INTROSPECTION`| Blocks the schema introspection | `false` |
|
||||||
| `ENABLE_ACCESS_LOG` | Enable the access log | `false` |
|
| `ENABLE_ACCESS_LOG` | Enable the access log | `false` |
|
||||||
| `READ_ONLY_MODE` | Enable the read only mode | `false` |
|
| `READ_ONLY_MODE` | Enable the read only mode | `false` |
|
||||||
|
| `ALLOWED_URLS` | Allow access only to certain URLs | `/v1/graphql,/v1/version` |
|
||||||
|
|
||||||
|
|
||||||
### Caching
|
### Caching
|
||||||
@@ -101,6 +103,11 @@ If rate limit has been reached - the proxy will return `429 Too Many Requests` e
|
|||||||
|
|
||||||
You can enable the read-only mode by setting the `READ_ONLY_MODE` environment variable to `true` - which will block all the `mutation` queries.
|
You can enable the read-only mode by setting the `READ_ONLY_MODE` environment variable to `true` - which will block all the `mutation` queries.
|
||||||
|
|
||||||
|
### Allowing access to listed URLs
|
||||||
|
|
||||||
|
You can allow access only to certain URLs by setting the `ALLOWED_URLS` environment variable to a comma-separated list of URLs. If enabled - other URLs will return `403 Forbidden` error and request will **not** reach the proxied service.
|
||||||
|
|
||||||
|
|
||||||
### Monitoring endpoint
|
### Monitoring endpoint
|
||||||
|
|
||||||
Example metrics produced by the proxy:
|
Example metrics produced by the proxy:
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gookit/goutil/envutil"
|
"github.com/gookit/goutil/envutil"
|
||||||
graphql "github.com/lukaszraczylo/go-simple-graphql"
|
graphql "github.com/lukaszraczylo/go-simple-graphql"
|
||||||
libpack_config "github.com/lukaszraczylo/graphql-monitoring-proxy/config"
|
libpack_config "github.com/lukaszraczylo/graphql-monitoring-proxy/config"
|
||||||
@@ -33,6 +35,13 @@ func parseConfig() {
|
|||||||
c.Client.GQLClient.SetEndpoint(c.Server.HostGraphQL)
|
c.Client.GQLClient.SetEndpoint(c.Server.HostGraphQL)
|
||||||
c.Server.AccessLog = envutil.GetBool("ENABLE_ACCESS_LOG", false)
|
c.Server.AccessLog = envutil.GetBool("ENABLE_ACCESS_LOG", false)
|
||||||
c.Server.ReadOnlyMode = envutil.GetBool("READ_ONLY_MODE", false)
|
c.Server.ReadOnlyMode = envutil.GetBool("READ_ONLY_MODE", false)
|
||||||
|
c.Server.AllowURLs = func() []string {
|
||||||
|
urls := envutil.Getenv("ALLOWED_URLS", "")
|
||||||
|
if urls == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return strings.Split(urls, ",")
|
||||||
|
}()
|
||||||
cfg = &c
|
cfg = &c
|
||||||
enableCache() // takes close to no resources, but can be used with dynamic query cache
|
enableCache() // takes close to no resources, but can be used with dynamic query cache
|
||||||
loadRatelimitConfig()
|
loadRatelimitConfig()
|
||||||
|
|||||||
@@ -9,8 +9,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func proxyTheRequest(c *fiber.Ctx) error {
|
func proxyTheRequest(c *fiber.Ctx) error {
|
||||||
|
if !checkAllowedURLs(c) {
|
||||||
|
cfg.Logger.Error("Request blocked", map[string]interface{}{"path": c.Path()})
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsSkipped, nil)
|
||||||
|
c.Status(403).SendString("Request blocked - not allowed URL")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
c.Request().Header.Add("X-Real-IP", c.IP())
|
c.Request().Header.Add("X-Real-IP", c.IP())
|
||||||
c.Request().Header.Add("X-Forwarded-For", c.IP())
|
c.Request().Header.Add(fiber.HeaderXForwardedFor, string(c.Request().Header.Peek("X-Forwarded-For")))
|
||||||
|
|
||||||
proxy.WithTlsConfig(&tls.Config{
|
proxy.WithTlsConfig(&tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
|||||||
@@ -31,6 +31,18 @@ func StartHTTPProxy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkAllowedURLs(c *fiber.Ctx) bool {
|
||||||
|
if len(cfg.Server.AllowURLs) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, allowedURL := range cfg.Server.AllowURLs {
|
||||||
|
if c.Path() == allowedURL {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func healthCheck(c *fiber.Ctx) error {
|
func healthCheck(c *fiber.Ctx) error {
|
||||||
// query := `{ __typename }`
|
// query := `{ __typename }`
|
||||||
// _, err := cfg.Client.GQLClient.Query(query, nil, nil)
|
// _, err := cfg.Client.GQLClient.Query(query, nil, nil)
|
||||||
@@ -131,6 +143,7 @@ func logAndMonitorRequest(c *fiber.Ctx, userID, opType, opName string, wasCached
|
|||||||
if cfg.Server.AccessLog {
|
if cfg.Server.AccessLog {
|
||||||
cfg.Logger.Info("Request processed", map[string]interface{}{
|
cfg.Logger.Info("Request processed", map[string]interface{}{
|
||||||
"ip": c.IP(),
|
"ip": c.IP(),
|
||||||
|
"fwd-ip": string(c.Request().Header.Peek("X-Forwarded-For")),
|
||||||
"user_id": userID,
|
"user_id": userID,
|
||||||
"op_type": opType,
|
"op_type": opType,
|
||||||
"op_name": opName,
|
"op_name": opName,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type config struct {
|
|||||||
HostGraphQL string
|
HostGraphQL string
|
||||||
AccessLog bool
|
AccessLog bool
|
||||||
ReadOnlyMode bool
|
ReadOnlyMode bool
|
||||||
|
AllowURLs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
Client struct {
|
Client struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user