Kubernetes RBAC分析变得容易
Krane是一个简单的Kubernetes RBAC静态分析工具。它确定了K8S RBAC设计中的潜在安全风险,并就如何减轻它们提出了建议。 Krane仪表板呈现当前的RBAC安全姿势,并让您浏览其定义。
您可以通过在目标Kubernetes群集中安装Helm Chart或使用Docker在本地运行它来开始使用Krane。
假设您在计算机上安装了Helm CLI。
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespace遵循有关如何向前方的Krane仪表板的Helm图表安装输出。
假设您的码头机在本地计算机上运行。如果还没有安装Docker-Compose。
Krane取决于Redisgraph。 docker-compose堆栈定义了在本地构建和运行Krane服务所需的所有内容。它也将照顾其重新依赖。
docker-compose up -d
如果在本地机器上尚未存在, Krane Docker映像将自动进行预构建。
请注意,在本地运行docker-compose时, Krane不会自动启动RBAC报告和仪表板。取而代之的是,默认情况下,容器将睡觉24小时 - 可以在docker-compose.override.yml中调整此值。执行到运行的Krane容器中以运行命令。本地docker-compose还将在容器内安装Kube Config( ~/.kube/config ),使您能够针对您已经可以访问的任何Kubernetes群集运行报告。
执行运行的Krane容器。
docker-compose exec krane bash进入容器后,您可以开始使用krane命令。尝试krane -help 。
krane -h检查正在运行哪些服务和相关端口:
docker-compose ps
阻止Krane及其依赖服务:
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上下文要针对运行群集运行报告,您必须提供kubectl上下文
krane report -k <context>
如果您计划针对多个群集运行该工具,并且为每个群集名称分别使用-c <cluster-name> RBAC图。
要针对本地RBAC YAML/JSON文件运行报告,请提供目录路径
krane report -d </path/to/rbac-directory>
注意: Krane期望在指定目录路径中存在以下文件(YAML或JSON格式):
如果不使用POD安全策略,则可以通过手动创建一个使用以下内容的psp文件来绕过上述期望:
{
"items" : []
}请注意,在Kubernetes v1.21中弃用了PodSecurityPolicy ,并从v1.25中的Kubernetes中删除。
从Kubernetes群集中运行的容器运行报告
krane report --incluster
注意: Krane使用的服务帐户将需要访问RBAC资源。有关详细信息,请参见先决条件。
验证RBAC定义是CI/CD管道中的一步
krane report --ci -d </path/to/rbac-directory>
注意: Krane希望在本地存储的RBAC资源文件中遵循某些命名约定。请参见上面的部分。为了运行krane命令,建议CI执行者参考quay.io/appvia/krane:latest docker image。
CI模式由--ci标志启用。当检测到一个或多个危险时, Krane将返回非零状态代码以及破坏风险规则的详细信息。
要查看RBAC Facets树,网络图和最新报告发现,您需要首先启动仪表板服务器。
krane dashboard
群集标志-c <cluster-name>如果要使用特定群集名称运行仪表板,则可以传递。仪表板将查找与文件系统中被缓存的指定群集名称相关的数据。
上面的命令将在默认端口8000上启动本地Web服务器,并显示仪表板链接。
Krane Indexes RBAC在Redisgraph中引起了影响。这使我们能够有效地查询依赖关系网络,并简单地使用Redisgraph支持的Cypherql的子集。
相关RBAC对象的图中创建了以下节点:
Psp围绕POD安全策略围绕属性的PSP节点。仅在使用K8 <1.25时适用。Rule - 规则节点代表围绕Kubernetes资源的访问控制规则。Role - 角色节点代表给定的角色或聚类。 kind属性定义角色类型。Subject - 主题代表集群中的所有可能的参与者( kind :用户,组和serviceaccount)Namespace -Kubernetes名称空间节点。 :SECURITY - 定义规则和PSP节点之间的链接。仅在使用K8 <1.25时适用。:GRANT - 定义与该角色相关的角色和规则之间的联系。:ASSIGN - 定义Actor(主题)和给定的角色/簇(角色节点)之间的链接。:RELATION - 定义两个不同的参与者(主题)节点之间的联系。:SCOPE - 定义角色和名称空间节点之间的链接。:ACCESS - 定义主题和名称空间节点之间的链接。:AGGREGATE - 定义簇共簇(一个聚合另一个A-(aggregates)->B另一个)之间的链接:COMPOSITE - 定义聚类之间的链接(一个聚集在另一个簇中) A<-(is a composite of)-B所有边缘都是双向的,这意味着可以在任一方向上查询图。唯一的例外是:AGGREGATE和:COMPOSITE关系,尽管与相同的边缘节点有关。
为了直接查询图形,您可以将其执行到运行的redisgraph容器中,启动redis-cli并运行任意查询。遵循官方说明以获取命令的示例。
您也可以从Krane Console查询该图。首先执行运行Krane容器,然后
# 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 |
+----------------+--------------------------------+-----------+------------------------------------------------+
注意:上面的示例查询将选择具有分配的角色/群集授予访问update configmaps所有主题。
RBAC风险规则在规则文件中定义。每个规则的结构在很大程度上是自我解释的。可以通过在Custom规则文件中添加额外的自定义规则来扩展内置集 /覆盖。
宏是一组常见/共享属性的“容器”,并由一个或多个风险规则引用。如果您选择在给定的风险规则中使用宏,则需要按名称引用它,例如macro: <macro-name> 。请注意,引用macro定义的属性将优先于规则级别上定义的相同属性。
宏可以包含以下任何属性:
query - 重新查询。比template优先。需要定义writer 。writer - 作者是用于格式query结果集的红宝石表达式。作者优先于template 。template - 内置查询/作者模板名称。如果未指定query和writer ,则选择的查询生成器将与匹配的作者一起使用。 规则可以包含以下任何属性:
id [必需]规则ID是唯一的规则标识符。
group_title [必需]标题适用于属于此风险检查的所有项目。
severity [必需]的严重性,作为:危险,警告,:信息之一。
info [必需]有关如何减轻风险的检查和建议的文本信息。
query [conditonal] redisgraph查询。
template优先。需要定义writer 。 writer [conditonal]作者是用于格式查询结果集的红宝石表达式。
template 。需要定义query 。 template [conditonal]内置查询/作者模板名称。如果未指定query和writer ,则选择的查询生成器将与匹配的作者一起使用。
某些内置模板需要在单个规则级别上指定match_rules属性,以构建正确的查询。当前需要它的模板:
match_rules指定的访问规则构建多匹配图查询。生成的图形查询返回以下列: match_rules [conditonal] template依赖匹配规则以构建查询时需要。
match_rules :
- resources : ['cronjobs']
verbs : ['update'] custom_params [可选]要在规则query和writer表示中评估和替换的自定义键值对列表。
custom_params :
- attrA : valueA
- attrB : valueB{{attrA}}和{{attrB}}键的模板占位符分别将分别用valueA和valueB替换。 threshold [可选]数值。当定义时,此功能将作为模板占位符{{threshold}}在writer表达式中可用。
macro [可选]引用指定宏定义的常见参数。
disabled [可选]设置为true时,它将禁用给定规则并将其排除在评估之外。默认情况下,所有规则均已启用。
- 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上面的示例明确定义了用于评估RBAC风险的图形query ,以及用于格式查询结果集的writer表达式。查询只需选择所有Subjects (不包括白名单)和他们可以访问的Namespaces 。请注意,结果集将仅包括具有访问2以上名称空间的Subjects (在那里注意到threshold值值?)。最后writer的表达式将被捕获为格式化结果项目输出。
writer可以通过result对象访问结果设置的项目, result.subject_name result.subject_kind方法匹配查询返回的元素。
笔记:
{{threshold}} writer表达式中的占位符将被规则的threshold关键字值代替。{{whitelist_subject_names}}表示一个自定义字段,该字段将与给定规则id定义的白色列表值插值。如果未在白名单中定义占位符字段名称,则默认情况下将用空数组['']代替。在下面了解有关白名单的更多信息。 内置模板可显着简化风险规则的定义,但是,它们旨在提取特定的信息,并且可能不适合您的自定义规则。如果您发现自己在多个规则中重复使用相同的query或writer表达式,则应考虑将其提取到macro ,并在自定义规则中引用以使其干燥。
- 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 : ['*']上面的示例显示了内置规则之一。它引用了risky-role模板,该模板将在处理后通过在规则评估触发前注入query和writer表达方式来扩展规则。 match_rules将用于构建适当的匹配查询。
可选的白名单包含一组自定义定义的属性名称和相应的(白名单)值。
属性名称及其值是任意的。它们在白名单文件中定义,并分为三个单独的部分:
global - 顶级范围。此处定义的自定义属性将适用于所有风险规则,而不论群集名称如何。common - 自定义属性将范围为特定的风险规则id而不管群集名称如何。cluster (带有群集名称的嵌套列表) - 定制属性将适用于给定群集名称的特定风险规则id 。每个风险规则在评估后,都将尝试插入query中使用的所有参数占位持有人,例如{{your_whitelist_attribute_name}} 。如果占位符参数名称(即双卷发支架之间的名称)匹配该风险规则id的任何白名单属性名称,则将其替换为其计算值。如果找不到给定占位持有人的值,它将用['']代替。
下面的白名单示例为具有id属性值匹配的“ Some-strik-Rule-id”的风险规则产生以下placeholder-key => value映射
{{whitelist_role_names}} => ['acp:prometheus:operator']
{{whitelist_subject_names}} => ['privileged-psp-user', 'another-user']
在自定义图查询中使用时,上面的占位符键将在风险规则评估时被各自的值所取代。
例子:
---
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可以轻松地部署到本地或远程Kubernetes群集。
Kubernetes名称空间,服务帐户以及适当的RBAC必须存在于集群中。请参阅参考的先决条件。
默认情况下, Krane Entrypoint执行bin/cluster-run,该bin/clustruster-run等待redisgraph实例在启动RBAC报告循环和仪表板Web服务器之前就可以使用。
您可以通过以下环境变量控制集群内执行的某些方面:
KRANE_REPORT_INTERVAL在RBAC静态分析报告运行中以秒为单位定义间隔。默认值: 300 (以秒为单位,即5分钟)。KRANE_REPORT_OUTPUT定义RBAC风险报告输出格式。可能的值:json , :yaml ,: :none 。默认值:: :json 。在开始之前,您需要以下工具:
安装头盔图:
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespace有关其他可设置的选项和参数的详细信息,请参见values.yaml文件。
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请注意,默认情况下, Krane仪表板服务不会公开!
kubectl port-forward svc/krane 8000
--context= < docker-desktop >
--namespace=krane
# Open Krane dashboard at http://localhost:8000您可以在K8S目录中找到示例部署清单。
修改您的部署所需的清单,确保您在其部署文件中引用Krane Docker映像的正确版本。有关可用标签,请参见Krane Docker注册表,或者只使用latest 。
如果您的K8S群集随附内置的Kubernetes Controller支持( docker-desktop默认支持它),则您可以将Krane及其依赖项用单个Docker stack命令:
docker stack deploy
--orchestrator kubernetes
--namespace krane
--compose-file docker-compose.yml
--compose-file docker-compose.k8s.yml krane注意:在运行上面的命令之前,请确保正确设置当前的kube上下文!
现在,应用程序堆栈应部署到Kubernetes群集,并准备好所有服务。请注意, Krane将自动启动其报告循环和仪表板服务器。
docker stack services --orchestrator kubernetes --namespace krane krane上面的命令将产生以下输出:
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
通过访问http:// localhost:8000检查您的Kubernetes群集RBAC安全姿势。
请注意,对于远程群集部署
kubectl --context=my-remote-cluster --namespace=krane port-forward svc/krane 8000删除堆栈
docker stack rm krane
--orchestrator kubernetes
--namespace krane克兰(Krane)将通过其松弛整合通知您有关中和高严重性的异常。
要启用通知在config/config.yaml文件中指定Slack webhook_url & channel ,或者可以设置SLACK_WEBHOOK_URL和SLACK_CHANNEL环境变量。环境变量将优先于配置文件值。
本节介绍了实现本地发展的步骤。
使用
./bin/setupKrane取决于Redisgraph。 docker-compose是使Krane在本地运行的依赖关系的最快方法。
docker-compose up -d redisgraph检查Redisgraph服务已升起:
docker-compose ps停止服务:
docker-compose down此时,您应该能够通过在本地壳中调用命令来修改Krane代码库和测试结果。
$ ./bin/krane --help # to get help
$ ./bin/krane report -k docker-desktop # to generate your first report for
# local docker-desktop k8s cluster
...启用仪表板UI本地开发模式
$ cd dashboard
$ npm install
$ npm start这将自动启动仪表板服务器,打开默认浏览器并注意源文件更改。
Krane获得了改善Skaffold的开发人员经验的预先配置。通过在本地或远程Kubernetes群集中运行整个堆栈来迭代项目并验证应用程序,这变得更加容易。代码热填充使本地更改自动传播到运行的容器,以更快地开发生命周期。
skaffold dev --kube-context docker-desktop --namespace krane --port-forward与本地进行测试
bundle exec rspec我们欢迎社区的任何贡献!请查看我们的贡献指南,以获取有关如何入门的更多信息。如果您使用Krane ,发现它有用或对Kubernetes安全性感兴趣,请通过主演和观看此仓库来告知我们。谢谢!
加入我们社区渠道的讨论。
克兰(Krane)是一个社区项目,我们欢迎您的贡献。要报告错误,建议改进或请求新功能,请打开GitHub问题。有关如何提供帮助的更多信息,请参阅我们的贡献指南。
有关我们的项目计划的详细信息,请参见我们的路线图。
作者:Marcin Ciszak [email protected]
版权(C)2019-2020 Appvia Ltd
该项目是根据Apache许可证(版本2.0)分发的。