From 3e6b76df76084bdbe02bee210b8ddfa652f2238b Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:00:33 +0100 Subject: [PATCH] fix(kubernetes): improve in-cluster execution (#3397) --- job.yaml | 11 +++++ prowler-role.yaml | 11 +++++ prowler-rolebinding.yaml | 12 +++++ .../kubernetes/kubernetes_provider.py | 9 +++- .../kubernetes/kubernetes_provider_new.py | 45 +++++++++++++++---- 5 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 job.yaml create mode 100644 prowler-role.yaml create mode 100644 prowler-rolebinding.yaml diff --git a/job.yaml b/job.yaml new file mode 100644 index 00000000000..528e299e6ac --- /dev/null +++ b/job.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: prowler +spec: + containers: + - name: prowler + image: docker.io/prowler/kubernetes + command: ["prowler"] + args: ["kubernetes"] + imagePullPolicy: Never diff --git a/prowler-role.yaml b/prowler-role.yaml new file mode 100644 index 00000000000..7acb69e0b81 --- /dev/null +++ b/prowler-role.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: prowler-read-cluster +rules: +- apiGroups: [""] + resources: ["pods", "configmaps", "nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["clusterrolebindings", "rolebindings", "clusterroles", "roles"] + verbs: ["get", "list", "watch"] diff --git a/prowler-rolebinding.yaml b/prowler-rolebinding.yaml new file mode 100644 index 00000000000..dde2837c11b --- /dev/null +++ b/prowler-rolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: prowler-read-cluster-default-sa +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prowler-read-cluster +subjects: +- kind: ServiceAccount + name: default + namespace: default diff --git a/prowler/providers/kubernetes/kubernetes_provider.py b/prowler/providers/kubernetes/kubernetes_provider.py index 10400b4585d..0624d1ce488 100644 --- a/prowler/providers/kubernetes/kubernetes_provider.py +++ b/prowler/providers/kubernetes/kubernetes_provider.py @@ -27,10 +27,17 @@ def __set_credentials__(self, kubeconfig_file, context): config.load_kube_config( config_file=os.path.abspath(kubeconfig_file), context=context ) + context = config.list_kube_config_contexts()[0][0] else: # Otherwise try to load in-cluster config config.load_incluster_config() - context = config.list_kube_config_contexts()[0][0] + context = { + "name": "In-Cluster", + "context": { + "cluster": "in-cluster", # Placeholder, as the real cluster name is not available + "user": "service-account-name", # Also a placeholder + }, + } return client.ApiClient(), context except Exception as error: logger.critical( diff --git a/prowler/providers/kubernetes/kubernetes_provider_new.py b/prowler/providers/kubernetes/kubernetes_provider_new.py index 55f43645c76..302a9e54b06 100644 --- a/prowler/providers/kubernetes/kubernetes_provider_new.py +++ b/prowler/providers/kubernetes/kubernetes_provider_new.py @@ -37,10 +37,17 @@ def setup_session(self, kubeconfig_file, context): config.load_kube_config( config_file=os.path.abspath(kubeconfig_file), context=context ) + context = config.list_kube_config_contexts()[0][0] else: # Otherwise try to load in-cluster config config.load_incluster_config() - context = config.list_kube_config_contexts()[0][0] + context = { + "name": "In-Cluster", + "context": { + "cluster": "in-cluster", # Placeholder, as the real cluster name is not available + "user": "service-account-name", # Also a placeholder + }, + } return client.ApiClient(), context except Exception as error: logger.critical( @@ -96,18 +103,38 @@ def get_context_user_roles(self): ) sys.exit(1) - def print_credentials(self): + def get_pod_current_namespace(self): + """Retrieve the current namespace from the pod's mounted service account info.""" + try: + with open( + "/var/run/secrets/kubernetes.io/serviceaccount/namespace", "r" + ) as f: + return f.read().strip() + except Exception as error: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return "default" + def print_credentials(self): # Get the current context - cluster_name = self.context.get("context").get("cluster") - user_name = self.context.get("context").get("user") - namespace = self.context.get("namespace", "default") - roles = self.get_context_user_roles() - roles_str = ", ".join(roles) if roles else "No associated Roles" + if self.context.get("name") == "In-Cluster": + report = f""" +This report is being generated using the Kubernetes configuration below: + +Kubernetes Pod: {Fore.YELLOW}[prowler]{Style.RESET_ALL} Namespace: {Fore.YELLOW}[{self.get_pod_current_namespace()}]{Style.RESET_ALL} +""" + print(report) + else: + cluster_name = self.context.get("context").get("cluster") + user_name = self.context.get("context").get("user") + namespace = self.context.get("namespace", "default") + roles = self.get_context_user_roles() + roles_str = ", ".join(roles) if roles else "No associated Roles" - report = f""" + report = f""" This report is being generated using the Kubernetes configuration below: Kubernetes Cluster: {Fore.YELLOW}[{cluster_name}]{Style.RESET_ALL} User: {Fore.YELLOW}[{user_name}]{Style.RESET_ALL} Namespace: {Fore.YELLOW}[{namespace}]{Style.RESET_ALL} Roles: {Fore.YELLOW}[{roles_str}]{Style.RESET_ALL} """ - print(report) + print(report)