Introduction
Le durcissement de la sécurité Apache Spark est plus efficace quand vous appliquez un petit jeu de contrôles éprouvés avec des résultats clairs et testables. Ce guide propose un workflow reproductible, un plan pilote local sans risque et des exemples à copier-coller pour le contrôle d'accès, les secrets, les permissions, l'exposition réseau et des vérifications de durcissement. Il s'adresse aux équipes data qui veulent des actions concrètes, rapides à valider, et faciles à promouvoir vers staging puis production. Nous gardons les concepts clés visibles, comme Apache Spark security, Apache Spark hardening, Apache Spark access control, Apache Spark secrets et Apache Spark permissions, afin de rester aligné avec les pratiques de l'industrie.
Ce que vous allez obtenir :
- Un workflow de durcissement réutilisable pour limiter les retours arrière
- Un pilote « local-first » exécutable en moins d'une heure
- Des réglages Spark concrets pour ACLs, secrets et chiffrement
- Des vérifications rapides qui prouvent l'efficacité du durcissement
Ce qu'il faut sécuriser dans Spark
Spark est au centre de votre plateforme de données et interagit avec de nombreux services (Kafka, HDFS, Kubernetes/YARN, Apache Airflow, NiFi, stockage objet/cloud). Concentrez vos efforts sur cinq axes :
- Accès et actions
- Qui peut voir les UIs Spark (driver, executors, history server) ?
- Qui peut soumettre, annuler ou modifier des jobs ?
- Permissions sous Spark
- Droits HDFS ou stockage objet
- Comptes de service et rôles Kubernetes/YARN
- Secrets
- Identifiants cloud
- Matériels d'auth pour bases/Kafka/HDFS
- Données en mouvement
- RPC internes Spark et trafic shuffle
- Connecteurs externes (JDBC, Kafka, stockage cloud)
- Exposition réseau
- Adresses et ports des drivers/executors
- Exposition des UIs et reverse proxy
Vue d'ensemble du workflow
Adoptez un flux court, réutilisable, et évitez les changements « big bang » :
- Définir la portée et le succès
- Choisissez un job représentatif et 3 à 5 contrôles à activer (ex. : ACLs, redaction des logs, authent interne, chiffrement réseau, UI derrière proxy)
- Formulez des résultats mesurables (ex. : un utilisateur non autorisé ne voit pas l'UI ; aucun secret dans les logs)
- Baseline
- Capturez la configuration actuelle et les ports ouverts
- Appliquer les contrôles en dev
- Ne changez que ce que vous mesurez ; gardez de petits diffs documentés
- Valider localement
- Exécutez des checks rapides ; capturez des preuves (commandes, captures, logs)
- Promouvoir avec une checklist
- Faites avancer les changements ; placez les valeurs spécifiques à l'environnement dans des fichiers de config ou des secret stores
Plan pilote local
Portée : un job Spark qui lit depuis un stockage et écrit des résultats, plus l'UI d'historique.
Contrôles à activer en premier :
- Contrôle d'accès : ACLs pour voir/modifier
- Secrets : redaction des logs et pas de secrets en ligne de commande
- Protection interne : authentification et chiffrement réseau
- Exposition : liaison sur interfaces internes et UIs derrière un proxy avec auth
Résultats mesurables :
- Un utilisateur non autorisé ne peut ni voir l'UI ni tuer des jobs
- Aucun secret dans les logs driver/executor
- Spark rapporte l'auth interne et le chiffrement activés
- L'UI est injoignable depuis des réseaux non fiables
Étapes de déploiement :
- Activez les configs ci-dessous dans un bac à sable
- Lancez un job simple et validez
- Si tout passe, appliquez les mêmes diffs vers staging
Contrôle d'accès et permissions
Activez les ACLs Spark et définissez qui peut voir ou contrôler les jobs. Appliquez un moindre privilège sur la couche plateforme.
spark-defaults.conf (noyau ACLs et UIs) :
spark.acls.enable=true
spark.admin.acls=alice, bob
spark.ui.view.acls=analytics-team
spark.ui.view.acls.groups=data-readers
spark.history.ui.acls.enable=true
# Optionnel : groupes admin séparés
authz.admin.groups=platform-admins
Exemples spark-submit (surcharges au niveau job) :
spark-submit \
--conf spark.acls.enable=true \
--conf spark.admin.acls=alice \
--conf spark.ui.view.acls=analytics-team \
--class com.example.Job \
local:///opt/jobs/example.jar
Permissions plateforme :
- HDFS/stockage objet : donnez lecture/écriture uniquement au rôle du job ; utilisez deny list ou politiques bucket/dossier adaptées
- Kubernetes : exécutez avec un compte de service dédié ; liez uniquement les rôles nécessaires
- YARN : utilisez les ACLs de file d'attente et Kerberos pour HDFS si pertinent
Gestion des secrets
Principes :
- Ne passez jamais de secrets en ligne de commande ni dans le code
- Préférez les identités de charge (ex. rôles d'instance ou de pod) aux clés statiques
- Stockez les secrets restants dans un provider ; montez-les en fichiers ou variables d'environnement avec le moindre privilège
- Redigez les logs
Redaction des logs (Spark) :
spark.redaction.regex=(?i)password|secret|token|authorization|apikey
Kubernetes : monter des secrets et éviter l'exposition en CLI :
spark-submit \
--master k8s://https://kubernetes.default.svc \
--conf spark.kubernetes.namespace=data \
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark-sa \
--conf spark.kubernetes.driver.secrets.app-secrets=/etc/creds \
--conf spark.executorEnv.APP_CREDENTIALS_FILE=/etc/creds/app.json \
--class com.example.Job \
local:///opt/jobs/example.jar
Hadoop credential provider (pour les connecteurs lisant la conf Hadoop) :
# Créer un store JCEKS local
hadoop credential create db.password -value ***REDACTED*** -provider jceks://file/etc/creds/conn.jceks
# Le référencer dans les configs Hadoop/Spark
hadoop.security.credential.provider.path=jceks://file/etc/creds/conn.jceks
YARN avec Kerberos (exemple) :
spark-submit \
--master yarn \
--principal [email protected] \
--keytab /etc/security/keytabs/spark-user.keytab \
--class com.example.Job \
local:///opt/jobs/example.jar
Exposition réseau et chiffrement
Liez-vous sur des interfaces internes, restreignez les ports et chiffrez à la fois les échanges internes Spark et toute UI exposée.
Réglages de base :
# Lier le driver et épingler des ports connus
spark.driver.bindAddress=0.0.0.0
spark.driver.host=driver.internal
spark.ui.port=4040
spark.blockManager.port=7079
spark.driver.port=7078
# Auth et chiffrement internes
spark.authenticate=true
spark.network.crypto.enabled=true
spark.io.encryption.enabled=true
Utilisez TLS pour les points d'exposition externes (par exemple via un reverse proxy devant l'UI). Gardez l'UI Spark hors d'Internet public et exigez une authentification au niveau du proxy.
Exemple Kubernetes NetworkPolicy (restreindre UI et driver) :
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: spark-restrict
namespace: data
spec:
podSelector:
matchLabels:
app: spark-driver
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: platform
ports:
- protocol: TCP
port: 4040
- protocol: TCP
port: 7078
egress:
- to:
- namespaceSelector:
matchLabels:
name: storage
Si vous exposez l'UI, faites-le uniquement via un proxy qui ajoute authentification et terminaison TLS. Gardez le driver/executors accessibles uniquement depuis des sous-réseaux de confiance.
Vérifications de durcissement sûres
Exécutez ces checks rapides pendant le pilote.
- Les ACLs fonctionnent
- Tentez d'ouvrir l'UI du job avec un utilisateur non autorisé ; attendez-vous à un HTTP 403 au proxy ou aucune route
- Demandez à un utilisateur non autorisé d'essayer de tuer un job ; attendez-vous à un échec
- Les logs redigent les secrets
- Soumettez un job avec un faux secret nommé TOKEN et confirmez qu'il n'apparaît pas dans les logs driver/executor
grep -iE 'password|secret|token|authorization|apikey' /path/to/driver.log || echo 'OK: redacted'
- Auth interne et chiffrement activés
- Affichez la SparkConf effective au démarrage du job
val conf = spark.sparkContext.getConf
println("spark.authenticate=" + conf.get("spark.authenticate"))
println("spark.network.crypto.enabled=" + conf.get("spark.network.crypto.enabled"))
println("spark.io.encryption.enabled=" + conf.get("spark.io.encryption.enabled"))
Attendez-vous à true pour toutes les valeurs.
- UI non atteignable publiquement
- Depuis un réseau non fiable, tentez d'atteindre le port UI ; attendez-vous à un timeout ou un blocage par pare-feu
- Ports et binds
- Confirmez que seuls les ports prévus écoutent et uniquement sur des interfaces internes
ss -lntp | grep -E ':4040|:7078|:7079'
- Pas de secrets en ligne de commande
- Inspectez les arguments de processus pour spark-submit et l'executor ; attendez-vous à aucune information d'identification
ps aux | grep spark-submit | grep -viE 'password|secret|token|authorization|apikey'
- Permissions de stockage et de plateforme
- Vérifiez que le rôle du job ne peut pas lire en dehors de ses buckets/chemins et que les comptes de service K8s ou YARN n'ont que les permissions requises
Conclusion
Un petit ensemble de contrôles apporte l'essentiel de la valeur : activez les ACLs, redigez les logs, exigez l'authentification interne, chiffrez le trafic interne et gardez les UIs hors des réseaux non fiables. Démarrez avec un pilote local restreint, prouvez les résultats via des checks rapides, puis déployez les mêmes diffs en staging et production. Au fur et à mesure, alignez Spark avec les systèmes adjacents (Kafka, HDFS, Apache Airflow, NiFi) selon les mêmes principes : moindre privilège, pas de secrets en ligne de commande et exposition réseau minimale. Ce guide vise un Apache Spark hardening pragmatique, fondé sur des preuves et adapté à l'échelle de vos workloads.