From 756f667163222917ac15b222ebf210d83466034c Mon Sep 17 00:00:00 2001 From: vshivara Date: Tue, 11 Mar 2025 07:56:41 -0400 Subject: [PATCH] Adding the tests for Pod Security Admission. JIRA: CGTS-74433 Change-Id: I2177683f45e46a9b4da45a7dfb1276a10d99afdd Signed-off-by: vshivara --- .../kubectl_get_namespaces_keywords.py | 14 + .../object/kubectl_get_namespaces_output.py | 28 +- .../k8s/pods/kubectl_apply_pods_keywords.py | 33 +- .../secret/kubectl_create_secret_keywords.py | 5 +- .../psa-baseline-pod-allow.yaml | 13 + .../psa-baseline-pod-deny.yaml | 13 + .../psa-privileged-allow-any.yaml | 70 ++++ .../psa-restricted-pod-allow.yaml | 20 ++ .../psa-restricted-pod-deny.yaml | 20 ++ .../nightly_regression/psa_ns.yaml | 37 ++ resources/images/pause.tar | Bin 0 -> 258560 bytes .../security/test_pod_security_admission.py | 317 ++++++++++++++++++ 12 files changed, 550 insertions(+), 20 deletions(-) create mode 100644 resources/cloud_platform/nightly_regression/psa-baseline-pod-allow.yaml create mode 100644 resources/cloud_platform/nightly_regression/psa-baseline-pod-deny.yaml create mode 100644 resources/cloud_platform/nightly_regression/psa-privileged-allow-any.yaml create mode 100644 resources/cloud_platform/nightly_regression/psa-restricted-pod-allow.yaml create mode 100644 resources/cloud_platform/nightly_regression/psa-restricted-pod-deny.yaml create mode 100644 resources/cloud_platform/nightly_regression/psa_ns.yaml create mode 100755 resources/images/pause.tar create mode 100644 testcases/cloud_platform/regression/security/test_pod_security_admission.py diff --git a/keywords/k8s/namespace/kubectl_get_namespaces_keywords.py b/keywords/k8s/namespace/kubectl_get_namespaces_keywords.py index 8aeb161a..db287c15 100644 --- a/keywords/k8s/namespace/kubectl_get_namespaces_keywords.py +++ b/keywords/k8s/namespace/kubectl_get_namespaces_keywords.py @@ -29,3 +29,17 @@ class KubectlGetNamespacesKeywords(BaseKeyword): namespaces_list_output = KubectlGetNamespacesOutput(kubectl_get_namespaces_output) return namespaces_list_output + + def get_namespaces_by_label(self, label) -> KubectlGetNamespacesOutput: + """ + Gets the k8s namespaces available for a given label. + Args: + + Returns: KubectlGetNamespacesOutput + + """ + kubectl_get_namespaces_output = self.ssh_connection.send(export_k8s_config(f"kubectl get ns -l={label}")) + self.validate_success_return_code(self.ssh_connection) + namespaces_list_output = KubectlGetNamespacesOutput(kubectl_get_namespaces_output) + + return namespaces_list_output diff --git a/keywords/k8s/namespace/object/kubectl_get_namespaces_output.py b/keywords/k8s/namespace/object/kubectl_get_namespaces_output.py index f586a074..3763fd23 100644 --- a/keywords/k8s/namespace/object/kubectl_get_namespaces_output.py +++ b/keywords/k8s/namespace/object/kubectl_get_namespaces_output.py @@ -5,32 +5,34 @@ from keywords.k8s.namespace.object.kubectl_namespace_object import KubectlNamesp class KubectlGetNamespacesOutput: + """ + Class for 'kubectl get ns output' keywords + """ def __init__(self, kubectl_get_namespaces_output: str): """ Constructor Args: - kubectl_get_namespaces_output: Raw string output from running a "kubectl get ns" command. + kubectl_get_namespaces_output (str): Raw string output from running a "kubectl get ns" command. """ - self.kubectl_namespaces: [KubectlNamespaceObject] = [] kubectl_get_namespaces_table_parser = KubectlGetNamespacesTableParser(kubectl_get_namespaces_output) output_values_list = kubectl_get_namespaces_table_parser.get_output_values_list() for namespace_dict in output_values_list: - if 'NAME' not in namespace_dict: + if "NAME" not in namespace_dict: raise ValueError(f"There is no NAME associated with the namespace: {namespace_dict}") - namespace = KubectlNamespaceObject(namespace_dict['NAME']) + namespace = KubectlNamespaceObject(namespace_dict["NAME"]) - if 'STATUS' in namespace_dict: - namespace.set_status(namespace_dict['STATUS']) + if "STATUS" in namespace_dict: + namespace.set_status(namespace_dict["STATUS"]) - if 'AGE' in namespace_dict: - namespace.set_age(namespace_dict['AGE']) + if "AGE" in namespace_dict: + namespace.set_age(namespace_dict["AGE"]) self.kubectl_namespaces.append(namespace) @@ -43,13 +45,15 @@ class KubectlGetNamespacesOutput: """ return self.kubectl_namespaces - def is_namespace(self, namespace_name) -> bool: + def is_namespace(self, namespace_name: str) -> bool: """ This function will get the namespace with the name specified from this get_namespace_output. - Args: - namespace_name: The name of the namespace of interest. - Returns: bool + Args: + namespace_name (str): The name of the namespace of interest. + + Returns: + bool: This function return a bool value. """ for ns in self.kubectl_namespaces: diff --git a/keywords/k8s/pods/kubectl_apply_pods_keywords.py b/keywords/k8s/pods/kubectl_apply_pods_keywords.py index a33b33b4..9b037260 100644 --- a/keywords/k8s/pods/kubectl_apply_pods_keywords.py +++ b/keywords/k8s/pods/kubectl_apply_pods_keywords.py @@ -1,28 +1,49 @@ from keywords.base_keyword import BaseKeyword from keywords.k8s.k8s_command_wrapper import export_k8s_config +from starlingx.framework.ssh.ssh_connection import SSHConnection class KubectlApplyPodsKeywords(BaseKeyword): """ Class for Kubectl apply pod keywords + """ - def __init__(self, ssh_connection): + def __init__(self, ssh_connection: SSHConnection): """ Constructor + Args: - ssh_connection: + ssh_connection (SSHConnection): ssh connection + """ self.ssh_connection = ssh_connection - def apply_from_yaml(self, yaml_file: str): + def apply_from_yaml(self, yaml_file: str) -> None: """ Applies a pod yaml config - Args: - yaml_file (): the yaml file - Returns: + Args: + yaml_file (str): the yaml file + + Returns: None """ self.ssh_connection.send(export_k8s_config(f"kubectl apply -f {yaml_file}")) self.validate_success_return_code(self.ssh_connection) + + def fail_apply_from_yaml(self, yaml_file: str) -> None: + """ + Checks if applying a pod yaml config fails + + Args: + yaml_file (str): the yaml file + + Returns: + None: This function does not return a value. + + """ + self.ssh_connection.send(export_k8s_config(f"kubectl apply -f {yaml_file}")) + rc = self.ssh_connection.get_return_code() + if 1 != rc: + raise Exception(f"Expected deployment of {yaml_file} to fail, instead it passed, investigate") diff --git a/keywords/k8s/secret/kubectl_create_secret_keywords.py b/keywords/k8s/secret/kubectl_create_secret_keywords.py index 58b3a8c8..4b81651c 100644 --- a/keywords/k8s/secret/kubectl_create_secret_keywords.py +++ b/keywords/k8s/secret/kubectl_create_secret_keywords.py @@ -16,12 +16,13 @@ class KubectlCreateSecretsKeywords(BaseKeyword): """ self.ssh_connection = ssh_connection - def create_secret_for_registry(self, registry: Registry, secret_name: str): + def create_secret_for_registry(self, registry: Registry, secret_name: str, namespace: str = "default"): """ Create a secret for the registry Args: registry (): the registry secret_name (): the secret name + namespace (): the namespace Returns: @@ -30,7 +31,7 @@ class KubectlCreateSecretsKeywords(BaseKeyword): password = registry.get_password() docker_server = registry.get_registry_url() self.ssh_connection.send( - export_k8s_config(f"kubectl create secret docker-registry {secret_name} --docker-server={docker_server} " f"--docker-username={user_name} --docker-password={password}") + export_k8s_config(f"kubectl create secret -n {namespace} docker-registry {secret_name} --docker-server={docker_server} " f"--docker-username={user_name} --docker-password={password}") ) def create_secret_generic(self, secret_name: str, tls_crt: str, tls_key: str, namespace: str): diff --git a/resources/cloud_platform/nightly_regression/psa-baseline-pod-allow.yaml b/resources/cloud_platform/nightly_regression/psa-baseline-pod-allow.yaml new file mode 100644 index 00000000..ffd35387 --- /dev/null +++ b/resources/cloud_platform/nightly_regression/psa-baseline-pod-allow.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: baseline-pod-allow + namespace: baseline-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + privileged: false + imagePullSecrets: + - name: local-secret \ No newline at end of file diff --git a/resources/cloud_platform/nightly_regression/psa-baseline-pod-deny.yaml b/resources/cloud_platform/nightly_regression/psa-baseline-pod-deny.yaml new file mode 100644 index 00000000..bca8dd2e --- /dev/null +++ b/resources/cloud_platform/nightly_regression/psa-baseline-pod-deny.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: baseline-pod-deny + namespace: baseline-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + privileged: true + imagePullSecrets: + - name: local-secret \ No newline at end of file diff --git a/resources/cloud_platform/nightly_regression/psa-privileged-allow-any.yaml b/resources/cloud_platform/nightly_regression/psa-privileged-allow-any.yaml new file mode 100644 index 00000000..c9bf42ab --- /dev/null +++ b/resources/cloud_platform/nightly_regression/psa-privileged-allow-any.yaml @@ -0,0 +1,70 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: privileged-1 + namespace: privileged-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + privileged: false + imagePullSecrets: + - name: local-secret +--- +apiVersion: v1 +kind: Pod +metadata: + name: privileged-2 + namespace: privileged-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + privileged: true + imagePullSecrets: + - name: local-secret +--- +apiVersion: v1 +kind: Pod +metadata: + name: privileged-3 + namespace: privileged-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + imagePullSecrets: + - name: local-secret +--- +apiVersion: v1 +kind: Pod +metadata: + name: privileged-4 + namespace: privileged-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + runAsNonRoot: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + imagePullSecrets: + - name: local-secret \ No newline at end of file diff --git a/resources/cloud_platform/nightly_regression/psa-restricted-pod-allow.yaml b/resources/cloud_platform/nightly_regression/psa-restricted-pod-allow.yaml new file mode 100644 index 00000000..8281a921 --- /dev/null +++ b/resources/cloud_platform/nightly_regression/psa-restricted-pod-allow.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: restricted-pod-allow + namespace: restricted-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + imagePullSecrets: + - name: local-secret \ No newline at end of file diff --git a/resources/cloud_platform/nightly_regression/psa-restricted-pod-deny.yaml b/resources/cloud_platform/nightly_regression/psa-restricted-pod-deny.yaml new file mode 100644 index 00000000..034059f9 --- /dev/null +++ b/resources/cloud_platform/nightly_regression/psa-restricted-pod-deny.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: restricted-pod-deny + namespace: restricted-ns +spec: + containers: + - name: pause + image: registry.local:9001/pause + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + runAsNonRoot: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + imagePullSecrets: + - name: local-secret \ No newline at end of file diff --git a/resources/cloud_platform/nightly_regression/psa_ns.yaml b/resources/cloud_platform/nightly_regression/psa_ns.yaml new file mode 100644 index 00000000..ac593fb8 --- /dev/null +++ b/resources/cloud_platform/nightly_regression/psa_ns.yaml @@ -0,0 +1,37 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: baseline-ns + labels: + pod-security.kubernetes.io/enforce: baseline + pod-security.kubernetes.io/enforce-version: latest + pod-security.kubernetes.io/warn: baseline + pod-security.kubernetes.io/warn-version: latest + pod-security.kubernetes.io/audit: baseline + pod-security.kubernetes.io/audit-version: latest +--- +apiVersion: v1 +kind: Namespace +metadata: + name: privileged-ns + labels: + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/enforce-version: latest + pod-security.kubernetes.io/warn: privileged + pod-security.kubernetes.io/warn-version: latest + pod-security.kubernetes.io/audit: privileged + pod-security.kubernetes.io/audit-version: latest +--- +apiVersion: v1 +kind: Namespace +metadata: + name: restricted-ns + labels: + pod-security.kubernetes.io/enforce: restricted + pod-security.kubernetes.io/enforce-version: latest + pod-security.kubernetes.io/warn: restricted + pod-security.kubernetes.io/warn-version: latest + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/audit-version: latest +--- diff --git a/resources/images/pause.tar b/resources/images/pause.tar new file mode 100755 index 0000000000000000000000000000000000000000..5b468bd758f0d97bd275b93538b281767136e120 GIT binary patch literal 258560 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 z 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 K1Oxv+G4Q`jc|(){ literal 0 HcmV?d00001 diff --git a/testcases/cloud_platform/regression/security/test_pod_security_admission.py b/testcases/cloud_platform/regression/security/test_pod_security_admission.py new file mode 100644 index 00000000..0d25e2d7 --- /dev/null +++ b/testcases/cloud_platform/regression/security/test_pod_security_admission.py @@ -0,0 +1,317 @@ +from pytest import FixtureRequest, mark + +from starlingx.config.configuration_file_locations_manager import ConfigurationFileLocationsManager +from starlingx.config.configuration_manager import ConfigurationManager +from starlingx.framework.logging.automation_logger import get_logger +from starlingx.framework.resources.resource_finder import get_stx_resource_path +from starlingx.framework.ssh.ssh_connection import SSHConnection +from starlingx.framework.validation.validation import validate_equals +from starlingx.keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords +from starlingx.keywords.docker.images.docker_load_image_keywords import DockerLoadImageKeywords +from starlingx.keywords.files.file_keywords import FileKeywords +from starlingx.keywords.k8s.files.kubectl_file_delete_keywords import KubectlFileDeleteKeywords +from starlingx.keywords.k8s.namespace.kubectl_get_namespaces_keywords import KubectlGetNamespacesKeywords +from starlingx.keywords.k8s.pods.kubectl_apply_pods_keywords import KubectlApplyPodsKeywords +from starlingx.keywords.k8s.pods.kubectl_get_pods_keywords import KubectlGetPodsKeywords +from starlingx.keywords.k8s.secret.kubectl_create_secret_keywords import KubectlCreateSecretsKeywords + + +@mark.p0 +def test_policy_labels_on_platform_namespaces(): + """ + Verify that cert-manager, armada, kube-system, deployment namespaces contains the + privileged policy labels + Steps: + - Get the platform namespaces with the privileged policy labels + - Assert the expected namespace is ["cert-manager", "kube-system", + "deployment", "flux-helm"] + """ + + label = "pod-security.kubernetes.io/audit=privileged,pod-security.kubernetes.io/audit-version=latest," "pod-security.kubernetes.io/enforce=privileged,pod-security.kubernetes.io/enforce-version=latest," "pod-security.kubernetes.io/warn=privileged,pod-security.kubernetes.io/warn-version=latest " + active_ssh = LabConnectionKeywords().get_active_controller_ssh() + + get_logger().log_info("Get the privileged namespace list based on release") + expected_ns = ["cert-manager", "deployment", "flux-helm", "kube-system"] + get_logger().log_info("Get the platform namespaces with labels") + actual_ns = KubectlGetNamespacesKeywords(active_ssh).get_namespaces_by_label(label=label).get_namespaces() + actual_ns_names = [ns.get_name() for ns in actual_ns] + validate_equals(actual_ns_names, expected_ns, "Verifying that the retrieved namespaces match the expected values.") + + +def deploy_policy_ns(request: FixtureRequest, ssh_connection: SSHConnection) -> None: + """ + Function to deploy the privileged-ns, baseline-ns and restricted-ns namespaces + in setup and delete the namespaces in teardown + + Args: + request (FixtureRequest): request needed for adding teardown + ssh_connection (SSHConnection): the ssh connection + Returns: + None: This function does not return a value. + """ + + # Transfer the pod yaml file to the active controller + # Defines pod definition file name, source (local) and destination (remote) file paths. + psa_file_name = "psa_ns.yaml" + + config_file_locations = ConfigurationFileLocationsManager() + ConfigurationManager.load_configs(config_file_locations) + local_path = get_stx_resource_path(f"resources/cloud_platform/nightly_regression/{psa_file_name}") + remote_path = f"/home/{ConfigurationManager.get_lab_config().get_admin_credentials().get_user_name()}/{psa_file_name}" + file_keywords = FileKeywords(ssh_connection) + file_keywords.upload_file(get_stx_resource_path(local_path), remote_path, overwrite=False) + + get_logger().log_info(f"Creating resource from file {remote_path}") + kubectl_apply_pods_keywords = KubectlApplyPodsKeywords(ssh_connection) + kubectl_apply_pods_keywords.apply_from_yaml(yaml_file=remote_path) + + def teardown(): + KubectlFileDeleteKeywords(ssh_connection).delete_resources(remote_path) + + request.addfinalizer(teardown) + + +def deploy_docker_image_to_local_registry(ssh_connection: SSHConnection, secret_namespace: str) -> None: + """ + Deploy images to the local registry + Args: + ssh_connection (SSHConnection): the ssh connection + secret_namespace (str): the namespace + Returns: + None: This function does not return a value. + + """ + local_registry = ConfigurationManager.get_docker_config().get_registry("local_registry") + + get_logger().log_info(f"Deploy docker images to local registry to {local_registry}") + FileKeywords(ssh_connection).upload_file(get_stx_resource_path("resources/images/pause.tar"), "/home/sysadmin/pause.tar") + KubectlCreateSecretsKeywords(ssh_connection).create_secret_for_registry(local_registry, "local-secret", secret_namespace) + docker_load_image_keywords = DockerLoadImageKeywords(ssh_connection) + docker_load_image_keywords.load_docker_image_to_host("pause.tar") + docker_load_image_keywords.tag_docker_image_for_registry("k8s.gcr.io/pause:latest", "pause", local_registry) + docker_load_image_keywords.push_docker_image_to_registry("pause", local_registry) + + +@mark.p1 +def test_deny_pod_in_baseline_ns(request: FixtureRequest): + """ + Test to verify that baseline-ns rejects the pod with "privileged: true" + + Args: + request (FixtureRequest): request needed for adding teardown + Steps: + - Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + - Upload the psa pod yaml to the lab + - Deploy images to the local registry for this testcase + - Deploy the pod with "privileged: true" and expect it to reject + """ + ssh_connection = LabConnectionKeywords().get_active_controller_ssh() + psa_baseline_pod_deny_file_name = "psa-baseline-pod-deny.yaml" + namespace = "baseline-ns" + + # Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + deploy_policy_ns(request, ssh_connection) + + # Upload the psa pod yaml to the lab + local_path = get_stx_resource_path(f"resources/cloud_platform/nightly_regression/{psa_baseline_pod_deny_file_name}") + config_file_locations = ConfigurationFileLocationsManager() + ConfigurationManager.load_configs(config_file_locations) + remote_path = f"/home/{ConfigurationManager.get_lab_config().get_admin_credentials().get_user_name()}/{psa_baseline_pod_deny_file_name}" + + get_logger().log_info(f"Upload yaml on local {local_path} to {remote_path} on active controller") + file_keywords = FileKeywords(ssh_connection) + file_keywords.upload_file(get_stx_resource_path(local_path), remote_path, overwrite=True) + + # Deploy images to the local registry for this testcase + deploy_docker_image_to_local_registry(ssh_connection, namespace) + + # Deploy the pod with "privileged: true" and expect it to reject + get_logger().log_info(f"Deploy {remote_path} with 'privileged: true' on active controller and expect it to reject") + kubectl_apply_pods_keywords = KubectlApplyPodsKeywords(ssh_connection) + kubectl_apply_pods_keywords.fail_apply_from_yaml(remote_path) + + +@mark.p1 +def test_allow_pod_in_baseline_ns(request: FixtureRequest): + """ + Test to verify that baseline-ns accepts the pod with "privileged: false" + Args: + request (FixtureRequest): request needed for adding teardown + Steps: + - Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + - Upload the psa pod yaml to the lab + - Deploy images to the local registry for this testcase + - Deploy the pod with "privileged: false" and expect it to accept + Raises: + AssertionError: If the pod does not reach 'running' status within the + specified timeout, an AssertionError will be raised + with a descriptive error message. + """ + ssh_connection = LabConnectionKeywords().get_active_controller_ssh() + psa_baseline_pod_deny_file_name = "psa-baseline-pod-allow.yaml" + namespace = "baseline-ns" + + # Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + deploy_policy_ns(request, ssh_connection) + + # Upload the psa pod yaml to the lab + local_path = get_stx_resource_path(f"resources/cloud_platform/nightly_regression/{psa_baseline_pod_deny_file_name}") + config_file_locations = ConfigurationFileLocationsManager() + ConfigurationManager.load_configs(config_file_locations) + remote_path = f"/home/{ConfigurationManager.get_lab_config().get_admin_credentials().get_user_name()}/{psa_baseline_pod_deny_file_name}" + + get_logger().log_info(f"Upload yaml on local {local_path} to {remote_path} on active controller") + + file_keywords = FileKeywords(ssh_connection) + file_keywords.upload_file(get_stx_resource_path(local_path), remote_path, overwrite=True) + + # Deploy images to the local registry for this testcase + deploy_docker_image_to_local_registry(ssh_connection, namespace) + + # Deploy the pod with "privileged: false" and expect it to accept + get_logger().log_info(f"Deploy {remote_path} with 'privileged: false' on active controller and expect it to accept") + kubectl_apply_pods_keywords = KubectlApplyPodsKeywords(ssh_connection) + kubectl_apply_pods_keywords.apply_from_yaml(remote_path) + + get_pod_obj = KubectlGetPodsKeywords(ssh_connection) + pod_obj = get_pod_obj.get_pods(namespace).get_pods() + pod_name = [pod.get_name() for pod in pod_obj][0] + pod_status = get_pod_obj.wait_for_pod_status(pod_name, "Running", namespace) + validate_equals(pod_status, True, "Veryfing that the baseline-ns namespace accepts the pod with the 'privileged: false' configuration.") + + +@mark.p1 +def test_deny_pod_in_restricted_ns(request: FixtureRequest): + """ + Test to verify that restricted-ns rejects the pod with restricted values + Args: + request (FixtureRequest): request needed for adding teardown + + Steps: + - Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + - Upload the psa pod yaml to the lab + - Deploy images to the local registry for this testcase + - Deploy the pod with restricted values and expect it to reject in restricted-ns + """ + ssh_connection = LabConnectionKeywords().get_active_controller_ssh() + psa_restricted_pod_deny_file_name = "psa-restricted-pod-deny.yaml" + namespace = "restricted-ns" + + # Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + deploy_policy_ns(request, ssh_connection) + + # Upload the psa pod yaml to the lab + local_path = get_stx_resource_path(f"resources/cloud_platform/nightly_regression/{psa_restricted_pod_deny_file_name}") + config_file_locations = ConfigurationFileLocationsManager() + ConfigurationManager.load_configs(config_file_locations) + remote_path = f"/home/{ConfigurationManager.get_lab_config().get_admin_credentials().get_user_name()}/{psa_restricted_pod_deny_file_name}" + + get_logger().log_info(f"Upload yaml on local {local_path} to {remote_path} on active controller") + file_keywords = FileKeywords(ssh_connection) + file_keywords.upload_file(get_stx_resource_path(local_path), remote_path, overwrite=True) + + # Deploy images to the local registry for this testcase + deploy_docker_image_to_local_registry(ssh_connection, namespace) + + # Deploy the pod with restricted values and expect it to reject in restricted-ns + get_logger().log_info(f"Deploy {remote_path} with restricted values and expect it to reject in restricted-ns") + kubectl_apply_pods_keywords = KubectlApplyPodsKeywords(ssh_connection) + kubectl_apply_pods_keywords.fail_apply_from_yaml(remote_path) + + +@mark.p1 +def test_allow_pod_in_restricted_ns(request: FixtureRequest): + """ + Test to verify that restricted-ns accepts the pod + Args: + request (FixtureRequest): request needed for adding teardown + Steps: + - Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + - Upload the psa pod yaml to the lab + - Deploy images to the local registry for this testcase + - Deploy the pod and expect it to accept in restricted-ns + Raises: + AssertionError: If the pod does not reach 'running' status within the + specified timeout, an AssertionError will be raised + with a descriptive error message. + """ + ssh_connection = LabConnectionKeywords().get_active_controller_ssh() + psa_restricted_pod_allow_file_name = "psa-restricted-pod-allow.yaml" + namespace = "restricted-ns" + + # Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + deploy_policy_ns(request, ssh_connection) + + # Upload the psa pod yaml to the lab + local_path = get_stx_resource_path(f"resources/cloud_platform/nightly_regression/{psa_restricted_pod_allow_file_name}") + config_file_locations = ConfigurationFileLocationsManager() + ConfigurationManager.load_configs(config_file_locations) + remote_path = f"/home/{ConfigurationManager.get_lab_config().get_admin_credentials().get_user_name()}/{psa_restricted_pod_allow_file_name}" + + get_logger().log_info(f"Upload yaml on local {local_path} to {remote_path} on active controller") + + file_keywords = FileKeywords(ssh_connection) + file_keywords.upload_file(get_stx_resource_path(local_path), remote_path, overwrite=True) + + # Deploy images to the local registry for this testcase + deploy_docker_image_to_local_registry(ssh_connection, namespace) + + # Deploy the pod and expect it to accept in restricted-ns + get_logger().log_info(f"Deploy {remote_path} in restricted-ns on active controller and expect it to accept") + kubectl_apply_pods_keywords = KubectlApplyPodsKeywords(ssh_connection) + kubectl_apply_pods_keywords.apply_from_yaml(remote_path) + + get_pod_obj = KubectlGetPodsKeywords(ssh_connection) + pod_obj = get_pod_obj.get_pods(namespace).get_pods() + pod_name = [pod.get_name() for pod in pod_obj][0] + pod_status = get_pod_obj.wait_for_pod_status(pod_name, "Running", namespace) + validate_equals(pod_status, True, "Veryfing that the restricted-ns namespace accepts the pod.") + + +@mark.p1 +def test_allow_any_in_privileged_ns(request: FixtureRequest): + """ + Test to verify that privileged-ns accepts any pod + Args: + request (FixtureRequest): request needed for adding teardown + Steps: + - Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + - Upload the psa pod yaml to the lab + - Deploy images to the local registry for this testcase + - Deploy the pods in privileged-ns and expect it to accept + Raises: + AssertionError: If the pod does not reach 'running' status within the + specified timeout, an AssertionError will be raised + with a descriptive error message. + """ + ssh_connection = LabConnectionKeywords().get_active_controller_ssh() + psa_privileged_pod_allow_file_name = "psa-privileged-allow-any.yaml" + namespace = "privileged-ns" + + # Deploy the privileged-ns, baseline-ns and restricted-ns namespaces + deploy_policy_ns(request, ssh_connection) + + # Upload the psa pod yaml to the lab + local_path = get_stx_resource_path(f"resources/cloud_platform/nightly_regression/{psa_privileged_pod_allow_file_name}") + config_file_locations = ConfigurationFileLocationsManager() + ConfigurationManager.load_configs(config_file_locations) + remote_path = f"/home/{ConfigurationManager.get_lab_config().get_admin_credentials().get_user_name()}/{psa_privileged_pod_allow_file_name}" + + get_logger().log_info(f"Upload yaml on local {local_path} to {remote_path} on active controller") + + file_keywords = FileKeywords(ssh_connection) + file_keywords.upload_file(get_stx_resource_path(local_path), remote_path, overwrite=True) + + # Deploy images to the local registry for this testcase + deploy_docker_image_to_local_registry(ssh_connection, namespace) + + # Deploy the pods in privileged-ns and expect it to accept + get_logger().log_info(f"Deploy {remote_path} in privileged-ns on active controller and expect it to accept") + kubectl_apply_pods_keywords = KubectlApplyPodsKeywords(ssh_connection) + kubectl_apply_pods_keywords.apply_from_yaml(remote_path) + + get_pod_obj = KubectlGetPodsKeywords(ssh_connection) + pod_obj = get_pod_obj.get_pods(namespace).get_pods() + pod_name = [pod.get_name() for pod in pod_obj][0] + pod_status = get_pod_obj.wait_for_pod_status(pod_name, "Running", namespace) + validate_equals(pod_status, True, "Veryfing that the privileged-ns namespace accepts the pod.")