Skip to content

Commit 1c0c254

Browse files
Devportal alpha release commit
1 parent 671e8d5 commit 1c0c254

File tree

14 files changed

+102
-41
lines changed

14 files changed

+102
-41
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
/.idea/
22
/src/__pycache__/
3+
/src/Contrib/__pycache__/
4+
/contrib/devportal/src/__pycache__/
35
/venv/

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ NGINX Instance Manager ->> NGINX: Publish config to NGINX instances
8888
| Cookie-based stickiness | X | |
8989
| Maps | X | |
9090
| NGINX Plus REST API access | X | |
91-
| NGINX App Protect WAF | Per-policy CRUD at `server` and `location` level with dataplane-based bundle compilation | Security policies can be dynamically fetched from source of truth |
92-
| API Gateway | Swagger and OpenAPI YAML and JSON schema support | Automated configuration, HTTP methods and rate limiting enforcement |
91+
| NGINX App Protect WAF | Per-policy CRUD at `server` and `location` level with dataplane-based bundle compilation | Security policies can be dynamically fetched from source of truth |
92+
| API Gateway | Swagger and OpenAPI YAML and JSON schema support | Automated configuration, HTTP methods and rate limiting enforcement |
93+
| API Developer Portal | Swagger and OpenAPI YAML and JSON schema support | Based on Redocly |
9394

9495
## How to use
9596

@@ -105,7 +106,7 @@ This is the recommended method to run NGINX Declarative API on a Linux virtual m
105106

106107
### As a Python application
107108

108-
This repository has been tested with and requires Python 3.9 or newer.
109+
This repository requires Python 3.10+
109110
A running instance of [redis](https://redis.io/) is required: redis host and port can be configured in the `config.toml` file.
110111

111112
Run NGINX Declarative API using:
@@ -124,8 +125,8 @@ The docker image can be built and run using:
124125
```
125126
$ git clone https://github.com/fabriziofiorucci/NGINX-Declarative-API
126127
$ cd NGINX-Declarative-API
127-
$ docker build -t nginx-declarative-api:latest -f contrib/docker/Dockerfile .
128-
$ docker run --name nginx-declarative-api -d -p 5000:5000 nginx-declarative-api:latest
128+
$ docker build --no-cache -t nginx-declarative-api -f ./Dockerfile .
129+
$ docker run --name nginx-declarative-api -d -p 5000:5000 nginx-declarative-api
129130
```
130131

131132
Pre-built docker images are available on Docker Hub at https://hub.docker.com/repository/docker/fiorucci/nginx-declarative-api/general and can be run using:

USAGE-v3.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Locations `.declaration.http.servers[].locations[].uri` match modifiers in `.dec
5353

5454
### API Gateway ###
5555

56-
Swagger files and OpenAPI schemas can be used to automatically configure NGINX as an API Gateway.
56+
Swagger files and OpenAPI schemas can be used to automatically configure NGINX as an API Gateway. Developer portal creation is supported through [Redocly](https://redocly.com/)
5757

5858
Declaration path `.declaration.http.servers[].locations[].apigateway` defines the API Gateway configuration:
5959

@@ -62,9 +62,10 @@ Declaration path `.declaration.http.servers[].locations[].apigateway` defines th
6262
- `api_gateway.strip_uri` - removes the `.declaration.http.servers[].locations[].uri` part of the URI before forwarding requests to the upstream
6363
- `api_gateway.server_url` - the base URL of the upstream server
6464
- `developer_portal.enabled` - enable/disable Developer portal provisioning
65+
- `developer_portal.uri` - the trailing part of the Developer portal URI, this is appended to `.declaration.http.servers[].locations[].uri`. If omitted it defaults to `devportal.html`
6566
- `rate_limit` - optional, used to enforce rate limiting at the API Gateway level
6667

67-
A sample API Gateway declaration to publish the `https://petstore.swagger.io` REST API and enforce:
68+
A sample API Gateway declaration to publish the `https://petstore.swagger.io` REST API DevPortal, API Gateway and enforce:
6869

6970
- REST API endpoint URIs
7071
- HTTP Methods
@@ -116,7 +117,8 @@ is:
116117
"server_url": "https://petstore.swagger.io/v2"
117118
},
118119
"developer_portal": {
119-
"enabled": false
120+
"enabled": false,
121+
"uri": "/petstore-devportal.html"
120122
},
121123
"rate_limit": {
122124
"profile": "petstore_ratelimit",
@@ -150,6 +152,10 @@ It can be tested using:
150152

151153
curl -iH "Host: apigw.nginx.lab" http://<NGINX_INSTANCE_IP_ADDRESS>/petstore/store/inventory
152154

155+
The API Developer portal can be accessed at:
156+
157+
http://<NGINX_INSTANCE_IP_ADDRESS>/petstore/petstore-devportal.html
158+
153159
### Maps ###
154160

155161
Map entries `.declaration.maps[].entries.keymatch` can be:

contrib/docker-compose/docker-compose.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ services:
1414
volumes:
1515
- redis_data:/data:rw
1616

17+
devportal:
18+
image: fiorucci/nginx-declarative-api-devportal:latest
19+
user: "${USERID}:${USERGROUP}"
20+
container_name: "devportal"
21+
restart: always
22+
ports:
23+
- "5001:5000"
24+
1725
nginx-dapi:
1826
image: fiorucci/nginx-declarative-api:latest
1927
user: "${USERID}:${USERGROUP}"

contrib/docker-compose/nginx-dapi.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ USERNAME=`whoami`
3030
export USERID=`id -u $USERNAME`
3131
export USERGROUP=`id -g $USERNAME`
3232

33+
echo "-> Updating docker images"
34+
docker-compose -f $DOCKER_COMPOSE_YAML pull
35+
3336
echo "-> Deploying NGINX Declarative API"
3437
COMPOSE_HTTP_TIMEOUT=240 docker-compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML up -d --remove-orphans
3538
}

contrib/docker/Dockerfile

Lines changed: 0 additions & 21 deletions
This file was deleted.

contrib/docker/start.sh

Lines changed: 0 additions & 4 deletions
This file was deleted.

etc/config.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,20 @@ port = 5000
2424

2525
# Redis backend for CI/CD automation
2626
[redis]
27-
host = "127.0.0.1"
27+
host = redis
2828
port = 6379
2929

30+
# Devportal helper
31+
[devportal]
32+
host = devportal
33+
port = 5001
34+
uri = "/v1/devportal"
35+
3036
# Staged configuration for NGINX Management Suite
3137
[nms]
3238
config_dir = '/etc/nginx'
3339
certs_dir = '/etc/nginx/ssl'
40+
devportal_dir = '/etc/nginx/devportal'
3441

3542
# Time to wait to get status after committing a staged config
3643
staged_config_publish_waittime = 2

src/Contrib/DevPortal.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
API Gateway Developer Portal support functions
3+
"""
4+
5+
import json
6+
import requests
7+
import base64
8+
9+
# NGINX Declarative API modules
10+
from NcgConfig import NcgConfig
11+
import Contrib.GitOps
12+
import Contrib.MiscUtils
13+
14+
15+
def buildDevPortal(openapischema):
16+
response = requests.post(f"http://{NcgConfig.config['devportal']['host']}:"
17+
f"{NcgConfig.config['devportal']['port']}{NcgConfig.config['devportal']['uri']}",
18+
headers={'Content-Type': 'application/json'}, data=openapischema)
19+
20+
return response.status_code, json.loads(response.text)
21+
22+
23+
# Builds the declarative JSON for the API Gateway configuration
24+
# Return a tuple: status, description. If status = 200 things were successful
25+
def createDevPortal(locationDeclaration: dict):
26+
if locationDeclaration['apigateway']['openapi_schema']:
27+
status, apiSchemaString = Contrib.GitOps.getObjectFromRepo(
28+
content=locationDeclaration['apigateway']['openapi_schema'], base64Encode=False)
29+
30+
if Contrib.MiscUtils.yaml_or_json(apiSchemaString) == 'yaml':
31+
# YAML to JSON conversion
32+
apiSchemaString = Contrib.MiscUtils.yaml_to_json(apiSchemaString)
33+
34+
status, devportalJSON = buildDevPortal(openapischema=apiSchemaString)
35+
devportalHTML = base64.b64encode(bytes(devportalJSON['devportal'], 'utf-8')).decode('utf-8')
36+
37+
return 200, devportalHTML

src/Contrib/GitOps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ def getObjectFromRepo(content: str, base64Encode: bool=True):
3535
else:
3636
content = bytes(content, 'utf-8').decode("utf-8")
3737

38-
return status_code, content
38+
return status_code, content

0 commit comments

Comments
 (0)