Introducción general sobre la política de autorización
A diferencia de las aplicaciones monolíticas, que pueden ejecutarse en un solo lugar, las aplicaciones de microservicios distribuidas a nivel mundial hacen llamadas a través de límites de red. Esto significa que habrá más puntos de entrada en tus aplicaciones y más oportunidades para que se produzcan ataques maliciosos. Además, como los pods de Kubernetes tienen IPs transitorias, las reglas de cortafuegos tradicionales basadas en IPs no son adecuadas para proteger el acceso entre cargas de trabajo. En una arquitectura de microservicios, se necesita un nuevo enfoque de seguridad. Cloud Service Mesh se basa en funciones de seguridad como las cuentas de servicio de Kubernetes y las políticas de seguridad de Istio, y proporciona aún más funciones para ayudarte a proteger tus aplicaciones.
En esta página se ofrece a los operadores de aplicaciones una descripción general del AuthorizationPolicy
recurso personalizado (CR). Las políticas de autorización te permiten habilitar el control de acceso en cargas de trabajo en las capas de aplicación (L7) y de transporte (L3/4). Configuras políticas de autorización para especificar permisos: ¿qué puede hacer este servicio o usuario?
Políticas de autorización
Las solicitudes entre los servicios de tu malla (y entre los usuarios finales y los servicios) se permiten de forma predeterminada. Utiliza el AuthorizationPolicy
CR para definir políticas granulares para tus cargas de trabajo. Después de aplicar las políticas de autorización, Cloud Service Mesh las distribuye a los proxies sidecar. Cuando las solicitudes llegan a una carga de trabajo, el proxy sidecar comprueba las políticas de autorización para determinar si se deben permitir o denegar.
Ámbito de la política
Puedes aplicar una política a toda la malla de servicios, a un espacio de nombres o a una carga de trabajo concreta.
Para aplicar una política en toda la malla, especifica el espacio de nombres raíz,
istio-system
, en el campometadata:namespace
:apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "mesh-wide" namespace: istio-system spec: ...
Para aplicar una política a un espacio de nombres, especifica el espacio de nombres en el campo
metadata:namespace
:apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "currencyservice" namespace: currencyservice spec: ...
Para restringir una política a una carga de trabajo específica, incluye el campo
selector
.apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "frontend" namespace: demo spec: selector: matchLabels: app: frontend ...
Estructura básica
Una política de autorización incluye el ámbito de la política, un action
y una lista de rules
:
Como se ha descrito en la sección anterior, el ámbito de la política puede ser toda la malla, un espacio de nombres o una carga de trabajo específica. Si lo incluye, el campo
selector
especifica el objetivo de la política.El campo
action
especifica si se debeALLOW
oDENY
la solicitud. Si no especifica ninguna acción, se asignará el valorALLOW
de forma predeterminada. Para que no haya dudas, te recomendamos que especifiques siempre la acción. Las políticas de autorización también admiten las accionesAUDIT
yCUSTOM
.El elemento
rules
especifica cuándo se debe activar la acción.El campo
from
delrules
especifica las fuentes de la solicitud.El campo
to
delrules
especifica las operaciones de la solicitud.El campo
when
especifica las condiciones adicionales que se deben cumplir para aplicar la regla.
En el siguiente ejemplo:
La política se aplica a las solicitudes al servicio
frontend
en el espacio de nombresdemo
.Las solicitudes se permiten cuando "hello:world" está en el encabezado de la solicitud; de lo contrario, se deniegan.
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"]
Control de acceso en la operación de solicitud
Puedes controlar el acceso a operaciones de solicitudes específicas, como métodos HTTP o puertos TCP, añadiendo una sección to
en rules
.
En el siguiente ejemplo, solo se permiten los métodos HTTP GET
y POST
en el currencyservice
del espacio de nombres 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"]
Control de acceso en identidades autenticadas
En los ejemplos anteriores, las políticas permiten solicitudes de cargas de trabajo no autenticadas. Si tienes habilitado el STRICT
TLS mutuo (mTLS), puedes restringir el acceso en función de la identidad de la carga de trabajo o del espacio de nombres desde el que se envía la solicitud en la sección source
.
Usa el campo
principals
onotPrincipal
para controlar el acceso a nivel de carga de trabajo.Usa el campo
namespaces
onotNamespaces
para controlar el acceso a nivel de espacio de nombres.
Para rellenar todos los campos anteriores, debes tener habilitado STRICT
mTLS. Si no puedes configurar STRICT
mTLS, consulta Rechazar solicitudes de texto sin formato para ver una solución alternativa.
Carga de trabajo identificada
En el ejemplo siguiente, las solicitudes a currencyservice
solo se permiten desde el servicio frontend
. Las solicitudes al currencyservice
de otras cargas de trabajo se deniegan.
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"]
Para especificar una cuenta de servicio, el principals
de la autoridad de certificación de Cloud Service Mesh (AC de Mesh) y el servicio de autoridad de certificación (servicio de AC) deben tener el siguiente formato:
principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]
PROJECT_ID.svc.id.goog
es el dominio de confianza de la Mesh CA. Si usas la CA de Istio (antes conocida como Citadel), el dominio de confianza predeterminado es cluster.local
.
Espacio de nombres identificado
En el siguiente ejemplo se muestra una política que deniega las solicitudes si la fuente no es el espacio de nombres 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"]
Coincidencia de valor
La mayoría de los campos de las políticas de autorización admiten todos los esquemas de coincidencia siguientes:
- Concordancia exacta: coincidencia exacta de la cadena.
- Coincidencia con comodín mediante el carácter comodín
"*"
:- Coincidencia de prefijo: una cadena que termina en
"*"
. Por ejemplo,"test.example.*"
coincide con"test.example.com"
o"test.example.com.cn"
. - Coincidencia de sufijo: una cadena que empieza por
"*"
. Por ejemplo,"*.example.com"
coincide con"eng.example.com"
o"test.eng.example.com"
.
- Coincidencia de prefijo: una cadena que termina en
- Concordancia de presencia: para especificar que un campo debe estar presente y no estar vacío, usa el formato
fieldname: ["*"]
. Esto es diferente de dejar un campo sin especificar, lo que significa que se buscará cualquier valor, incluido el valor vacío.
Hay algunas excepciones. Por ejemplo, los siguientes campos solo admiten coincidencias exactas:
- El campo
key
de la secciónwhen
- La
ipBlocks
de la secciónsource
- El campo
ports
de la secciónto
La siguiente política de ejemplo permite el acceso a rutas con el prefijo /test/*
o el sufijo */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"]
Coincidencia de exclusión
Para que coincidan las condiciones negativas, como notValues
en el campo when
, notIpBlocks
en el campo source
y notPorts
en el campo to
, Cloud Service Mesh admite la coincidencia de exclusión. En el siguiente ejemplo se requiere una solicitud válida
principals
, que se deriva de la autenticación JWT, si la ruta de la solicitud no es /healthz
. Por lo tanto, la política excluye las solicitudes a la ruta /healthz
de la autenticación 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: ["*"]
Rechazar solicitudes de texto sin formato
En Cloud Service Mesh 1.5 y versiones posteriores, mTLS automático está habilitado de forma predeterminada. Con mTLS automático, un proxy sidecar del lado del cliente detecta automáticamente si el servidor tiene un sidecar. El sidecar del cliente envía mTLS a las cargas de trabajo con sidecars y texto sin formato a las cargas de trabajo sin sidecars. Para disfrutar de la máxima seguridad, te recomendamos que habilites mTLS ESTRICTO.
Si no puedes habilitar mTLS con el modo STRICT
en una carga de trabajo o un espacio de nombres, puedes hacer lo siguiente:
- crear una política de autorización para permitir explícitamente el tráfico con
namespaces
oprincipals
no vacíos, o - Rechaza el tráfico con
namespaces
oprincipals
vacíos.
Como namespaces
y principals
solo se pueden extraer con una solicitud mTLS, estas políticas rechazan cualquier tráfico sin cifrar.
La siguiente política deniega la solicitud si la entidad de seguridad de la solicitud está vacía (como ocurre con las solicitudes de texto sin formato). La política permite
solicitudes si la entidad no está vacía. El símbolo ["*"]
significa que la coincidencia no está vacía, y si se usa con notPrincipals
, significa que la coincidencia se basa en un principal vacío.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-mtls
namespace: NAMESPACE
spec:
action: DENY
rules:
- from:
- source:
notPrincipals: ["*"]
Prioridad de las políticas de autorización
Puedes configurar políticas de autorización ALLOW
y DENY
independientes, pero debes conocer la prioridad de las políticas y el comportamiento predeterminado para asegurarte de que las políticas hacen lo que quieres. En el siguiente diagrama se describe la precedencia de las políticas.
Las políticas de ejemplo de las siguientes secciones ilustran algunos de los comportamientos predeterminados y las situaciones en las que pueden resultarle útiles.
No permitir nada
En el siguiente ejemplo se muestra una política de ALLOW
que no coincide con nada. De forma predeterminada, si no hay otras políticas de ALLOW
, las solicitudes siempre se rechazan.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-nothing
spec:
action: ALLOW
Es una buena práctica de seguridad empezar con la política de no permitir nada y añadir gradualmente más políticas ALLOW
para abrir más acceso a una carga de trabajo.
Denegar todo el acceso
En el siguiente ejemplo se muestra una política DENY
que coincide con todo. Como las políticas de DENY
se evalúan antes que las de ALLOW
, todas las solicitudes se deniegan, aunque haya una política de ALLOW
que coincida con la solicitud.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
spec:
action: DENY
rules:
- {}
Una política de denegación total es útil si quieres inhabilitar temporalmente todo el acceso a una carga de trabajo.
Permitir todo el acceso
En el siguiente ejemplo se muestra una política ALLOW
que coincide con todo y permite el acceso completo a una carga de trabajo. La política que permite todo hace que otras políticas ALLOW
sean inútiles, ya que siempre permite la solicitud.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-all
spec:
action: ALLOW
rules:
- {}
Una política de permitir todo es útil si quieres exponer temporalmente el acceso completo a una carga de trabajo. Si hay políticas de DENY
, las solicitudes se pueden denegar, ya que las políticas de DENY
se evalúan antes que las de ALLOW
.
Prácticas recomendadas
Crea una cuenta de servicio de Kubernetes para cada servicio y especifica la cuenta de servicio en el Deployment. Por ejemplo:
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 ...
Empieza con una política de denegación total y añade de forma incremental más políticas
ALLOW
para abrir más acceso a las cargas de trabajo.Si usas JWTs en tu servicio:
Crea una política
DENY
para bloquear las solicitudes no autenticadas. Por ejemplo:apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: requireJWT namespace: admin spec: action: DENY rules: - from: - source: notRequestPrincipals: ["*"]
Aplica una política que no permita nada.
Define las políticas de
ALLOW
para cada carga de trabajo. Para ver ejemplos, consulta Token JWT.
Siguientes pasos
Consulta más información sobre las funciones de seguridad de Cloud Service Mesh:
- Configurar la autenticación de usuarios de Cloud Service Mesh
- Configurar políticas de auditoría para tus servicios
- Configurar la seguridad de transporte
- Integrar Identity-Aware Proxy con Cloud Service Mesh
- Prácticas recomendadas para usar pasarelas de salida de Cloud Service Mesh en clústeres de GKE
Consulta más información sobre las políticas de autorización en la documentación de Istio: