spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.53k stars 3.33k forks source link

OpenAPI Validation Proposal and Design #1397

Open jpgough opened 4 years ago

jpgough commented 4 years ago

Objective

In zonal architectures a valuable security mechanism is the ability to terminate messages that do not match an expected request in the zone nearest to the outside world - usually termed the demilitarized zone DMZ. In discussions with other gateway providers, this is becoming a more frequent ask amongst users of API Gateways.

The aim of this proposal is to provide a filter for the Spring Cloud Gateway that uses the Atlassian Swagger Request Validator to inspect the body of application/json requests and terminate with a 4xx error if the request if it does not match the target services OpenAPI specification.

Design Considerations

Reading the Body

The pre-requisite of this working is that the body of the request must be read. No modification of the body is required, however it does need to be converted into the SimpleRequest type recognised by the validator library. There are several ways that the body can be read - using custom code to cache the body or integrating with some of the code from Spring Cloud Gateway that provides a similar service for Retry Logic (e.g. emitting a EnableBodyCachingEvent). Would this be the intended usage of the event? Is there a better way to implement this?

Locating the Specification

The location of the OpenAPI specification to validate against is the next problem to solve. In the prototype I have we use a pre-flight strategy (similar to CORS) that makes the request to the target service and requests the OpenAPI specification from a well known path, it then goes on to cache the specification. If a redeployment happens this can then cause issues, unless a concept of versioning is built into the gateway - which is likely too much for a general solution.

For this reason it would be necessary to provide multiple options and functionality around the validation logic. For example on a failure re-acquire the OpenAPI specification. Alternatively, as is true with many reverse proxying/API Management tools sourcing the specification from a fixed location might be necessary. Or provide a custom override that is specific to the end users specification sourcing strategy. The design should implement the first two and leave an open configuration point for the developer to use a custom bean.

Support Alternate Validators

The final point is whether this whole solution should provide the ability to plug in different types of validators for different content types. E.g. if I want to use the OpenAPI validator to inspect JSON and an XSD to inspect XML? This would need to be factored into the design, and would likely make the location strategy relevant to all types of validators.

Project Location Considerations

Given the trade offs between performance and caching of the request body the question arises as to whether this should be an external project or added as functionality into the Spring Cloud Gateway core?

Open Questions

I would be interested in feedback on this or thumbs up if others are also looking for this pattern. I have a working prototype that I'd now like to write as a full solution.

tony-clarke-amdocs commented 4 years ago

Very interesting. We have developed a swagger predicate. Instead of using the out of box predicates we defined a new one which works of the swagger specifications provided to the gateway. We also have some enforcement of the content-type header (a filter) based on the produces/consumes properties in the swagger spec. Having a way to do full schema validation would be a great boon. One challenge is how to read the entire body when the client is doing chunked encoding. Any ideas how to handle this?

jpgough commented 4 years ago

@tony-clarke-amdocs I'm going to look into this. At the moment my understanding of the Atlassian Validator is that it needs the complete message - an idea would almost be to support a just in time validation of what we have so far. It would certainly be interesting to look into - not sure how possible it would be.

spencergibb commented 4 years ago

yup, any reading of the body all at once requires and the gateway becomes memory constrained.

spencergibb commented 4 years ago

/cc @csterwa

spencergibb commented 4 years ago

related #173

elekktrisch commented 2 years ago

interesting indeed! intuitively, I had expected that cloud-gateway already supports that, but couldn't find any examples for it.

jpgough commented 2 years ago

@elekktrisch if there is interest I can look toward a contribution of this to either Spring Cloud Gateway or as a filter that others can use outside of the main project.

I think the points above are valid around memory constraints and requirements to read in the full message first. Those consequences are potentially worth the trade-off in some gateway settings.

bhathiya commented 1 year ago

@jpgough do you have your prototype in a sharable location?