My working sample to export to MQTTS topic using app-service-configurable insecure mode for EdgeX Foundry Geneva release
- EdgeX Foundry Geneva release.
- Using
docker-app-service-configurable:1.2.0
in insecure mode (without Secret Store).- A bit of a special method to get around the bug.
- Export to MQTTS topic using client certificate authentication.
In this case, use test.mosquitto.org
for testing purposes.
- CA Cert File
- Download
mosquitto.org.crt
from https://test.mosquitto.org/.$ mkdir certs $ curl https://test.mosquitto.org/ssl/mosquitto.org.crt -o certs/ca.crt $ ls -l certs
- Download
- Client Key File
- Generate my own key.
$ openssl genrsa -out certs/client.key $ ls -l certs
- Generate the CSR. Note that Country Name, State Name, Organization Name and Common Name have to be changed from default.
$ openssl req -out certs/client.csr -key certs/client.key -new You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:JP State or Province Name (full name) [Some-State]:Tokyo Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]:EdgeX Foundry Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:app-service-mqtt Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: $ ls -l certs
- Generate my own key.
- Client Cert File
- Get my CSR string.
-----BEGIN CERTIFICATE REQUEST----- MIIClTCCAX0CAQAwUDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRYwFAYD VQQKDA1FZGdlWCBGb3VuZHJ5MRkwFwYDVQQDDBBhcHAtc2VydmljZS1tcXR0MIIB ... hZGwRAKfpbaW6yKdEqPq8D2roV6Y2j/4pWcC073dvTa5NWPtqtWadNbYVFrbWpZC m8j02K4xwUpfuX5/7cpRQOoGVFTSgxx9Nfvr8pcShb+BI3xRV2w7PQc= -----END CERTIFICATE REQUEST-----
- Paste my CSR string to the form at https://test.mosquitto.org/ssl/.
- The file
clinet.crt
is downloaded. Place this intocerts
dir.
- The file
- Get my CSR string.
Now I have these four files.
$ ls -l certs/
total 16
-rw-rw-r-- 1 kuro kuro 1452 Oct 15 06:06 ca.crt
-rw-r--r-- 1 kuro kuro 1261 Oct 15 06:12 client.crt
-rw-rw-r-- 1 kuro kuro 972 Oct 15 06:08 client.csr
-rw------- 1 kuro kuro 1675 Oct 15 06:07 client.key
The CSR will not be used anymore. I can safely remove the CSR.
$ rm certs/client.csr
Finally, the files are placed as follows:
- demo
|- docker-compose.yml
|- mqtt-export
| |- configuration.toml
|- certs
|- ca.crt
|- client.crt
|- client.key
To use MQTTS, I have to pass my cert files to app-service. EdgeX Foundry has an excellent ability to override the configuration using environment variables, but currently, there is an issue in the latest edgexfoundry/docker-app-service-configurable:1.2.0
that I can't pass the value which includes the character =
.
Because the cert files usually contain =
, I can not use the environment variable to pass my certs. That's why I have to modify TOML file manually.
In this case, use configuration.toml
for mqtt-export
from the official repository.
Download it,
$ mkdir mqtt-export
$ curl https://raw.githubusercontent.com/edgexfoundry/app-service-configurable/master/res/mqtt-export/configuration.toml -o mqtt-export/configuration.toml
and then change these lines:
[Writable.InsecureSecrets.mqtt.Secrets]
username = ""
password = ""
cacert = ""
clientcert = ""
clientkey = ""
as follows:
[Writable.InsecureSecrets.mqtt.Secrets]
username = ""
password = ""
cacert = """-----BEGIN CERTIFICATE-----
MIIDdjCCAl6gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMCR0Ix
FzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTESMBAGA1UE
...
mxXnSWchJCoy6J8IP8hjggMOVbeLG5H5LMnn4xKzqlsM5fKzCtA0n7Wqcf+TrPXB
hjesoN8T8GxSGvXMIISiZ72HqBYxBp1mGt8=
-----END CERTIFICATE-----"""
clientcert = """-----BEGIN CERTIFICATE-----
MIIDdjCCAl6gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMCR0Ix
FzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTESMBAGA1UE
...
mxXnSWchJCoy6J8IP8hjggMOVbeLG5H5LMnn4xKzqlsM5fKzCtA0n7Wqcf+TrPXB
hjesoN8T8GxSGvXMIISiZ72HqBYxBp1mGt8=
-----END CERTIFICATE-----"""
clientkey = """-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAuYPrFTipQzNQdv3tXxlfUVd2xtfXs9KXBmLg8/QCR4+f4HZa
031mBzWVAs3619VxrN8+RN5YZ022umXIBAA4hrjRJBS7KoJ5Aa2ekonSpdTth97s
...
IecGjp8X8MdIC23jJcCX76SeevOvBcCukPnaehK1I1vTgRnQ6ANG0RTrM2G/S1/C
yIqAjI5tOVmn1HkDeK/I9wgKxpY9oLlQ2tzjdbBQbOZ1H18lds4=
-----END RSA PRIVATE KEY-----"""
Note that specify cacert
with the content of ca.crt
, clientcert
with client.crt
, and clientkey
with client.key
. All of them have to be quoted by a triple quote.
Because of the strict validation of whitespace and line breaks of the PEM format, I have to allow for the indentation to look funny.
Leave the rest of TOML file as its default.
In this case, use docker-compose-geneva-mongo-no-secty.yml
from the official repository.
Download it as docker-compose.yml
,
$ curl https://raw.githubusercontent.com/edgexfoundry/developer-scripts/master/releases/geneva/compose-files/docker-compose-geneva-mongo-no-secty.yml -o docker-compose.yml
and then add app-service-mqtt
service:
app-service-mqtt:
image: edgexfoundry/docker-app-service-configurable:1.2.0
ports:
- "127.0.0.1:48097:48097"
container_name: edgex-app-service-configurable-mqtt
hostname: edgex-app-service-configurable-mqtt
networks:
- edgex-network
environment:
<<: *common-variables
edgex_profile: mqtt-export
Service_Host: edgex-app-service-configurable-mqtt
Service_Port: 48097
MessageBus_SubscribeHost_Host: edgex-core-data
Binding_PublishTopic: events
Writable_Pipeline_ExecutionOrder: "TransformToJSON, MQTTSecretSend, MarkAsPushed"
Writable_Pipeline_Functions_MQTTSecretSend_Parameters_brokeraddress: tcps://test.mosquitto.org:8884
Writable_Pipeline_Functions_MQTTSecretSend_Parameters_topic: edgex/data
Writable_Pipeline_Functions_MQTTSecretSend_Parameters_clientid: edgex
Writable_Pipeline_Functions_MQTTSecretSend_Parameters_authmode: clientcert
Writable_Pipeline_Functions_MQTTSecretSend_Parameters_skipverify: "true"
volumes:
- ./mqtt-export:/res/mqtt-export
depends_on:
- consul
- data
There are some points:
brokeraddress
,topic
,clientid
- These have to be changed depends on my environment.
volumes
- It's required to pass my
configuration.toml
to the container. - Mount
./mqtt-export
on my docker host as/res/mqtt-export
in the container. /res/mqtt-export
is used byapp-service
because I specifymqtt-export
as its profile inedgex_profile
.
- It's required to pass my
skipverify
- It's required when I got
x509: certificate signed by unknown authority
error.
- It's required when I got
Subscribe my topic using cert files:
$ mosquitto_sub -d -h test.mosquitto.org -t "edgex/data" -p 8884 --cafile ./certs/ca.crt --cert ./certs/client.crt --key ./certs/client.key
Client mosq/0VxxnD7xMr8ADA4SBl sending CONNECT
Client mosq/0VxxnD7xMr8ADA4SBl received CONNACK (0)
Client mosq/0VxxnD7xMr8ADA4SBl sending SUBSCRIBE (Mid: 1, Topic: edgex/data, QoS: 0, Options: 0x00)
Client mosq/0VxxnD7xMr8ADA4SBl received SUBACK
Subscribed (mid: 1): 0
...
and then start EdgeX Foundry.
$ docker-compose up -d
Creating network "demo_edgex-network" with driver "bridge"
Creating volume "demo_db-data" with default driver
Creating volume "demo_log-data" with default driver
Creating volume "demo_consul-config" with default driver
Creating volume "demo_consul-data" with default driver
Creating edgex-mongo ... done
Creating edgex-core-consul ... done
Creating edgex-support-scheduler ... done
Creating edgex-support-notifications ... done
Creating edgex-core-metadata ... done
Creating edgex-core-data ... done
Creating edgex-core-command ... done
Creating edgex-app-service-configurable-mqtt ... done
Creating edgex-device-rest ... done
Creating edgex-app-service-configurable-rules ... done
Creating edgex-sys-mgmt-agent ... done
Creating edgex-device-virtual ... done
Creating edgex-kuiper ... done
A short time later I got values exported to the topic to which I'm subscribing.
$ mosquitto_sub -d -h test.mosquitto.org -t "edgex/data" -p 8884 --cafile ./certs/ca.crt --cert ./certs/client.crt --key ./certs/client.key
Client mosq/0VxxnD7xMr8ADA4SBl sending CONNECT
Client mosq/0VxxnD7xMr8ADA4SBl received CONNACK (0)
Client mosq/0VxxnD7xMr8ADA4SBl sending SUBSCRIBE (Mid: 1, Topic: edgex/data, QoS: 0, Options: 0x00)
Client mosq/0VxxnD7xMr8ADA4SBl received SUBACK
Subscribed (mid: 1): 0
Client mosq/0VxxnD7xMr8ADA4SBl sending PINGREQ
Client mosq/0VxxnD7xMr8ADA4SBl received PINGRESP
Client mosq/0VxxnD7xMr8ADA4SBl received PUBLISH (d0, q0, r0, m0, 'edgex/data', ... (277 bytes))
{"id":"ebd8364b-1e24-423d-a160-89e56ce2c38e","device":"Random-Boolean-Device","origin":1602755098464914455,"readings":[{"id":"e2b73e05-693e-48ce-af8b-81706b1e6d7d","origin":1602755098458341738,"device":"Random-Boolean-Device","name":"Bool","value":"false","valueType":"Bool"}]}
Client mosq/0VxxnD7xMr8ADA4SBl received PUBLISH (d0, q0, r0, m0, 'edgex/data', ... (277 bytes))
{"id":"1f606d54-0a5c-4e7d-b723-fb1721544cde","device":"Random-Boolean-Device","origin":1602755098484135940,"readings":[{"id":"c62219a4-4dc2-4677-b670-941817f85b95","origin":1602755098478954904,"device":"Random-Boolean-Device","name":"Bool","value":"false","valueType":"Bool"}]}
Client mosq/0VxxnD7xMr8ADA4SBl received PUBLISH (d0, q0, r0, m0, 'edgex/data', ... (274 bytes))
{"id":"b70a7b14-ac40-47fb-8213-31abeebc5563","device":"Random-Integer-Device","origin":1602755103493184338,"readings":[{"id":"db7c9327-4389-415a-b80d-2f4e4dc91b9c","origin":1602755103484147140,"device":"Random-Integer-Device","name":"Int8","value":"32","valueType":"Int8"}]}
Client mosq/0VxxnD7xMr8ADA4SBl received PUBLISH (d0, q0, r0, m0, 'edgex/data', ... (278 bytes))
{"id":"f351cd0a-db03-48bd-aac1-7eafc985f47c","device":"Random-Integer-Device","origin":1602755103510821938,"readings":[{"id":"09221884-dc50-4eaf-857c-2ecda5960cda","origin":1602755103503012981,"device":"Random-Integer-Device","name":"Int16","value":"7584","valueType":"Int16"}]}
...
- See the logs.
$ docker-compose logs -f app-service-mqtt
- If I got
Error parsing CA Certificate
error:- Check the certs in
configuration.toml
is correct. Especially quoting, whitespace, and line breaks.
- Check the certs in
- If I got
x509: certificate signed by unknown authority
error:- Add
Writable_Pipeline_Functions_MQTTSecretSend_Parameters_skipverify: "true"
toenvorinment:
in mydocker-compose.yml
.
- Add