Présentation des règles d'autorisation
Contrairement à une application monolithique pouvant être exécutée au même endroit, les applications de microservices distribuées à l'échelle mondiale effectuent des appels au-delà des limites du réseau. Cela signifie qu'elles présentent un plus grand nombre de points d'entrée dans vos applications et davantage de possibilités pour les attaques malveillantes. De plus, étant donné que les pods Kubernetes ont des adresses IP temporaires, les règles de pare-feu basées sur l'adresse IP traditionnelles ne permettent pas de sécuriser l'accès entre les charges de travail. Dans une architecture de microservices, une nouvelle approche de la sécurité est nécessaire. S'appuyant sur des fonctionnalités de sécurité telles que les comptes de service Kubernetes et les règles de sécurité d'Istio, Cloud Service Mesh offre encore plus de fonctionnalités pour sécuriser vos applications.
Cette page offre aux opérateurs d'applications une présentation de la ressource personnalisée (CR, custom resource) AuthorizationPolicy
. Les règles d'autorisation vous permettent d'activer le contrôle d'accès sur les charges de travail au niveau des couches d'application (L7) et de transport (L3/4). On configure des règles d'autorisation pour spécifier des autorisations, c'est-à-dire ce qu'un service ou un utilisateur a le droit de faire.
Règles d'autorisation
Les requêtes entre les services de votre maillage (et entre les utilisateurs finaux et les services) sont autorisées par défaut. Utilisez la CR AuthorizationPolicy
pour définir des règles précises pour vos charges de travail. Une fois les règles d'autorisation appliquées, Cloud Service Mesh les distribue aux proxys side-car. Lorsque des requêtes arrivent dans une charge de travail, le proxy side-car vérifie les règles d'autorisation pour déterminer si la requête doit être autorisée ou refusée.
Champ d'application des règles
Vous pouvez appliquer une règle à l'ensemble du maillage de services, à un espace de noms ou à une charge de travail individuelle.
Pour appliquer une règle à l'échelle du maillage, spécifiez l'espace de noms racine,
istio-system
, dans le champmetadata:namespace
:apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "mesh-wide" namespace: istio-system spec: ...
Pour appliquer une règle à un espace de noms, spécifiez l'espace de noms dans le champ
metadata:namespace
:apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "currencyservice" namespace: currencyservice spec: ...
Pour limiter une règle à une charge de travail spécifique, incluez un champ
selector
.apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "frontend" namespace: demo spec: selector: matchLabels: app: frontend ...
Structure de base
Une règle d'autorisation comprend le champ d'application de la règle, une action (action
) et une liste de règles (rules
) :
Comme décrit dans la section précédente, le champ d'application de la règle peut être l'ensemble du maillage, un espace de noms ou une charge de travail spécifique. Si vous l'incluez, le champ
selector
spécifie la cible de la règle.Le champ
action
indique si la requête doit être définie surALLOW
ouDENY
. Si vous ne spécifiez aucune action, celle-ci est définie par défaut surALLOW
. Par souci de clarté, nous vous recommandons de toujours spécifier l'action (les règles d'autorisation sont également compatibles avec les actionsAUDIT
etCUSTOM
).rules
spécifier quand déclencher l'action.Le champ
from
des règles (rules
) spécifie les sources de la requête.Le champ
to
du fichierrules
spécifie opérations de la demande.Le champ
when
indique conditions nécessaires pour appliquer la règle.
Dans l'exemple suivant :
la règle est appliquée aux requêtes adressées au service
frontend
dans l'espace de nomsdemo
;les requêtes sont autorisées lorsque "hello:world" figure dans l'en-tête de la requête. Sinon, elles sont refusées.
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "hello-world"
namespace: demo
spec:
selector:
matchLabels:
app: frontend
action: ALLOW
rules:
- when:
- key: request.headers[hello]
values: ["world"]
Contrôle des accès lors des opérations de requête
Vous pouvez contrôler l'accès à des opérations de requête spécifiques, telles que des méthodes HTTP ou des ports TCP en ajoutant une section to
sous rules
.
Dans l'exemple suivant, seules les méthodes HTTP GET
et POST
sont autorisées pour currencyservice
dans l'espace de noms demo
.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: currencyservice
namespace: demo
spec:
selector:
matchLabels:
app: currencyservice
action: ALLOW
rules:
- to:
- operation:
methods: ["GET", "POST"]
Contrôle des accès avec une identité authentifiée
Dans les exemples précédents, les règles autorisent les requêtes provenant de charges de travail non authentifiées. Si le protocole TLS mutuel (mTLS) STRICT
est activé, vous pouvez limiter l'accès en fonction de l'identité de la charge de travail ou de l'espace de noms dont provient la requête dans la section source
.
Utilisez le champ
principals
ounotPrincipal
pour contrôler les accès au niveau de la charge de travail.Utilisez le champ
namespaces
ounotNamespaces
pour contrôler les accès au niveau de l'espace de noms.
Tous les champs ci-dessus nécessitent l'activation du protocole mTLS STRICT
. Si vous ne pouvez pas définir le protocole mTLS STRICT
, reportez-vous à la section Refuser les requêtes en texte brut pour trouver une autre solution.
Charge de travail identifiée
Dans l'exemple suivant, les requêtes adressées à currencyservice
ne sont autorisées qu'à partir du service frontend
. Les requêtes adressées à currencyservice
depuis d'autres charges de travail sont refusées.
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "currencyservice"
namespace: demo
spec:
selector:
matchLabels:
app: currencyservice
action: ALLOW
rules:
- from:
- source:
principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]
Pour spécifier un compte de service, le principals
pour
Autorité de certification Cloud Service Mesh (Mesh CA)
et Certificate Authority Service
(Service CA) doit être au format suivant:
principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]
PROJECT_ID.svc.id.goog
est le domaine de confiance pour Mesh CA. Si vous utilisez Istio CA (anciennement appelé Citadel), le domaine approuvé par défaut est cluster.local
.
Espace de noms identifié
L'exemple suivant illustre une règle qui refuse les requêtes si la source n'est pas l'espace de noms foo
:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: httpbin-deny
namespace: foo
spec:
selector:
matchLabels:
app: httpbin
version: v1
action: DENY
rules:
- from:
- source:
notNamespaces: ["foo"]
Mise en correspondance des valeurs
La plupart des champs des règles d'autorisation sont compatibles avec tous les schémas correspondants suivants :
- Correspondance exacte : correspondance de chaîne exacte.
- Correspondance générique avec le caractère générique
"*"
:- Correspondance de préfixe : chaîne qui se termine par le caractère
"*"
. Par exemple,"test.example.*"
correspond à"test.example.com"
ou"test.example.com.cn"
. - Correspondance de suffixe : chaîne qui commence par le caractère
"*"
. Par exemple,"*.example.com"
correspond à"eng.example.com"
ou"test.eng.example.com"
.
- Correspondance de préfixe : chaîne qui se termine par le caractère
- Correspondance de présence : pour spécifier qu'un champ doit être présent et non vide, utilisez le format
fieldname: ["*"]
. Cela diffère de laisser un champ non spécifié, ce qui signifie qu'il correspond à tout, y compris à une valeur vide.
Il existe quelques exceptions. Par exemple, les champs suivants ne sont compatibles qu'avec une correspondance exacte :
- Le champ
key
de la sectionwhen
ipBlocks
dans la sectionsource
- Le champ
ports
de la sectionto
L'exemple de règle suivant autorise l'accès aux chemins comportant le préfixe /test/*
ou le suffixe */info
:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: tester
namespace: default
spec:
selector:
matchLabels:
app: products
action: ALLOW
rules:
- to:
- operation:
paths: ["/test/*", "*/info"]
Correspondance d'exclusion
Pour faire correspondre des conditions à exclure comme notValues
dans le champ when
, notIpBlocks
dans le champ source
ou notPorts
dans le champ to
, Cloud Service Mesh est compatible avec la correspondance d'exclusion. L'exemple suivant nécessite une requête principals
valide, dérivée de l'authentification JWT, si le chemin de la requête n'est pas /healthz
. Par conséquent, la règle exclut les requêtes adressées au chemin /healthz
depuis l'authentification JWT :
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: disable-jwt-for-healthz
namespace: default
spec:
selector:
matchLabels:
app: products
action: ALLOW
rules:
- to:
- operation:
notPaths: ["/healthz"]
from:
- source:
requestPrincipals: ["*"]
Refuser des requêtes en texte brut
Dans Cloud Service Mesh 1.5 et versions ultérieures, l'authentification mTLS automatique est activée par défaut. Le protocole mTLS automatique permet à un proxy side-car client de détecter automatiquement si le serveur possède un side-car. Le side-car client envoie le protocole mTLS aux charges de travail avec des side-cars, et envoie du texte brut aux charges de travail sans side-car. Pour une sécurité optimale, nous vous recommandons d'activer mTLS STRICT.
Si vous ne parvenez pas à activer l'authentification mTLS en mode STRICT
pour une charge de travail ou un espace de noms, vous pouvez :
- créer une règle d'autorisation pour autoriser explicitement le trafic avec une valeur
namespaces
non vide ou une valeurprincipals
non vide, ou ; - refuser le trafic avec les valeurs
namespaces
ouprincipals
vides.
Étant donné que namespaces
et principals
ne peuvent être extraits que par une requête mTLS, ces règles rejettent dans les faits tout trafic en texte brut.
La règle suivante refuse la requête si le compte principal de la requête est vide (ce qui est le cas des requêtes en texte brut). La règle autorise les requêtes si le "principal" n'est pas vide. ["*"]
indique une correspondance non vide, tandis que l'utilisation de notPrincipals
indique une correspondance avec un "principal" vide.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-mtls
namespace: NAMESPACE
spec:
action: DENY
rules:
- from:
- source:
notPrincipals: ["*"]
Priorité des règles d'autorisation
Vous pouvez configurer des règles d'autorisation ALLOW
et DENY
distinctes, mais vous devez comprendre la priorité des règles et le comportement par défaut pour vous assurer qu'elles fonctionnent comme vous le souhaitez. Le schéma suivant décrit la priorité des règles.
Les exemples de règles présentés dans les sections suivantes illustrent certains comportements par défaut et les situations dans lesquelles ils peuvent vous être utiles.
Ne rien autoriser
L'exemple suivant montre une règle ALLOW
qui ne correspond à rien. Par défaut, s'il n'existe aucune autre règle ALLOW
, les requêtes sont toujours refusées.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-nothing
spec:
action: ALLOW
Une bonne pratique de sécurité consiste à commencer par la règle qui n'autorise rien ("allow-nothing") et à ajouter de manière incrémentielle des règles ALLOW
pour ouvrir davantage d'accès à une charge de travail.
Refuser tous les accès
L'exemple suivant montre une règle DENY
qui correspond à tout. Étant donné que les règles DENY
sont évaluées avant les règles ALLOW
, toutes les requêtes sont refusées, même si une règle ALLOW
correspond à la requête.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
spec:
action: DENY
rules:
- {}
Une règle qui refuse tous les accès ("deny-all") est utile si vous souhaitez désactiver temporairement tout accès à une charge de travail.
Autoriser tous les accès
L'exemple suivant montre une règle ALLOW
qui correspond à tout et autorise un accès complet à une charge de travail. La règle "allow-all" rend les autres règles ALLOW
inutiles, car elle autorise toujours la requête.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-all
spec:
action: ALLOW
rules:
- {}
Une règle qui autorise tous les accès ("allow-all") est utile si vous souhaitez exposer temporairement un accès complet à une charge de travail. S'il existe des règles DENY
, les requêtes peuvent toujours être refusées puisque les règles DENY
sont évaluées avant les règles ALLOW
.
Bonnes pratiques
Créez un compte de service Kubernetes pour chaque service et spécifiez le compte de service dans le déploiement. Exemple :
apiVersion: v1 kind: ServiceAccount metadata: name: frontend-sa namespace: demo --- apiVersion: apps/v1 kind: Deployment metadata: name: frontend namespace:demo spec: selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: serviceAccountName: frontend-sa ...
Commencez par une règle "allow-nothing", puis ajoutez progressivement des règles
ALLOW
pour permettre davantage d'accès aux charges de travail.Si vous utilisez des jetons JWT pour votre service, procédez comme suit :
Créez une règle
DENY
pour bloquer les requêtes non authentifiées, par exemple :apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: requireJWT namespace: admin spec: action: DENY rules: - from: - source: notRequestPrincipals: ["*"]
Appliquer une règle 'allow-nothing".
Définissez des règles
ALLOW
pour chaque charge de travail. Pour obtenir des exemples, consultez la page Jeton JWT.
Étape suivante
En savoir plus sur les fonctionnalités de sécurité de Cloud Service Mesh:
- Configurer l'authentification des utilisateurs dans Cloud Service Mesh
- Configurer des règles d'audit pour vos services
- Configurer la sécurité du transport
- Intégrer Identity-Aware Proxy à Cloud Service Mesh
- Bonnes pratiques d'utilisation des passerelles de sortie Cloud Service Mesh sur des clusters GKE
Pour en savoir plus sur les règles d'autorisation, consultez la documentation d'Istio :