mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
feat(kubernetes): add resource metadata to report (#6479)
This commit is contained in:
@@ -528,11 +528,17 @@ class Check_Report_Kubernetes(Check_Report):
|
||||
resource_id: str
|
||||
namespace: str
|
||||
|
||||
def __init__(self, metadata):
|
||||
super().__init__(metadata)
|
||||
self.resource_name = ""
|
||||
self.resource_id = ""
|
||||
self.namespace = ""
|
||||
def __init__(self, metadata, resource_metadata):
|
||||
super().__init__(metadata, resource_metadata)
|
||||
self.resource_id = (
|
||||
getattr(resource_metadata, "uid", None)
|
||||
or getattr(resource_metadata, "name", None)
|
||||
or ""
|
||||
)
|
||||
self.resource_name = getattr(resource_metadata, "name", "")
|
||||
self.namespace = getattr(resource_metadata, "namespace", "cluster-wide")
|
||||
if not self.namespace:
|
||||
self.namespace = "cluster-wide"
|
||||
|
||||
|
||||
# Testing Pending
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_always_pull_images_plugin(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"AlwaysPullImages admission control plugin is set in pod {pod.name}."
|
||||
|
||||
+3
-5
@@ -8,17 +8,15 @@ class apiserver_anonymous_requests(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"API Server does not have anonymous-auth enabled in pod {pod.name}."
|
||||
)
|
||||
for container in pod.containers.values():
|
||||
if "--anonymous-auth=true" in container.command:
|
||||
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"API Server has anonymous-auth enabled in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_audit_log_maxage_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Audit log max age is set appropriately in the API server in pod {pod.name}."
|
||||
audit_log_maxage_set = False
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_audit_log_maxbackup_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Audit log max backup is set appropriately in the API server in pod {pod.name}."
|
||||
audit_log_maxbackup_set = False
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_audit_log_maxsize_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Audit log max size is set appropriately in the API server in pod {pod.name}."
|
||||
audit_log_maxsize_set = False
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_audit_log_path_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Audit log path is set in the API server in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_auth_mode_include_node(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"API Server authorization mode includes Node in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_auth_mode_include_rbac(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"API Server authorization mode includes RBAC in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_auth_mode_not_always_allow(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Server authorization mode is not set to AlwaysAllow in pod {pod.name}."
|
||||
always_allow_in_auth_mode = True
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_client_ca_file_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Client CA file is set appropriately in the API server in pod {pod.name}."
|
||||
client_ca_file_set = False
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_deny_service_external_ips(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Server has DenyServiceExternalIPs admission controller enabled in pod {pod.name}."
|
||||
deny_service_external_ips = False
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_disable_profiling(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Profiling is disabled in pod {pod.name}."
|
||||
profiling_enabled = False
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_encryption_provider_config_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Encryption provider config is set appropriately in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_etcd_cafile_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"etcd CA file is set appropriately in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_etcd_tls_config(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"TLS configuration for etcd is set appropriately in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_event_rate_limit(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"EventRateLimit admission control plugin is set in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_kubelet_cert_auth(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Server has appropriate kubelet certificate authority configured in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-5
@@ -8,17 +8,15 @@ class apiserver_kubelet_tls_auth(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Server has appropriate kubelet TLS authentication configured in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
if "--kubelet-client-certificate" not in str(
|
||||
container.command
|
||||
) and "--kubelet-client-key" not in str(container.command):
|
||||
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"API Server is missing kubelet TLS authentication arguments in pod {pod.name}."
|
||||
break
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_namespace_lifecycle_plugin(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"NamespaceLifecycle admission control plugin is set in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_no_always_admit_plugin(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"AlwaysAdmit admission control plugin is not set in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_no_token_auth_file(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"API Server does not have token-auth-file enabled in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_node_restriction_plugin(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"NodeRestriction admission control plugin is set in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_request_timeout_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Request timeout is set appropriately in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_security_context_deny_plugin(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
security_context_deny_set = False
|
||||
pod_security_policy_set = False
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_service_account_key_file_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Service account key file is set appropriately in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_service_account_lookup_true(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Service account lookup is set to true in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_service_account_plugin(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"ServiceAccount admission control plugin is set in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -14,10 +14,9 @@ class apiserver_strong_ciphers_only(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Server is configured with strong cryptographic ciphers in pod {pod.name}."
|
||||
strong_ciphers_set = False
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class apiserver_tls_config(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in apiserver_client.apiserver_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"TLS certificate and key are set appropriately in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class controllermanager_bind_address(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in controllermanager_client.controllermanager_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Controller Manager is bound to the loopback address in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class controllermanager_disable_profiling(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in controllermanager_client.controllermanager_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Controller Manager does not have profiling enabled in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class controllermanager_garbage_collection(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in controllermanager_client.controllermanager_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Controller Manager has an appropriate garbage collection threshold in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class controllermanager_root_ca_file_set(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in controllermanager_client.controllermanager_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Controller Manager does not have the root CA file set in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class controllermanager_rotate_kubelet_server_cert(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in controllermanager_client.controllermanager_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Controller Manager has RotateKubeletServerCertificate set to true in pod {pod.name}."
|
||||
kubelete_server_cert = True
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class controllermanager_service_account_credentials(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in controllermanager_client.controllermanager_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Controller Manager is not using service account credentials in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class controllermanager_service_account_private_key_file(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in controllermanager_client.controllermanager_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Controller Manager does not have the service account private key file set in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_admission_hostport_containers(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Pod {pod.name} does not use HostPorts."
|
||||
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_admission_windows_hostprocess_containers(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Pod {pod.name} does not have the ability to run a Windows HostProcess."
|
||||
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_allowPrivilegeEscalation_containers(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Pod {pod.name} does not allow for privilege escalation."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_containers_added_capabilities(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Pod {pod.name} does not have added capabilities."
|
||||
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_containers_capabilities_assigned(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Pod {pod.name} without capabilities issues found."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_hostIPC_containers(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
if pod.host_ipc:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Pod {pod.name} is using hostIPC."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_hostNetwork_containers(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
if pod.host_network:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Pod {pod.name} is using hostNetwork."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_hostPID_containers(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
if pod.host_pid:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Pod {pod.name} is using hostPID."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_net_raw_capability_admission(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Pod {pod.name} does not have NET_RAW capability."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_privileged_containers(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Pod {pod.name} does not contain a privileged container."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_minimize_root_containers_admission(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Pod {pod.name} is not running as root user."
|
||||
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_no_secrets_envs(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Pod {pod.name} does not contain any secret environment variables."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class core_seccomp_profile_docker_default(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in core_client.pods.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
|
||||
pod_seccomp_correct = (
|
||||
pod.security_context
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import socket
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from kubernetes.client.models import V1PodSecurityContext, V1SecurityContext
|
||||
from pydantic import BaseModel
|
||||
|
||||
from kubernetes import client
|
||||
@@ -144,18 +142,16 @@ class Core(KubernetesService):
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Container:
|
||||
class Container(BaseModel):
|
||||
name: str
|
||||
image: str
|
||||
command: Optional[List[str]]
|
||||
ports: Optional[List[dict]]
|
||||
env: Optional[List[dict]]
|
||||
security_context: Optional[V1SecurityContext]
|
||||
security_context: Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class Pod:
|
||||
class Pod(BaseModel):
|
||||
name: str
|
||||
uid: str
|
||||
namespace: str
|
||||
@@ -169,7 +165,7 @@ class Pod:
|
||||
host_pid: Optional[str]
|
||||
host_ipc: Optional[str]
|
||||
host_network: Optional[str]
|
||||
security_context: Optional[V1PodSecurityContext]
|
||||
security_context: Any
|
||||
containers: Optional[dict]
|
||||
|
||||
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class etcd_client_cert_auth(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in etcd_client.etcd_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Etcd has client certificate authentication enabled in pod {pod.name}."
|
||||
|
||||
@@ -6,10 +6,9 @@ class etcd_no_auto_tls(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in etcd_client.etcd_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Etcd is not configured to use self-signed certificates for TLS in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class etcd_no_peer_auto_tls(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in etcd_client.etcd_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Etcd is not using automatically generated self-signed certificates for peer TLS connections in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class etcd_peer_client_cert_auth(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in etcd_client.etcd_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Etcd is configured for peer client certificate authentication in pod {pod.name}."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class etcd_peer_tls_config(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in etcd_client.etcd_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Etcd is configured with TLS for peer connections in pod {pod.name}."
|
||||
|
||||
+3
-5
@@ -6,10 +6,9 @@ class etcd_tls_encryption(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in etcd_client.etcd_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Etcd does not have TLS encryption configured in pod {pod.name}."
|
||||
@@ -18,7 +17,6 @@ class etcd_tls_encryption(Check):
|
||||
if "--cert-file" in str(container.command) and "--key-file" in str(
|
||||
container.command
|
||||
):
|
||||
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Etcd has configured TLS encryption in pod {pod.name}."
|
||||
|
||||
@@ -17,10 +17,9 @@ class etcd_unique_ca(Check):
|
||||
apiserver_ca_files.append(command.split("=")[1])
|
||||
for pod in etcd_client.etcd_pods:
|
||||
etcd_ca_files = []
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Etcd uses a different CA file from the Kubernetes cluster CA in pod {pod.name}, but verify if the content is the same."
|
||||
for container in pod.containers.values():
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_authorization_mode(Check):
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
authorization = cm.kubelet_args.get("authorization")
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if not authorization:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `readOnlyPort` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_client_ca_file_set(Check):
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
authentication = cm.kubelet_args.get("authentication")
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if not authentication:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `readOnlyPort` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_conf_file_ownership(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for node in core_client.nodes.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = node.namespace
|
||||
report.resource_name = node.name
|
||||
report.resource_id = node.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=node
|
||||
)
|
||||
# It can only be checked if Prowler is being executed inside a worker node or if the file is the default one
|
||||
if node.inside:
|
||||
if is_owned_by_root("/etc/kubernetes/kubelet.conf") is None:
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_conf_file_permissions(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for node in core_client.nodes.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = node.namespace
|
||||
report.resource_name = node.name
|
||||
report.resource_id = node.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=node
|
||||
)
|
||||
# It can only be checked if Prowler is being executed inside a worker node or if the file is the default one
|
||||
if node.inside:
|
||||
if not get_file_permissions("/etc/kubernetes/kubelet.conf"):
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_config_yaml_ownership(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for node in core_client.nodes.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = node.namespace
|
||||
report.resource_name = node.name
|
||||
report.resource_id = node.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=node
|
||||
)
|
||||
# It can only be checked if Prowler is being executed inside a worker node or if the file is the default one
|
||||
if node.inside:
|
||||
if is_owned_by_root("/var/lib/kubelet/config.yaml") is None:
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_config_yaml_permissions(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for node in core_client.nodes.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = node.namespace
|
||||
report.resource_name = node.name
|
||||
report.resource_id = node.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=node
|
||||
)
|
||||
# It can only be checked if Prowler is being executed inside a worker node or if the file is the default one
|
||||
if node.inside:
|
||||
if not get_file_permissions("/var/lib/kubelet/config.yaml"):
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_disable_anonymous_auth(Check):
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
authentication = cm.kubelet_args.get("authentication", {})
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Kubelet has anonymous access enabled in config file {cm.name}."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class kubelet_disable_read_only_port(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if "readOnlyPort" not in cm.kubelet_args:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `readOnlyPort` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class kubelet_event_record_qps(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if "eventRecordQPS" not in cm.kubelet_args:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `eventRecordQPS` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class kubelet_manage_iptables(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if "makeIPTablesUtilChains" not in cm.kubelet_args:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `makeIPTablesUtilChains` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class kubelet_rotate_certificates(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if "rotateCertificates" not in cm.kubelet_args:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `streamingConnectionIdleTimeout` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_service_file_ownership_root(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for node in core_client.nodes.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = node.namespace
|
||||
report.resource_name = node.name
|
||||
report.resource_id = node.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=node
|
||||
)
|
||||
# It can only be checked if Prowler is being executed inside a worker node or if the file is the default one
|
||||
if node.inside:
|
||||
if (
|
||||
|
||||
+3
-4
@@ -7,10 +7,9 @@ class kubelet_service_file_permissions(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for node in core_client.nodes.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = node.namespace
|
||||
report.resource_name = node.name
|
||||
report.resource_id = node.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=node
|
||||
)
|
||||
# It can only be checked if Prowler is being executed inside a worker node or if the file is the default one
|
||||
if node.inside:
|
||||
if not get_file_permissions(
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class kubelet_streaming_connection_timeout(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if "streamingConnectionIdleTimeout" not in cm.kubelet_args:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `streamingConnectionIdleTimeout` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -17,10 +17,9 @@ class kubelet_strong_ciphers_only(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if "tlsCipherSuites" not in cm.kubelet_args:
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Kubelet does not have the argument `tlsCipherSuites` in config file {cm.name}, verify it in the node's arguments."
|
||||
|
||||
+3
-4
@@ -6,10 +6,9 @@ class kubelet_tls_cert_and_key(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for cm in kubelet_client.kubelet_config_maps:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = cm.namespace
|
||||
report.resource_name = cm.name
|
||||
report.resource_id = cm.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cm
|
||||
)
|
||||
if (
|
||||
"tlsCertFile" not in cm.kubelet_args
|
||||
or "tlsPrivateKeyFile" not in cm.kubelet_args
|
||||
|
||||
+3
-3
@@ -9,14 +9,14 @@ class rbac_cluster_admin_usage(Check):
|
||||
for binding in rbac_client.cluster_role_bindings.values():
|
||||
# Check if the binding refers to the cluster-admin role
|
||||
if binding.roleRef.name == "cluster-admin":
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=binding.metadata
|
||||
)
|
||||
report.namespace = (
|
||||
"cluster-wide"
|
||||
if not binding.metadata.namespace
|
||||
else binding.metadata.namespace
|
||||
)
|
||||
report.resource_name = binding.metadata.name
|
||||
report.resource_id = binding.metadata.uid
|
||||
report.status = "MANUAL"
|
||||
report.status_extended = f"Cluster Role Binding {binding.metadata.name} uses cluster-admin role."
|
||||
findings.append(report)
|
||||
|
||||
+3
-4
@@ -14,10 +14,9 @@ class rbac_minimize_csr_approval_access(Check):
|
||||
for crb in rbac_client.cluster_role_bindings.values():
|
||||
for subject in crb.subjects:
|
||||
if subject.kind in ["User", "Group"]:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = subject.name
|
||||
report.resource_id = subject.uid if hasattr(subject, "uid") else ""
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=subject
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"User or group '{subject.name}' does not have access to update the CSR approval sub-resource."
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
|
||||
+3
-4
@@ -14,10 +14,9 @@ class rbac_minimize_node_proxy_subresource_access(Check):
|
||||
for crb in rbac_client.cluster_role_bindings.values():
|
||||
for subject in crb.subjects:
|
||||
if subject.kind in ["User", "Group"]:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = subject.name
|
||||
report.resource_id = subject.uid if hasattr(subject, "uid") else ""
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=subject
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"User or group '{subject.name}' does not have access to the node proxy sub-resource."
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
|
||||
+6
-8
@@ -13,10 +13,9 @@ class rbac_minimize_pod_creation_access(Check):
|
||||
findings = []
|
||||
# Check ClusterRoleBindings for pod create access
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = cr.metadata.name
|
||||
report.resource_id = cr.metadata.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cr.metadata
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"ClusterRole {cr.metadata.name} does not have pod create access."
|
||||
@@ -30,10 +29,9 @@ class rbac_minimize_pod_creation_access(Check):
|
||||
|
||||
# Check RoleBindings for pod create access
|
||||
for role in rbac_client.roles.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = role.metadata.namespace
|
||||
report.resource_name = role.metadata.name
|
||||
report.resource_id = role.metadata.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=role.metadata
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Role {role.metadata.name} does not have pod create access."
|
||||
|
||||
+3
-4
@@ -15,10 +15,9 @@ class rbac_minimize_pv_creation_access(Check):
|
||||
for crb in rbac_client.cluster_role_bindings.values():
|
||||
for subject in crb.subjects:
|
||||
if subject.kind in ["User", "Group"]:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = subject.name
|
||||
report.resource_id = subject.uid if hasattr(subject, "uid") else ""
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=subject
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"User or group '{subject.name}' does not have access to create PersistentVolumes."
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
|
||||
+6
-8
@@ -13,10 +13,9 @@ class rbac_minimize_secret_access(Check):
|
||||
findings = []
|
||||
# Check ClusterRoleBindings for seceret access
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = cr.metadata.name
|
||||
report.resource_id = cr.metadata.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cr.metadata
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"ClusterRole {cr.metadata.name} does not have secret access."
|
||||
@@ -30,10 +29,9 @@ class rbac_minimize_secret_access(Check):
|
||||
|
||||
# Check RoleBindings for secret access
|
||||
for role in rbac_client.roles.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = role.metadata.namespace
|
||||
report.resource_name = role.metadata.name
|
||||
report.resource_id = role.metadata.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=role.metadata
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Role {role.metadata.name} does not have secret access."
|
||||
|
||||
+3
-4
@@ -14,10 +14,9 @@ class rbac_minimize_service_account_token_creation(Check):
|
||||
for crb in rbac_client.cluster_role_bindings.values():
|
||||
for subject in crb.subjects:
|
||||
if subject.kind in ["User", "Group"]:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = subject.name
|
||||
report.resource_id = subject.uid if hasattr(subject, "uid") else ""
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=subject
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"User or group '{subject.name}' does not have access to create service account tokens."
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
|
||||
+3
-4
@@ -17,10 +17,9 @@ class rbac_minimize_webhook_config_access(Check):
|
||||
for crb in rbac_client.cluster_role_bindings.values():
|
||||
for subject in crb.subjects:
|
||||
if subject.kind in ["User", "Group"]:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = subject.name
|
||||
report.resource_id = subject.uid if hasattr(subject, "uid") else ""
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=subject
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"User or group '{subject.name}' does not have access to create, update, or delete webhook configurations."
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
|
||||
+6
-8
@@ -7,10 +7,9 @@ class rbac_minimize_wildcard_use_roles(Check):
|
||||
findings = []
|
||||
# Check ClusterRoles for wildcards
|
||||
for cr in rbac_client.cluster_roles.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = "cluster-wide"
|
||||
report.resource_name = cr.metadata.name
|
||||
report.resource_id = cr.metadata.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=cr.metadata
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"ClusterRole {cr.metadata.name} does not use wildcards."
|
||||
@@ -28,10 +27,9 @@ class rbac_minimize_wildcard_use_roles(Check):
|
||||
|
||||
# Check Roles for wildcards
|
||||
for role in rbac_client.roles.values():
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = role.metadata.namespace
|
||||
report.resource_name = role.metadata.name
|
||||
report.resource_id = role.metadata.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=role.metadata
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Role {role.metadata.name} does not use wildcards."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class scheduler_bind_address(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in scheduler_client.scheduler_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Scheduler is bound to the loopback address in pod {pod.name}."
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@ class scheduler_profiling(Check):
|
||||
def execute(self) -> Check_Report_Kubernetes:
|
||||
findings = []
|
||||
for pod in scheduler_client.scheduler_pods:
|
||||
report = Check_Report_Kubernetes(self.metadata())
|
||||
report.namespace = pod.namespace
|
||||
report.resource_name = pod.name
|
||||
report.resource_id = pod.uid
|
||||
report = Check_Report_Kubernetes(
|
||||
metadata=self.metadata(), resource_metadata=pod
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Scheduler has profiling enabled in pod {pod.name}."
|
||||
|
||||
Reference in New Issue
Block a user