Análisis de Kubernetes RBAC facilitada
Krane es una simple herramienta de análisis estático de Kubernetes RBAC. Identifica posibles riesgos de seguridad en el diseño de K8S RBAC y hace sugerencias sobre cómo mitigarlos. Krane Dashboard presenta una postura actual de seguridad RBAC y le permite navegar a través de su definición.
Puede comenzar con Krane instalándolo a través de la tabla de timón en su clúster de Kubernetes objetivo o ejecutándolo localmente con Docker.
Se supone que tiene CLI de timón instalada en su máquina.
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespaceSiga la salida de instalación del gráfico de timón en cómo el tablero Krane de puerto.
Se supone que tiene Docker ejecutándose en su máquina local. Instale Docker-Compose si aún no lo ha hecho.
Krane depende del redisgraph. La pila docker-compose define todo lo que se requiere para construir y ejecutar el servicio Krane localmente. También se encargará de su dependencia de Redisgraph.
docker-compose up -d
La imagen de Krane Docker se construirá automáticamente si aún no está presente en la máquina local.
Tenga en cuenta que cuando se ejecuta docker-compose localmente, Krane no iniciará el informe RBAC y el tablero automáticamente. En cambio, el contenedor dormirá durante 24 h de forma predeterminada: este valor se puede ajustar en docker-compose.override.yml . Ejecutar en un contenedor Krane en ejecución para ejecutar comandos. docker-compose local también Mount Kube Config ( ~/.kube/config ) dentro del contenedor le permite ejecutar informes sobre cualquier grupo de Kubernetes a los que ya tiene acceso.
Ejecutar en un contenedor Krane en ejecución.
docker-compose exec krane bash Una vez en el contenedor, puede comenzar a usar los comandos krane . Prueba krane -help .
krane -hPara inspeccionar qué servicios se están ejecutando y los puertos asociados:
docker-compose ps
Para detener a Krane y sus servicios de dependencia:
docker-compose down
$ krane --help
NAME:
krane
DESCRIPTION:
Kubernetes RBAC static analysis & visualisation tool
COMMANDS:
dashboard Start K8s RBAC dashboard server
help Display global or [command] help documentation
report Run K8s RBAC report
GLOBAL OPTIONS:
-h, --help
Display help documentation
-v, --version
Display version information
-t, --trace
Display backtrace when an error occurs
AUTHOR:
Marcin Ciszak <[email protected]> - Appvia Ltd <appvia.io>
kubectl localPara ejecutar un informe contra un clúster en ejecución, debe proporcionar un contexto de Kubectl
krane report -k <context>
También puede pasar el indicador -c <cluster-name> si planea ejecutar la herramienta contra múltiples clústeres e indexar gráfico RBAC por separado para cada nombre de clúster.
Para ejecutar un informe contra archivos locales de RBAC YAML/JSON, proporcione una ruta de directorio
krane report -d </path/to/rbac-directory>
Nota: Krane espera que los siguientes archivos (en formato YAML o JSON) estén presentes en la ruta de directorio especificada:
Si las políticas de seguridad POD no están en uso, puede evitar las expectativas anteriores creando un archivo psp manualmente con el siguiente contenido:
{
"items" : []
} Tenga en cuenta que PodSecurityPolicy estaba en desuso en Kubernetes V1.21, y se eliminó de Kubernetes en V1.25.
Para ejecutar un informe desde un contenedor que se ejecuta en el clúster de Kubernetes
krane report --incluster
Nota: La cuenta de servicio utilizada por Krane requerirá acceso a los recursos RBAC. Ver Requisitos previos para más detalles.
Para validar la definición de RBAC como un paso en la tubería de CI/CD
krane report --ci -d </path/to/rbac-directory>
Nota: Krane espera que se siga cierta convención de nombres para archivos de recursos RBAC almacenados localmente. Ver sección de arriba. Para ejecutar los comandos krane , se recomienda que el ejecutor de CI haga referencia a Quay.io/Appvia/Krane:Latest Docker Image.
El modo CI está habilitado por la bandera --ci . Krane devolverá el código de estado no cero junto con los detalles de las reglas de riesgo de ruptura cuando se hayan detectado uno o más peligros.
Para ver el árbol de facetas RBAC, el gráfico de red y los últimos hallazgos de informes, debe iniciar primero el servidor del tablero.
krane dashboard
Cluster Flag -c <cluster-name> se puede pasar si desea ejecutar el tablero con un nombre específico del clúster. Dashboard buscará datos relacionados con el nombre del clúster especificado que se almacena en caché en el sistema de archivos.
El comando anterior iniciará el servidor web local en el puerto predeterminado 8000 y mostrará el enlace del tablero.
Los índices de Krane , RBAC entra en Redisgraph. Esto nos permite consultar la red de dependencias de manera eficiente y simplemente utilizando el subconjunto de CypherQL compatible con RedisGraph.
Los siguientes nodos se crean en el gráfico para los objetos RBAC relevantes:
Psp : un nodo PSP que contiene atributos alrededor de la política de seguridad del POD. Solo aplicable cuando se trabaja con K8S <1.25.Rule : el nodo de regla representa la regla de control de acceso en torno a los recursos de Kubernetes.Role : el nodo de rol representa un rol o racor dado. El atributo kind define el tipo de rol.Subject : el sujeto representa a todos los actores posibles en el clúster ( kind : usuario, grupo y serviceCcount)Namespace - Kubernetes Nodo de espacio de nombres. :SECURITY : define un enlace entre la regla y los nodos PSP. Solo aplicable cuando se trabaja con K8S <1.25.:GRANT : define un vínculo entre el rol y la regla asociada con ese papel.:ASSIGN - Define un enlace entre un actor (sujeto) y dado de rol/clusterrol (nodo de roles).:RELATION : define un enlace entre dos nodos de actor (sujeto) diferentes.:SCOPE : define un enlace entre los nodos de roles y del espacio de nombres.:ACCESS : define un enlace entre los nodos de sujeto y espacio de nombres.:AGGREGATE -Define un enlace entre clusterroles (un clusterrole agrega otro) A-(aggregates)->B:COMPOSITE : define un enlace entre clusterrols (un rigor se puede agregar en otro) A<-(is a composite of)-B Todos los bordes son bidireccionales, lo que significa que el gráfico se puede consultar en cualquier dirección. Solo las excepciones son :AGGREGATE y :COMPOSITE que son unidireccionales, aunque se preocupan por los mismos nodos de borde.
Para consultar el gráfico directamente, puede ejecutar en un contenedor redisgraph en ejecución, inicie redis-cli y ejecute sus consultas arbitrarias. Siga las instrucciones oficiales para ver ejemplos de comandos.
También puede consultar el gráfico de la consola Krane . Primero ejecute en ejecutar Krane Container, luego
# Start Krane console - this will open interactive ruby shell with Krane code preloaded
console
# Instantiate Graph client
graph = Krane :: Clients :: RedisGraph . client cluster : 'default'
# Run arbitrary CypherQL query against indexed RBAC Graph
res = graph . query ( %Q(
MATCH (r:Rule {resource: "configmaps", verb: "update"})<-[:GRANT]-(ro:Role)<-[:ASSIGN]-(s:Subject)
RETURN s.kind as subject_kind, s.name as subject_name, ro.kind as role_kind, ro.name as role_name) )
# Print the results
res . print_resultset # Results...
+----------------+--------------------------------+-----------+------------------------------------------------+
| subject_kind | subject_name | role_kind | role_name |
+----------------+--------------------------------+-----------+------------------------------------------------+
| ServiceAccount | bootstrap-signer | Role | system:controller:bootstrap-signer |
| User | system:kube-controller-manager | Role | system::leader-locking-kube-controller-manager |
| ServiceAccount | kube-controller-manager | Role | system::leader-locking-kube-controller-manager |
| User | system:kube-scheduler | Role | system::leader-locking-kube-scheduler |
| ServiceAccount | kube-scheduler | Role | system::leader-locking-kube-scheduler |
+----------------+--------------------------------+-----------+------------------------------------------------+
Nota: La consulta de ejemplo anterior seleccionará todos los sujetos con roles asignados/ClusterRoles otorgando acceso a update configmaps .
Las reglas de riesgo RBAC se definen en el archivo de reglas. La estructura de cada regla se explica en gran medida. El conjunto incorporado se puede ampliar / anularse agregando reglas personalizadas adicionales al archivo de reglas Cutom.
Las macros son "contenedores" para un conjunto de atributos comunes/compartidos, y referenciados por una o más reglas de riesgo. Si elige usar macro en una regla de riesgo determinada, necesitaría hacer referencia por su nombre, por ejemplo, macro: <macro-name> . Tenga en cuenta que los atributos definidos en macro referenciada tendrán prioridad sobre los mismos atributos definidos en el nivel de regla.
Macro puede contener cualquiera de los siguientes atributos:
query - Consulta Redisgraph. Tiene precedencia sobre template . Requiere que writer sea definido.writer : el escritor es una expresión de Ruby utilizada para formatear el conjunto de resultados query . El escritor tiene prioridad sobre template .template - Nombre de plantilla de consulta/escritor incorporado. Si query y writer no se especifican, el generador de consultas elegido se utilizará junto con el escritor coincidente. La regla puede contener cualquiera de los siguientes atributos:
id [requerido] La identificación de la regla es un identificador de regla único.
group_title [requerido] Título que se aplica a todos los elementos que caen bajo esta verificación de riesgos.
severity [requerida] Severidad, como uno de: Danger ,: ADVERTENCIA ,: INFO.
info [requerido] Información textual sobre el cheque y las sugerencias sobre cómo mitigar el riesgo.
query [conditonal] consulta redisgraph.
template . Requiere que writer sea definido. writer [conditonal] es una expresión de rubí utilizada para formatear el conjunto de resultados de consulta.
template . Requiere que query sea definida. template [conditonal] consulta incorporada/escritor nombre de plantilla. Si query y writer no se especifican, el generador de consultas elegido se utilizará junto con el escritor coincidente.
Algunas plantillas incorporadas requieren que el atributo match_rules se especifique en el nivel de regla individual para construir una consulta correcta. Las plantillas que actualmente lo requieren:
match_rules . Consulta gráfica generada Devuelve las siguientes columnas: match_rules [conditonal] requerido cuando template se basa en las reglas de coincidencia para construir una consulta.
match_rules :
- resources : ['cronjobs']
verbs : ['update'] custom_params [Opcional] Lista de pares de valor clave personalizados para ser evaluados y reemplazados en una query de reglas y representación writer .
custom_params :
- attrA : valueA
- attrB : valueB{{attrA}} y {{attrB}} se reemplazarán con valueA y valueB respectivamente. threshold [opcional] Valor numérico. Cuando se definiera, esto estará disponible como marcador de posición de plantilla {{threshold}} en la expresión writer .
Referencia macro [opcional] a parámetros comunes definidos en una macro con nombre.
disabled [Opcional] Cuando se establece en true , deshabilitará la regla dada y la excluirá de la evaluación. Por defecto, todas las reglas están habilitadas.
- id : verbose-rule-example
group_title : Example rule
severity : :danger
info : Risk description and instructions on how to mitigate it goes here
query : |
MATCH
(s:Subject)-[:ACCESS]->(ns:Namespace)
WHERE
NOT s.name IN {{whitelist_subject_names}}
RETURN
s.kind as subject_kind,
s.name as subject_name,
COLLECT(ns.name) as namespace_names
ORDER BY
subject_kind,
subject_name,
namespace_names DESC
threshold : 2
writer : |
if result.namespace_names.count > {{threshold}}
"#{result.subject_kind} #{result.subject_name} can access namespaces: #{result.namespace_names.join(', ')}"
end
disabled : true El ejemplo anterior define explícitamente una query gráfica que se utiliza para evaluar el riesgo de RBAC, y una expresión writer utilizada para formatear el conjunto de resultados de consulta. La consulta simplemente selecciona todos Subjects (excluyendo la lista blanca) y Namespaces a los que tienen acceso. Tenga en cuenta que el conjunto de resultados solo incluirá Subjects que tengan acceso a más de 2 espacios de nombres (¿Valor threshold notado allí?). La expresión del último writer se capturará como salida de elemento de resultado formateado.
writer puede acceder al elemento establecido de resultados a través del objeto result con métodos de coincidencia de elementos devueltos por la consulta, por ejemplo, result.subject_kind , result.subject_name etc.
Nota:
{{threshold}} El marcador de posición en la expresión writer será reemplazado por el valor de la palabra clave threshold de la regla.{{whitelist_subject_names}} representa un campo personalizado que se interpolará con los valores de la lista blanca definidas para una id de regla dada. Si el nombre de campo de un marcador de posición no se define en la lista blanca, se sustituirá con una matriz vacía [''] de forma predeterminada. Lea más sobre la lista blanca a continuación. Las plantillas integradas simplifican significativamente la definición de la regla de riesgo, sin embargo, están diseñadas para extraer información específica y pueden no ser una buena opción para sus reglas personalizadas. Si se encuentra reutilizando la misma query o expresiones writer en múltiples reglas, debe considerar extraerlas a una macro y hacer referencia a sus reglas personalizadas para secarlas.
- id : risky-any-verb-secrets
group_title : Risky Roles/ClustersRoles allowing all actions on secrets
severity : :danger
info : Roles/ClusterRoles allowing all actions on secrets. This might be dangerous. Review listed Roles!
template : risky-role
match_rules :
- resources : ['secrets']
verbs : ['*'] El ejemplo anterior muestra una de las reglas incorporadas. Hace referencia a la plantilla risky-role que al procesar expandirá la regla inyectando query y las expresiones writer antes de que la evaluación de las reglas desencadene. match_rules se utilizará para construir una consulta de coincidencia apropiada.
Whitelist opcional contiene un conjunto de nombres de atributos definidos personalizados y valores respectivos (la lista blanca).
Los nombres de los atributos y sus valores son arbitrarios. Se definen en el archivo de la lista blanca y se dividen en tres secciones separadas:
global - Alcance de nivel superior. Los atributos personalizados definidos aquí se aplicarán a todas las reglas de riesgo independientemente del nombre del clúster.common : los atributos personalizados se alcanzarán a id de regla de riesgo específica, independientemente del nombre del clúster.cluster (con una lista anidada de nombres de clúster): los atributos personalizados se aplicarán a id de regla de riesgo específica para un nombre de clúster dado. Cada regla de riesgo, tras la evaluación, intentará interpolar todos los marcadores de posición de los parámetros utilizados en la query , por ejemplo {{your_whitelist_attribute_name}} . Si un nombre de parámetro de marcador de posición (es decir, un nombre entre los soportes dobles rizados) coincide con cualquiera de los nombres de atributos con la lista blanca para esa id de regla de riesgo, se reemplazará con su valor calculado. Si no se encuentran valores para un marcador de posición dado, se sustituirá con [''] .
Ejemplo Whitelist a continuación produce el siguiente placeholder-key => value para una regla de riesgo con valor de atributo de id que coincide con "alguna regla de riesgo"
{{whitelist_role_names}} => ['acp:prometheus:operator']
{{whitelist_subject_names}} => ['privileged-psp-user', 'another-user']
Las claves de marcador de posición anterior, cuando se usan en las consultas de gráficos personalizados, serán reemplazadas por sus valores respectivos tras la evaluación de las reglas de riesgo.
Ejemplo:
---
rules :
global : # global scope - applies to all risk rule and cluster names
whitelist_role_names : # custom attribute name
- acp:prometheus:operator # custom attribute values
common : # common scope - applies to specific risk rule id regardless of cluster name
some-risk-rule-id : # this corresponds to risk rule id defined in config/rules.yaml
whitelist_subject_names : # custom attribute name
- privileged-psp-user # custom attribute values
cluster : # cluster scope - applies to speciifc risk rule id and cluster name
default : # example cluster name
some-risk-rule-id : # risk rule id
whitelist_subject_names : # custom attribute nane
- another-user # custom attribute values Krane se puede implementar fácilmente en los grupos de Kubernetes locales o remotos.
El espacio de nombres de Kubernetes, la cuenta de servicio junto con el RBAC apropiado debe estar presente en el clúster. Vea los requisitos previos como referencia.
El valor predeterminado de Krane EntryPoint ejecuta bin/en-cluster-sunn, lo que espera que la instancia de redisgraph esté disponible antes de iniciar el bucle de informe RBAC y el servidor web de tablero .
Puede controlar ciertos aspectos de la ejecución en el clúster con las siguientes variables de entorno:
KRANE_REPORT_INTERVAL - Define el intervalo en segundos para el informe de análisis estático RBAC ejecutado. Valor predeterminado: 300 (en segundos, es decir, 5 minutos).KRANE_REPORT_OUTPUT - Define el formato de salida del informe de riesgo RBAC. Valores posibles :json , :yaml , :none . Valor predeterminado :: :json .Antes de comenzar, necesitará las siguientes herramientas:
Instalar gráfico de timón:
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespaceConsulte el archivo Values.yaml para obtener detalles de otras opciones y parámetros configurables.
kubectl create
--context < docker-desktop >
--namespace krane
-f k8s/redisgraph-service.yaml
-f k8s/redisgraph-deployment.yaml
-f k8s/krane-service.yaml
-f k8s/krane-deployment.yaml¡Tenga en cuenta que el servicio de panel de Krane no está expuesto de forma predeterminada!
kubectl port-forward svc/krane 8000
--context= < docker-desktop >
--namespace=krane
# Open Krane dashboard at http://localhost:8000Puede encontrar el ejemplo de manifiesto de implementación en el directorio K8S.
Modifique los manifiestos según sea necesario para sus implementaciones Asegúrese de hacer referencia a la versión correcta de Krane Docker Image en su archivo de implementación. Consulte Krane Docker Registry para ver las etiquetas disponibles, o simplemente use latest .
Si su clúster K8S viene con soporte de controlador compuesto en kubernetes incorporado ( docker-desktop lo admite por defecto), puede implementar Krane y sus dependencias con un solo comando de pila Docker:
docker stack deploy
--orchestrator kubernetes
--namespace krane
--compose-file docker-compose.yml
--compose-file docker-compose.k8s.yml kraneNota: ¡Asegúrese de que su contexto de Kube actual esté configurado correctamente antes de ejecutar el comando anterior!
La pila de aplicaciones ahora debe implementarse en un clúster de Kubernetes y todos los servicios listos y expuestos. Tenga en cuenta que Krane iniciará automáticamente su bucle de informe y servidor de tablero.
docker stack services --orchestrator kubernetes --namespace krane kraneEl comando anterior producirá la siguiente salida:
ID NAME MODE REPLICAS IMAGE PORTS
0de30651-dd5 krane_redisgraph replicated 1/1 redislabs/redisgraph:1.99.7 *:6379->6379/tcp
aa377a5f-62b krane_krane replicated 1/1 quay.io/appvia/krane:latest *:8000->8000/tcp
Consulte su postura de seguridad RBAC Kubernetes visitando http: // localhost: 8000.
Tenga en cuenta que para las implementaciones de clúster remotas es probable que necesite el servicio Krane de puerto primero primero
kubectl --context=my-remote-cluster --namespace=krane port-forward svc/krane 8000Para eliminar la pila
docker stack rm krane
--orchestrator kubernetes
--namespace kraneKrane le notificará sobre las anomalías detectadas de gravedad media y alta a través de su integración floja.
Para habilitar las notificaciones, especifique Slack webhook_url & channel en el archivo config/config.yaml, o alternativamente configure las variables de entorno SLACK_WEBHOOK_URL y SLACK_CHANNEL . Las variables de entorno tendrán prioridad sobre los valores de archivo de configuración.
Esta sección describe pasos para habilitar el desarrollo local.
Instalar dependencias de código Krane con
./bin/setup Krane depende del redisgraph. docker-compose es la forma más rápida de hacer que las dependencias de Krane funcionen localmente.
docker-compose up -d redisgraphPara inspeccionar el servicio redisgraph está activo:
docker-compose psPara detener los servicios:
docker-compose downEn este punto, debería poder modificar la base de código de Krane y probar los resultados invocando comandos en el shell local.
$ ./bin/krane --help # to get help
$ ./bin/krane report -k docker-desktop # to generate your first report for
# local docker-desktop k8s cluster
...Para habilitar el modo de desarrollo local de la interfaz de usuario del tablero
$ cd dashboard
$ npm install
$ npm startEsto iniciará automáticamente el servidor del tablero, abrirá el navegador predeterminado y observará los cambios de archivos de origen.
Krane viene preconfigurado para mejorar la experiencia del desarrollador con Skaffold. Iterando en el proyecto y validando la aplicación ejecutando toda la pila en el clúster de Kubernetes local o remoto se vuelve más fácil. Código de relieve caliente permite que los cambios locales se propagen automáticamente al contenedor en ejecución para un ciclo de vida de desarrollo más rápido.
skaffold dev --kube-context docker-desktop --namespace krane --port-forwardEjecutar pruebas localmente con
bundle exec rspec¡Agradecemos cualquier contribución de la comunidad! Eche un vistazo a nuestra guía de contribución para obtener más información sobre cómo comenzar. Si usa Krane , busque útil o generalmente está interesado en la seguridad de Kubernetes, háganoslo saber protagonizando y observando este repositorio. ¡Gracias!
Únase a la discusión en nuestro canal comunitario.
Krane es un proyecto comunitario y damos la bienvenida a sus contribuciones. Para informar un error, sugiera una mejora o solicite una nueva función, abra un problema de GitHub. Consulte nuestra guía de contribución para obtener más información sobre cómo puede ayudar.
Vea nuestra hoja de ruta para obtener detalles sobre nuestros planes para el proyecto.
Autor: Marcin Ciszak [email protected]
Copyright (c) 2019-2020 AppVia Ltd
Este proyecto se distribuye bajo la licencia Apache, versión 2.0.