Skip to content

Commit

Permalink
doc(init): Add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ldebruijn committed Sep 24, 2023
1 parent e3fcaac commit 063c803
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 17 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,36 @@ It is dead-simple yet highly customizable security sidecar compatible with any H

[![Go](https://github.com/ldebruijn/go-graphql-armor/actions/workflows/go.yml/badge.svg)](https://github.com/ldebruijn/go-graphql-armor/actions/workflows/go.yml)

<!-- TOC -->

## Features

* Persisted Operations
* Field Suggestions Redaction

## Installation

```makefile
Build & Test
```make
make build
make test
```

```makefile
make build_container
Run Container
```make
make run_container
```

## Documentation

[//]: # (todo)
[Documentation](docs/README.md)

## Configuration

We recommend configuring the binary using a yaml file, place a file called `armor.yml` in the same directory as you're running the binary.

For all the configuration options check out the [Configuration Documentation](docs/configuration.md)

```yaml
web:
read_timeout: 5s
Expand All @@ -45,7 +51,6 @@ target:

persisted_operations:
enabled: true
allow_unpersisted_operations: false
fail_unknown_operations: true
store:
# Only one store will be used
Expand Down
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Documentation

Please see each section for in-depth documentation

* [Configuration](configuration.md)
* [Persisted Operations](persisted_operations.md)
* [Block Field Suggestions](block_field_suggestions.md)
23 changes: 23 additions & 0 deletions docs/block_field_suggestions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Field Suggestions

Field suggestions in a GraphQL server, though convenient, can pose risks. They can reveal internal details, like field or operation names, potentially aiding malicious actors.

Disabling field suggestions prevent the discovery of your GraphQL schema even when Introspection is disabled.

<!-- TOC -->

## Configuration

You can configure `go-graphql-armor` to remove field suggestions from your API.

```yaml
block_field_suggestions:
# Enable the feature, this will remove any field suggestions on your API
enable: true
# The mask to use instead.
mask: [redacted]
```
## How does it work?
We scan each `errors[].message` field and replace the message with a mask when we encounter a field suggestion.
71 changes: 71 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Configuration

go-graphql-armor can be configured in various ways, though we recommend configuring it via a `armor.yml`. file

<!-- TOC -->

# armor.yml

The best way to configure `go-graphql-armor` is by specifying a `armor.yml` in the same directory as you're running the binary.

The following outlines the structure of the yaml

```yaml
web:
read_timeout: 5s
write_timeout: 10s
idle_timeout: 120s
shutdown_timeout: 20s
host: 0.0.0.0:8080
path: /graphql

target:
host: http://localhost:8081
timeout: 10s
keep_alive: 180s

persisted_operations:
enabled: true
fail_unknown_operations: true
store:
# Only one store will be used
# Armor will look at all files in the dir and try to load persisted operations from any `.json` file
dir: "./my-dir"
# Armor will look at all objects in the bucket and try to load persisted operations from any `.json` file
gcp_bucket: "gs://somebucket"

field_suggestions:
enabled: true
mask: [redacted]
```
For a more in-depth view of each option visit the accompanying documentation page.
## Environment Variables
If so desired `go-graphql-armor` _can_ be configured using environment variables. write out the full configuration path for each value.

For example:

```bash
PERSISTED_OPERATIONS_ENABLED: true
WEB_PATH: /graphql
PERSISTED_OPERATIONS_STORE_GCP_BUCKET: gs://my-bucket
```

## Command line arguments

Usage: go-graphql-armor [options] [arguments]

Examples:

```bash
go-graphql-armor \
--persisted-operations-enabled=true \
--web-path=/graphql \
--persisted-operations-store-gcp-bucket=gs://my-bucket
```

## Which configuration is applied?

During startup `go-graphql-armor` will output its applied configuration. It will do this in command line argument format, though it will apply and output configuration from any of these sources.
55 changes: 55 additions & 0 deletions docs/persisted_operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Persisted Operations

Persisted Operations are essentially an operation allowlist. Persisted Operations provide an additional layer of security to your GraphQL API by disallowing arbitrary queries to be performed against your APIs.

Check [Production Considerations](https://www.graphile.org/postgraphile/production/#simple-query-allowlist-persisted-queries--persisted-operations) for a more in-depth reasoning.

We recommend that all GraphQL APIs that only intend a specific/known set of clients to use the API should use Persisted Operations.

<!-- TOC -->

## Configuration

You can configure `go-graphql-armor` to enable Persisted Operations.

```yaml
# ...

persisted_operations:
# Enable or disable the feature, enabled by default
enabled: true
# Fail unknown operations, disable this feature to allow unknown operations to reach your GraphQL API
fail_unknown_operations: true
# Determines the strategy for loading the supported operations.
# Only one store will be used
store:
# Load persisted operations from a directory on the local filesystem.
# Will look at all files in the directory and attempt to load any file with a `.json` extension
dir: "./my-dir"
# Load persisted operations from a GCP Cloud Storage bucket.
# Will look at all the objects in the bucket and try to load any object with a `.json` extension
gcp_bucket: "gs://somebucket"

# ...
```

## Parsing Structure

To be able to parse Persisted Operations go-graphql-armor expects a `key-value` structure for `hash-operation` in the files.

`any-file.json`
```json
{
"key": "query { product(id: 1) { id name } }",
"another-key": "query { hello }"
}
```

Once loaded, any incoming operation with a known hash will be modified to include the operations specified as the value.

## Request Structure

We follow the [APQ specification](https://github.com/apollographql/apollo-link-persisted-queries#apollo-engine) for **sending** hashes to the server.

> **Important:**
> While we use the specification for APQ, be aware that _automatically_ persisting unknown operations is **NOT** supported.
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ type Config struct {
GcpBucket string `conf:"gs://something/foo" yaml:"gcp_bucket"`
Dir string `conf:"" yaml:"dir"`
}
FailUnknownOperations bool `conf:"default:true" yaml:"fail_unknown_operations"`
AllowUnPersistedOperations bool `conf:"default:false" yaml:"allow_unpersisted_operations"`
FailUnknownOperations bool `conf:"default:false" yaml:"fail_unknown_operations"`
}

var ErrNoLoaderSupplied = errors.New("no loader supplied")
Expand Down Expand Up @@ -101,7 +100,7 @@ func (p *PersistedOperationsHandler) Execute(next http.Handler) http.Handler {
return
}

if p.cfg.AllowUnPersistedOperations && payload.Query != "" {
if !p.cfg.FailUnknownOperations && payload.Query != "" {
next.ServeHTTP(w, r)
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ func TestNewPersistedOperations(t *testing.T) {
name: "Allows unpersisted requests if configured",
args: args{
cfg: Config{
Enabled: true,
AllowUnPersistedOperations: true,
Enabled: true,
FailUnknownOperations: true,
},
payload: RequestPayload{
Query: "query { foo }",
Expand All @@ -69,8 +69,8 @@ func TestNewPersistedOperations(t *testing.T) {
name: "Returns error if no hash match is found and unpersisted operations are not allowed",
args: args{
cfg: Config{
Enabled: true,
AllowUnPersistedOperations: false,
Enabled: true,
FailUnknownOperations: false,
},
payload: RequestPayload{
Extensions: Extensions{
Expand Down Expand Up @@ -103,8 +103,8 @@ func TestNewPersistedOperations(t *testing.T) {
name: "Swaps in query payload if hash operation is known, updates content length accordingly",
args: args{
cfg: Config{
Enabled: true,
AllowUnPersistedOperations: false,
Enabled: true,
FailUnknownOperations: false,
},
payload: RequestPayload{
Extensions: Extensions{
Expand Down
6 changes: 3 additions & 3 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dev.setup:

.PHONY: build
build:
go build -ldflags "$(LDFLAGS)" ./cmd/main.go
CGO_ENABLED=0 go build -ldflags "$(LDFLAGS)" ./cmd/main.go

.PHONY: test
test:
Expand All @@ -23,9 +23,9 @@ lint:
golangci-lint run --timeout 3m

.PHONY: run_container
build_container:
build_container: build
docker build github.com/ldebruijn/go-graphql-armor -t go-graphql-armor .

.PHONY: run_container
run_container:
run_container: build_container
go run -d -p 8080:8080 go-graphql-armor

0 comments on commit 063c803

Please sign in to comment.