ブログ | NGINX

宣言型 API を使用した OpenAPI から API ゲートウェイとしての NGINX へ

NGINX は、高性能 Web サーバーとロードバランサーを強化するための最優先の選択肢の 1 つとして長い間認識されてきました。 しかし、マイクロサービス アーキテクチャの台頭と効率的な API 管理の必要性により、NGINX も API ゲートウェイの構築に人気の選択肢になりました。

このブログでは、宣言型 API アプローチを使用して、OpenAPI スキーマ定義を、 Web アプリケーション ファイアウォールセキュリティと開発者ポータルを備えた API ゲートウェイとして実行される、完全に機能する NGINX 構成に変換する方法について説明します。

NGINX Plus を活用して API 管理プロセスを効率化し、アプリケーションのパフォーマンスを最適化する方法について、ステップバイステップの手順と洞察を提供します。

API ゲートウェイの紹介

API ゲートウェイは、クライアントとバックエンド サービス間の通信を管理および保護するための中央ハブとして機能します。 これは、クライアントとバックエンド サーバーの間に位置し、受信した要求をルーティングして適切なサービスに配布するリバース プロキシとして機能します。 これにより、クライアントとサービス間の通信がより効率的になり、API ゲートウェイが認証承認レート制限、キャッシュなどのタスクを処理できるようになります。

さらに、API ゲートウェイはセキュリティ レイヤーとして機能し、バックエンド サービスを潜在的な脅威や攻撃から保護します。 暗号化、トークンベースの認証、アクセス制御などのセキュリティ対策を実施し、許可されたユーザーのみがサービスにアクセスできるようにします。 API ゲートウェイは、これらのセキュリティ機能を 1 か所に統合して管理することで、システムの全体的なセキュリティ アーキテクチャを簡素化し、複数のサービスにわたるセキュリティ対策の実装の複雑さを軽減します。

NGINX 宣言型 API プロジェクト

コミュニティがサポートするNGINX Declarative APIプロジェクトは、 NGINX Instance Manager用の宣言型 REST API のセットを提供します。

NGINX Plus 構成ライフサイクルを管理し、JSON サービス定義を使用して NGINX Plus 構成を作成するために使用できます。 NGINX インスタンス マネージャーと併用すると、GitOps 統合がサポートされます。参照オブジェクトの更新について真実のソースがチェックされ、NGINX 構成が自動的に同期されます。

OpenAPI スキーマを使用すると、NGINX を API ゲートウェイとして自動的に構成できます。 開発者ポータルの作成はRedoclyを通じてサポートされます。

前提条件

このブログのコンテンツを実行するには、次のものが必要です。

ラボの概要

すべての前提条件をインストールして実行すると、NGINX インスタンス マネージャーは、NGINX App Protect WAF を使用して NGINX Plus インスタンスをオンラインとして表示します。

NGINX PlusインスタンスはdeclarativeAPITestインスタンスグループの一部です。

宣言型 API のデプロイ

NGINX 宣言型 API プロジェクトは、NGINX インスタンス マネージャーによって提供される 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 を実行し、 https ://raw.githubusercontent.com/f5devcentral/NGINX-Declarative-API/main/contrib/postman/NGINX%20Declarative%20API.postman_collection.json にある NGINX Declarative API コレクションをインポートします。

7. Postman コレクション変数を編集して、環境に合わせて調整します。

8. 次の変数を設定します。

  • ncg_host - 宣言型 API docker-compose が実行されている Linux ホストのホスト名または IP アドレス
  • ncg_port - NGINX 宣言型 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
                            }
                        ]
                    }
                }
            ]
        }
    }
}


出力セクションでは以下を定義します。

  • NGINXインスタンスマネージャサーバーは、宣言型APIがNGINX設定を公開します。
  • TLS証明書とキー - これらは、保存されている信頼できるソースのURLで参照できます。
  • NGINXアプリはWAFセキュリティポリシーを保護します。これらは、保存されている真実のソースのURLによって参照できます。

宣言セクションでは以下について説明します。

  • 作成するNGINXサーバー
  • TLSオフロードを実行するかどうか
  • アクセスとエラーエントリを記録する場所
  • API Gateway 構成がデプロイされ、クライアントがアクセスできるようになる/petstoreベース URI
  • 公開されるAPIゲートウェイ構成と開発者ポータル
  • NGINX App Protect WAFの有効化方法、使用するセキュリティポリシー、セキュリティ違反を記録する場所
  • クライアントのリクエストを認証および承認する方法

API Gateway 宣言セクションでは、宣言型 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 セキュリティが適用され、開発者ポータルが公開されます。

API ゲートウェイのテスト

注: 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. 開発者ポータルには、次のURLからアクセスできます。


https://apigw.nginx.lab/petstore/petstore-devportal.html


始める

この記事で紹介した NGINX ソリューションをお試しいただくには、今すぐ 30 日間の無料トライアルを開始するか、弊社までお問い合わせのうえ、ユースケースについてご相談ください

NGINX Agentをダウンロードしてください。無料のオープンソースです。


「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 q。"