Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Note de traduction.: L'auteur de l'article — Reuven Harrison — possĂšde plus de 20 ans d'expĂ©rience dans le dĂ©veloppement de logiciels et est actuellement directeur technique et cofondateur de Tufin, une entreprise spĂ©cialisĂ©e dans les solutions de gestion des politiques de sĂ©curitĂ©. En considĂ©rant les politiques rĂ©seau de Kubernetes comme un excellent moyen de segmentation des rĂ©seaux au sein des clusters, il souligne nĂ©anmoins qu'elles ne sont pas si simples Ă  appliquer dans la pratique. Ce document (assez volumineux) vise Ă  accroĂźtre la sensibilisation des professionnels Ă  ce sujet et Ă  les aider dans la crĂ©ation des configurations nĂ©cessaires.

Aujourd'hui, de nombreuses entreprises choisissent de plus en plus Kubernetes pour dĂ©ployer leurs applications. L'intĂ©rĂȘt pour ce logiciel est tel que certains le qualifient de « nouveau systĂšme d'exploitation pour les centres de donnĂ©es ». Progressivement, Kubernetes (ou k8s) commence Ă  ĂȘtre perçu comme une partie critique de l'entreprise, nĂ©cessitant l'organisation de processus commerciaux matures, y compris l'assurance de la sĂ©curitĂ© rĂ©seau.

Pour les professionnels de la sécurité, qui se retrouvent confrontés à la gestion de Kubernetes, la politique par défaut de cette plateforme peut représenter une véritable surprise : tout est autorisé.

Ce guide vous aidera à comprendre le fonctionnement interne des politiques réseau ; à distinguer celles-ci des rÚgles des pare-feu traditionnels. Il traitera également de certaines difficultés et fournira des recommandations pour protéger les applications dans Kubernetes.

Politiques réseau Kubernetes

Le mécanisme des politiques réseau de Kubernetes permet de contrÎler les interactions des applications déployées sur la plateforme à un niveau réseau (le troisiÚme niveau dans le modÚle OSI). Les politiques réseau ne disposent pas de certaines fonctionnalités avancées des pare-feu modernes, telles que le contrÎle au niveau 7 du modÚle OSI et la détection des menaces, mais elles offrent un niveau de sécurité réseau de base, qui constitue un bon point de départ.

Les politiques rĂ©seau contrĂŽlent les communications entre les pod’.

Les charges de travail dans Kubernetes sont rĂ©parties entre les pods, qui sont constituĂ©s d'un ou plusieurs conteneurs dĂ©ployĂ©s ensemble. Kubernetes attribue Ă  chaque pod une adresse IP, accessible depuis d'autres pods. Les politiques rĂ©seau de Kubernetes dĂ©finissent les droits d'accĂšs pour les groupes de pods de la mĂȘme maniĂšre que les groupes de sĂ©curitĂ© dans le cloud sont utilisĂ©s pour gĂ©rer l'accĂšs aux instances de machines virtuelles.

Définition des politiques réseau

Comme les autres ressources Kubernetes, les politiques réseau sont définies en YAML. Dans l'exemple ci-dessous, l'application balance obtient l'accÚs à postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

(Note de traduction.: cette capture d'écran, comme toutes les suivantes, a été créée non pas avec les outils de Kubernetes, mais à l'aide de l'outil Tufin Orca, dont le développement est soutenu par l'auteur de l'article original, mentionné à la fin du document.

Pour définir votre propre politique réseau, des connaissances de base en YAML seront nécessaires. Ce langage est basé sur des indentations (utilisées par des espaces, et non des tabulations). Un élément indente appartient à l'élément indente le plus proche au-dessus de lui. Un nouvel élément de liste commence par un tiret, tous les autres éléments ressemblent à clé-valeur.

AprÚs avoir décrit la politique en YAML, utilisez kubectl, pour la créer dans le cluster :

kubectl create -f policy.yaml

Spécification de la politique réseau

La spécification de la politique réseau Kubernetes comprend quatre éléments :

  1. podSelector: dĂ©finit les pods affectĂ©s par cette politique (cibles) — obligatoire ;
  2. policyTypes: indique quels types de politiques sont inclus : ingress et/ou egress — facultatif, mais je recommande de l'indiquer explicitement dans tous les cas ;
  3. ingress: dĂ©finit le trafic entrant autorisĂ© vers les pods cibles — facultatif ;
  4. egress: dĂ©finit le trafic trafic sortant des pods cibles — facultatif.

L'exemple suivant, tiré du site Kubernetes (j'ai remplacé role sur app), montre comment tous les quatre éléments sont utilisés :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: db
  policyTypes:    # <<<
  - Ingress
  - Egress
  ingress:        # <<<
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:         # <<<
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité
Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Veuillez noter que l'inclusion des quatre Ă©lĂ©ments n'est pas obligatoire. Seul podSelectorest obligatoire, les autres paramĂštres peuvent ĂȘtre utilisĂ©s Ă  votre convenance.

Si vous omettez policyTypes, la politique sera interprétée comme suit :

  • Par dĂ©faut, il est supposĂ© qu'elle dĂ©finit le cĂŽtĂ© ingress. Si aucune indication explicite Ă  cet Ă©gard n'est prĂ©sente dans la politique, le systĂšme considĂ©rera que tout le trafic est interdit.
  • Comportement sur le cĂŽtĂ© egress sera dĂ©terminĂ© par la prĂ©sence ou l'absence du paramĂštre egress correspondant.

Pour éviter des erreurs, je recommande de toujours indiquer explicitement policyTypes.

Conformément à la logique ci-dessus, si les paramÚtres ingress et/ou egress sont omis, la politique interdire tous les trafics (voir « RÚgle de nettoyage » ci-dessous).

Politique par dĂ©faut — autoriser

Si aucune politique n'est définie, Kubernetes autorise par défaut tout le trafic. Tous les pods peuvent librement échanger des informations entre eux. D'un point de vue de sécurité, cela peut sembler illogique, mais rappelez-vous que Kubernetes a été initialement développé par des concepteurs pour permettre l'interaction entre les applications. Les politiques réseau ont été ajoutées plus tard.

Espaces de noms

Les espaces de noms (Namespaces) sont un mécanisme de collaboration de Kubernetes. Ils sont destinés à isoler des environnements logiques les uns des autres, tout en permettant par défaut l'échange de données entre les espaces.

Comme la plupart des composants de Kubernetes, les politiques réseau résident dans un espace de noms spécifique. Dans le bloc métadonnées vous pouvez spécifier à quel espace appartient la politique :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

Si l'espace de noms dans les métadonnées n'est pas explicitement indiqué, le systÚme utilisera le namespace spécifié dans kubectl (par défaut namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

Je recommande d'indiquer explicitement le namespace, à moins que vous ne rédigiez une politique destinée à plusieurs espaces de noms.

Principal élément podSelector dans la politique choisira les pods de l'espace de noms auquel appartient la politique (il n'a pas accÚs aux pods d'un autre espace de noms).

De mĂȘme, les podSelectors dans les blocs ingress et egress peuvent choisir des pods uniquement de leur espace de noms, sauf si vous les combinez Ă  l'aide de namespaceSelector (- cela sera abordĂ© dans la section « Filtrer par espaces de noms et pods »).

RĂšgles de nommage des politiques

Les noms des politiques doivent ĂȘtre uniques au sein d'un mĂȘme espace de noms. Deux politiques portant le mĂȘme nom ne peuvent exister dans un mĂȘme espace, mais des politiques avec des noms identiques peuvent exister dans des espaces diffĂ©rents. Cela est pratique lorsque vous souhaitez rĂ©utiliser la mĂȘme politique dans plusieurs espaces.

J'aime particuliÚrement une des façons de nommer. Il s'agit d'associer le nom de l'espace de noms aux pods cibles. Par exemple :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Étiquettes

Des Ă©tiquettes personnalisĂ©es peuvent ĂȘtre attachĂ©es aux objets Kubernetes, tels que les pods et les espaces de noms. Les Ă©tiquettes (labels — labels) sont l'Ă©quivalent des tags dans le cloud. Les politiques rĂ©seau Kubernetes utilisent des Ă©tiquettes pour sĂ©lectionner pods, auxquelles elles s'appliquent :

podSelector:
  matchLabels:
    role: db


 ou espaces de noms, auxquels ils s'appliquent. Dans cet exemple, tous les pods dans les espaces de noms avec les étiquettes correspondantes sont sélectionnés :

namespaceSelector:
  matchLabels:
    project: myproject

Une mise en garde : lors de l'utilisation namespaceSelector assurez-vous que les espaces de noms sélectionnés contiennent bien l'étiquette souhaitée. Notez que les espaces de noms intégrés, tels que default et kube-system, ne contiennent par défaut aucune étiquette.

Vous pouvez ajouter une étiquette à un espace de cette maniÚre :

kubectl label namespace default namespace=default

Dans ce cas, le namespace dans la section métadonnées doit faire référence au véritable nom de l'espace et non à l'étiquette :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

Source et destinataire

Les politiques pour les pare-feu sont constituĂ©es de rĂšgles avec des sources et des destinations. Les politiques rĂ©seau Kubernetes sont dĂ©finies pour une cible — un ensemble de pod’ s auquel elles s'appliquent, puis Ă©tablissent des rĂšgles pour le trafic entrant (ingress) et/ou sortant (egress). Dans notre exemple, la cible de la politique sera tous les pod’ s dans l’espace de noms default avec un label de clĂ© app et la valeur db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: db   # <<<
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité
Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Sous-section ingress dans cette politique ouvre le trafic entrant vers les pod’ s cibles. En d'autres termes, l'ingress agit comme source, et la cible — comme destinataire correspondant. De mĂȘme, l'egress est le destinataire, et la cible est sa source.

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

C'est Ă©quivalent Ă  deux rĂšgles pour le pare-feu : Ingress → Cible ; Cible → Egress.

Egress et DNS (important !)

En limitant le trafic sortant, faites particuliĂšrement attention Ă  DNS — Kubernetes utilise ce service pour faire correspondre les services avec les adresses IP. Par exemple, la politique suivante ne fonctionnera pas, car vous n'avez pas autorisĂ© l'application balance Ă  accĂ©der Ă  DNS :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Vous pouvez corriger cela en ouvrant l'accĂšs au service DNS :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Le dernier Ă©lĂ©ment to — est vide, et donc, il choisit indirectement tous les pod’ s dans tous les espaces de noms, permettant balance d'envoyer des requĂȘtes DNS au service Kubernetes correspondant (qui fonctionne gĂ©nĂ©ralement dans l'espace kube-system).

Cette approche fonctionne, cependant, elle est trop permissive et peu sĂ©curisĂ©e, car elle permet d'envoyer des requĂȘtes DNS en dehors du cluster.

Vous pouvez améliorer cela par trois étapes successives.

1. Autoriser les requĂȘtes DNS uniquement Ă  l'intĂ©rieur au cluster en ajoutant namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

2. Autoriser les requĂȘtes DNS uniquement dans l'espace de noms kube-system.

Pour cela, il faut ajouter une Ă©tiquette dans l'espace de noms kube-system: kubectl label namespace kube-system namespace=kube-system — et l'inclure dans la politique en utilisant namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

3. Les paranos peuvent aller encore plus loin et restreindre les requĂȘtes DNS Ă  un service DNS spĂ©cifique dans kube-system. La section « Filtrer par espaces de noms et pods » expliquera comment y parvenir.

Une autre option est d'autoriser DNS au niveau de l'espace de noms. Dans ce cas, il ne sera pas nécessaire de l'ouvrir pour chaque service :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Vide podSelector sélectionne tous les pods dans l'espace de noms.

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Premier matching et ordre des rĂšgles

Dans les pare-feux classiques, l'action (« Autoriser » ou « Interdire ») concernant un paquet est déterminée par la premiÚre rÚgle à laquelle il correspond. Dans Kubernetes, l'ordre des politiques n'a pas d'importance.

Par défaut, lorsque les politiques ne sont pas définies, les communications entre les pods sont autorisées et ils peuvent échanger librement des informations. DÚs que vous commencez à formuler des politiques, chaque pod affecté par au moins l'une d'elles devient isolé selon la disjonction (OU logique) de toutes les politiques qui le choisissent. Les pods non affectés par aucune politique restent ouverts.

Il est possible de modifier ce comportement avec une rĂšgle de nettoyage.

RÚgle de nettoyage (« Interdire »)

Les politiques de pare-feu interdisent généralement tout trafic qui n'est pas explicitement autorisé.

Il n'existe pas d'action « interdire » (deny) dans Kubernetes, mais un effet similaire peut ĂȘtre obtenu avec une politique classique (permissive) en choisissant un groupe vide de pods source (ingress) :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Cette politique sélectionne tous les pods dans l'espace de noms et laisse l'ingress indéfini, interdisant tout le trafic entrant.

De maniĂšre similaire, il est possible de restreindre tout le trafic sortant de l'espace de noms :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Notez que toute politique supplémentaire permettant le trafic vers les pods dans l'espace de noms aura la priorité sur cette rÚgle (similaire à l'ajout d'une rÚgle d'autorisation avant une rÚgle d'interdiction dans la configuration du pare-feu).

Autoriser tout (Any-Any-Any-Allow)

Pour créer une politique « Autoriser tout », il est nécessaire de compléter la politique restrictive ci-dessus avec un élément vide ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Elle ouvre l'accĂšs depuis tous les pods dans tous les espaces de noms (et toutes les IP) Ă  n'importe quel pod dans l'espace de noms default. Ce comportement est activĂ© par dĂ©faut, donc il n'est gĂ©nĂ©ralement pas nĂ©cessaire de le dĂ©finir Ă  nouveau. Cependant, il peut parfois ĂȘtre nĂ©cessaire de dĂ©sactiver temporairement certaines autorisations spĂ©cifiques pour diagnostiquer un problĂšme.

La rĂšgle peut ĂȘtre affinĂ©e pour autoriser l'accĂšs uniquement Ă  un ensemble spĂ©cifique de pods (app:balance) dans l'espace de noms default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

La politique suivante autorise tout le trafic entrant (ingress) et sortant (egress), y compris l'accĂšs Ă  n'importe quelle IP en dehors du cluster :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité
Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Union de plusieurs politiques

Les politiques sont combinées par un OU logique à trois niveaux ; les autorisations de chaque pod sont définies par la disjonction de toutes les politiques qui le concernent :

1. Dans les champs from et to vous pouvez définir trois types d'éléments (tous combinés par OU) :

  • namespaceSelector — sĂ©lectionne l'espace de noms dans son ensemble ;
  • podSelector — sĂ©lectionne des pods ;
  • ipBlock — sĂ©lectionne une sous-rĂ©seau.

Dans ce cas, le nombre d'Ă©lĂ©ments (mĂȘme identiques) dans les sous-sections from/to n'est pas limitĂ©. Tous seront combinĂ©s par un OU logique.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

2. L'intĂ©rieur d'une politique section ingress peut contenir de nombreux Ă©lĂ©ments from (qui sont combinĂ©s avec un OU logique). De mĂȘme, la section egress peut inclure de nombreux Ă©lĂ©ments to (qui sont Ă©galement combinĂ©s avec une disjonction) :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

3. Différentes politiques sont également combinées avec un OU logique

Mais lors de leur combinaison, il existe une restriction, à laquelle a indiqué Chris Cooney: Kubernetes peut combiner des politiques uniquement avec différents policyTypes (Ingress ou Egress). Les politiques définissant l'ingress (ou l'egress) se substitueront les unes aux autres.

Relation entre les espaces de noms

Par dĂ©faut, l'Ă©change d'informations entre les espaces de noms est autorisĂ©. Cela peut ĂȘtre modifiĂ© par une politique restrictive qui limitera le trafic sortant et/ou entrant vers l'espace de noms (voir « RĂšgle de nettoyage » ci-dessus).

En bloquant l'accÚs à l'espace de noms (voir « RÚgle de nettoyage » ci-dessus), vous pouvez faire des exceptions à la politique restrictive, en autorisant les connexions d'un espace de noms spécifique grùce à namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

En conséquence, tous les pods dans l'espace de noms default auront accÚs aux pods postgres dans l'espace de noms database. Mais que faire si vous souhaitez ouvrir l'accÚs à postgres seulement des pods spécifiques dans l'espace de noms default?

Filtrage par namespace et pods

Kubernetes version 1.11 et plus permet de combiner des opérateurs namespaceSelector et podSelector avec une logique ET. Cela ressemble à ceci :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Pourquoi cela est-il interprété comme un ET au lieu d'un OU habituel ?

Veuillez noter que podSelector ne commence pas par un tiret. En YAML, cela signifie que podSelector et celui qui le prĂ©cĂšde namespaceSelector sont liĂ©s au mĂȘme Ă©lĂ©ment de la liste. Par consĂ©quent, ils sont combinĂ©s avec un ET.

Ajouter un tiret devant podSelector conduira à la création d'un nouvel élément de liste qui sera combiné avec le précédent namespaceSelector à l'aide de l'opérateur logique OU.

Pour sélectionner des pods avec une étiquette spécifique dans tous les espaces de noms, entrez vide namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Des étiquettes multiples sont combinées avec ET

Les rÚgles du pare-feu avec plusieurs objets (hÎtes, réseaux, groupes) sont combinées à l'aide de l'opérateur logique OU. La rÚgle suivante sera appliquée si la source du paquet correspond à Host_1 OU Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

En revanche, dans Kubernetes, différentes étiquettes sont podSelector ou namespaceSelector combinées par l'opérateur logique ET. Par exemple, la rÚgle suivante sélectionnera des pods ayant les deux étiquettes role=db Et version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

La mĂȘme logique s'applique Ă  tous les types d'opĂ©rateurs : sĂ©lecteurs d'objectifs de politiques, sĂ©lecteurs de pods et sĂ©lecteurs d'espaces de noms.

Sous-réseaux et adresses IP (IPBlocks)

Pour segmenter le réseau, les pare-feu utilisent des VLAN, des adresses IP et des sous-réseaux.

Dans Kubernetes, les adresses IP sont attribuées automatiquement aux pods et peuvent changer fréquemment, c'est pourquoi des étiquettes sont utilisées pour sélectionner des pods et des espaces de noms dans les politiques réseau.

Sous-réseaux (ipBlocks) sont utilisés pour gérer les connexions externes (North-South) entrantes (ingress) ou sortantes (egress). Par exemple, cette politique ouvre à tous les pods de l'espace de noms default l'accÚs au service DNS de Google :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Un sélecteur de pods vide dans cet exemple signifie «sélectionner tous les pods dans l'espace de noms».

Cette politique ouvre l'accÚs uniquement à 8.8.8.8 ; l'accÚs à toute autre IP est interdit. Ainsi, vous avez en fait bloqué l'accÚs au service DNS interne de Kubernetes. Si vous souhaitez néanmoins l'ouvrir, veuillez le préciser explicitement.

Habituellement ipBlocks et les podSelectors sont mutuellement exclusifs, car les adresses IP internes des pods ne sont pas utilisées dans ipBlocks. En spécifiant les IP internes des pods, vous autoriserez essentiellement les connexions vers/depuis des pod avec ces adresses. En pratique, vous ne saurez pas quelle adresse IP utiliser, c'est pourquoi il ne faut pas les appliquer pour choisir des pod.

Comme contre-exemple, la politique suivante inclut toutes les adresses IP et permet donc l'accĂšs Ă  tous les autres pod :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Vous pouvez accorder l'accÚs uniquement aux IP externes, en excluant les adresses IP internes des pod. Par exemple, si le sous-réseau de votre pod est 10.16.0.0/14 :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Ports et protocoles

Les pod Ă©coutent gĂ©nĂ©ralement un seul port. Cela signifie que vous pouvez simplement ne pas spĂ©cifier de numĂ©ros de port dans les politiques et laisser tout par dĂ©faut. Cependant, il est recommandĂ© de rendre les politiques aussi restrictives que possible, donc dans certains cas, vous pouvez quand mĂȘme spĂ©cifier des ports :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
      - port: 443      # <<<
        protocol: TCP  # <<<
      - port: 80       # <<<
        protocol: TCP  # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Notez que le sélecteur ports s'applique à tous les éléments dans le bloc to ou from, dans lequel il est contenu. Pour spécifier des ports différents pour différents ensembles d'éléments, divisez ingress ou egress en plusieurs sous-sections avec to ou from et dans chacune spécifiez vos ports :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # <<<
     - port: 443       # <<<
       protocol: TCP   # <<<
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
     - port: 80        # <<<
       protocol: TCP   # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduction aux politiques réseau Kubernetes pour les professionnels de la sécurité

Fonctionnement des ports par défaut :

  • Si vous omettez complĂštement la dĂ©finition des ports (ports), cela signifie tous les protocoles et tous les ports ;
  • Si vous omettez la dĂ©finition du protocole (protocol), cela signifie TCP ;
  • Si vous omettez la dĂ©finition du port (port), cela signifie tous les ports.

Meilleure pratique : ne vous fiez pas aux valeurs par défaut, spécifiez clairement ce dont vous avez besoin.

Veuillez noter qu'il est nécessaire d'utiliser les ports des pods, et non des services (plus de détails dans le paragraphe suivant).

Les politiques sont-elles définies pour les pods ou pour les services ?

En général, les pods dans Kubernetes communiquent entre eux via un service - un équilibreur de charge virtuel qui redirige le trafic vers les pods qui implémentent le service. On pourrait penser que les politiques réseau contrÎlent l'accÚs aux services, mais ce n'est pas le cas. Les politiques réseau de Kubernetes travaillent avec les ports des pods, et non des services.

Par exemple, si un service écoute le port 80, mais redirige le trafic vers le port 8080 de ses pods, la politique réseau doit spécifiquement indiquer 8080.

Un tel mĂ©canisme doit ĂȘtre reconnu comme non optimal : lorsque la configuration interne du service (dont les ports sont Ă©coutĂ©s par les pods) change, il faudra mettre Ă  jour les politiques rĂ©seau.

Une nouvelle approche architecturale utilisant le Service Mesh (par exemple, voir Istio ci-dessous — note du traducteur) permet de rĂ©soudre ce problĂšme.

Est-il nécessaire de définir des rÚgles pour Ingress et Egress ?

La réponse courte est oui, pour que le pod A puisse communiquer avec le pod B, il faut lui permettre d'établir une connexion sortante (pour cela, il faut configurer la politique d'egress), et le pod B doit pouvoir accepter une connexion entrante (pour cela, il faut une politique d'ingress, respectivement).

Cependant, en pratique, on peut compter sur la politique par défaut qui autorise les connexions dans un sens ou dans l'autre.

Si un pod-source est sélectionné par une ou plusieurs egress-politiques, les restrictions qui s'appliquent à lui seront définies par leur disjonction. Dans ce cas, il sera nécessaire d'autoriser explicitement la connexion au pod-destinataire. Si le pod n'est sélectionné par aucune politique, son trafic sortant (egress) est par défaut autorisé.

De mĂȘme, le sort du pod-destinataire, sĂ©lectionnĂ© par une ou plusieurs ingress-politiques, sera dĂ©terminĂ© par leur disjonction. Dans ce cas, il faut explicitement lui permettre de recevoir du trafic du pod-source. Si le pod n'est sĂ©lectionnĂ© par aucune politique, tout le trafic entrant (ingress) pour lui est autorisĂ© par dĂ©faut.

Voir le point « Stateful ou Stateless » ci-dessous.

Journaux

Les politiques réseau de Kubernetes ne savent pas journaliser le trafic. Cela complique la détermination de l'efficacité de la politique et rend l'analyse en matiÚre de sécurité trÚs difficile.

ContrĂŽle du trafic vers des services externes

Les politiques réseau de Kubernetes ne permettent pas de spécifier un nom de domaine complet (DNS) dans les sections egress. Cela entraßne des désagréments importants lorsqu'il s'agit de limiter le trafic vers des destinataires externes qui n'ont pas d'adresse IP fixe (comme aws.com).

Vérification de la politique

Les pare-feu vous avertiront ou mĂȘme refuseront d’accepter une politique erronĂ©e. Kubernetes effectue Ă©galement une certaine vĂ©rification. Lors de la dĂ©finition d'une politique rĂ©seau via kubectl, Kubernetes peut affirmer qu'elle est incorrecte et refuser de l'accepter. Dans d'autres cas, Kubernetes acceptera la politique et complĂ©tera les dĂ©tails manquants. Vous pouvez les voir avec la commande :

kubernetes get networkpolicy  -o yaml

Gardez à l'esprit que le systÚme de vérification de Kubernetes n'est pas infaillible et peut laisser passer certains types d'erreurs.

Exécution

Kubernetes ne gĂšre pas la mise en Ɠuvre des politiques rĂ©seau lui-mĂȘme, mais agit simplement comme une API de passerelle, dĂ©lĂ©guant la lourde tĂąche de contrĂŽle Ă  un systĂšme sous-jacent appelĂ© Container Networking Interface (CNI). DĂ©finir des politiques dans un cluster Kubernetes sans assigner le CNI appropriĂ© est comparable Ă  crĂ©er des politiques sur un serveur de gestion de pare-feu sans les appliquer par la suite dans les pare-feu. Vous devez vous assurer de disposer d'un CNI adĂ©quat ou, dans le cas des plateformes Kubernetes hĂ©bergĂ©es dans le cloud, (vous pouvez consulter la liste des fournisseurs ici — note de traduction.), d'activer des politiques rĂ©seau qui Ă©tabliront le CNI pour vous.

Notez que Kubernetes ne vous avertira pas si vous définissez une politique réseau sans CNI auxiliaire approprié.

Stateful ou Stateless ?

Tous les CNI Kubernetes auxquels j'ai été confronté gardent l'état (par exemple, Calico utilise le conntrack de Linux). Cela permet au pod de recevoir des réponses sur la connexion TCP initiée sans avoir à l'établir à nouveau. Cependant, je ne connais aucun standard Kubernetes qui garantirait la conservation de l'état (statefulness).

Gestion avancée des politiques de sécurité

Voici quelques moyens d'améliorer l'efficacité de l'application des politiques de sécurité dans Kubernetes :

  1. Le modÚle architectural Service Mesh utilise des conteneurs sidecar pour fournir une télémétrie détaillée et un contrÎle du trafic au niveau des services. Par exemple, Istio.
  2. Certains fournisseurs de CNI ont enrichi leurs outils pour aller au-delà des politiques réseau de Kubernetes.
  3. Tufin Orca offre de la transparence et de l'automatisation des politiques réseau de Kubernetes.

Le paquet Tufin Orca gÚre les politiques réseau de Kubernetes (et sert de source pour les captures d'écran ci-dessus).

Informations supplémentaires

Conclusion

Les politiques réseau de Kubernetes offrent un bon ensemble d'outils pour la segmentation des clusters, mais elles sont peu intuitives et présentent de nombreuses subtilités. Je pense qu'en raison de cette complexité, de nombreuses politiques des clusters existants contiennent des erreurs. Des solutions possibles à ce problÚme incluent l'automatisation des définitions de politiques ou l'application d'autres outils de segmentation.

J'espÚre que ce guide contribuera à clarifier certaines questions et à résoudre les problÚmes auxquels vous pourriez faire face.

P.S. de l'auteur

Lisez aussi dans notre blog :

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster