A dojot é uma plataforma brasileira desenvolvida principalmente pelo CPqD e que surgiu com uma proposta open source, visando facilitar o desenvolvimento de soluções e subsidiar o ecossistema IoT com conteúdo local voltado às necessidades do País.
O código dos componentes que compõem a solução está disponível no repositório do Github. Descritivos detalhados da arquitetura, do funcionamento dos componentes e alguns casos de uso podem ser encontrados na documentação.
Introdução
No artigo anterior, abordamos a configuração da comunicação entre uma Raspberry Pi e a plataforma dojot. Um ponto ainda não avaliado na comunicação é a garantia que a conversa está ocorrendo de fato entre a dojot e o correto dispositivo.
Visando solucionar essa questão, este artigo visa implementar a segurança dos dados trafegados a partir da encriptação das mensagens com o uso de certificados digitais.
Iniciaremos utilizando um dispositivo simples e enviando sinais através da linha de comando.
Iremos então alterar a configuração de segurança da dojot, forçando o uso de TLS em toda a comunicação MQTT.
Em seguida, iremos solicitar à plataforma dojot a assinatura de um novo certificado e então utilizá-lo para que comunicação seja restabelecida.
Por fim, seguiremos os mesmos passos para configurar a Raspberry Pi utilizada no artigo anterior, permitindo que ela também se comunique com a dojot de forma segura.
Criação do device
Seguindo os mesmos passos descritos na série introdutória à plataforma dojot, criamos um dispositivo diretamente pela interface gráfica, ao qual foi atribuído o device id 7b7184. Esse será o dispositivo utilizado ao longo deste artigo.
No artigo de introdução também mencionamos o comando a seguir, que permite a comunicação com o broker MQTT.
Em destaque, o device id, que deve ser atualizado de acordo com o id gerado pelo sistema.
mosquitto_pub -i ‘admin:7b7184’ -t /admin/7b7184/attrs -p 1883 -m ‘{"temperatura":23}’
Note que a comunicação é realizada através da porta 1883. Essa é a porta padrão para comunicação MQTT.
Para casos onde a comunicação MQTT utiliza TLS, a porta padrão passa a ser a 8883.
Habilitando TLS na plataforma dojot
Buscando facilitar a rotina de desenvolvimento, as configurações da plataforma presentes no repositório mantêm o TLS desabilitado por padrão. Para que a comunicação possa ser realizada com o uso de TLS, precisaremos inicialmente habilitar esta funcionalidade.
Vá até o diretório docker-compose, baixado durante o processo de instalação, e abra o arquivo docker-compose.yml.
Nele, estão listados todos os contêineres utilizados pela solução.
Procure pelo contêiner nomeado iotagent-mqtt:
iotagent-mqtt:
image: dojot/iotagent-mosca
depends_on:
- mosca-redis
- kafka
- data-broker
- auth
- ejbca
ports:
- 1883:1883
- 8883:8883
restart: always
environment:
DOJOT_SERVICE_MANAGEMENT: 'internal'
logging:
driver: json-file
options:
max-size: 100m
Neste trecho, estão listados quais contêineres compõem as dependências deste componente, junto com as portas que serão vinculadas ao host, o critério de inicialização, as variáveis de ambiente e as opções de log.
Nas variáveis de ambiente, habilite a comunicação TLS adicionando uma nova variável, conforme destacado a seguir:
iotagent-mqtt:
image: dojot/iotagent-mosca
depends_on:
- mosca-redis
- kafka
- data-broker
- auth
- ejbca
ports:
- 1883:1883
- 8883:8883
restart: always
environment:
DOJOT_SERVICE_MANAGEMENT: 'internal'
MOSCA_TLS: 'true'
logging:
driver: json-file
options:
max-size: 100m
Para que a modificação seja aplicada ao ambiente, execute o seguinte comando:
docker-compose up -d
Agora, ao tentarmos conectar à porta 1883, a conexão é rejeitada.
O mesmo ocorre para conexão na 8883, pois é preciso enviar um certificado para validação de autenticidade.
Configurando um certificado para o dispositivo
O servidor precisa ter em sua posse o certificado digital dos dispositivos que enviarão mensagens.
De forma geral, a troca de mensagens é realizada com a utilização das chaves privadas de ambas as partes e suas correspondentes chaves públicas, contidas nos certificados.
A plataforma dojot conta com uma Autoridade Certificadora, baseada em EJBCA e denominada IOTmidCA.
Para obtenção do certificado, os seguintes passos devem ser seguidos:
- Criação do par de chaves (arquivo .key)
- Criação o pedido de certificado (arquivo .csr)
- Obtenção do certificado junto à Autoridade Certificadora (arquivo .crt)
Para facilitar essas etapas, recomendamos a utilização da ferramenta certificate-retriever, criada exatamente para este fim. Seu código está contido neste repositório.
Os comandos abaixo realizam a cópia dos arquivos para o diretório local e a criação o diretório certs dentro do mesmo.
git clone https://github.com/dojot/certificate-retriever.git cd certificate-retriever mkdir certs
O script generateLoginPwd.py deve ser utilizado para obtenção do certificado assinado.
Neste script, são necessários os seguintes parâmetros:
- host: protocolo e endereço onde a plataforma dojot está sendo executada. No nosso caso, https://localhost:8000
- device_name: ID do dispositivo para o qual será criado o certificado. Aqui, continuaremos utilizando o dispositivo 7b7184.
- ca_name: nome da Autoridade Certificadora. Na dojot, a CA existente leva o nome IOTmidCA.
Importante: o certificado só pode ser criado para deviceIDs que estejam presentes na plataforma – e, portanto, visíveis pela interface web.
Utilize python3 para a execução do script, enviando também os parâmetros mencionados.
python3 generateLoginPwd.py https://localhost:8000 7b7184 IOTmidCA
As credenciais de acesso a serem utilizadas são:
- user: admin
- password: admin
O log de saída deverá exibir uma mensagem similar à listada abaixo:
Authenticated CA certificates retrieved 7b7184 key pair created at ./certs//7b7184.key 7b7184 certificate signed. Avaliable at ./certs//7b7184.crt
Neste caso,o certificado foi criado em ./certs/7b7184.crt.
Adicionalmente, o certificado da Autoridade Certificadora foi armazenado em ./certs/IOTmidCA.crt
Ambos serão utilizados – em conjunto com o arquivo 7b7184.key – para a comunicação entre o client MQTT e o servidor da dojot.
Utilizando a conexão com TLS
Finalmente, uma vez criado o par de chaves do dispositivo e obtido o certificado, podemos realizar a comunicação utilizando TLS.
Para essa finalidade, utilizaremos o cliente mosquitto_pub, visando manter um nível mínimo de complexidade, facilitando assim a depuração de possíveis erros.
Partindo do comando anterior:
mosquitto_pub -i ‘admin:7b7184’ -t /admin/7b7184/attrs -p 1883 -m ‘{"temperatura":23}’
Precisaremos alterar a porta a ser utilizada, passando também os parâmetros que indiquem a localização da chave e do certificado assinado do dispositivo, juntamente com o certificado da CA.
Sendo assim, o comando que exemplifica essas mudanças é mostrado a seguir:
mosquitto_pub -i ‘admin:7b7184’ -t /admin/7b7184/attrs -p 8883 -m ‘{"temperatura":23}’ --cafile ./certs/IOTmidCA.crt --cert ./certs/7b7184.crt --key ./certs/7b7184.key
Note que os caminhos para o arquivo são relativos ao diretório atual, então os configure de acordo, caso esteja em um diretório diferente do ./certificate-retriever.
Utilizando um dispositivo real para comunicação com TLS
No artigo anterior, configuramos a utilização de uma Raspberry Pi em conjunto com o SensorHat para envio de dados de temperatura, pressão e umidade à plataforma dojot. Neste dispositivo, também recebíamos alertas nos casos de temperatura abaixo de 20ºC ou acima de 40ºC.
Como a plataforma dojot agora está com a configuração de TLS ativada, precisaremos configurar este dispositivo para utilizar certificado em sua comunicação.
Partiremos do script criado para este dispositivo e, então, o modificaremos para que o cliente realize a conexão com o broker de forma segura.
Criando o dispositivo na plataforma dojot
Como o modelo virtual do Raspberry Pi foi criado no artigo acima mencionado, iremos assumir que a plataforma já o possua em sua listagem de dispositivos.
Criando o certificado para a Raspberry Pi
A partir do utilitário de configuração de certificados, podemos gerar um novo certificado para este dispositivo – lembrando que as credenciais são admin/admin.
python3 generateLoginPwd.py https://localhost:8000 36fc0a IOTmidCA
Com isso, os seguintes arquivos serão gerados no diretório ./certs:
- IOTmidCA.crt
- 36fc0a.crt
- 36fc0a.key
Configurando a comunicação com TLS a partir do Raspberry Pi
Copie os três arquivos gerados no passo anterior para um diretório da Raspberry Pi. Neste exemplo, utilizaremos o diretório /etc/ssl/certs. Caso esteja utilizando o emulador, faça referência ao path local que leva aos arquivos.
Será utilizado como base o script de comunicação criado no artigo anterior, onde a Raspberry Pi foi configurada para trocar dados com a dojot:
from sense_emu import SenseHat
import paho.mqtt.client as mqtt
import json
import time
#
# Properties definition
tenant_name = "admin"
device_id = "36fc0a"
#
# Internal definitions setup
client_id = "{}:{}".format(tenant_name, device_id)
topic_to_publish = "/{}/{}/attrs".format(tenant_name, device_id)
topic_to_subscribe = "/{}/{}/config".format(tenant_name, device_id)
def on_message(client, userdata, message):
decoded_message = json.loads(message.payload.decode())
message_text = decoded_message['display']
print("Received", decoded_message)
sense.clear()
if message_text == "high":
sense.show_message("HOT")
elif message_text == "low":
sense.show_message("COLD")
#
# MQTT Client setup and connection
client = mqtt.Client(client_id)
client.on_message = on_message
print("Connecting to mqtt broker")
client.connect(host='localhost', port=1883)
client.loop_start()
print("Subscribing to topic", topic_to_subscribe)
client.subscribe(topic_to_subscribe)
#
# Raspberry Pi's Sensor initialization
print("Initializing SenseHat emulator")
sense = SenseHat()
#
# Execution loop
while True:
message = {
"temperature" : sense.temperature,
"pressure": sense.pressure,
"humidity": sense.humidity
}
print("Publishing", message, 'to topic', topic_to_publish)
client.publish(topic_to_publish, json.dumps(message))
time.sleep(4)
Faremos as alterações necessárias para que a conexão do cliente com o broker seja realizada utilizando os certificados criados. As linhas em destaque no trecho a seguir foram incluídas com tal finalidade. Nelas, foram inseridas as seguintes funcionalidades:
- Importação da biblioteca para ssl.
- Indicação do diretório de certificados.
- Indicação dos arquivos de certificado da CA, do dispositivo e chave do dispositivo.
- Configuração do uso de certificado na biblioteca MQTT.
- Alteração da porta de comunicação para a 8883 – padrão para MQTT com TLS
from sense_emu import SenseHat
import paho.mqtt.client as mqtt
import json
import time
import ssl
#
# Properties definition
tenant_name = "admin"
device_id = "36fc0a"
certs_dir= "/etc/ssl/certs"
#
# Internal definitions setup
client_id = "{}:{}".format(tenant_name, device_id)
ca_cert="/{}/IOTmidCA.crt".format(certs_dir)
cert_file="/{}/{}.crt".format(certs_dir, device_id)
key_file="/{}/{}.key".format(certs_dir, device_id)
topic_to_publish = "/{}/{}/attrs".format(tenant_name, device_id)
topic_to_subscribe = "/{}/{}/config".format(tenant_name, device_id)
def on_message(client, userdata, message):
decoded_message = json.loads(message.payload.decode())
message_text = decoded_message['display']
print("Received", decoded_message)
sense.clear()
if message_text == "high":
sense.show_message("HOT")
elif message_text == "low":
sense.show_message("COLD")
#
# MQTT Client setup and connection
client = mqtt.Client(client_id)
client.tls_set(ca_certs=ca_cert, certfile=cert_file, keyfile=key_file, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2)
client.on_message = on_message
print("Connecting to mqtt broker")
client.connect(host='localhost', port=8883)
client.loop_start()
print("Subscribing to topic", topic_to_subscribe)
client.subscribe(topic_to_subscribe)
#
# Raspberry Pi's Sensor initialization
print("Initializing SenseHat emulator")
sense = SenseHat()
#
# Execution loop
while True:
message = {
"temperature" : sense.temperature,
"pressure": sense.pressure,
"humidity": sense.humidity
}
print("Publishing", message, 'to topic', topic_to_publish)
client.publish(topic_to_publish, json.dumps(message))
time.sleep(4)
Com isso, a troca de dados entre o dispositivo e a plataforma já pode ser retomada, desta vez utilizando uma via segura para comunicação.
Conclusão
Até aqui, foram vistos os principais procedimentos envolvendo a geração e utilização de certificados a partir da plataforma dojot. Com isso, a comunicação entre dispositivo e dojot passa a ser segura, garantindo ainda que a autoria dos dados gerados realmente é do dispositivo esperado.
Nas séries futuras, utilizaremos essa segurança para que então possamos integrar a plataforma dojot com uma solução de blockchain, garantindo a autenticidade do histórico das informações a partir do uso de um ledger distribuído, potencializando a auditoria de dados.










