Summary

Our demo Card application deployed as here in has OpenAPI yaml and is published here: https://deck-api.api.kambur.ie/shuffledDeck.yaml. Requests should be validated, on API Gateway (in our case APISIX) before hitting application servers for performance (as then bad requests never hit application servers to be validated) and security reasons (bad requests get caught sooner and away from application servers reducing potentail attack footprint). Note that APISIX needs to be >= 3.17.

Implementation

yaml version of OpenAPI

APISIX’s oas-validate plugin can’t consume yaml - needs json instead. The following change to pipeline will take yaml file and convert as json and use existing sidecar to make available.

  - name: Deploy to Kubernetes
    run: |
      export IMAGE_TAG IMAGE_NAME
      
      # 1. Convert OpenAPI YAML to JSON
      yq eval -o=json src/main/resources/swagger/api-docs/shuffledDeck.yaml > src/main/resources/swagger/api-docs/shuffledDeck.json
      
      # 2. Generate ConfigMap with the JSON file instead of YAML
      kubectl create configmap api-docs \
        --from-file=shuffledDeck.json=src/main/resources/swagger/api-docs/shuffledDeck.json \
        --from-file=swagger-ui.html=src/main/resources/swagger/api-docs/swagger-ui.html \
        --from-file=health=src/main/resources/swagger/health \
        -n ramblings \
        --dry-run=client -o yaml | kubectl apply -f -
      
      # 3. Apply deployment with envsubst
      envsubst < kubernetes/k8s-deployment.yaml | kubectl apply -f -

Modify the route to validate

Simply, add plugins/oas-validator to the route in question and point to the generated json. Job done.

Ah, don’t forget to fix all kinds of hidden mistakes in your API spec.

 curl http://127.0.0.1:9180/apisix/admin/routes/1 \
  -H "X-API-KEY: $APISIX_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -X PUT \
  -i \
  -d '{
    "name": "1",
    "status": 1,
    "id": "1",
    "enable_websocket": false,
    "priority": 0,
    "uri": "/deck-api/*",
    "methods": [
      "GET",
      "POST",
      "PUT",
      "DELETE",
      "PATCH"
    ],
    "plugins": {
      "oas-validator": {
        "spec_url": "http://ramblings-app.ramblings.svc.cluster.local:80/shuffledDeck.json",
        "timeout": 5000,
        "verbose_errors": true
      }
    },
    "upstream_id": "1"
  }'

Test