2
2
3
3
from typing import List
4
4
5
+ from icekube .relationships import Relationship
6
+
5
7
WORKLOAD_TYPES = [
6
8
"ReplicationController" ,
7
9
"DaemonSet" ,
@@ -27,40 +29,40 @@ def workload_query(
27
29
28
30
attack_paths = {
29
31
# Subject -> Role Bindings
30
- " BOUND_TO" : "MATCH (src)-[:BOUND_TO]->(dest)" ,
32
+ Relationship . BOUND_TO : "MATCH (src)-[:BOUND_TO]->(dest)" ,
31
33
# Role Binding -> Role
32
- " GRANTS_PERMISSION" : "MATCH (src)-[:GRANTS_PERMISSION]->(dest)" ,
34
+ Relationship . GRANTS_PERMISSION : "MATCH (src)-[:GRANTS_PERMISSION]->(dest)" ,
33
35
# Pod -> Service Account
34
- " USES_ACCOUNT" : "MATCH (src:Pod)-[:USES_ACCOUNT]->(dest:ServiceAccount)" ,
36
+ Relationship . USES_ACCOUNT : "MATCH (src:Pod)-[:USES_ACCOUNT]->(dest:ServiceAccount)" ,
35
37
# Pod -> Secrett
36
- " MOUNTS_SECRET" : "MATCH (src:Pod)-[:MOUNTS_SECRET]->(dest:Secret)" ,
38
+ Relationship . MOUNTS_SECRET : "MATCH (src:Pod)-[:MOUNTS_SECRET]->(dest:Secret)" ,
37
39
# Subject has permission to create pod within namespace with target
38
40
# Service Account
39
- " CREATE_POD_WITH_SA" : f"""
41
+ Relationship . CREATE_POD_WITH_SA : f"""
40
42
MATCH (src)-[:GRANTS_PODS_CREATE|{ create_workload_query ()} ]->(ns:Namespace)<-[:WITHIN_NAMESPACE]-(dest:ServiceAccount)
41
43
""" ,
42
44
# Subject has permission to update workload within namespace with target
43
45
# Service Account
44
- " UPDATE_WORKLOAD_WITH_SA" : f"""
46
+ Relationship . UPDATE_WORKLOAD_WITH_SA : f"""
45
47
MATCH (src)-[:GRANTS_UPDATE|GRANTS_PATCH]->(workload)-[:WITHIN_NAMESPACE]->(ns:Namespace)<-[:WITHIN_NAMESPACE]-(dest:ServiceAccount)
46
48
WHERE { workload_query ()}
47
49
""" ,
48
50
# Subject -> Pod
49
- " EXEC_INTO" : "MATCH (src)-[:GRANTS_EXEC_CREATE]->(dest:Pod)<-[:GRANTS_GET]-(src)" ,
51
+ Relationship . EXEC_INTO : "MATCH (src)-[:GRANTS_EXEC_CREATE]->(dest:Pod)<-[:GRANTS_GET]-(src)" ,
50
52
# Subject -> Pod
51
- " REPLACE_IMAGE" : "MATCH (src)-[:GRANTS_PATCH]->(dest:Pod)" ,
53
+ Relationship . REPLACE_IMAGE : "MATCH (src)-[:GRANTS_PATCH]->(dest:Pod)" ,
52
54
# Subject -> Pod
53
- " DEBUG_POD" : "MATCH (src)-[:GRANTS_EPHEMERAL_PATCH]->(dest:Pod)" ,
55
+ Relationship . DEBUG_POD : "MATCH (src)-[:GRANTS_EPHEMERAL_PATCH]->(dest:Pod)" ,
54
56
# Subject has permission to read authentication token for Service Account
55
- " GET_AUTHENTICATION_TOKEN_FOR" : """
57
+ Relationship . GET_AUTHENTICATION_TOKEN_FOR : """
56
58
MATCH (src)-[:GRANTS_GET|GRANTS_LIST|GRANTS_WATCH]->(secret:Secret)-[:AUTHENTICATION_TOKEN_FOR]->(dest:ServiceAccount)
57
59
""" ,
58
60
# Subject -> Secret
59
- " ACCESS_SECRET" : "MATCH (src)-[:GRANTS_GET|GRANTS_LIST|GRANTS_WATCH]->(dest:Secret)" ,
61
+ Relationship . ACCESS_SECRET : "MATCH (src)-[:GRANTS_GET|GRANTS_LIST|GRANTS_WATCH]->(dest:Secret)" ,
60
62
# Generate service account token
61
- " GENERATE_TOKEN" : "MATCH (src)-[:GRANTS_TOKEN_CREATE]->(dest:ServiceAccount)" ,
63
+ Relationship . GENERATE_TOKEN : "MATCH (src)-[:GRANTS_TOKEN_CREATE]->(dest:ServiceAccount)" ,
62
64
# RBAC escalate verb to change a role to be more permissive
63
- " RBAC_ESCALATE_TO" : [
65
+ Relationship . RBAC_ESCALATE_TO : [
64
66
# RoleBindings
65
67
"""
66
68
MATCH (src:RoleBinding)-[:GRANTS_ESCALATE]->(role)-[:WITHIN_NAMESPACE]->(:Namespace)<-[:WITHIN_NAMESPACE]-(dest)
@@ -73,39 +75,39 @@ def workload_query(
73
75
""" ,
74
76
],
75
77
# Subject -> User / Group / ServiceAccount
76
- " GENERATE_CLIENT_CERTIFICATE" : """
78
+ Relationship . GENERATE_CLIENT_CERTIFICATE : """
77
79
MATCH (src)-[:GRANTS_CERTIFICATESIGNINGREQUESTS_CREATE]->(cluster:Cluster), (dest)
78
80
WHERE (src)-[:HAS_CSR_APPROVAL]->(cluster) AND (src)-[:GRANTS_APPROVE]->(:Signer {
79
81
name: "kubernetes.io/kube-apiserver-client"
80
82
}) AND (dest:User OR dest:Group OR dest:ServiceAccount)
81
83
""" ,
82
84
# Impersonate
83
- " CAN_IMPERSONATE" : "MATCH (src)-[:GRANTS_IMPERSONATE]->(dest)" ,
85
+ Relationship . CAN_IMPERSONATE : "MATCH (src)-[:GRANTS_IMPERSONATE]->(dest)" ,
84
86
# Pod breakout
85
- " IS_PRIVILEGED" : "MATCH (src:Pod {privileged: true})<-[:HOSTS_POD]-(dest:Node)" ,
86
- " CAN_CGROUP_BREAKOUT" : 'MATCH (src:Pod)<-[:HOSTS_POD]-(dest:Node) WHERE "SYS_ADMIN" in src.capabilities' ,
87
- " CAN_LOAD_KERNEL_MODULES" : 'MATCH (src:Pod)<-[:HOSTS_POD]-(dest:Node) WHERE "SYS_MODULE" in src.capabilities' ,
88
- " CAN_ACCESS_DANGEROUS_HOST_PATH" : "MATCH (src:Pod {dangerous_host_path: true})<-[:HOSTS_POD]-(dest:Node)" ,
89
- " CAN_NSENTER_HOST" : 'MATCH (src:Pod {hostPID: true})<-[:HOSTS_POD]-(dest:Node) WHERE all(x in ["SYS_ADMIN", "SYS_PTRACE"] WHERE x in src.capabilities)' ,
90
- " CAN_ACCESS_HOST_FD" : 'MATCH (src:Pod)<-[:HOSTS_POD]-(dest:Node) WHERE "DAC_READ_SEARCH" in src.capabilities' ,
87
+ Relationship . IS_PRIVILEGED : "MATCH (src:Pod {privileged: true})<-[:HOSTS_POD]-(dest:Node)" ,
88
+ Relationship . CAN_CGROUP_BREAKOUT : 'MATCH (src:Pod)<-[:HOSTS_POD]-(dest:Node) WHERE "SYS_ADMIN" in src.capabilities' ,
89
+ Relationship . CAN_LOAD_KERNEL_MODULES : 'MATCH (src:Pod)<-[:HOSTS_POD]-(dest:Node) WHERE "SYS_MODULE" in src.capabilities' ,
90
+ Relationship . CAN_ACCESS_DANGEROUS_HOST_PATH : "MATCH (src:Pod {dangerous_host_path: true})<-[:HOSTS_POD]-(dest:Node)" ,
91
+ Relationship . CAN_NSENTER_HOST : 'MATCH (src:Pod {hostPID: true})<-[:HOSTS_POD]-(dest:Node) WHERE all(x in ["SYS_ADMIN", "SYS_PTRACE"] WHERE x in src.capabilities)' ,
92
+ Relationship . CAN_ACCESS_HOST_FD : 'MATCH (src:Pod)<-[:HOSTS_POD]-(dest:Node) WHERE "DAC_READ_SEARCH" in src.capabilities' ,
91
93
# Can jump to pods running on node
92
- " ACCESS_POD" : "MATCH (src:Node)-[:HOSTS_POD]->(dest:Pod)" ,
94
+ Relationship . ACCESS_POD : "MATCH (src:Node)-[:HOSTS_POD]->(dest:Pod)" ,
93
95
# Can exec into pods on a node
94
- " CAN_EXEC_THROUGH_KUBELET" : "MATCH (src)-[:GRANTS_PROXY_CREATE]->(:Node)-[:HOSTS_POD]->(dest:Pod)" ,
96
+ Relationship . CAN_EXEC_THROUGH_KUBELET : "MATCH (src)-[:GRANTS_PROXY_CREATE]->(:Node)-[:HOSTS_POD]->(dest:Pod)" ,
95
97
# Can update aws-auth ConfigMap
96
- " UPDATE_AWS_AUTH" : """
98
+ Relationship . UPDATE_AWS_AUTH : """
97
99
MATCH (src)-[:GRANTS_PATCH|GRANTS_UPDATE]->(:ConfigMap {
98
100
name: 'aws-auth', namespace: 'kube-system'
99
101
}), (dest:Group {
100
102
name: 'system:masters'
101
103
})
102
104
""" ,
103
- " AZURE_POD_IDENTITY_EXCEPTION" : [
105
+ Relationship . AZURE_POD_IDENTITY_EXCEPTION : [
104
106
# Create workload based of existing APIE
105
107
f"""
106
108
MATCH (src)-[:GRANTS_GET|GRANTS_LIST|GRANTS_WATCH]->(azexc:AzurePodIdentityException)-[:WITHIN_NAMESPACE]->(ns:Namespace), (dest:ClusterRoleBinding)
107
109
WHERE (dest.name = 'aks-cluster-admin-binding' OR dest.name = 'aks-cluster-admin-binding-aad') AND (EXISTS {{
108
- MATCH (src)-[:{ create_workload_query ()} |GRANTS_POD_CREATE ]->(ns)
110
+ MATCH (src)-[:{ create_workload_query ()} |GRANTS_PODS_CREATE ]->(ns)
109
111
}} OR EXISTS {{
110
112
MATCH (src)-[:GRANTS_PATCH|GRANTS_UPDATE]->(workload)-[:WITHIN_NAMESPACE]->(ns)
111
113
WHERE { workload_query ()}
0 commit comments