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, Anthos Service Meshoffre 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, Anthos 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
).Les règles (
rules
) spécifient le moment auquel déclencher l'action.Le champ
from
des règles (rules
) spécifie les sources de la requête.Le champ
to
des règles (rules
) spécifie les operations de la requête.Le champ
when
spécifie les conditions supplémentaires 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 operations 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, principals
de l'autorité de certification Anthos Service Mesh (Mesh 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
, Anthos 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 les versions 1.5 et ultérieures d'Anthos Service Mesh, le protocole mTLS automatique est activé 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 mTLS avec le mode STRICT
pour une charge de travail ou un espace de noms, la solution consiste à créer une règle d'autorisation afin d'autoriser explicitement le trafic avec namespaces
non vide ou principals
non vide ou de refuser le trafic avec namespaces
vide ou principals
vide. É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. Les requêtes de note peuvent toujours être refusées s'il existe des règles DENY
, car elles 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.
Étapes suivantes
Découvrez les fonctionnalités de sécurité d'Anthos Service Mesh :
- Configurer l'authentification des utilisateurs avec Anthos Service Mesh
- Configurer des règles d'audit pour vos services
- Configurer la sécurité du transport
- Intégrer Identity-Aware Proxy à Anthos Service Mesh
- Bonnes pratiques relatives à l'utilisation des passerelles de sortie Anthos Service Mesh sur les clusters GKE
Pour en savoir plus sur les règles d'autorisation, consultez la documentation d'Istio :