In this section, we will show how to configure the security services. Currently, the security services are enabled by default. The security services constitute the following components:
Service |
Description |
Kong |
API Gateway used to control access from external systems |
PostgreSQL |
Database required by Kong |
Vault |
Used by EdgeX to store and manage secrets |
security-secretstore-setup |
Used to set up the secret store |
security-proxy-setup |
Used to set up the API Gateway |
Secret Store
Vault is used by EdgeX for secret management (e.g. certificates, keys, passwords, …) and is referred to as the Secret Store.
Use of Secret Store by all services can be disabled globally, but doing so will also disable the API Gateway, as it depends on the Secret Store.
Thus the following command will disable both:
$ sudo snap set edgexfoundry security-secret-store=off
API Gateway
Kong
is used for access control to the EdgeX services from external systems and is referred to as the API Gateway.
For more details please refer to the EdgeX API Gateway documentation.
The API Gateway can be disabled by using the following command:
$ sudo snap set edgexfoundry security-proxy=off
Note - by default all services in the snap except for the API Gateway are restricted to listening on ‘localhost’ (i.e. the services are not addressable from another system). In order to make a service accessible remotely, the appropriate configuration override of the ‘Service.ServerBindAddr’ needs to be made (e.g. sudo snap set edgexfoundry env.core-data.service.server-bind-addr=0.0.0.0
).
API Gateway user setup
JWT tokens
Before the API Gateway can be used, a user and group must be created, and a JWT access token generated. This can be accomplished via the
secrets-config
command, or by using snap set
commands.
The first step is to add a user. You need to create a public/private keypair, which can be done with
# Create private key:
$ openssl ecparam -genkey -name prime256v1 -noout -out private.pem
# Create public key:
$ openssl ec -in private.pem -pubout -out public.pem
If you then create the user using the secrets-config command, then you need to provide:
- The username
- The public key
- (optionally) ID. This is a unique string identifying the credential. It will be required in the next step to create the JWT token. If you don’t specify it,
then an auto generated one will be output by the secrets-config command
$ edgexfoundry.secrets-config proxy adduser --token-type jwt --user user01 --algorithm ES256 --public_key public.pem --id USER_ID
Alternatively, to do this using snap set
:
# set user=username,user id,algorithm (ES256 or RS256)
sudo snap set edgexfoundry env.security-proxy.user=user01,USER_ID,ES256
# set public-key to the contents of a PEM-encoded public key file
sudo snap set edgexfoundry env.security-proxy.public-key="$(cat public.pem)"
The second step is then to generate a token using the user ID which you specified:
$ edgexfoundry.secrets-config proxy jwt --algorithm ES256 --private_key private.pem --id USER_ID --expiration=1h
TOKEN="copy manually from output of secrets-config command"
Alternatively , you can generate the token on a different device using a bash script:
header='{
"alg": "ES256",
"typ": "JWT"
}'
TTL=$((EPOCHSECONDS+3600))
payload='{
"iss":"USER_ID",
"iat":'$EPOCHSECONDS',
"nbf":'$EPOCHSECONDS',
"exp":'$TTL'
}'
JWT_HEADER=`echo -n $header | openssl base64 -e -A | sed s/\+/-/ | sed -E s/=+$//`
JWT_PAYLOAD=`echo -n $payload | openssl base64 -e -A | sed s/\+/-/ | sed -E s/=+$//`
JWT_SIGNATURE=`echo -n "$JWT_HEADER.$JWT_PAYLOAD" | openssl dgst -sha256 -binary -sign private.pem | openssl asn1parse -inform DER -offset 2 | grep -o "[0-9A-F]\+$" | tr -d '\n' | xxd -r -p | base64 -w0 | tr -d '=' | tr '+/' '-_'`
TOKEN=$JWT_HEADER.$JWT_PAYLOAD.$JWT_SIGNATURE
The resulting JWT token must be included
via an HTTP Authorization: Bearer <access-token>
header on any REST calls used to access EdgeX services via the API Gateway.
Example:
$ curl -k -X GET https://localhost:8443/coredata/api/v1/ping? -H "Authorization: Bearer $TOKEN"
Additional users can be added by repeatedly calling the secrets-config command as above. Only one user can however be set at any time when using the snap configure hook, so
the current user must first be removed by setting the snap configuration settings to an empty string, before setting the values again:
$ sudo snap set edgexfoundry env.security-proxy.user=""
$ sudo snap set edgexfoundry env.security-proxy.public-key=""
$ sudo snap set edgexfoundry env.security-proxy.user=user02,USER_ID2,ES256
$ sudo snap set edgexfoundry env.security-proxy.public-key="$(cat public.pem)"
API Gateway TLS certificate setup
By default Kong is configured with an EdgeX signed TLS certificate. Client validation of this certificate requires the root CA certificate from the EdgeX instance. This file
(ca.pem
) can be copied from the directory $SNAP_DATA/secrets/ca
.
It is also possible to install your own TLS certificate to be used by the gateway. The steps to do so are as follows:
Start by provisioning a TLS certificate to use. One way to do so for testing purposes is to use the edgeca snap:
$ sudo snap install edgeca
$ edgeca gencsr --cn localhost --csr csrfile --key csrkeyfile
$ edgeca gencert -o localhost.cert -i csrfile -k localhost.key
Then install the certificate:
$ sudo snap set edgexfoundry env.security-proxy.tls-certificate="$(cat localhost.cert)"
$ sudo snap set edgexfoundry env.security-proxy.tls-private-key="$(cat localhost.key)"
This sample certificate is signed by the EdgeCA root CA, so by specifying the Root CA certificate for validation then a connection can now be made using your new certificate:
$ curl -v --cacert /var/snap/edgeca/current/CA.pem -X GET https://localhost:8443/coredata/api/v1/ping? -H "Authorization: Bearer $TOKEN"
To set the certificate again, you first need to clear the current setting by setting the values to an empty string:
$ sudo snap set edgexfoundry env.security-proxy.tls-certificate=""
$ sudo snap set edgexfoundry env.security-proxy.tls-private-key=""
If you are using a different server name than localhost, then it needs to be specified first using the optional tls-sni configuration setting. Example:
$ edgeca gencsr --cn server01 --csr csrfile --key csrkeyfile
$ edgeca gencert -o server.cert -i csrfile -k server.key
$ sudo snap set edgexfoundry env.security-proxy.tls-certificate=""
$ sudo snap set edgexfoundry env.security-proxy.tls-private-key=""
$ sudo snap set edgexfoundry env.security-proxy.tls-sni="server01"
$ sudo snap set edgexfoundry env.security-proxy.tls-certificate="$(cat server.cert)"
$ sudo snap set edgexfoundry env.security-proxy.tls-private-key="$(cat server.key)"
$ curl -v --cacert /var/snap/edgeca/current/CA.pem -X GET https://server01:8443/coredata/api/v1/ping? -H "Authorization: Bearer $TOKEN"