Skip to content

mmlt/apigw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

API Gateway

API Gateway (APIGW) is a reverse proxy that implements authorization based on OAuth2 scopes and a Swagger API definition.

It's typical use case is to provide authorization for a REST service.

                +--------------+
                |              |
                |  OAuth2 IDP  |
                |              |
                +------+-------+
                       ^
                       | tokeninfo
                       |
                +------+-------+        +----------------+
                |              |        |                |
  Request ----->+  APIGW       +------->+  REST service  |
                |              |        |                |
                +--------------+        +----------------+

The APIGW will only pass a request to the upstream service when all of the following conditions are met:

  • the requested path is in the swagger api definition
  • if the swagger definition does not contain oauth2 scopes for the requested path:
    • the request is passed
  • if the swagger definition does contain oauth2 scopes for the requested path:
    • the request contains a valid OAuth2 access_token
    • the tokeninfo returned scopes are a superset of the swagger defined scopes

Features

  • TSL (or not)

  • Load balancing over upstream services.

  • Swagger definitions are read from upstream server(s) on start-up (and periodically checked for updates).

  • Configurable CORS headers (by default Access-Control-Allow-Methods are read from OpenAPI endpoint definitions).

  • Configurable error responses.

  • Caching of tokeninfo responses to reduces load on tokeninfo endpoint.

  • IIS Compatible log file

    • user field contains ClientID
  • Prometheus stats

    • Histogram of handling time of successful requests - by Method
    • Counter of fully handled request - by ClientID, Status
  • Simplicity; APIGW protects one Swagger defined API (for multiple API's use multiple instances icw L7 path routing).

  • Unit and e2e tests to validate behavior (see coverage report)

Roadmap

  • Add API level throttling.
  • Add client specific throttling
  • Fuzzing of request urls.
  • Add Swagger parameter validation (currently a {parameter} matches any type). Swagger definition contains parameters specs
  • Create /health endpoint (on management port) that checks internal state
  • Improve configuration
    • Dynamic configuration of CORS Access-Control-Allow-Origin header. For example a ConfigMap with allowed origins that is easy to reload.
    • Create a /reload endpoint (on management port) to dynamically reload config when the ConfigMap is updated.

Architecture

echo middleware:

  • error handler with custom messages
  • path rewriting
  • CORS header handling
  • oauth access token + scope validation see OAuth2 RFC at https://tools.ietf.org/html/rfc6749
  • reverse proxy with load balancing

Run

Apigw is configured by yaml file, see configYaml in apigw_test.go for an example.

Assuming an config_http.yaml in the CWD do apigw -v=2 --logtostderr --config=config_http.yaml to get basic logging at stderr.

Development

Prereqs: GO 1.12 or later, GOBIN in path for tools.

Tools:

Run tests

See Makefile on how to run tests.

e2e tests (in process)

apigw_test.go runs e2e tests with all servers in a single process. This is great for testing new functionality but not so great for performance testing/tuning. TODO write e2e tests were all servers have their own golang runtime environment:

	ctx, cancel := context.Background()
	defer cancel()
	if err := exec.CommandContext(ctx, "go", "run", "upstreamsvr.go t1 localhost:1323").Run(); err != nil {
        //handle error
	}

Manual tests

Get Prometheus metrics: curl localhost:9102/metrics

Get API version (no auth required): curl -v localhost:8080/api/v1/version

Get accounts must fail because auth is required: curl -v localhost:8080/api/v1/accounts -> 400

Login via Examplesite to obtain a bearer token, then get accounts: curl -v -H "Authorization: Bearer 2dd46d2e-5711-4608-8722-79b36b60f851" localhost:8080/api/v1/accounts

Known issues

All headers send by back-end are copied in response. In some cases this violates the specs. For example when a backend returns an Access-Control-Allow-Origin header. Work-a-round: backend should not send Access-Control-Allow headers.

About

OAuth2 reverse proxy that enforces Swagger API spec.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages