Beapi Spring Boot Starter
Stable Version : 0.7.1
Development Version : 0.8.0
Springboot Version : 2.6.2 (or greater)
JVM : 17 (has previously been tested with as low as 1.8)
License - Reciprocal Public License
Documentation - https://beapi-io.github.io/spring-boot-starter-beapi/
Demo Application - https://github.com/Beapi-io/beapi-java-demo
Configuration Files - https://github.com/orubel/spring-boot-starter-beapi-config (Note : Move these into your 'iostateDir' location as found in your demo-application/src/main/resources/beapi_api.yaml file)
BeAPI stresses convention over config...
Most everything you need for API development should be provided & configured 'out of the box' BUT you have the ability to configure and override everything to your hearts content
Beapi abstracts all RULES for API endpoints ...
All API RULES can be shared/syncronized with all services in a distributed API architecture without requiring restarts of all servers to do so. Similar docs like [https://flic.kr/p/2keNR8v]('OpenAPI' cannot and do not support RBAC/ABAC roles). This is essential when you want to integrate MULTIPLE API services across different parts of your company/product/service.
In current architectures, DATA for endpoints is bound to FUNCTIONALITY ( see Cross Cutting Concern ) through things like 'annotations'; this makes it so that you have to duplicate this DATA everywhere(see OpenApi) as said data is hardcoded into functionality via those annotations. And UNFORTUNATELY existing tools (like OpenAPI) refuse to include/synchronize RBAC rules across services making it so other services become insecure when using tools like OpenApi.
By abstracting it into an externally reloadable file, things like RBAC/'endpoint ROLES' can be easily adjusted without requiring a restart of services. Plus using functionality like webhooks, one can synchronize all services from a MASTER server. This allows for changes to API endpoint DATA on a distributed API architecture without restarting services.
BeAPI automates common usage...
By abstracting the rules, this allows for easier automation and allows for automated batching and 'Api Chaining® '
Functionality
-
Security
- Zero Trust Security by default
- Automated Role Based Access Control (RBAC);
- Automated Attribute Based Access Control (ABAC)
- Full OWASP API Security Compliance
- Automated RBAC+OWASP checks on cache; this is something that API Gateways do not do and we correct for.
-
Configuration Management
- Reloadable API RULES (ie connectors) WITHOUT server/application restart
- Automated synchronization of API RULES w/ services via webhooks (will be adding to beapi_java_demo)
-
Automation
- Automated Role-based Batching
- API Chaining(R)
- Autogenerated Role-based API Docs
- Return type inference (Accept)
- Connector Scaffolding (coming in 0.7.X)
- Automated Role-based Webhooks (coming soon)
Gradle Implementation
repositories {
mavenLocal()
mavenCentral()
maven {
url 'https://s01.oss.sonatype.org/content/repositories/releases'
}
}
...
dependencies {
...
implementation 'io.beapi:spring-boot-starter-beapi:0.6.5'
...
}
Getting a Token and calling your api -
Using the Java-demo implementation, this will get you your BEARER token to use in your calls/app:
curl -v -H "Content-Type: application/json" -X POST -d '{"username":"admin","password":"@6m!nP@s5"}' http://localhost:8080/authenticate
Then call your api normally:
curl -v -H "Content-Type: application/json" -H "Authorization: Bearer {your_token_here}" --request GET "http://localhost:8080/v{appVersion}/user/show/5"
Q&A
-
Why does the 0.6.0 version not build anymore?
- There was tracking code in the 0.6.0' version that was being used to track installs; This was mainly to see which corporations are violating the licensing. Now that we have that data, we no longer need the tracker installed. Unfortunately, this breaks the 0.6.0 build. Feel free to use the 0.7.0 build as it's more up to date :)
-
Why Not bind the endpoints to the 'MODEL'(ie GraphQL)?
- First 'resource' in API spec (per Roy Fielding) is used in the sense of 'Uniform Resource Indicator' (ie URI). This points to a service or business logic which then calls data which may be a mixture of two tables (ie JOIN), a file, a link to another api, etc. By binding to your model, you are asking it to become the 'business logic','communication logic' as well as 'data handling' and not only breaks the API spec/standard but limits what your API can return. This breaks rules of AOP, Separation of Control', OWASP API security and over complicates your build and testing. This also makes your entire environment slower and harder to scale. So yeah... bad idea in general.
-
Why require a cache?
- Caching is actually listed as part of the API requirements in Roy Fieldings dissertation; You cannot name an professional API implementation that does not use a cache. Unfortunately, many developers do not understand proper caching techniques (with API's). So we took that as an opportunity to handle that for you. You're welcome.
-
Why not just use @RequestMapping, @GetMapping, etc?
- The RequestMapping annotations create HARD CODED 'rules' to functionality; you cannot update/synchronize these 'rules' across your shared servers. This breaks the rules for configuration management when applying rules for the shared state across your entire architecture and can create security issues in the api gateway. We abstract the rules away from the business logic so that they CAN be updated and shared with all running services WITHOUT requiring restarts.
- By abstracting this data from the functionality, we are better able to make LIVE CHANGES TO ENDPOINT RULES when functionality hasn't changed. So for example if we want to disable privileges or change how a certain ROLE accesses endpoints, we can do that on the fly without taking down servers.
-
Why can't 'API Chaining(R)' have more than ONE UNSAFE method in the chain?
- FIRST, You can only send ONE METHOD with a chain; you cannot send a PUT and POST method in the same call. But you can just default every other call to a SAFE call (ie GET) as long as client has AUTHORITY to the endpoint. SECOND, since it can only have one UNSAFE METHOD, you can only send ONE DATASET. We made it to be as simple as possible while encompassing the most commonly used calls thus simplifying the processing and the client call.
-
Isn't it BAD to send form data with a GET request? I thought you could only send URI encoded data??
- Per W3C guidelines : 'A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported'. API Chaining(tm) is that direct connection with purpose. It provides the necessary backend checks and limits what can be sent.
Flowchart
flowchart TD
A[DispatcherServlet] --> B[RequestInitializationFilter]
B --> |preHandler| C(ApiInterceptor)
C --> D[ExchangeService]
C --> E[BatchExchangeService]
C --> F[ChainExchangeService]
D --> G[Controller extends BeapiRequestHandler]
E --> G[Controller extends BeapiRequestHandler]
F --> G[Controller extends BeapiRequestHandler]
G --> |postHandler| C