Skip to content

A simple proxy for validating API requests against an OpenAPI definition

License

Notifications You must be signed in to change notification settings

olensmar/openapi-sidecar

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

openapi-sidecar

A simple HTTP proxy/sidecar for validating incoming requests against an OpenAPI definition and returning nice errors if requests don't match any defined operation or its defined request parameters/schema. Valid requests will be forwarded to the target service and its response will be returned accordingly.

Useful if you

  • don't want to write all that logic yourself
  • want to guard your service from unwanted requests

Supports both OpenAPI 2.0 and 3.X definitions.

Example

The included deployment.yaml will deploy the swagger3 petstore service with the openapi-sidecar configured with port-rewriting (see below). Add it to your cluster with

kubectl apply -f k8s/deployment.yaml

Use port-forwarding to make the service available on port 8001 on your local machine:

kubectl port-forward service/petstore 8001:80
Forwarding from 127.0.0.1:8001 -> 8000
Forwarding from [::1]:8001 -> 8000

(you should be able to access Swagger-UI at http://localhost:8001 in your browser now)

Try sending a valid request to the service with curl:

curl -X GET "http://localhost:8001/api/v3/pet/findByStatus?status=sold" -H  "accept: application/json"
[{"id":5,"category":{"id":1,"name":"Dogs"},"name":"Dog 2","photoUrls":["url1","url2"],"tags":[{"id":1,"name":"tag2"},{"id":2,"name":"tag3"}],"status":"sold"}]

This request gets forwarded to the petstore service and its response is returned accordingly.

Now try sending an invalid request with an incorrect status value:

 curl -X GET "http://localhost:8001/api/v3/pet/findByStatus?status=something" -H  "accept: application/json"          
{"code":"400","message":"parameter \"status\" in query has an error: value is not one of the allowed values\nSchema:\n  {\n    \"default\": \"available\",\n    \"enum\": [\n      \"available\",\n      \"pending\",\n      \"sold\"\n    ],\n    \"type\": \"string\"\n  }\n\nValue:\n  \"something\"\n | "}

Use jq to extract the message:

curl -X GET "http://localhost:8001/api/v3/pet/findByStatus?status=something" -H  "accept: application/json" | jq -r '.message'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   302  100   302    0     0  15894      0 --:--:-- --:--:-- --:--:-- 15894
parameter "status" in query has an error: value is not one of the allowed values
Schema:
  {
    "default": "available",
    "enum": [
      "available",
      "pending",
      "sold"
    ],
    "type": "string"
  }

Value:
  "something"
 | 

The error message above was created by the openapi-sidecar and returned to the client - no request was forwarded to the petstore service.

Usage modes

You can use the openapi-sidecar in two ways:

  • as a regular proxy with the client calling the proxy directly
  • by rewriting the ip-table of your pod to reroute traffic internally to the sidecar

Regular Proxy

To use the openapi-sidecar as a proxy, simply add it to your pod/deployment as follows:

      containers:
        - .. your service container
        - name: openapi-proxy
          image: kubeshop/openapi-sidecar:latest
          ports:
            - containerPort: <port you want to expose>
          env:
            - name: PROXY_PORT
              value: "<port you want to proxy to listen on"
            - name: SERVICE_PORT
              value: "<port your target service is listening on>"
            - name: OPENAPI_PATH
              value: "<url or path to the openapi definition to use for validation>"

If you specify a path (and not a complete URL) for the OpenAPI definition it will be retrieved from the target service at the specified SERVICE_PORT.

The following example taken from the included deployment.yaml is for the petstore3 service:

      containers:
        - name: service
          image: swaggerapi/petstore3:unstable
          ports:
            - containerPort: 8080
        - name: proxy
          image: kubeshop/openapi-sidecar:latest
          ports:
            - containerPort: 8000
          env:
            - name: PROXY_PORT
              value: "8000"
            - name: SERVICE_PORT
              value: "8080"
            - name: OPENAPI_PATH
              value: "/api/v3/openapi.json"

In this case clients would use port 8000 instead of 8080 to get request-validation functionality.

With port-rewriting

If you for some reason can't (or don't want to) change the port of the target service (or the service client) you can use the included openapi-sidecar-init docker image to dynamically rewrite the ports of the pod (see the init.sh script to see how this is done).

Adding this to the example above:

      initContainers:
        - name: init-networking
          image: kubeshop/openapi-sidecar-init:latest
          securityContext:
            capabilities:
              add:
                - NET_ADMIN
            privileged: true
          env:
            - name: SOURCE_PORT
              value: "8080"
            - name: TARGET_PORT
              value: "8000"
      containers:
        - name: service
          image: swaggerapi/petstore3:unstable
          ports:
            - containerPort: 8080
        - name: proxy
          image: olensmar/openapi-sidecar:latest
          ports:
            - containerPort: 8000
          env:
            - name: PROXY_PORT
              value: "8000"
            - name: SERVICE_PORT
              value: "8080"
            - name: OPENAPI_PATH
              value: "/api/v3/openapi.json"

The init-container will rewrite the iptable of the pod as to redirect traffic going to the service on port 8080 to go to port 8000 instead (which will then proxy back to the "real" 8080).

Building

This project contains builds docker images:

Kudos

To Venil Noronha's https://venilnoronha.io/hand-crafting-a-sidecar-proxy-and-demystifying-istio article, which provided much of the boilerplate and insight needed for this.

About

A simple proxy for validating API requests against an OpenAPI definition

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published