Configurando conexão segura com o uso de TLS na plataforma dojot

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.

Dispositivo criado sob o ID 7b7184

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
Aplicando as alterações de configuração.
Note que apenas os serviços afetados são reiniciados.

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.

Dispositivo criado no artigo anterior, ao qual foi atribuído o ID 36fc0a.

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.

Dispositivos reais e segurança na comunicação

Trocando informações com uma Raspberry Pi e plataforma dojot
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Home » Internet Das Coisas » Configurando conexão segura com o uso de TLS na plataforma dojot

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: