Logo OpenSCAP

Cet article est une présentation de la mise en place d’un système de vérification de règles de sécurité sur OpenStack.

Public visé : Administrateurs Systèmes ayant des connaissances en OpenStack et Puppet.

Par Adrien Beudin, Consultant Cloud @Objectif Libre

Gestion de la conformité sur un Cloud OpenStack avec Puppet, Foreman et OpenSCAP

Introduction

Comment être sûr que l’ensemble des instances d’un cloud OpenStack (c’est valable pour les autres types) soient configurées correctement pour ne pas nuire à la sécurité de l’entreprise? Cette question est logique, surtout lorsqu’on donne accès en self-service à des utilisateurs.

C’est là qu’intervient la gestion de conformité (compliance) pour créer un référentiel de sécurité. Le couplage à un outil de configuration management permet en plus son application automatique.

OpenSCAP

SCAP (Secure Content Automation Protocol) est un ensemble de normes ouvertes sélectionnées qui énumèrent les défauts des logiciels et les problèmes de configurations liés à la sécurité. On y trouve également les systèmes de mesure pour déterminer la présence de vulnérabilités et la fourniture des mécanismes de classement (score) des résultats de ces mesures afin d’évaluer l’impact de la découverte de problèmes de sécurité. Enfin SCAP définit, également, la manière dont ces normes sont combinées.

Il existe une implémentation open source de SCAP, OpenSCAP (en savoir plus). Cette implémentation est certifiée par la NIST (National Institute of Standards and Technology).

Pourquoi Puppet ?

Pour rappel, Puppet est un outil de configuration management en mode client-serveur. Les agents (clients) se connectent régulièrement (tous les 30 min par défauts) pour vérifier la conformité avec un référentiel.

Ce référentiel (manifeste Puppet) est centralisé sur un serveur qui compile la configuration pour le client avant que celui-ci l’applique. Une fois la configuration appliquée par le client (on parle ici d’application du catalogue), celui-ci renvoie un rapport au serveur.

Pourquoi utiliser Puppet dans le cas de la compliance ? Le principe de mode agent-server de Puppet avec un lancement régulier, correspond bien au besoin. Cela permet de s’assurer d’avoir un état toujours conforme à la configuration demandée.

Pour avoir une vision de ce qui se passe et d’avoir des rapports il est utile d’utiliser Foreman. Foreman est un outil de provisioning, monitoring, configuration. Il peut s’intégrer avec plusieurs outils de configuration management dont Puppet.

Enfin il existe un plugin OpenSCAP pour Foreman. Celui-ci permet de configurer le client OpenSCAP sur les hôtes et de récupérer les rapports. Il faut cependant noter que ce plugin ne gère pas l’auto remédiation, donc il faudra donc écrire du code Puppet pour chaque règle sélectionnée.

Mise en place

Infrastructure

L’infrastructure de Puppet et Foreman doit permettre de scaler les instances de Puppet, car le nombre d’instances va augmenter et les masters Puppet vont avoir de plus en plus de demandes à traiter.

Point important à ne pas négliger : la scalabilité de l’autorité de certificat de Puppet. Les certificats Puppet sont signés par une autorité de certification qui stocke les fichiers dans un répertoire. Plusieurs solutions sont envisageables, (cf conférence FOSDEM 2018).

Le plus simple à mettre en place est un serveur Foreman qui fait office de d’autorité de certification et de faire des plusieurs master Puppet.

Exemple d’infrastructure:

Mise en place d’une Policy

Plusieurs étapes sont nécessaires pour réaliser un police de conformité (compliance policy) ; dans un premier temps, on définit les règles qui nous semblent intéressantes à vérifier.

Pour ce faire, on utilise les outils OpenSCAP et on vérifie quel profil correspond le mieux à nos besoins. OpenSCAP propose 2 outils:

  • SCAP Security Guide, implémentation des guides de sécurité recommandé par la PCI DSS, STIG, and USGCB
  • SCAP Workbench, interface graphique pour OpenSCAP

Une fois le profil sélectionné, il est possible de le modifier pour :

  • désactiver certaines règles
  • changer les valeurs des seuils

Cette configuration va être stockée dans un fichier Tailoring.

Ensuite, il faut créer la police de conformité qui sera déployée sur les instances. Tout se fait depuis l’interface de Foreman où on uploade les fichiers :

  • SCAP Content (profile)
  • Tailoring

Puis on définit sur quelle instance on veut affecter la police. Deux possibilités :

  • Affectation manuelle via les actions sur une instance dans Foreman
  • Affectation via un groupe dans Foreman

Le plus simple est d’utiliser les groupes, car il est possible d’affecter automatiquement les hôtes à un groupe en utilisant le plugin foreman_default_hostgroup.

Le problème avec ce plugin étant qu’il ne gère pas le multi-critères (l’opérateur AND) pour affecter l’hôte au bon groupe.

Pour résoudre ce problème, il existe un patch.

Donc pour affecter une machine à un groupe, il faut tout d’abord créer le groupe dans Foreman et configurer le plugin.

Exemple de configuration du Plugin :

---
:default_hostgroup:
  :facts_map:
    "Redhat7":
      "os.name": "RedHat"
      "os.release.major": "7" 
    "Centos7": 
      "os.name": "Centos"
      "os.release.major": "7"

Avec cette configuration, on va affecter les machines Redhat 7 au groupe Redhat7.

Une fois la police créée dans Foreman, il faut utiliser le module Puppet foreman_scap_client sur toutes les instances. Ce module va installer et configurer un client SCAP sur les instances.

L’exécution du client est décorrélée de l’exécution du run Puppet, il se lance via cron (la périodicité est définie dans la police créée précédemment).

Quand le client se lance, il récupère  sur le serveur Foreman les fichiers SCAP (content et tailoring), et réaliser la vérification. A la suite de cette vérification, le client va envoyer un rapport ARF à Foreman.

Puppet Modules

Comme indiqué ci-dessus, le plugin foreman_scap_client ne gère pas l’auto remédiation, donc il faudra soit utiliser un module déjà existant soit créer son propre module.

Les problèmes liés au cloud

Nous venons de décrire le fonctionnement de OpenSCAP avec Puppet et Foreman. Cependant plusieurs problèmes sont rencontrés dans une utilisation Cloud, ici OpenStack. C’est ce que nous allons détailler maintenant.

Doublons

Le principal problème rencontré est l’unicité des noms. Puppet utilise par défaut le hostname de la machine pour générer le certificat.

Comme Puppet et Foreman ne gèrent pas l’isolation par tenants d’OpenStack, il y a potentiellement un risque de doublons.

Pour ce faire, le meilleur moyen est de générer un nom aléatoire. Nous conseillons pour rester cohérent d’utiliser l’ID de l’instance.

Ceci n’est cependant pas suffisant car si un utilisateur rebuild une instance, l’ID de change pas et on se retrouve de nouveau dans l’incapacité de signer le certificat automatiquement, car celui-ci existe déjà dans Puppet.

Deux possibilités dans ce cas:

  • Il est possible d’activer une option dans Puppet pour forcer la régénération automatique d’un certificat. Attention, cette option n’est pas sécurisée.
  • La seconde est d’utiliser en plus de l’ID de l’instance OpenStack un chiffre aléatoire.

Exemple de configuration pour Puppet:

echo certname = `openssl rand -hex 7`-`ls /var/lib/cloud/instances/`.novalocal >> /etc/puppet/puppet.conf

Purge

Ce problème de purge n’est pas uniquement lié au problème de doublon ; qui dit plateforme de cloud, dit:

  • self service (création et suppression des instances par les utilisateurs)
  • auto-scaling

Ces deux fonctionnalités vont générer des entrées dans Foreman qui ne seront plus mises à jours après leur suppression.

Il faut donc penser à mettre un purge sur les instances out of sync. A travers un simple script cron. Par exemple ici pour Foreman:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import requests
from requests_oauthlib import OAuth1
import json
import yaml


config = yaml.load(file('/etc/foreman/settings.yaml', 'r'))

url_base = "https://localhost/api/"
client_key = config[':oauth_consumer_key']
client_secret = config[':oauth_consumer_secret']


search = 'last_report+<=+"1+days+ago"+and+status.enabled+%3D+true'

auth = OAuth1(client_key=client_key, client_secret=client_secret)

try:
  url = url_base + "hosts?&search={}".format(search)
  response = requests.get(url=url, auth=auth, verify=False)

except Exception as e:
  print "Foreman error"
  raise Exception(e)

nodes = response.json()

for node in nodes['results']:
  name = node['certname']
  url = url_base + "hosts/{}".format(name)
  try:
    response =  requests.delete(url=url, auth=auth, verify=False)
    print response.json()
  except Exception as e:
    print "Foreman error"
    raise Exception(e)

Security Guide

Il est important de bien tester la configuration du fichier de Tailoring, car certaines règles SCAP ne sont pas compatibles avec l’utilisation cloud. Et si celles-ci sont activées, elles pourraient rendre l’instance inopérante. En voici quelques exemples :

  • Activation du firewall
  • Certaines configurations SSH
  • etc…

De même certaines règles ne peuvent pas être applicables/testées :

  • Séparation des partitions
  • Options dans le UEFI
  • etc…

Accès réseau

Un dernier problème à travailler dans un environnent OpenStack est la ségrégation des tenants. Il faut trouver des solutions pour que toutes les instances puissent contacter l’infrastructure Puppet et Foreman. Les solutions possibles sont:

  • De créer une machine relais qui va permettre de faire transiter les demandes vers Puppet.
  • D’utiliser une solution de SNAT transparent (proposé par le SDN de l’infrastructure OpenStack, comme par exemple Cisco ACI avec la gestion de contrat).
  • Affecter automatiquement une Floating-IP ou un réseau provider sur toutes les instances. Mais on perd le coté générique de OpenStack…

Conclusion

La mise en place d’une solution pour vérifier la conformité des instances est une idée intéressante, même si la mise en place est un peu plus compliquée que sur une infrastructure legacy.