Skip to content

Configuring Add-on Service

In the current EdgeX security serivces, we set up and configure all security related properties and environments for the existing default serivces like core-data, core-metadata, device-virtual, and so on.

The settings and service environment variables are pre-wired and ready to run in secure mode without any update or modification to the Docker-compose files. However, there are some pre-built add-on services like some device services (e.g.device-camera, device-modbus), and some of application services (e.g. app-http-export, app-mqtt-export) are not pre-wired for by default. Also if you are adding on your custom application service, there is no pre-wiring for it and thus need some configuration efforts to make them run in secure mode.

EdgeX provides a way for a user to add and configure those add-on services into EdgeX Docker software stack running in secure mode. This can be done vai Docker-compose files with a few additional environment variables and some modification of micro-service's Dockerfile. From edgex-compose repository, the compose-builder utility provides some ways to deal with those add-on services like through add-security.yml via make targets to generate docker-compose file for running them in secure mode. For more details, please refer to README documentation of compose-builder.

The above same guidelines can also be applied to custom device and application services, i.e. non-EdgeX built services.

One of the major security features in EdgeX Ireland release is to utilize the service security-bootstrapper to ensure the right starting sequence so that all services have their needed security dependencies when they start up.

Currently EdgeX uses Vault as the default implementation for secret store and Consul as the configuration and/or registry server if user chooses to do so. There are some default services pre-configured to have Secret Stores created by default such as EdgeX core/support services, device-virtual, device-rest, and app-rules-engine services.

For running additional add-on services (e.g. device-camera, app-http-export) in secure mode, their Secret Stores are not generated by default but they can be generated through some configuring steps as shown below.

In the following scenario, we assume the EdgeX services are running in Docker environments, and thus the examples are given in terms of Docker-compose ways. It should not be much or bigger difference for snap running environment to apply the same steps or concepts if found to do so.

If users want to configure and set up an add-on service, e.g. device-camera, they can achieve this by following the steps that are outlined below:

Make add-on services security-bootstrapper compatible

To use the Docker entrypoint scripts for gating mechanism from security-bootstrapper, the Dockerfile of device-camera should inherit shell scripting capability like alpine-based as the base Docker image and should install dumb-init(see details in Why you need an init system) via apk add --update command.

Dockerfile example using alpine-base image and add dumb-init:

......
FROM alpine:3.12

# dumb-init needed for injected secure bootstrapping entrypoint script when run in secure mode.
RUN apk add --update --no-cache dumb-init
......

and then for the service itself should add /edgex-init/ready_to_run_wait_install.sh as the entrypoint script for the service in gating fashion and add related Docker volumes for edgex-init and for Secret Store token, which will be outlined in the next section.

A good example of this will be like app-service-rules:

...
  app-service-rules:
    entrypoint: ["/edgex-init/ready_to_run_wait_install.sh"]
    command: "/app-service-configurable ${DEFAULT_EDGEX_RUN_CMD_PARMS}"
    volumes:
      - edgex-init:/edgex-init:ro,z
      - /tmp/edgex/secrets/app-rules-engine:/tmp/edgex/secrets/app-rules-engine:ro,z
    depends_on:
      - security-bootstrapper
...

Note that we also add command directive override in the above example because we override Docker's entrypoint script in the original Dockerfile and Docker ignores the original command when the entrypoint script is overridden. In this case, we also override the command for app-service-rules service with arguments to execute.

Configure the service's Secret Store to use

Make sure the TOML configuration file of add-on service like device-camera contains the proper [SecretStore] section.

Example:

[SecretStore]
Type = "vault"
Host = "localhost"
Port = 8200
Path = "device-camera/"
Protocol = "http"
RootCaCertPath = ""
ServerName = ""
TokenFile = "/tmp/edgex/secrets/device-camera/secrets-token.json"
  [SecretStore.Authentication]
  AuthType = "X-Vault-Token"

Note that the service key device-camera must be used for the Path and in the TokenFile path to keep it consistent and easier to maintain. And then add the add-on service's service key to EdgeX service secretstore-setup's ADD_SECRETSTORE_TOKENS environment variable in the environment section of docker-compose as the example shown below:

...
  secretstore-setup:
    container_name: edgex-secretstore-setup
    depends_on:
    - security-bootstrapper
    - vault
    environment:
      ADD_SECRETSTORE_TOKENS: 'device-camera'
...

With that, secretstore-setup then will generate Secret Store token from Vault and store it in the TokenFile path specified in the TOML configuration file like the above example.

Also note that the value of ADD_SECRETSTORE_TOKENS can take more than one service in a form of comma separated list like "device-camera, device-modbus" if needed.

(Optional) Configure known secrets for add-on services

The ADD_KNOWN_SECRETS environment variable on secretstore-setup allows for known secrets to be added to an add-on service's Secret Store.

For the Ireland release, the only known secret is the Redis DB credentials identified by the name redisdb. Any add-on service needing access to the Redis DB such as App Service HTTP Export with Store and Forward enabled will need the Redis DB credentials put in its Secret Store. Also, since the Redis DB service is now used for the MessageBus implementation, all services that connect to the MessageBus also need the Redis DB credentials

Note that the steps needed for connecting add-on services to the Secure MessageBus are:

  1. Utilizing the security-bootstrapper to ensure proper startup sequence
  2. Creating the Secret Store for the add-on service
  3. Adding the redisdb's known secret to the add-on service's Secret Store

and if the add-on service is not connecting to the bus or the Redis database, then this step can be skipped.

So given an example for service device-virtual to use the Redis message bus in secure mode, we need to tell secretstore-setup to add the redisdb known secret to Secret Store for device-virtual. This can be done through the configuration of adding redisdb[device-virtual] into the environment variable ADD_KNOWN_SECRETS in secretstore-setup service's environment section, in which redisdb is the name of the known secret and device-virtual is the service key of the add-on service.

...
  secretstore-setup:
    container_name: edgex-secretstore-setup
    depends_on:
    - security-bootstrapper
    - vault
    environment:
      ADD_SECRETSTORE_TOKENS: 'device-camera, my-service'
      ADD_KNOWN_SECRETS: redisdb[app-rules-engine],redisdb[device-rest],redisdb[device-virtual]
...

In the above docker-compose section of secretstore-setup, we specify the known secret of redisdb to add/copy the Redis database credentials to the Secret Store for the app-rules-engine, device-rest, and device-virtual services.

We can also use the alternative or simpler form of ADD_KNOWN_SECRETS environment variable's value like

    ADD_KNOWN_SECRETS: redisdb[app-rules-engine, device-rest, device-virtual]

in which all add-on services are put together in a comma separated list associated with the known secret redisdb.

(Optional) Configure the ACL role of configuration/registry to use if the service depends on it

This is a new step coming from securing Consul security features as part of EdgeX Ireland release.

If the add-on service uses Consul as the configuration and/or registry service, then we also need to configure the environment variable ADD_REGISTRY_ACL_ROLES to tell security-bootstrapper to generate an ACL role for Consul to associate with its token.

An example of configuring ACL roles of the registry Consul for the add-on services device-modbus and app-http-export is shown as follows:

...
  consul:
    container_name: edgex-core-consul
    depends_on:
    - security-bootstrapper
    - vault
    entrypoint:
    - /edgex-init/consul_wait_install.sh
    environment:
      ADD_REGISTRY_ACL_ROLES: app-http-export,device-modbus
...

The configuration of Edgex service consul's environment variable ADD_REGISTRY_ACL_ROLES tells the security-bootstrapper to set up Consul ACL role so that the ACL token is generated, hence the permission is granted for that service with the access to Consul in secure mode.

Without this step the add-on service will get status Forbidden (HTTP status code = 403) error when the service is depending on Consul and attempting to access Consul for configuration or service registry.

(Optional) Configure the API gateway access route for add-on service

If it is desirable to let user or other application services outside EdgeX's Docker network access the endpoint of the add-on service, then we can configure and add it via proxy-setup service's ADD_PROXY_ROUTE environment variable. proxy-setup adds those services listed in that environment variable into the API gateway (also known as Kong) route so that the endpoint can be accessible using Kong's proxy endpoint.

One example of adding API gateway access routes for both device-camera and device-modbus is given as follows:

...
edgex-proxy:
      ...
    environment:
      ...
      ADD_PROXY_ROUTE: "device-camera.http://edgex-device-camera:59985, device-modbus.http://edgex-device-modbus:59901"
      ...
...

where in the comma separated list, the first part of configured value device-camera is the service key and the URL format is the service's hostname with its docker network port number 59985 for device-camera. The same idea applies to device-modbus with its values.

With that setup, we can then access the endpoints of device-camera from Kong's host like https://<HostName>:8443/device-camera/{device-name}/name assuming the caller can resolve <HostName> from DNS server.

For more details on the introduction to the API gateway and how it works, please see APIGateway documentation page.