Skip to content

Nginx Component of API Gateway

Edge Xpert uses Nginx as a component of the API gateway, as described below:

Service Description
nginx The main component of API Gateway.

Started when the --api-gateway option is used with the edgexpert up command
proxy-auth The proxy-auth is used to process advanced authentication request for Nginx.

The proxy-auth contains the secrets-config utility to assist in common configuration tasks. The commands and options are described in the EdgeX Foundry documentation.

Started when the --api-gateway option is used with the edgexpert up command
redis The database used by proxy-auth.

Started as default service with the edgexpert up command

Introduction

Edge Xpert used kong as the API gateway before v2.2 release. Although kong is fast, highly-extensible with its feature-advanced plugins, it does not officially support arm32 platform and has a relatively high memory footprint and image size compared to other microservices.

Therefore, we decided to replace kong with nginx since nginx is lightweight and it supports more architecture which kong is also built on top of it. As nginx does not support complicated authentication and authorization mechanisms, proxy-auth is a dedicated microservice that handles JWT, LDAP authentication and role-based access control authorization.

Architecture

As demonstrated above, nginx provides similar functionality to kong when combined with http_auth_request_module and the proxy-auth microservice.

Start the Nginx

To start the Nginx, use the following command:

edgexpert up --api-gateway

Using a Bring-Your-Own External TLS Certificate for API Gateway

The API gateway will generate a default self-signed TLS certificate that is used for external communication. Since this certificate is not trusted by client software, it is common to replace this auto-generated certificate with one generated from a known certificate authority, such as an enterprise PKI, or a commercial certificate authority.

The process for obtaining a certificate is out-of-scope for this documentation. For the purposes of the example, the X.509 PEM-encoded certificate is assumed to be called cert.pem and the unencrypted PEM-encoded private key is called key.pem. Do not use an encrypted private key otherwise the API gateway will hang on startup in order to prompt for a password.

For the purposes of the example, the external DNS name of the API gateway is assumed to be edge001.example.com. The API gateway requires a client to support Server Name Identification (SNI) and that the client connects to the API gateway using a DNS host name. The API gateway uses the host name supplied by the client to determine which certificate to present to the client. The API gateway will continue to serve the default (untrusted) certificate if clients connect via IP address or do not provide SNI at all.

First copy the default nginx configuration at /etc/edgexpert/nginx.conf.xpert and update it:

ssl_certificate /edgex/secrets/nginx/nginx.crt;
ssl_certificate_key /edgex/secrets/nginx/nginx.key;
These are the configurations to set up TLS certificate for nginx, update the path to where you want to mount the certificate and private key later. For example:
ssl_certificate /cert.pem;
ssl_certificate_key /key.pem;

Then update docker-compose-security.yml to mount the certificate, private key and updated nginx.conf file to nginx container:

services:
  nginx:
    volumes:
      <path_to_cert.pem>:/cert.pem
      <path_to_key.pem>:/key.pem
      <path_to_updated_nginx.conf>:/etc/nginx/nginx.conf

Note

You can directly modify the default /etc/edgexpert/docker-compose-security.yml or keep the local -compose-security.yml and leverage docker-compose override mechanism

The following command can verify the certificate installation was successful.

echo "GET /" | openssl s_client -showcerts -servername edge001.example.com -connect 127.0.0.1:8443

Using API Gateway to Proxy Existing EdgeX Microservices

Once the resource mapping and access token to API gateway are in place, a client can use the access token to use the protected EdgeX REST API resources behind the API gateway. Again, without the API Gateway in place, here is the sample request to hit the ping endpoint of the Core Data using curl:

curl http://<host-system-ip>:59880/api/v2/ping

With the security service and JWT authentication enabled, the command changes to:

curl -k -H 'Authorization: Bearer <JWT>' https://<host-system-ip>:8443/core-data/api/v2/ping

For information on creating JWTs to access the gateway, refer to Creating Access Token for API Gateway Authentication.

The /core-data/ path in the URL is used to identify which EdgeX microservice the request is routed to. Since each EdgeX microservice has a dedicated service port open to accept incoming requests, there is a mapping table kept by the API gateway that maps the path to the microservice port.

Microservice Path
Core Data core-data
Core Metadta core-metadata
Core Command core-command
Support Notifications support-notifications
Support Scheduler support-scheduler
System Management Agent sys-mgmt-agent
Device Virtual device-virtual
Kuiper rules-engine
Consul consul

API Gateway management interfaces

Edge Xpert provides default nginx configuration file at /etc/edgexpert/nginx.conf.xpert:

events { }

http {
    resolver 127.0.0.11;

    map $1 $upstream_host {
        core-consul core-consul:8500;
        core-data core-data:59880;
        core-metadata core-metadata:59881;
        core-command core-command:59882;
        support-notifications support-notifications:59860;
        support-scheduler support-scheduler:59861;
        sys-mgmt-agent sys-mgmt:58890;
        rules-engine kuiper:59720;
        device-virtual device-virtual:59900;
        device-rest device-rest:59986;
        device-mqtt device-mqtt:59982;
        device-opc-ua device-opc-ua:59953;
        device-bacnet-ip device-bacnet-ip:59980;
        device-bacnet-mstp device-bacnet-mstp:59981;
        device-modbus device-modbus:59901;
        device-s7 device-s7:59958;
        device-gps device-gps:59987;
    }

    server {
        listen 8443 ssl;
        ssl_certificate /edgex/secrets/nginx/nginx.crt;
        ssl_certificate_key /edgex/secrets/nginx/nginx.key;
        error_page 500 @process_proxy_auth_error;

        location ~ ^/([\w'-]+)/(.+)$ {
            auth_request /_auth-jwt;
            auth_request_set $backend_status $upstream_status;
            proxy_pass http://$upstream_host/$2$is_args$args;
        }

        location = /_auth-jwt {
            internal;

            proxy_method GET;
            proxy_pass_request_body off;
            proxy_pass_request_headers on;
            proxy_set_header Content-Length "";

            # required for proxy-auth RBAC authorization
            proxy_set_header X-Original-Uri $request_uri;
            proxy_set_header X-Original-Method $request_method;

            proxy_pass http://proxy-auth:8079/jwt-auth;
        }

        location @process_proxy_auth_error {
            if ($backend_status = 400) {
                return 400;
            } 
            if ($backend_status = 401) {
                return 401;
            } 
            if ($backend_status = 403) {
                return 403;
            } 
            if ($backend_status = 500) {
                return 500;
            }
        }
    }
}
This example consists of setting up HTTPS, path/route mapping and JWT authentication using different Nginx directives. For more information on the Nginx configuration, refer to the Nginx documentation.