Passer au contenu principal

RocketChat

Rocket Chat

Situation initiale

La prod actuelle se trouve sur escandalo, une machine mise à disposition par Yula, et uniquement accessible en IPv4 (185.217.152.58). Cette machine n'est d'ailleurs plus présente dans l'infra maintenue de Yulpa ; pour preuve le reverse DNS utilisé par ces derniers : 58.152.217.185.not.updated.as199712.fr.

Il n'est pas non plus possible de mettre à jour sa base (son OS), car il s'agit d'un conteneur LXC. Tenter de le mettre à jour casse l'ABI de virtualisation utilisée sur l'hôte et le conteneur ne redémarre plus.

Cette machine dispose de la version de Rocket.Chat 3.0.11 publiée le 2020-04-03 (src.). Elle a été installée selon une installation standard, sans Docker, mais via un rôle Ansible. (src.)

Cette machine est malheureusement infectée par un crypto miner qui accapare souvent toutes les ressources de la machine si bien qu'il faille la redémarrer régulièrement. Ce crypto miner se serait installé via le fait que la base de données MongoDB ait été rendue accessible publiquement (port 27017). Bien que ce port soit maintenant bloqué, le mal est fait et le crypto miner persistant. Il n'est d'ailleurs pas détectable, car il s'est greffé à pas mal de libs systèmes (dont les coreutils).

En outre, il est fort à parier que le serveur soit membre d'un botnet, car, régulièrement, une charge utile s'ouvre sur le port 2000 (en TCP). Il s'agit vraisemblablement du port utilisé par un serveur distant de type « Command and control » (src.). Nous avons détecté ce comportement via l'outil de Monitoring fourni par Shodan. (src.)

En outre, le certificat de cette machine retourne un domaine pour chat-temp.lghs.be qui semble indiquer que le chat était précédemment accessible par cette adresse également. Voici le rapport d'état qu'on reçoit par mail pour ce souci (toujours via Shodan.io) :

185.217.152.58

// Trigger: ssl_expired
// Port: 443 / tcp
// Hostname(s): 58.152.217.185.not.updated.as199712.fr, chat-temp.lghs.be
// Timestamp: 2022-12-17T00:11:09.909515
// Alert ID: lghs-chat1 (IJCF1NPFL1DV31Q0)

Plan de migration

Bien que l'objectif final soit de permettre une migration à Mattermost, l'état du serveur actuel est tel qu'une migration directe à Mattermost dans des conditions instables (à cause du crypto miner) n'est pas possible sans prendre le risque d'une corruption de données.

De même, il n'existait pas avant ce projet de migration de script permettant un import de données au sein de Mattermost. Ce dernier, lorsque la fonctionnalité de « compliance report » est active ne permet pas d'insérer des données en conservant la date de publication. (Notons que la fonctionnalité de confirmité - « compliance report » - est activée par défaut et ne peut, à notre connaissance, pas être désactivée facilement sur les versions actuelles de Mattermost). Insérer des données dans le passé est donc impossible. Pour qu'elles soit conservées, il faut que les données historiques soient migrées directement dès le début avant mêê que de nouvelles données soient insérées.

La migration vers Mattermost doit donc se faire en 2 étapes :

Phase 1 : Upgrade à la dernière version de Rocket.Chat ce qui permet :

  1. D'avoir un serveur stable, plus vulnérable à partir duquel continuer la migration
  2. D'activer la version Entreprise de Rocket.Chat gratuitement pour 30 afin de bénéficier de la levée des limites en matière de notifications push. En effet, il est désormais nécessaire de passer de la version Community à la version Entreprise de Rocket.Chat afin de supprimer la limite de 1000 notifications push par mois pouvant être énvoyées par le serveur. (src.)

Phase 2 : Migration des données et des bots vers Mattermost.

Déploiement d'une nouvelle machine

Bien qu'on dispose d'une machine offerte par Hivane Network (src.) pour notre nouvelle machine de prod, notre phase 1 va nécessiter une machine temporaire. Pour ce faire, nous allons déployer une machine sur Scaleway.

Nous utilisons le compte personnel de William Gathoye.

Pour que les autres membres du LgHS puissent y accéder, voici les étapes de création que nous avons suivies.

  1. Connectez-vous à un compte existant sur https://console.scaleway.com.
  2. Dans la barre du haut, dans Organization Dashboard, cliquez sur le lien Create Project.
  3. Spécifiez le nom du projet (ici lghs) et cliquez sur le bouton Create new project.
  4. Ajoutons maintenant les clés SSH des différents protagonistes du LgHS afin qu'ils puissent accéder à la machine que nous allons créer. Pour ce faire, cliquez sur votre nom d'organisation en haut à droite dans la barre du haut et clisuez sur SSH Keys.
  5. Cliquez ensuite sur le bouton Add a new SSH key.
  6. Créez ensuite une clé au format ed25519 avec la commande suivante :(src.)
ssh-keygen -t ed25519  
  1. Dans le premier champ de la boite de dialogue suivante, collez la clé publique (fichier .pub) qui vient d'être générée.
  2. Dans le second champ, collez un nom de clé pour savoir qui est qui, ici william_gathoye_ssh_key_2021-10-23_lghs_ed25519 (avoir les prénoms + noms, la date de génération et le type de clé est une bonne idée, car ces informations ne seront plus affichées par la suite au sein de l'interface de Scaleway).
  3. Cliquez enfin sur le bouton Add an SSH key
  4. Rendez-vous maintenant dans la partie Instances.
  5. Cliquez sur le bouton Create an instance.
  6. Sélectionnez la zone de Paris 1
  7. Sélectionnez le type de machine Dev&Test
  8. Sélectionnez la gamme DEV1-M
  9. Choisissez Debian Bullseye (c'est-à-dire Debian 11)
  10. Nommez votre volume lghs-chat
  11. Sélectionnez le volume qui vient d'être créé (lghs-chat)
  12. Nommez votre machine lghs-chat
  13. Assurez-vous que les clés SSH que vous avez créées précédemment soient bien toutes visibles à cette étape.
  14. Confirmez la création de l'instance par Create a new instance
  15. Attendez quelques secondes que la machine se crée.
  16. Vous allez tomber sur cet écran avec un résumé de la configuration de la machine. Ce qui nous intéresse ici ce sont les adresses IPv4 et IPv6. Cliquez sur les boutons ad-hoc pour les copier dans votre presse papier.
  17. Assurez-vous d'avoir vos identifiants à portée de main ou d'avoir une délégation d'accès sur le compte Cloudflare du Liege Hackerspace. Connectez-vous à l'interface de Cloudflare via https://dash.cloudflare.com afin de configurer les entrées DNS relatives à cette nouvelle instance.
  18. Tapez votre code d'identification multifacteur (cette option devrait être activée pourvotre compte; dans le cas contraire, ça représenterait un risque de sécurité qu'il serait nécessaire de corriger).
  19. Dans le cas où vous administrez plusieurs compte Cloudflare à l'aide des mêmes identifiants, il se peut qu'il vous soit demandé de choisir le compte approprité. Dans pareil cas, ici choisissez Liège HackerSpace.
  20. Le LgHs dispose de plusieurs noms de domaines. Les domaines placés sur lghs.be désignent les URL que les utilisateurs finaux devront taper pour accéder au service, là où les domaines sur lghs.space concernent les domaines techniques. Ici créont un domaine technique. Pour ce faire,choisissez lghs.space.
  21. Assurez-vous que le bon domaine ait été sélectionné (1); choisissez le menu DNS; le sous-menu Records (3) devrait alors se sélectionner automatiquement; cliquez sur le bouton Add record (4), sélectionnez le type AAAA (5), spécifiez un sous-domaine (ici chat-migration) (6); spécifiez l'IPv6 que vous avez copiée précédemment à partir du panneau de résumé chez Scaleway (7); désactivez Cloudflare en proxy de l'adresse IP (8); et cliquez sur le bouton Save. Réitérez l'opération pour l'adresse IPv4 précédemment copiée (même procédure, changez juste le type en A).

Connexion à la machine

Créez une entrée dans votre fichier ~/.ssh/config :

Host lghs-chat-migration  
User root  
Hostname chat-migration.lghs.space  
Port 22  
IdentityFile ~/.ssh/keys/william_gathoye_ssh_key_2021-10-23_lghs_ed25519  

Attention, notez que si vous décidez de placer par la suite la machine derrière Cloudflare, il faudra alors remapper le domaine sur les adresses IP réelles et non celles de Cloudflare. Pour ce faire il faudra placer les adresses IP réelles dans votre fichier hosts. C'est la seule méthode valable, OpenSSH est alors assez malin pour choisir la bonne adresse IP selon la stack IP employée (il comprend le fichier hosts et ne prendra donc pas le premier venu). (src.)

Voici un exemple avec vahine :

/etc/hosts  
[...]  
2001:67c:1740:9022::150 vahine.lghs.space  
193.106.119.150 vahine.lghs.space  
[...]  
~/.ssh/config  
Host lghs-chat1-new  
User root  
Hostname vahine.lghs.space  
# Add an entry in /etc/hosts in order to force the resolution to the  
# following non Cloudflare proxy addresses  
# 2001:67c:1740:9022::150 vahine.lghs.space  
# 193.106.119.150 vahine.lghs.space  
Port 22  
IdentityFile ~/.ssh/keys/william_gathoye_ssh_key_2021-10-23_lghs_ed25519  

Déploiement d'un Rocket.Chat 3.0.11

Connectez-vous à ladite machine et préparons l'environnement Docker.

Commencez par mettre à jour la machine et à installer les outils dont nous aurons besoin :

apt update && apt dist-upgrade -y && apt install -y tmux vim  

Lancez un tmux, très utile pour conserver le shell lors de la migration, et éviter que celle-ci soit perdue en cas de déconnexion.

tmux new -s wget  

Installons le moteur Docker pour Debian 11 (src.) :

apt-get remove docker docker-engine docker.io containerd runc  
apt-get update  
apt-get install -y ca-certificates curl gnupg lsb-release  
mkdir -p /etc/apt/keyrings  
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg  
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null  
apt-get update  
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin  

Une fois installé, vérifiez que la version 2 de Compose a bien été installée (en effet nous utilisons cette version plutôt que la version 1 dépréciée) :

$ docker compose version  
Docker Compose version v2.14.1  

Installez le frontend NGINX (dépôt Debian) et certbot via snap (la méthode officielle pour avoir la dernière version) : src.

apt install -y nginx  
apt install -y snapd  
snap install core  
snap refresh core  
snap install --classic certbot  
ln -s /snap/bin/certbot /usr/bin/certbot  

Créez les répertoires dont on a besoin pour le déploiement Docker :

mkdir /srv/chat.lghs.be  
cd /srv/chat.lghs.be/  

Placez dans ce dossier le fichier Docker Compose (docker-compose-prod.yml) suivant :

# Syntax reference: https://docs.docker.com/compose/compose-file/compose-file-v3/  
version: "3.9"

services:
rocket-chat-mongo-db:
image: mongo:4.2.22

A container name is needed otherwise, compose will just use a name

generated from the current directory suffixed by the service key name

+ a number

container_name: rocket-chat-mongo-db
environment:

In this YAML grammar, 'environment' is a mapping

src.: https://stackoverflow.com/a/43111065/3514658

MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 'E3kbYg4ohchFqw2ZVyfV8ZwF0HRcY5iE'
MONGO_INITDB_DATABASE: rocketchat
command: --config /etc/mongo/mongod.conf
volumes:

In this YAML grammar, 'volumes' is a list

Store the MariaDB content to the physical host

  • "/srv/chat.lghs.be/data/db:/data/db/"
    networks:

In this YAML grammar, 'networks' is a list

  • rocket-chat-network
    ports:

In this YAML grammar, 'ports' is a list that must be a string (hence

quotes) as numbers in YAML is parsing numbers as a base-60 values.

  • "27017:27017"

We should always have a restart policy

restart: always

rocket-chat-mongo-db-express:

image: mongo-express

restart: always

ports:

- 8081:8081

environment:

ME_CONFIG_MONGODB_ADMINUSERNAME: root

ME_CONFIG_MONGODB_ADMINPASSWORD: example

ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/

rocket-chat-web:
image: rocket.chat:3.0.12
container_name: rocket-chat-web
environment:
#ROOT_URL: https://chat.lghs.be
ROOT_URL: http://localhost:3000
MONGO_URL: mongodb://root:E3kbYg4ohchFqw2ZVyfV8ZwF0HRcY5iE@rocket-chat-mongo-db:27017/rocketchat?authSource=admin&replicaSet=rs01
MONGO_OPLOG_URL: mongodb://rocket-chat-mongo-db:27017/local?replicaSet=rs01
#USE_NATIVE_OPLOG: true
volumes:

In this YAML grammar, 'volumes' is a list

Store the MariaDB content to the physical host

  • "/srv/chat.lghs.be/data/www:/app/uploads/"
    depends_on:
  • rocket-chat-mongo-db
    networks:

In this YAML grammar, 'networks' is a list

  • rocket-chat-network
    ports:

In this YAML grammar, 'ports' is a list that must be a string (hence

quotes) as numbers in YAML is parsing numbers as a base-60 values.

  • "3000:3000"

We should always have a restart policy

restart: always

networks:

Needed to avoid a default network to be created "merbau-suitecrm_default". As

the difference of Docker, Docker-Compose is always creating a dedicated

bridge network whose name is based on the project (current name folder)

rocket-chat-network:
name: rocket-chat-network


  1. restest avec les dernières données
  2. la mise en prod proprement dite (la conf oAuth ne change pas avec la dernière version de Rocket mais les sessions actives seront perdues, faudra juste faire un refresh/se reconnecter). Je te pingue d'ici quelques heures.