mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-06-05 23:03:48 +00:00
Add read only mode to block all the queries with mutations.
This commit is contained in:
@@ -24,7 +24,7 @@ I wanted to monitor the queries and responses of our graphql endpoint, but we di
|
|||||||
* MONITORING: Extracting user id from JWT token and adding it as a label to the metrics
|
* MONITORING: Extracting user id from JWT token and adding it as a label to the metrics
|
||||||
* MONITORING: Extracting the query name and type and adding it as a label to the metrics
|
* MONITORING: Extracting the query name and type and adding it as a label to the metrics
|
||||||
* MONITORING: Calculating the query duration and adding it to the metrics
|
* MONITORING: Calculating the query duration and adding it to the metrics
|
||||||
* SPEED: Caching the queries
|
* SPEED: Caching the queries, together with per-query cache and TTL
|
||||||
* SECURITY: Blocking schema introspection
|
* SECURITY: Blocking schema introspection
|
||||||
* SECURITY: Rate limiting queries based on user role
|
* SECURITY: Rate limiting queries based on user role
|
||||||
|
|
||||||
@@ -41,6 +41,7 @@ I wanted to monitor the queries and responses of our graphql endpoint, but we di
|
|||||||
* `LOG_LEVEL` - the log level (default: `info`)
|
* `LOG_LEVEL` - the log level (default: `info`)
|
||||||
* `BLOCK_SCHEMA_INTROSPECTION` - blocks the schema introspection (default: `false`)
|
* `BLOCK_SCHEMA_INTROSPECTION` - blocks the schema introspection (default: `false`)
|
||||||
* `ENABLE_ACCESS_LOG` - enable the access log (default: `false`)
|
* `ENABLE_ACCESS_LOG` - enable the access log (default: `false`)
|
||||||
|
* `READ_ONLY_MODE` - enable the read only mode (default: `false`)
|
||||||
|
|
||||||
### Caching
|
### Caching
|
||||||
|
|
||||||
@@ -85,6 +86,11 @@ If you'd like to change it - mount your configmap as `/app/ratelimit.json` file.
|
|||||||
Remember to include the `-` role, which is used for unauthenticated users or when claim can't be found for any reason.
|
Remember to include the `-` role, which is used for unauthenticated users or when claim can't be found for any reason.
|
||||||
If rate limit has been reached - the proxy will return `429 Too Many Requests` error.
|
If rate limit has been reached - the proxy will return `429 Too Many Requests` error.
|
||||||
|
|
||||||
|
|
||||||
|
### Read only mode
|
||||||
|
|
||||||
|
You can enable the read only mode by setting the `READ_ONLY_MODE` environment variable to `true` - which will block all the `mutation` queries.
|
||||||
|
|
||||||
### Monitoring endpoint
|
### Monitoring endpoint
|
||||||
|
|
||||||
Example metrics produced by the proxy:
|
Example metrics produced by the proxy:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
fiber "github.com/gofiber/fiber/v2"
|
fiber "github.com/gofiber/fiber/v2"
|
||||||
"github.com/graphql-go/graphql/language/ast"
|
"github.com/graphql-go/graphql/language/ast"
|
||||||
@@ -62,6 +63,14 @@ func parseGraphQLQuery(c *fiber.Ctx) (operationType, operationName string, cache
|
|||||||
for _, d := range p.Definitions {
|
for _, d := range p.Definitions {
|
||||||
if oper, ok := d.(*ast.OperationDefinition); ok {
|
if oper, ok := d.(*ast.OperationDefinition); ok {
|
||||||
operationType = oper.Operation
|
operationType = oper.Operation
|
||||||
|
if strings.ToLower(operationType) == "mutation" && cfg.Server.ReadOnlyMode {
|
||||||
|
cfg.Logger.Warning("Mutation blocked", m)
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsSkipped, nil)
|
||||||
|
c.Status(403).SendString("The server is in read-only mode")
|
||||||
|
should_block = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if oper.Name != nil {
|
if oper.Name != nil {
|
||||||
operationName = oper.Name.Value
|
operationName = oper.Name.Value
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func parseConfig() {
|
|||||||
c.Client.GQLClient = graphql.NewConnection()
|
c.Client.GQLClient = graphql.NewConnection()
|
||||||
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)
|
||||||
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()
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ type config struct {
|
|||||||
PortMonitoring int
|
PortMonitoring int
|
||||||
HostGraphQL string
|
HostGraphQL string
|
||||||
AccessLog bool
|
AccessLog bool
|
||||||
|
ReadOnlyMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
Client struct {
|
Client struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user