mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
feat(kubernetes): allow setting cluster name in in-cluster mode (#7695)
This commit is contained in:
@@ -20,3 +20,19 @@ kubectl logs prowler-XXXXX --namespace prowler-ns
|
||||
|
||||
???+ note
|
||||
By default, `prowler` will scan all namespaces in your active Kubernetes context. Use the [`--namespace`](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/kubernetes/namespace/) flag to specify the namespace(s) to be scanned.
|
||||
|
||||
???+ tip "Identifying the cluster in reports"
|
||||
When running in in-cluster mode, the Kubernetes API does not expose the actual cluster name by default.
|
||||
|
||||
To uniquely identify the cluster in logs and reports, you can:
|
||||
|
||||
- Use the `--cluster-name` flag to manually set the cluster name:
|
||||
```bash
|
||||
prowler -p kubernetes --cluster-name production-cluster
|
||||
```
|
||||
- Or set the `CLUSTER_NAME` environment variable:
|
||||
```yaml
|
||||
env:
|
||||
- name: CLUSTER_NAME
|
||||
value: production-cluster
|
||||
```
|
||||
|
||||
@@ -207,6 +207,7 @@ class Provider(ABC):
|
||||
kubeconfig_file=arguments.kubeconfig_file,
|
||||
context=arguments.context,
|
||||
namespace=arguments.namespace,
|
||||
cluster_name=arguments.cluster_name,
|
||||
config_path=arguments.config_file,
|
||||
mutelist_path=arguments.mutelist_file,
|
||||
fixer_config=fixer_config,
|
||||
|
||||
@@ -70,6 +70,7 @@ class KubernetesProvider(Provider):
|
||||
kubeconfig_file: str = None,
|
||||
context: str = None,
|
||||
namespace: list = None,
|
||||
cluster_name: str = None,
|
||||
config_path: str = None,
|
||||
config_content: dict = {},
|
||||
fixer_config: dict = {},
|
||||
@@ -84,6 +85,7 @@ class KubernetesProvider(Provider):
|
||||
kubeconfig_file (str): Path to the kubeconfig file.
|
||||
kubeconfig_content (str or dict): Content of the kubeconfig file.
|
||||
context (str): Context name.
|
||||
cluster_name (str): Cluster name.
|
||||
namespace (list): List of namespaces.
|
||||
config_content (dict): Audit configuration.
|
||||
config_path (str): Path to the configuration file.
|
||||
@@ -147,7 +149,9 @@ class KubernetesProvider(Provider):
|
||||
"""
|
||||
|
||||
logger.info("Instantiating Kubernetes Provider ...")
|
||||
self._session = self.setup_session(kubeconfig_file, kubeconfig_content, context)
|
||||
self._session = self.setup_session(
|
||||
kubeconfig_file, kubeconfig_content, context, cluster_name
|
||||
)
|
||||
if not namespace:
|
||||
logger.info("Retrieving all namespaces ...")
|
||||
self._namespaces = self.get_all_namespaces()
|
||||
@@ -227,6 +231,7 @@ class KubernetesProvider(Provider):
|
||||
kubeconfig_file: str = None,
|
||||
kubeconfig_content: Union[dict, str] = None,
|
||||
context: str = None,
|
||||
cluster_name: str = None,
|
||||
) -> KubernetesSession:
|
||||
"""
|
||||
Sets up the Kubernetes session.
|
||||
@@ -235,7 +240,7 @@ class KubernetesProvider(Provider):
|
||||
kubeconfig_file (str): Path to the kubeconfig file.
|
||||
kubeconfig_content (str or dict): Content of the kubeconfig file.
|
||||
context (str): Context name.
|
||||
|
||||
cluster_name (str): Cluster name.
|
||||
Returns:
|
||||
Tuple: A tuple containing the API client and the context.
|
||||
|
||||
@@ -270,11 +275,15 @@ class KubernetesProvider(Provider):
|
||||
# If the kubeconfig file is not found, try to use the in-cluster config
|
||||
logger.info("Using in-cluster config")
|
||||
config.load_incluster_config()
|
||||
# Use CLI flag or env var to set cluster name
|
||||
resolved_cluster_name = cluster_name or os.getenv(
|
||||
"CLUSTER_NAME", "in-cluster"
|
||||
)
|
||||
context = {
|
||||
"name": "In-Cluster",
|
||||
"context": {
|
||||
"cluster": "in-cluster", # Placeholder, as the real cluster name is not available
|
||||
"user": "service-account-name", # Also a placeholder
|
||||
"cluster": resolved_cluster_name,
|
||||
"user": "service-account-name",
|
||||
},
|
||||
}
|
||||
return KubernetesSession(
|
||||
|
||||
@@ -27,3 +27,9 @@ def init_parser(self):
|
||||
metavar="NAMESPACES",
|
||||
help="The namespaces where to scan for the Kubernetes resources. By default, Prowler will scan all namespaces available.",
|
||||
)
|
||||
k8s_auth_subparser.add_argument(
|
||||
"--cluster-name",
|
||||
nargs="?",
|
||||
metavar="CLUSTER_NAME",
|
||||
help="Manually specify the cluster name in in-cluster mode, by default it will be 'in-cluster'",
|
||||
)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from argparse import Namespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from kubernetes.config.config_exception import ConfigException
|
||||
|
||||
from kubernetes import client
|
||||
from prowler.config.config import (
|
||||
default_config_file_path,
|
||||
@@ -305,3 +307,49 @@ class TestKubernetesProvider:
|
||||
|
||||
assert connection.is_connected
|
||||
assert connection.error is None
|
||||
|
||||
def test_kubernetes_provider_incluster_with_env_var(self, monkeypatch):
|
||||
monkeypatch.setenv("CLUSTER_NAME", "env-cluster-name")
|
||||
|
||||
with (
|
||||
patch(
|
||||
"kubernetes.config.load_kube_config",
|
||||
side_effect=ConfigException("No kubeconfig"),
|
||||
),
|
||||
patch("kubernetes.config.load_incluster_config", return_value=None),
|
||||
patch("prowler.providers.kubernetes.kubernetes_provider.client.ApiClient"),
|
||||
patch(
|
||||
"prowler.providers.kubernetes.kubernetes_provider.KubernetesProvider.get_all_namespaces",
|
||||
return_value=["default"],
|
||||
),
|
||||
):
|
||||
session = KubernetesProvider.setup_session(
|
||||
kubeconfig_file=None,
|
||||
kubeconfig_content=None,
|
||||
context=None,
|
||||
cluster_name=None,
|
||||
)
|
||||
assert isinstance(session, KubernetesSession)
|
||||
assert session.context["context"]["cluster"] == "env-cluster-name"
|
||||
|
||||
def test_kubernetes_provider_incluster_with_cli_flag(self):
|
||||
with (
|
||||
patch(
|
||||
"kubernetes.config.load_kube_config",
|
||||
side_effect=ConfigException("No kubeconfig"),
|
||||
),
|
||||
patch("kubernetes.config.load_incluster_config", return_value=None),
|
||||
patch("prowler.providers.kubernetes.kubernetes_provider.client.ApiClient"),
|
||||
patch(
|
||||
"prowler.providers.kubernetes.kubernetes_provider.KubernetesProvider.get_all_namespaces",
|
||||
return_value=["default"],
|
||||
),
|
||||
):
|
||||
session = KubernetesProvider.setup_session(
|
||||
kubeconfig_file=None,
|
||||
kubeconfig_content=None,
|
||||
context=None,
|
||||
cluster_name="cli-cluster-name",
|
||||
)
|
||||
assert isinstance(session, KubernetesSession)
|
||||
assert session.context["context"]["cluster"] == "cli-cluster-name"
|
||||
|
||||
Reference in New Issue
Block a user