Archives de l’auteur : xavki

Raspberry, déploiement de vos règles iptables avec Ansible

Lors d’un précédent article et d’une précédente vidéo, nous avions découvert comment commencer à sécuriser vos raspberry avec iptables. Ce firewall natif à Linux se configure très facilement et est d’une efficacité redoutable.

Néanmoins, déployer les règles à la main ce n’est pas pratique en cas de nécessité de reconfigurer vos serveurs. Mais pour éviter ce genre de problème nous allons continuer à développer nos rôles ansible. Notre objectif est de disposer d’une infrastructure de plusieurs raspberry. Pour cela, nous configurons un bastion qui servira comme point d’entrée ssh pour rebondir les autres serveurs de notre infra.

Si vous le souhaitez vous pouvez retrouver tous les éléments sur ce dépôt.

L’inventory

Peu d’évolution sur notre inventory qui permet de faire la dictinction entre bastion et serveurs simples.

all:
  children:
    door:
      hosts:
        192.168.1.31:
    back:
      hosts:
        192.168.1.41:
        192.168.1.42:
        192.168.1.43:
        192.168.1.44:

Le rôle iptables : firewall

Notre rôle va servir à configurer simplement notre bastion. Nous verrons dans un prochain article comment configurer notre firewall pour les autres serveurs ?

- name: install iptables-persistent
  apt:
    name: iptables-persistent
    state: present

- name: only me
  iptables:
    chain: INPUT
    protocol: tcp
    destination_port: 22
    source: 192.168.1.1/24
    jump: ACCEPT

- name: specific
  iptables:
    chain: OUTPUT
    protocol: tcp
    destination_port: 22
    jump: ACCEPT

- name: icmp accept
  iptables:
    chain: INPUT
    protocol: icmp
    jump: ACCEPT

- name: icmp accept
  iptables:
    chain: OUTPUT
    protocol: icmp
    jump: ACCEPT

- name: Allow related and established connections
  iptables:
    chain: INPUT
    ctstate: ESTABLISHED,RELATED
    jump: ACCEPT

- name: Allow related and established connections
  iptables:
    chain: OUTPUT
    ctstate: ESTABLISHED,RELATED
    jump: ACCEPT

- name: Set the policy for the INPUT chain to DROP
  iptables:
    chain: OUTPUT
    policy: ACCEPT

- name: Set the policy for the INPUT chain to DROP
  iptables:
    chain: INPUT
    policy: DROP

- name: Set the policy for the INPUT chain to DROP
  iptables:
    chain: FORWARD
    policy: DROP

- name: persistent rules
  shell: iptables-save > /etc/iptables/rules.v4

1ère étape : nous installons iptables-persistent qui nous permet de rendre nos règles durables dans le temps. De base, iptables ne garde pas ses règles en cas de reboot. C’est ballot mais c’est comme ça. Iptales-persistent va maintenir les règles présentes dans un fichier de configuration. Pour nous ce sera /etc/iptables/riles.v4. Npus l’alimentons dans la dernière ligne de notre rôle en utilisant le module shell et en lançant iptables-save.

2ème étapes : pour notre notre bastion, il est nécessaire d’accepter les entrées de notre réseau local sur le port 22 (ssh). Idem

3ème étape : on accepte la sortie de notre bastion avec le port 22

4ème étape : on accepte les entrées/sorties pour les ping (icmp)

5ème étape : toutes les connexions établies sont maintenues

6ème étape : on peut accepter toutes les sorties mais à ajuster avec l’étape précédente

7ème étape : on refuse toutes les autres entrées et les forward

Iptables pour sécuriser votre raspberry pi

Sécuriser… un sujet préoccupant et qui est important lorsque l’on dispose de son infrastructure locale. Un des outil sà utiliser pour mettre en place quelques règles de base c’est bien sûr le firewall. Pour cela nous allons utiliser iptables.

Iptables permet de définir un firewall local très facilement. De base, il est présent sur linux et ne nécessite pas d’installation particulière, Raspbian en dispose donc. Reste néanmoins à créer les règles qu’il faut pour sécuriser nos raspberry.

Localement, j’ai choisi de créer un bastion. Commençons par configurer celui-ci via la ligne de commande avant de passer dans une prochaine étape au déploiement automatique des règles.

Voici donc les règles que je vous propose et dans l’ordre que je vous propose :

  • accepter les connexions ssh (port 22) entrantes via notre réseau local 192.168.1.0/24
  • accepter les pings (icmp) entrants
  • toutes les connexions établies doivent être assurées (acceptation en entrées et sorties)
  • accepter de sortir via le ssh et les pings
  • enfin après ces règles, refuser toutes les entrées et les forwards mais accepter toutes les sorties

Cela se traduit par les commandes iptables :

iptables -A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

Ingénieur Devops : sa boite à outils

Difficile de dresser une liste complète des outils qu’un devops doit connaître. D’ailleurs on pourrait aussi graduer le niveau requis dans chaque outil. En effet, je pense qu’un devops doit être ce qu’il y a de plus polyvalent et avoir quelques domaines privilégiés.

Sur le papier, certains imaginent le devops comme un MacGyver qui va être capable de faire du dev et de l’ops. Concrètement et au vue des précédents articles et vidéos que j’ai publié vous pouvez vous douter que mon point de vue est un peu différent. En outre, le cloud fait partie e ces outils mais n’est pas impératif.

Rappelons-le, le devops est là pour automatiser et organiser les déploiements pour permettre d’itérer trsè facilement les nouvelles versions de vos services.

Les schedulers ou ordonnanceurs de tâches sont donc inévitables :

  • Jenkins : mon préféré car il repose sur la fondation Apache, possède une grande communauté et est totalement gratuit
  • Gitlab : allie à la fois l’organisation des équipes, les déploiements et le code, il n’y a pas plus complet sauf qu’une partie repose sur la version d’entreprise payante
  • Rundeck : outil gratuit mais moins complet et un peu moins adapté à l’élaboration de pipeline
  • CircleCI : très bon outil assez complet mais avec une version payant à partir d’un certain niveau d’utilisation

Les orchestrateurs pour compléter les ordonnanceurs de tâches :

  • Ansible : de loins mon préféré par sa simplicité et dans un contexte de pipeline de déploiement d’applicatif, simple en python à base de ssh
  • Puppet : plus adapté à de la gestion globale d’une infrastructure
  • Chef : un peu plus complexe et plus adapté à une gestion d’une infra

Les outils de tests :

  • Jmeter : là encore mon préféré issue de la fondation Apache avec une large communauté et gratuit surtout
  • Postman : idéal pour tester des API mais les fonctions les plus intéressantes sont dans la version payante
  • JUnit : pour les tests unitaires du langage Java il existe dans tous les langages ce genre de librairie

Le monitoring, la collecte de métriques ou de logs :

  • prometheus : une base de données timeseries qui scrappe les routes qui lui sont données. Peut être rendu dynamique avec Consul ou le DNS par exemple. N2cessite des exporter pour afficher les métriques sur des routes au format openmetrics.
  • influxdb : une autre base timeseries qui ne scrape pas mais permet une bonne rétention des métriques (sur la durée, à la différence de prometheus).
  • zabbix : très bon outil complet de monitoring et collecte de métriques, fonctionne avec des agents.
  • munin/nagios : solution similaire à zabbix
  • grafana : incontournable pour visualiser des métriques et créer des alertes
  • elasticsearch/logstash/kibana : la triplette la plus puissante en matière de cllecte de logs et de leur analyse sous différentes formes.
  • Netdata : pour disposer de la plupart des métriques de votre machines, s’installe en une simple ligne de commande.

En matière d’organisation de dépôt l’inévitable gitflow qui permet d’organiser ses branches git pour collaborer facilement en équipe tout en ayant une construction robuste d’outils de production.

Les bases de données, en avoir quelques notions :

  • postgresql
  • elasticsearch
  • cassandra
  • mariadb
  • sqlite

Raspberry et Ansible : gestion des clefs SSH et suppression du user par défaut

Précédemment, nous avions découvert comment créer nos users avec ansible. Mais nous avons quelques lacunes avec cette gestion minimaliste des users. En effet, d’une part la connexion ne se fait que par mot de passe (ce n’est pas pratique et très sécurisé). D’autre part, l’existence du user pi est une vraie faille de sécurité. Toute installation d’un raspbian dispose systématiquement de ce user et bien sûr avec le même mot de passe (pratique mais pas sécurisé tout ça).

Création de nos users

Pour cela nous allons industrialiser tout cela avec Ansible. Pour appel, nous avions nos mots de passe stockés sous les varaiables de group_vars/all/all.yml avec ceci :

users_password_xavki: "{{ vault_users_password_xavki }}"
users_password_xavier: "{{ vault_users_password_xavier }}"

Et ces variables faisaient appel à un fichier vault situé au même endroit dans group_vars/all/vault.yml mais chiffré par un mot de passe :

$ANSIBLE_VAULT;1.1;AES256
613362633865666266653364373533323263663137623536316431313933653331336239623437613232343965386434353761386436333663303533653862350a333939363463653663656563643966653035353666623165323434613434616334313163616663643763396635313636323666356437393665366339636561650a623032376634633634353132343539613962306132373230343232306234346664336231343866326532363930303566313262376264383231306664386462303461646432646433386535333432643337613138653365396132386261373362366463646564373830656265613239366334636361336462313039323064666432646161326463666635366663313539303136313965623430386435303466386634663161393438363134376138393137373033323565353065383465356638

Maintenant créons un répertoire dédié au stockage de nos clefs publiques (PUBLIQUES j’insiste) : files. Il s’agit des clefs que nous allons diffuser et installer dans la home de nos users. S’agissant de clefs publiques, un chiffrement n’est pas nécessaire, seule la clef privée est d’une importance capitale.

Maintenant modifions notre playbook de création des users :

- name: deploy users
  hosts: all
  become: yes
  vars:
    users_admin:
    - { name: "xavki", password: "{{ vault_users_password_xavki }}" }
    users_no_admin:
    - { name: "xavier", password: "{{ vault_users_password_xavier }}" }
  tasks:
  - name: create group admin
    group:
      name: "admin"
      state: present

  - name: create admin user accounts
    user:
      name: "{{ item.name }}"
      password: "{{ item.password | password_hash('sha512')}}"
      groups: "admin"
    with_items:
    - "{{ users_admin }}"
    no_log: true
 
  - name: create standard user accounts
    user:
      name: "{{ item.name }}"
      password: "{{ item.password | password_hash('sha512')}}"
    with_items:
    - "{{ users_no_admin }}"
    no_log: true

  - name: add authorized keys
    authorized_key:
      user: "{{ item.name }}"
      key: "{{ lookup('file', 'files/'+ item.name + '.key.pub') }}"
    with_items: 
    - "{{ users_admin }}"
    - "{{ users_no_admin }}"
 
  - name: "Allow admin users to sudo without a password"
    lineinfile:
      dest: "/etc/sudoers"
      state: "present"
      regexp: "^%sudo"
      line: "%admin ALL=(ALL) NOPASSWD: ALL"

La tâche « add authorized keys » nous permet donc de récupérer ces clefs et de les placer par défaut dans la hoem de chaque users et selon la bonne pratique avec un répertoire « .ssh ».

Voici donc pour le déploiement de nos clefs correspondantes pour chaque utilisateurs.

Retrouvez les fichiers ici.

Suppression du user PI

Pour supprimer un utilisateur, la démarche est très simple, il suffit d’ajouter la tâches suivante :

- name: remove pi user
  user:
    name: "pi"
    state: absent

Profitons-en pour faire un peu d’organisation et de bonnes pratiques ansible. Pour cela nous allons utliser le principe de rôle. Un rôle est une sorte de module/librairie/fonction qui peut être appelé autant que nécessaire.

Pour cela nous allon créer un répertoire « roles » à la racine de notre ansible et taper la commande :

mkdir roles && cd roles
ansible-galaxy init users

Cette commande créée toute la structure nécessaire pour créer le contenu d’un rôle. A l’heure actuelle ce qui nous intéresse c’est uniquement le répertoire task et son fichier main.yml. C’ets la première chose qui est appelé quand on lance un rôle. Donc dans ce fichier nous recopions le conteneur de notre users.yml.

Ensuite il nous faut modifier notre playbook pour appeler le rôle et non plus les tâches une à une :

- name: deploy users
  become: yes
  hosts: all
  roles:
  - users

Et voilà le tour est joué. il ne reste plus qu’à jouer le playbook :

ansible-playbook -i list_servers.yml -u xavki users.yml

Retrouvez les fichiers ici.