NGINX 一直被公认为支持高性能 Web 服务器和负载均衡器的首选之一。 然而,随着微服务架构的兴起和高效API管理的需求,NGINX也成为构建API网关的热门选择。
在此博客中,我们将探讨如何使用声明性 API 方法将 OpenAPI 模式定义转换为功能齐全的 NGINX 配置,该配置作为具有Webapplication防火墙安全性的 API 网关和开发人员门户运行。
我们将提供分步说明和见解,指导如何利用 NGINX Plus 简化您的 API 管理流程并确保您的应用获得最佳性能。
API 网关作为管理和保护客户端和后端服务之间通信的中央枢纽。 它充当客户端和后端服务器之间的反向代理,路由传入的请求并将其分发到适当的服务。 这使得客户端和服务之间的通信更加有效,并且使得 API 网关能够处理诸如身份验证、授权、速率限制和缓存等任务。
此外,API 网关可以充当安全层,保护后端服务免受潜在威胁和攻击。 它可以实施加密、基于令牌的身份验证和访问控制等安全措施,确保只有授权用户才能访问服务。 通过在一个地方整合和管理这些安全功能,API 网关有助于简化系统的整体安全架构,并降低跨多个服务实施安全措施的复杂性。
社区支持的NGINX Declarative API项目为NGINX Instance Manager提供了一组声明式 REST API。
它可用于管理 NGINX Plus 配置生命周期并使用 JSON 服务定义创建 NGINX Plus 配置。 与 NGINX 实例管理器一起使用时支持 GitOps 集成:检查引用对象更新的真实来源,并自动保持 NGINX 配置同步。
OpenAPI 模式可用于自动将 NGINX 配置为 API 网关。 通过Redocly支持开发人员门户创建。
要运行本博客的内容,您需要:
声明式API测试
实例组安装并运行所有先决条件后,NGINX 实例管理器会显示 NGINX Plus 实例与 NGINX App Protect WAF 在线。
NGINX Plus 实例是declarativeAPI 测试
实例组的一部分
NGINX Declarative API 项目依赖于 NGINX Instance Manager 提供的 REST API,并提供基于 JSON 的声明式抽象。 按照以下说明运行声明性 API 项目:
1. 运行 docker ps 来验证 Docker 是否正在运行:
f5@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2. 在 Linux 主机上克隆 Github 存储库:
f5@ubuntu:~$ git clone https://github.com/f5devcentral/NGINX-Declarative-API/
Cloning into 'NGINX-Declarative-API'...
remote: Enumerating objects: 4072, done.
remote: Counting objects: 100% (1982/1982), done.
remote: Compressing objects: 100% (1332/1332), done.
remote: Total 4072 (delta 668), reused 876 (delta 609), pack-reused 2090
Receiving objects: 100% (4072/4072), 19.05 MiB | 4.88 MiB/s, done.
Resolving deltas: 100% (1154/1154), done.
f5@ubuntu:~$
3. 切换到 docker-compose 目录:
f5@ubuntu:~$ cd NGINX-Declarative-API/contrib/docker-compose/
4. 使用nginx-dapi.sh
脚本通过docker-compose启动所有容器。 在初始启动期间,所有 docker 镜像都会自动构建:
f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ ./nginx-dapi.sh -c start
-> Updating docker images
[+] Pulling 11/11
[...]
-> Deploying NGINX Declarative API
[+] Running 4/4
✔ Network nginx-dapi_dapi-network Created 0.1s
✔ Container redis Started 1.5s
✔ Container devportal Started 1.5s
✔ Container nginx-dapi Started
5. 检查正在运行的docker容器:
f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e29a2f783da2 nginx-declarative-api "/deployment/env/bin…" 5 minutes ago Up 5 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp nginx-dapi
97142840eaf7 redis "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis
6b50c0426643 nginx-declarative-api-devportal "/deployment/src/sta…" 5 minutes ago Up 5 minutes 0.0.0.0:5001->5000/tcp, :::5001->5000/tcp devportal
6. 在客户端主机上运行 Postman 并导入 NGINX Declarative API 集合,网址为https://raw.githubusercontent.com/f5devcentral/NGINX-Declarative-API/main/contrib/postman/NGINX%20Declarative%20API.postman_collection.json
7. 编辑 Postman 集合变量以使其适应您的环境:
8. 设置以下变量:
ncg_host
- 运行声明式 API docker-compose 的 Linux 主机的主机名或 IP 地址ncg_port
-NGINX Declarative API 的 TCP 端口: 5000 是默认值nim_host
- NGINX 实例管理器基本 URL(即 https://nms.k8s.ie.ff.lan)nim_username
- NGINX 实例管理器身份验证用户名nim_password
- NGINX 实例管理器身份验证密码9. 保存 Postman 上的所有更改
10. 在 Postman 集合中浏览到Petstore API Gateway RateLimit + JWT AuthN/AuthZ + WAF
并打开请求
JSON 声明如下:
{
"output": {
"type": "nms",
"nms": {
"url": "{{nim_host}}",
"username": "{{nim_username}}",
"password": "{{nim_password}}",
"instancegroup": "{{nim_instancegroup}}",
"synctime": 0,
"modules": [
"ngx_http_app_protect_module"
],
"certificates": [
{
"type": "certificate",
"name": "test_cert",
"contents": {
"content": "{{github_gitops_root}}/v4.2/testcert.crt"
}
},
{
"type": "key",
"name": "test_key",
"contents": {
"content": "{{github_gitops_root}}/v4.2/testcert.key"
}
}
],
"policies": [
{
"type": "app_protect",
"name": "production-policy",
"active_tag": "xss-blocked",
"versions": [
{
"tag": "xss-blocked",
"displayName": "Production Policy - XSS blocked",
"description": "This is a production-ready policy - XSS blocked",
"contents": {
"content": "{{github_gitops_root}}/v4.2/nap-policy-xss-blocked-bot-allowed.json"
}
},
{
"tag": "xss-allowed",
"displayName": "Production Policy - XSS allowed",
"description": "This is a production-ready policy - XSS allowed",
"contents": {
"content": "{{github_gitops_root}}/v4.2/nap-policy-xss-allowed.json"
}
}
]
}
]
}
},
"declaration": {
"http": {
"servers": [
{
"name": "Petstore API",
"names": [
"apigw.nginx.lab"
],
"resolver": "8.8.8.8",
"listen": {
"address": "0.0.0.0:443",
"http2": true,
"tls": {
"certificate": "test_cert",
"key": "test_key",
"ciphers": "DEFAULT",
"protocols": [
"TLSv1.2",
"TLSv1.3"
]
}
},
"log": {
"access": "/var/log/nginx/apigw.nginx.lab-access_log",
"error": "/var/log/nginx/apigw.nginx.lab-error_log"
},
"locations": [
{
"uri": "/petstore",
"urimatch": "prefix",
"apigateway": {
"openapi_schema": {
"content": "http://petstore.swagger.io/v2/swagger.json"
},
"api_gateway": {
"enabled": true,
"strip_uri": true,
"server_url": "https://petstore.swagger.io/v2"
},
"developer_portal": {
"enabled": true,
"uri": "/petstore-devportal.html"
},
"authentication": {
"client": [
{
"profile": "Petstore JWT Authentication"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},
"authorization": [
{
"profile": "JWT role based authorization",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],
"rate_limit": [
{
"profile": "petstore_ratelimit",
"httpcode": 429,
"burst": 0,
"delay": 0,
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
]
},
"log": {
"access": "/var/log/nginx/petstore-access_log",
"error": "/var/log/nginx/petstore-error_log"
},
"app_protect": {
"enabled": true,
"policy": "production-policy",
"log": {
"profile_name": "secops_dashboard",
"enabled": true,
"destination": "127.0.0.1:514"
}
}
}
]
}
],
"rate_limit": [
{
"name": "petstore_ratelimit",
"key": "$binary_remote_addr",
"size": "10m",
"rate": "2r/s"
}
],
"authentication": {
"client": [
{
"name": "Petstore JWT Authentication",
"type": "jwt",
"jwt": {
"realm": "Petstore Authentication",
"key": "{\"keys\": [{\"k\":\"ZmFudGFzdGljand0\",\"kty\":\"oct\",\"kid\":\"0001\"}]}",
"cachetime": 5
}
}
]
},
"authorization": [
{
"name": "JWT role based authorization",
"type": "jwt",
"jwt": {
"claims": [
{
"name": "roles",
"value": [
"~(devops)"
],
"errorcode": 403
}
]
}
}
]
}
}
}
输出
部分定义:
声明
部分描述:
/petstore
基本 URI,API 网关配置将部署在此 URI 中,并可供客户端访问API 网关声明部分描述了声明性 API 将如何提供其结果。
OpenAPI 模式通过其完整 URL 来引用:
"apigateway": {
"openapi_schema": {
"content": "http://petstore.swagger.io/v2/swagger.json"
},
请求创建 NGINX API 网关配置,并定义上游服务器。 当 NGINX 反向代理向上游发出请求时, /petstore
基本 URI 将被删除:
"api_gateway": {
"enabled": true,
"strip_uri": true,
"server_url": "https://petstore.swagger.io/v2"
},
请求在特定 URI 下创建并部署开发人员门户:
"developer_portal": {
"enabled": true,
"uri": "/petstore-devportal.html"
},
根据指定的客户端身份验证配置文件对/user/login
和/user/logout
强制执行客户端身份验证:
"authentication": {
"client": [
{
"profile": "Petstore JWT Authentication"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},
根据指定的客户端授权配置文件对/user/login
和/user/logout
强制执行客户端授权:
"authorization": [
{
"profile": "JWT role based authorization",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],
根据指定的配置文件对/user/login
和/user/logout
进行速率限制:
"rate_limit": [
{
"profile": "petstore_ratelimit",
"httpcode": 429,
"burst": 0,
"delay": 0,
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
]
},
12. 使用 Postman的“发送”
按钮将请求发布到声明性 API。响应类似于:
{
"code": 200,
"content": {
"createTime": "2024-04-26T17:09:10.419574328Z",
"details": {
"failure": [],
"pending": [],
"success": [
{
"name": "vm-test"
}
]
},
"id": "1060ec49-120e-45ca-820b-5203c8b3538d",
"message": "Instance Group config successfully published to declarativeAPITest",
"status": "successful",
"updateTime": "2024-04-26T17:09:10.881509913Z"
},
"configUid": "eecf1da6-9d8f-4e44-89cc-a470af79379d"
}
13. 在此阶段,NGINX 实例配置为 API 网关,强制实施 WAF 安全性并发布开发人员门户。
注意:假定 FQDN apigw.nginx.lab
解析为运行 NGINX 实例的虚拟机的 IP 地址
1. 切换到jwt
目录:
f5@ubuntu:~$ cd ~/NGINX-Declarative-API/contrib/gitops-examples/jwt
2. 访问未经身份验证的 REST API 端点:
$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/store/inventory
HTTP/2 200
date: Fri, 26 Apr 2024 17:13:54 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-methods: GET, POST, DELETE, PUT
access-control-allow-headers: Content-Type, api_key, Authorization
{"totvs":5,"aut":1,"FORsold":1,[...]
3. 速率限制:
$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login;curl -w '\n' -ki
https://apigw.nginx.lab/petstore/user/login
HTTP/2 401
date: Fri, 26 Apr 2024 17:14:51 GMT
content-type: text/html
content-length: 179
www-authenticate: Bearer realm="Petstore Authentication"
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
HTTP/2 429
date: Fri, 26 Apr 2024 17:14:51 GMT
content-type: text/html
content-length: 169
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
4. 身份验证及有效授权:
$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Authorization: Bearer `cat jwt.devops`"
HTTP/2 200
date: Fri, 26 Apr 2024 17:15:41 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-methods: GET, POST, DELETE, PUT
access-control-allow-headers: Content-Type, api_key, Authorization
x-expires-after: Fri Apr 26 18:15:41 UTC 2024
x-rate-limit: 5000
{"code":200,"type":"unknown","message":"logged in user session:1714151741883"}
5. 身份验证和无效授权:
$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Authorization: Bearer `cat jwt.guest`"
HTTP/2 403
date: Fri, 26 Apr 2024 17:16:07 GMT
content-type: text/html
content-length: 153
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
6. NGINX App Protect WAF 和跨站点脚本安全违规:
$ curl -w '\n' -ki "https://apigw.nginx.lab/petstore/store/inventory?
"
HTTP/2 200
content-type: text/html; charset=utf-8
cache-control: no-cache
pragma: no-cache
content-length: 246
<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.<br><br>Your support ID is: 7283327928460093545<br><br><a href='javascript:history.back();'>[Go Back]</a></body></html>
7. 可以通过以下方式访问开发者门户:
https://apigw.nginx.lab/petstore/petstore-devportal.html
要试用本文讨论的 NGINX 解决方案,请立即开始 30 天免费试用,或联系我们讨论您的用例:
下载NGINX Agent – 它是免费且开源的。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”