We will build a small, autonomous IoT system with two HTTP REST services, an MQTT broker and a dummy WebSocket application and protect everything using the Border Gateway.
Set up aliases for localhost
This tutorial will set up an OpenID Connect provider and the Border Gateway with TLS encryption using self-signed certificates (created for dummy domain names
bgw-ssl) locally on your machine using Docker and Docker Compose. To be able to access these components using the dummy domain names, add the following lines to your local
Clone the repository
Set an environment variable
BGW_HOME to the path of the cloned repository.
Start up the OpenID Connect provider
This will set up an instance of Keycloak with a Postgres backend and an nginx webserver. Wait until everything is up and running and make sure you can login at https://openid-ssl/auth/admin/ using credentials
keycloak . The certificate is self-signed, you can find the CA certificate at
Start up the backend
Start up the Border Gateway
bgw-external-interface service will listen on port 8443 for https connections, on port 8883 for mqtts connections and on port 9002 for wss connections. The certificate is self-signed, you can find the CA certificate at
Performing HTTP methods
Note that in the bgw configuration file
$BGW_HOME/test/tutorial/config.toml we allow rule
HTTPS/GET/# for anonymous access (more on authorization rules here). Also we configured the path
/sc to be forwarded to Service Catalog running at
sc:8082 in the user-defined Docker network
backend_services . So you should be able to access page https://bgw-ssl:8443/sc/main_broker in the browser and see output like this:
Since GET is the the only http method allowed for anonymous access, other methods will not be executed and Border Gateway will redirect you to the Keycloak login page (which is not useful for curl of course... we will see below how this works out when using the browser). Here is an example if we tried to add the dummy REST service to Service Catalog (we will get a http error message 302):
There is a user
tutorial (with password
tutorial) defined in Keycloak though that has (among others) authorization rule
HTTPS/PUT/#. So if you provide the correct basic authorization header, the following REST API call will be performed:
Note that a new service has been registered with Service Catalog visible at https://bgw-ssl:8443/sc/helloworld.
You can also retrieve an access token from the OpenID Connect provider and use it to authorize yourself:
Provide the access token as bearer token to update the service:
Note that when we registered the dummy REST service with Service catalog, we gave the internal API address https://bgw-ssl:8443/sc/helloworld though, we see API address https://bgw-ssl:8443/helloworld. This is done by Border Gateway´s address translation. HTTP responses are inspected for internal addresses of the IoT network and these are being translated into addresses that are accessible externally via Border Gateway. The same goes for the broker address shown at https://bgw-ssl:8443/sc/main_broker. It was originally registered in the Service Catalog config file as tcp://mosquitto:1883 and is being translated by Border Gateway for external access.. When we check
Accessing the MQTT broker
MQTT via Border Gateway is not configured for anonymous access as you can see when trying:
tutorial user has authorization rule
MQTT/+/mosquitto/1883/tutorial so this will work:
You can also retrieve an access token as described above and provide it in the username field (do not provide a password field):
Connection via WebSocket
We can use the tool
wscat to test a connection via WebSocket. Anonymous access is not allowed:
User tutorial has authorization rule
WS/CONNECT/+/+/# , so connecting is allowed:
You can also retrieve an access token as described above and provide it like this:
When you try to send or receive data, you will be disconnected as soon as the token lifespan is over.
Let´s say you want to limit access for user
tutorial to https://bgw-ssl:8443/sc/main_broker only and disallow all other paths. First we need to disallow anonymous access completely. To do this, comment out the
anonymous_bgw_rules definition for the default OpenID Connect provider in
We need to restart Border Gateway for the change to take effect.
When trying to open https://bgw-ssl:8443/sc/main_broker in the browser, anonymous access is not allowed and you will be forwarded to the Keycloak login page. Log in there with
tutorial / tutorial and you will be redirected to https://bgw-ssl:8443/sc/main_broker.
Now log in to https://openid-ssl/auth/admin/ as
keycloak / keycloak. Go to Realm1, Users, Edit user
tutorial, Attributes and replace the value of key
bgw_rules with value
Make sure to hit the Save button. This will not take effect immediately, since the access tokens are cached in redis (default lifespan in Keycloak is five minutes). To speed things up, just restart redis:
We want to limit subscription rights of user
tutorial to a certain topic. Let´s log into Keycloak Admin Console again and change the value of key
Since bgw-mqtt-proxy service is not aware of bgw-external-interface service, we need to use the broker´s internal hostname and port in the rule definition. Hit the Save button and restart redis. Now
tutorial is allowed to connect and subscribe to topic
But the user is not allowed to subscribe to any other topic:
Note that the return code in the
SUBACK is 128 which represents failure. So you will not receive messages published on this topic.
Now let´s have a look at publications. First subscribe to topic
Now open another console windows and publish something:
There is no standard way of telling a publisher that his publication is not allowed so from the publisher´s perspective, everything looks fine. Note though that the subscriber will not receive the message as it is not actually published but dropped by the Border Gateway.
and restart redis. Now publish again and you will see that the subscriber receives the message as a publication to topic
tutorial is allowed for user
Currently a fine-grained authorization for WebSocket connections is not supported.
Using client certificates
You can configure the Border Gateway to demand a client certificate for the TLS connection to be established. Change the following line in
Restart the Border Gateway for the change to take effect:
Now no connection to any of the services will be possible without providing a client certificate signed by
$BGW_HOME/certs/CA.pem. Here is how to provide an example client certificate for