Autorización Externa
Esta tarea muestra cómo configurar una política de autorización de Istio utilizando un nuevo valor para el campo de acción, CUSTOM,
para delegar el control de acceso a un sistema de autorización externo. Esto se puede utilizar para integrar con autorización OPA,
oauth2-proxy, su propio servidor de autorización externo personalizado y más.
Antes de empezar
Antes de comenzar esta tarea, haga lo siguiente:
Lea los conceptos de autorización de Istio.
Siga la guía de instalación de Istio para instalar Istio.
Despliegue workloads de prueba:
Esta tarea utiliza dos workloads,
httpbinycurl, ambos desplegados en el namespacefoo. Ambos workloads se ejecutan con un proxy Envoy sidecar. Despliegue el namespacefooy los workloads con el siguiente comando:$ kubectl create ns foo $ kubectl label ns foo istio-injection=enabled $ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n foo $ kubectl apply -f @samples/curl/curl.yaml@ -n fooVerifique que
curlpuede acceder ahttpbincon el siguiente comando:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{\http_code}\n" 200
Desplegar el autorizador externo
Primero, debe desplegar el autorizador externo. Para ello, simplemente desplegará el autorizador externo de ejemplo en un pod independiente en la mesh.
Ejecute el siguiente comando para desplegar el autorizador externo de ejemplo:
$ kubectl apply -n foo -f https://raw.githubusercontent.com/istio/istio/master/samples/extauthz/ext-authz.yaml service/ext-authz created deployment.apps/ext-authz createdVerifique que el autorizador externo de ejemplo está en funcionamiento:
$ kubectl logs "$(kubectl get pod -l app=ext-authz -n foo -o jsonpath={.items..metadata.name})" -n foo -c ext-authz 2021/01/07 22:55:47 Starting HTTP server at [::]:8000 2021/01/07 22:55:47 Starting gRPC server at [::]:9000
Alternativamente, también puede desplegar el autorizador externo como un contenedor separado en el mismo pod de la aplicación que necesita la autorización externa o incluso desplegarlo fuera de la mesh. En cualquier caso, también deberá crear un recurso de entrada de service para registrar el service en la mesh y asegurarse de que sea accesible para el proxy.
El siguiente es un ejemplo de entrada de service para un autorizador externo desplegado en un contenedor separado en el mismo pod de la aplicación que necesita la autorización externa.
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: external-authz-grpc-local
spec:
hosts:
- "external-authz-grpc.local" # El nombre del service a usar en el proveedor de extensión en la configuración de la mesh.
endpoints:
- address: "127.0.0.1"
ports:
- name: grpc
number: 9191 # El número de puerto a usar en el proveedor de extensión en la configuración de la mesh.
protocol: GRPC
resolution: STATICDefinir el autorizador externo
Para utilizar la acción CUSTOM en la política de autorización, debe definir el autorizador externo que está permitido
utilizar en la mesh. Esto se define actualmente en el proveedor de extensión
en la configuración de la mesh.
Actualmente, el único tipo de proveedor de extensión compatible es el proveedor Envoy ext_authz.
El autorizador externo debe implementar la API de verificación ext_authz de Envoy correspondiente.
En esta tarea, utilizará un autorizador externo de ejemplo que
permite solicitudes con la cabecera x-ext-authz: allow.
Edite la configuración de la mesh con el siguiente comando:
$ kubectl edit configmap istio -n istio-systemEn el editor, agregue las definiciones de proveedor de extensión que se muestran a continuación:
El siguiente contenido define dos proveedores externos
sample-ext-authz-grpcysample-ext-authz-httputilizando el mismo serviceext-authz.foo.svc.cluster.local. El service implementa tanto la API de verificación HTTP como gRPC según lo definido por el filtroext_authzde Envoy. Desplegará el service en el siguiente paso.data: mesh: |- # Agregue el siguiente contenido para definir los autorizadores externos. extensionProviders: - name: "sample-ext-authz-grpc" envoyExtAuthzGrpc: service: "ext-authz.foo.svc.cluster.local" port: "9000" - name: "sample-ext-authz-http" envoyExtAuthzHttp: service: "ext-authz.foo.svc.cluster.local" port: "8000" includeRequestHeadersInCheck: ["x-ext-authz"]Alternativamente, puede modificar el proveedor de extensión para controlar el comportamiento del filtro
ext_authzpara cosas como qué cabeceras enviar al autorizador externo, qué cabeceras enviar al backend de la aplicación, el estado a devolver en caso de error y más. Por ejemplo, lo siguiente define un proveedor de extensión que se puede utilizar conoauth2-proxy:data: mesh: |- extensionProviders: - name: "oauth2-proxy" envoyExtAuthzHttp: service: "oauth2-proxy.foo.svc.cluster.local" port: "4180" # El puerto predeterminado utilizado por oauth2-proxy. includeRequestHeadersInCheck: ["authorization", "cookie"] # cabeceras enviadas a oauth2-proxy en la solicitud de verificación. headersToUpstreamOnAllow: ["authorization", "path", "x-auth-request-user", "x-auth-request-email", "x-auth-request-access-token"] # cabeceras enviadas al backend de la aplicación cuando se permite la solicitud. headersToDownstreamOnAllow: ["set-cookie"] # cabeceras enviadas de vuelta al cliente cuando se permite la solicitud. headersToDownstreamOnDeny: ["content-type", "set-cookie"] # cabeceras enviadas de vuelta al cliente cuando se deniega la solicitud.
Habilitar con autorización externa
El autorizador externo ya está listo para ser utilizado por la política de autorización.
Habilite la autorización externa con el siguiente comando:
El siguiente comando aplica una política de autorización con el valor de acción
CUSTOMpara el workloadhttpbin. La política habilita la autorización externa para las solicitudes a la ruta/headersutilizando el autorizador externo definido porsample-ext-authz-grpc.$ kubectl apply -n foo -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: ext-authz spec: selector: matchLabels: app: httpbin action: CUSTOM provider: # El nombre del proveedor debe coincidir con el proveedor de extensión definido en la configuración de la mesh. # También puede reemplazar esto con sample-ext-authz-http para probar la otra definición de autorizador externo. name: sample-ext-authz-grpc rules: # Las reglas especifican cuándo activar el autorizador externo. - to: - operation: paths: ["/headers"] EOFEn tiempo de ejecución, las solicitudes a la ruta
/headersdel workloadhttpbinserán pausadas por el filtroext_authz, y una solicitud de verificación será enviada al autorizador externo para decidir si la solicitud debe ser permitida o denegada.Verifique que una solicitud a la ruta
/headerscon la cabecerax-ext-authz: denyes denegada por el servidorext_authzde ejemplo:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -H "x-ext-authz: deny" -s denied by ext_authz for not found header `x-ext-authz: allow` in the requestVerifique que una solicitud a la ruta
/headerscon la cabecerax-ext-authz: allowes permitida por el servidorext_authzde ejemplo:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -H "x-ext-authz: allow" -s | jq '.headers' ... "X-Ext-Authz-Check-Result": [ "allowed" ], ...Verifique que una solicitud a la ruta
/ipes permitida y no activa la autorización externa:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/ip" -s -o /dev/null -w "%{\http_code}\n" 200Verifique el registro del servidor
ext_authzde ejemplo para confirmar que fue llamado dos veces (para las dos solicitudes). La primera fue permitida y la segunda fue denegada:$ kubectl logs "$(kubectl get pod -l app=ext-authz -n foo -o jsonpath={.items..metadata.name})" -n foo -c ext-authz 2021/01/07 22:55:47 Starting HTTP server at [::]:8000 2021/01/07 22:55:47 Starting gRPC server at [::]:9000 2021/01/08 03:25:00 [gRPCv3][denied]: httpbin.foo:8000/headers, attributes: source:{address:{socket_address:{address:"10.44.0.22" port_value:52088}} principal:"spiffe://cluster.local/ns/foo/sa/curl"} destination:{address:{socket_address:{address:"10.44.3.30" port_value:80}} principal:"spiffe://cluster.local/ns/foo/sa/httpbin"} request:{time:{seconds:1610076306 nanos:473835000} http:{id:"13869142855783664817" method:"GET" headers:{key:":authority" value:"httpbin.foo:8000"} headers:{key:":method" value:"GET"} headers:{key:":path" value:"/headers"} headers:{key:"accept" value:"*/*"} headers:{key:"content-length" value:"0"} headers:{key:"user-agent" value:"curl/7.74.0-DEV"} headers:{key:"x-b3-sampled" value:"1"} headers:{key:"x-b3-spanid" value:"377ba0cdc2334270"} headers:{key:"x-b3-traceid" value:"635187cb20d92f62377ba0cdc2334270"} headers:{key:"x-envoy-attempt-count" value:"1"} headers:{key:"x-ext-authz" value:"deny"} headers:{key:"x-forwarded-client-cert" value:"By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=dd14782fa2f439724d271dbed846ef843ff40d3932b615da650d028db655fc8d;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/curl"} headers:{key:"x-forwarded-proto" value:"http"} headers:{key:"x-request-id" value:"9609691a-4e9b-9545-ac71-3889bc2dffb0"} path:"/headers" host:"httpbin.foo:8000" protocol:"HTTP/1.1"}} metadata_context:{} 2021/01/08 03:25:06 [gRPCv3][allowed]: httpbin.foo:8000/headers, attributes: source:{address:{socket_address:{address:"10.44.0.22" port_value:52184}} principal:"spiffe://cluster.local/ns/foo/sa/curl"} destination:{address:{socket_address:{address:"10.44.3.30" port_value:80}} principal:"spiffe://cluster.local/ns/foo/sa/httpbin"} request:{time:{seconds:1610076300 nanos:925912000} http:{id:"17995949296433813435" method:"GET" headers:{key:":authority" value:"httpbin.foo:8000"} headers:{key:":method" value:"GET"} headers:{key:":path" value:"/headers"} headers:{key:"accept" value:"*/*"} headers:{key:"content-length" value:"0"} headers:{key:"user-agent" value:"curl/7.74.0-DEV"} headers:{key:"x-b3-sampled" value:"1"} headers:{key:"x-b3-spanid" value:"a66b5470e922fa80"} headers:{key:"x-b3-traceid" value:"300c2f2b90a618c8a66b5470e922fa80"} headers:{key:"x-envoy-attempt-count" value:"1"} headers:{key:"x-ext-authz" value:"allow"} headers:{key:"x-forwarded-client-cert" value:"By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=dd14782fa2f439724d271dbed846ef843ff40d3932b615da650d028db655fc8d;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/curl"} headers:{key:"x-forwarded-proto" value:"http"} headers:{key:"x-request-id" value:"2b62daf1-00b9-97d9-91b8-ba6194ef58a4"} path:"/headers" host:"httpbin.foo:8000" protocol:"HTTP/1.1"}} metadata_context:{}También puede ver en el registro que mTLS está habilitado para la conexión entre el filtro
ext-authzy el servidorext-authzde ejemplo porque el principal de origen se rellena con el valorspiffe://cluster.local/ns/foo/sa/curl.Ahora puede aplicar otra política de autorización para el servidor
ext-authzde ejemplo para controlar quién puede acceder a él.
Limpieza
Elimine el namespace
foode su configuración:$ kubectl delete namespace fooElimine la definición del proveedor de extensión de la configuración de la mesh.
Expectativas de rendimiento
Consulte benchmarking de rendimiento.