softasap.sa_box_bootstap

Préparer votre serveur pour le déploiement

=======================================

Contexte

De nos jours, les déploiements passent de serveurs physiques à des machines virtuelles rapidement mises en place, comme celles fournies par Amazon, Digital Ocean, et d'autres fournisseurs basés sur OpenStack. Ainsi, la configuration d'une machine n'exige plus d'étapes d'administration manuelles. L'une des options consiste à utiliser des images de machines pré-configurées prêtes à l'emploi. Une autre approche consiste à recommencer un système de base et de l'approvisionner en fonction des besoins du projet avec des outils comme Ansible, Chef ou Puppet.

La première étape pour procéder à un approvisionnement personnalisé est de sécuriser de manière basique la machine, surtout si vous recevez une machine fraîchement installée avec un mot de passe root.

Défis à relever

À la fin de cet article, nous devrions être capables de sécuriser un serveur virtuel Ubuntu 14.04 LTS.

  • Configurer un pare-feu, en n'autorisant que les ports 22, 443 et 80.
  • Enregistrer vos clés publiques pour l'utilisateur de déploiement.
  • Sécuriser SSH pour autoriser uniquement l'accès par clés.
  • Mettre en place un processus automatique pour bannir les tentatives d'accès non autorisées à SSH depuis Internet.

Rôle de bootstrap

Ansible propose un concept intéressant de réutilisation de snippets de déploiement, appelés rôles. Voyons ce que fait le rôle sa-box-bootstrap :

Options de configuration

Les variables suivantes peuvent être remplacées :

  • root_dir - requis, Recettes de développeurs Ansible
  • option_enforce_ssh_keys_login (true|false) - si vous souhaitez renforcer la sécurité SSH.
  • ufw_rules_default - politique par défaut du pare-feu, souvent non modifiée.
  • ufw_rules_allow - ensemble de règles entrantes à configurer.
  • sshd_config_lines - changements nécessaires dans la configuration SSHD pour sécuriser la machine.
  • option_file2ban - si vrai, le paquet file2ban sera introduit.
  • whitelistedips - ensemble d'adresses IP considérées comme sûres - votre passerelle de bureau, serveur de compilation, etc. ; pour éviter d'être bloqué accidentellement.

Étape 1 : Activer le pare-feu

La première étape consiste à installer et configurer le pare-feu ufw :

- include: "{{root_dir}}/tasks_ufw.yml"

Par défaut, les règles de pare-feu suivantes s'appliquent (toutes les sorties autorisées, http, https et ssh autorisés à l'intérieur) :

ufw_rules_default:
  - {
      policy: deny,
      direction: incoming
    }
  - {
      policy: allow,
      direction: outgoing
    }

ufw_rules_allow:
  - {
      port: 80,
      proto: tcp
     }
  - {
      port: 443,
      proto: tcp
    }
  - {
      port: 22,
      proto: tcp
     }

Vous pouvez remplacer ces variables selon vos besoins.

Étape 2 : Créer un utilisateur pour le déploiement

Si vous souhaitez travailler et approvisionner cette machine, vous ne voulez probablement pas le faire en tant que root. La deuxième étape consiste donc à créer un utilisateur de déploiement, autorisé par un ensemble de clés SSH fournies, et autorisé à devenir sudoer sans mot de passe (exigence de base pour l'approvisionnement automatisé) :

- include: "{{root_dir}}/use/__create_deploy_user.yml user={{deploy_user}} group={{deploy_user}} home=/home/{{deploy_user}}"
  when: deploy_user is defined

- name: SSH | Autoriser les clés
  authorized_key: user={{deploy_user}} key="{{ lookup('file', item) }}"
  when: deploy_user_keys is defined
  with_items: "{{deploy_user_keys}}"
  sudo: yes

Vous pouvez définir l'utilisateur dans votre playbook, par exemple de cette manière :

jenkins_user: jenkins
jenkins_authorized_keys:
  - "{{playbook_dir}}/components/files/ssh/vyacheslav.pub"

et le passer ensuite comme paramètres au rôle :

roles:
   - {
       role: "sa-box-bootstrap",
       root_dir: "{{playbook_dir}}/public/ansible_developer_recipes",
       deploy_user: "{{jenkins_user}}",
       deploy_user_keys: "{{jenkins_authorized_keys}}"
     }

Étape 3 : Sécuriser SSH (optionnel)

- name: SSH | Renforcer la sécurité des clés SSH
  lineinfile: dest=/etc/ssh/sshd_config regexp="{{item.regexp}}" line="{{item.line}}"
  with_items: "{{sshd_config_lines}}"
  when: option_enforce_ssh_keys_login
  become: true
  tags: ssh

Si la variable option_enforce_ssh_keys_login est définie sur vrai, la configuration SSHD est modifiée selon les règles de sshd_config_lines. Par défaut, il utilise le protocole v2, interdisant la connexion root et l'authentification par mot de passe.

Étape 4 : Bannir les personnes malveillantes

Si la variable option_file2ban est définie sur vrai, l'outil file2ban est installé. Il surveillera les tentatives de connexion SSH infructueuses et bannira les intrus. Pour éviter d'être bloqué accidentellement, il est judicieux de mettre sur liste blanche vos IP, aussi bien des IP uniques que des masques de réseau sont supportés, par exemple :

whitelistedips:
 - 127.0.0.1
 - 127.0.0.1/8

Créer votre propre projet de bootstrap

Préparons un projet de bootstrap basique, qui pourra être utilisé à l’avenir. Il comprend les fichiers suivants :

  • bootstrap.sh - installe ansible ainsi que ses dépendances.
  • init.sh - initialise.
  • .projmodules - totalement compatible avec la syntaxe .gitmodules de git, spécifie la liste des dépendances qui seront utilisées par le playbook. En particulier, il inclut ansible - par défaut, des recettes_de_développeur (dépôt avec un ensemble de recettes de déploiement utiles) et le rôle ansible appelé sa-box-bootstrap responsable des étapes de sécurisation de la machine.
[submodule "public/ansible_developer_recipes"]
    path = public/ansible_developer_recipes
    url = [email protected]:Voronenko/ansible-developer_recipes.git
[submodule "roles/sa-box-bootstrap"]
        path = roles/sa-box-bootstrap
        url = [email protected]:softasap/sa-box-bootstrap.git
  • hosts - listez ici les informations d'identification initiales de la machine, qui vous ont été fournies pour le serveur
[bootstrap]
box_bootstrap ansible_ssh_host=192.168.0.17 ansible_ssh_user=your_user ansible_ssh_pass=your_password
  • box_vars.yml - définissez ici des substitutions spécifiques à l'environnement, comme votre nom d'utilisateur de déploiement et vos clés.
  • box_bootstrap.yml - ici, vous mettez les étapes d'approvisionnement de votre machine. La sécurisation de la machine est seulement la première étape. Pour remplacer les paramètres pour sa-box-bootstrap, passez les paramètres comme dans l’exemple ci-dessous.

- hosts: all

  vars_files:
    - ./box_vars.yml
  roles:
     - {
         role: "sa-box-bootstrap",
         root_dir: "{{playbook_dir}}/public/ansible_developer_recipes",
         deploy_user: "{{my_deploy_user}}",
         deploy_user_keys: "{{my_deploy_authorized_keys}}"
       }

Code en action

Le code peut être téléchargé à partir du dépôt https://github.com/Voronenko/devops-bootstrap-box-template. Pour l'utiliser, il suffit de le forker, d'ajuster les paramètres à vos besoins et de l'utiliser. Les ajustements incluent la création du fichier box_vars.yml. Vous pouvez y remplacer n'importe lesquelles des variables mentionnées ci-dessus. L'ensemble minimal requis est l'utilisateur de déploiement et vos clés publiques.

box_deploy_user: jenkins
box_deploy_authorized_keys:
  - "{{playbook_dir}}/components/files/ssh/vyacheslav.pub"

Assurez-vous d'avoir Ansible (utilisez bootstrap.sh pour l'installer) et de cloner les répertoires de rôles (init.sh). Ensuite, exécutez setup.sh. Si tout est correctement configuré, vous verrez quelque chose de ce genre :

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [box_bootstrap]

TASK: [sa-box-bootstrap | Définit correctement le nom d'hôte] ****************************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | debug var="ufw_rules_allow"] ************************
ok: [box_bootstrap] => {
    "var": {
        "ufw_rules_allow": [
            {
                "port": 80,
                "proto": "tcp"
            },
            {
                "port": 443,
                "proto": "tcp"
            },
            {
                "port": 22,
                "proto": "tcp"
            }
        ]
    }
}

TASK: [sa-box-bootstrap | UFW | Réinitialise] *************************************
ok: [box_bootstrap]

TASK: [sa-box-bootstrap | UFW | Configure les par défaut entrants/sortants] *********
ok: [box_bootstrap] => (item={'policy': 'deny', 'direction': 'incoming'})
ok: [box_bootstrap] => (item={'policy': 'allow', 'direction': 'outgoing'})

TASK: [sa-box-bootstrap | UFW | Configure les règles pour autoriser le trafic entrant] ****
ok: [box_bootstrap] => (item={'port': 80, 'proto': 'tcp'})
ok: [box_bootstrap] => (item={'port': 443, 'proto': 'tcp'})
ok: [box_bootstrap] => (item={'port': 22, 'proto': 'tcp'})

TASK: [sa-box-bootstrap | UFW | Configure les règles pour autoriser le trafic entrant depuis des hôtes spécifiques] ***
skipping: [box_bootstrap] => (item=ufw_rules_allow_from_hosts)

TASK: [sa-box-bootstrap | UFW | Active] ************************************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | Monit | Vérifie si installé] **********************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | Monit | Dépendance libssl-dev] **********************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | Monit | Téléchargement] ***********************************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | Monit | Installation] ************************************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | debug msg="Création de l'utilisateur de déploiement {{my_deploy_user}}:{{my_deploy_user}} avec le répertoire personnel /home/{{my_deploy_user}}"] ***
ok: [box_bootstrap] => {
    "msg": "Création de l'utilisateur de déploiement jenkins:jenkins avec le répertoire personnel /home/jenkins"
}

TASK: [sa-box-bootstrap | Utilisateur de déploiement | Création du groupe] ***********************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | Utilisateur de déploiement | Création de l'utilisateur] ************************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | Utilisateur de déploiement | Vérification de la présence de la clé] *******************
ok: [box_bootstrap]

TASK: [sa-box-bootstrap | Utilisateur de déploiement | Copie des authorized_keys depuis {{ansible_user_id}}] ***
skipping: [box_bootstrap]

TASK: [sa-box-bootstrap | Utilisateur de déploiement | Définir les permissions sur authorized_keys] ****
skipping: [box_bootstrap]

TASK: [sa-box-bootstrap | Utilisateur de déploiement | S'assurer que sudoers ne demande pas de mot de passe] ****
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | SSH | Autoriser les clés] *******************************
changed: [box_bootstrap] => (item=/home/slavko/labs/devops-bootstrap-box-template/components/files/ssh/vyacheslav.pub)

TASK: [sa-box-bootstrap | SSH | Renforcer la sécurité des clés SSH] ********************
ok: [box_bootstrap] => (item={'regexp': '^Protocol.*', 'line': 'Protocol 2'})
changed: [box_bootstrap] => (item={'regexp': '^PermitRootLogin.*', 'line': 'PermitRootLogin no'})
ok: [box_bootstrap] => (item={'regexp': '^RSAAuthentication.*', 'line': 'RSAAuthentication yes'})
ok: [box_bootstrap] => (item={'regexp': '^PubkeyAuthentication.*', 'line': 'PubkeyAuthentication yes'})
ok: [box_bootstrap] => (item={'regexp': '^ChallengeResponseAuthentication.*', 'line': 'ChallengeResponseAuthentication no'})
changed: [box_bootstrap] => (item={'regexp': '^PasswordAuthentication.*', 'line': 'PasswordAuthentication no'})
changed: [box_bootstrap] => (item={'regexp': '^MaxAuthTries.*', 'line': 'MaxAuthTries 3'})

TASK: [sa-box-bootstrap | SSH | Redémarrer SSHD] *********************************
changed: [box_bootstrap]

TASK: [sa-box-bootstrap | Installer les paquets de base d'Ubuntu] ***********************
changed: [box_bootstrap] => (item=unzip,mc)

PLAY RECAP ********************************************************************
box_bootstrap              : ok=21   changed=13   unreachable=0    failed=0   

Enfin, vous avez une machine sécurisée, avec l'utilisateur déployé que vous avez spécifié, autorisé à s'authentifier uniquement avec les clés que vous avez définies. L'accès root est interdit. Seuls certains ports entrants sont autorisés selon vos règles.

Vérifiez avec NMap et essayez de vous connecter :


ssh  192.168.0.17
Permission denied (publickey).

ssh -ldeploy_user 192.168.0.17
Bienvenue sur Ubuntu 14.04.2 LTS (GNU/Linux 3.13.0-32-generic x86_64)
deploy_user@LABBOX17:~$

Points d'intérêt

Vous pouvez réutiliser ce playbook pour créer vos propres projets de bootstrap et réutiliser le rôle pour configurer vos environnements plus rapidement de manière sécurisée avec Ansible.

À propos du projet

Role to perform basic securing of fresh instance for further automated deploy

Installer
ansible-galaxy install softasap.sa_box_bootstap
Licence
Unknown
Téléchargements
1.7k
Propriétaire
Get your application deployed in a robust way