Skip to content

Commit

Permalink
tests: try and get pipeline green again (#2259)
Browse files Browse the repository at this point in the history
* Test changes

* Try using flaky

* Mark vsr external route events as xfail; use single syslog pod for AP sec log tests.
  • Loading branch information
ciarams87 authored Dec 16, 2021
1 parent 69ad025 commit c4a38b1
Show file tree
Hide file tree
Showing 16 changed files with 125 additions and 50 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,12 @@ jobs:
{\"image\": \"opentracing\", \"marker\": \"vs\"}, \
{\"image\": \"ubi\", \"marker\": \"ts\"}, \
{\"image\": \"debian-plus\", \"marker\": \"vs\"}, \
{\"image\": \"debian-plus\", \"marker\": \"ts\"}, \
{\"image\": \"alpine-plus\", \"marker\":\"ingresses\"}, \
{\"image\": \"opentracing-plus\", \"marker\": \"vsr\"}, \
{\"image\": \"ubi-plus\", \"marker\": \"policies\"}]}"
else
echo "::set-output name=matrix::{\"k8s\": [\"1.19.11\", \"1.20.7\", \"1.21.2\", \"1.22.4\", \"1.23.0\"], \
\"images\": [{\"image\": \"debian\"}, {\"image\": \"debian-plus\"}]}"
echo "::set-output name=matrix::{\"k8s\": [\"1.19.11\", \"1.20.7\", \"1.21.2\", \"1.22.4\", \"1.23.0\"]}"
fi
smoke-tests:
Expand Down
5 changes: 5 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ def pytest_collection_modifyitems(config, items) -> None:
for item in items:
if "skip_for_nginx_plus" in item.keywords:
item.add_marker(skip_for_nginx_plus)
if config.getoption("--service") == "loadbalancer":
skip_for_loadbalancer = pytest.mark.skip(reason="Skip a test for loadbalancer service")
for item in items:
if "skip_for_loadbalancer" in item.keywords:
item.add_marker(skip_for_loadbalancer)
if "-ap" not in config.getoption("--image"):
appprotect = pytest.mark.skip(reason="Skip AppProtect test in non-AP image")
for item in items:
Expand Down
2 changes: 1 addition & 1 deletion tests/data/rate-limit/policies/rate-limit-secondary.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ metadata:
name: rate-limit-secondary
spec:
rateLimit:
rate: 10r/s
rate: 5r/s
key: ${binary_remote_addr}
zoneSize: 10M
6 changes: 5 additions & 1 deletion tests/docker/gitlab.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
FROM python:3.9

ARG GCLOUD_VERSION=364.0.0
ARG HELM_VERSION=3.5.4

RUN apt-get update && apt-get install -y curl git jq \
&& curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl \
&& chmod +x ./kubectl \
&& mv ./kubectl /usr/local/bin \
&& curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${GCLOUD_VERSION}-linux-x86_64.tar.gz \
&& tar xvzf google-cloud-sdk-${GCLOUD_VERSION}-linux-x86_64.tar.gz \
&& mv google-cloud-sdk /usr/lib/
&& mv google-cloud-sdk /usr/lib/ \
&& curl -LO https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz \
&& tar -zxvf helm-v${HELM_VERSION}-linux-amd64.tar.gz \
&& mv linux-amd64/helm /usr/local/bin/helm

WORKDIR /workspace/tests

Expand Down
1 change: 1 addition & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ more-itertools==8.12.0
mock==4.0.3
grpcio==1.42.0
grpcio-tools==1.42.0
flaky==3.7.0
35 changes: 35 additions & 0 deletions tests/suite/resources_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,19 @@ def get_pods_amount(v1: CoreV1Api, namespace) -> int:
pods = v1.list_namespaced_pod(namespace)
return 0 if not pods.items else len(pods.items)

def get_pod_name_that_contains(v1: CoreV1Api, namespace, contains_string) -> str:
"""
Get an amount of pods.
:param v1: CoreV1Api
:param namespace: namespace
:param contains_string: string to search on
:return: string
"""
for item in v1.list_namespaced_pod(namespace).items:
if contains_string in item.metadata.name:
return item.metadata.name
return ""

def create_service_from_yaml(v1: CoreV1Api, namespace, yaml_manifest) -> str:
"""
Expand Down Expand Up @@ -808,6 +821,28 @@ def get_file_contents(v1: CoreV1Api, file_path, pod_name, pod_namespace) -> str:
return result_conf


def clear_file_contents(v1: CoreV1Api, file_path, pod_name, pod_namespace):
"""
Execute 'cat /dev/null > file_path' command in a pod.
:param v1: CoreV1Api
:param pod_name: pod name
:param pod_namespace: pod namespace
:param file_path: an absolute path to a file in the pod
"""
command = ["cat /dev/null > ", file_path]
resp = stream(
v1.connect_get_namespaced_pod_exec,
pod_name,
pod_namespace,
command=command,
stderr=True,
stdin=False,
stdout=True,
tty=False,
)


def get_ingress_nginx_template_conf(
v1: CoreV1Api, ingress_namespace, ingress_name, pod_name, pod_namespace
) -> str:
Expand Down
25 changes: 21 additions & 4 deletions tests/suite/test_app_protect_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ def fin():

@pytest.mark.skip_for_nginx_oss
@pytest.mark.appprotect
@pytest.mark.flaky(max_runs=3)
@pytest.mark.parametrize(
"crd_ingress_controller_with_ap",
[{"extra_args": [f"-enable-custom-resources", f"-enable-app-protect"]}],
Expand Down Expand Up @@ -161,8 +162,16 @@ def test_responses_grpc_block(
# grpc.RpcError is also grpc.Call https://grpc.github.io/grpc/python/grpc.html#client-side-context
ex = e.details()
print(ex)

log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace)

log_contents = ""
retry = 0
while "ASM:attack_type" not in log_contents and retry <= 30:
log_contents = get_file_contents(
kube_apis.v1, log_loc, syslog_pod, test_namespace)
retry += 1
wait_before_test(1)
print(f"Security log not updated, retrying... #{retry}")

assert (
invalid_resp_text in ex and
'ASM:attack_type="Directory Indexing"' in log_contents and
Expand Down Expand Up @@ -195,8 +204,16 @@ def test_responses_grpc_allow(
except grpc.RpcError as e:
print(e.details())
pytest.fail("RPC error was not expected during call, exiting...")

log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace)

log_contents = ""
retry = 0
while "ASM:attack_type" not in log_contents and retry <= 30:
log_contents = get_file_contents(
kube_apis.v1, log_loc, syslog_pod, test_namespace)
retry += 1
wait_before_test(1)
print(f"Security log not updated, retrying... #{retry}")

assert (
valid_resp_txt in response.message and
'ASM:attack_type="N/A"' in log_contents and
Expand Down
45 changes: 19 additions & 26 deletions tests/suite/test_app_protect_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
get_file_contents, get_first_pod_name,
get_ingress_nginx_template_conf,
get_last_reload_time, get_pods_amount,
get_service_endpoint, get_test_file_name,
clear_file_contents, get_test_file_name,
scale_deployment, wait_before_test,
wait_until_all_pods_are_ready,
write_to_json)
write_to_json, get_pod_name_that_contains)
from suite.yaml_utils import get_first_ingress_host_from_yaml

src_ing_yaml = f"{TEST_DATA}/appprotect/appprotect-ingress.yaml"
Expand Down Expand Up @@ -84,8 +84,13 @@ def appprotect_setup(
src_pol_yaml = f"{TEST_DATA}/appprotect/{ap_policy}.yaml"
pol_name = create_ap_policy_from_yaml(kube_apis.custom_objects, src_pol_yaml, test_namespace)

print("------------------------- Deploy syslog server ---------------------------")
src_syslog_yaml = f"{TEST_DATA}/appprotect/syslog.yaml"
create_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)

def fin():
print("Clean up:")
delete_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)
delete_ap_policy(kube_apis.custom_objects, pol_name, test_namespace)
delete_ap_logconf(kube_apis.custom_objects, log_name, test_namespace)
delete_common_app(kube_apis, "simple", test_namespace)
Expand Down Expand Up @@ -297,6 +302,7 @@ def test_ap_enable_false_policy_incorrect(
delete_items_from_yaml(kube_apis, src_ing_yaml, test_namespace)
assert_valid_responses(response)

@pytest.mark.flaky(max_runs=3)
def test_ap_sec_logs_on(
self,
request,
Expand All @@ -309,15 +315,9 @@ def test_ap_sec_logs_on(
"""
Test corresponding log entries with correct policy (includes setting up a syslog server as defined in syslog.yaml)
"""
src_syslog_yaml = f"{TEST_DATA}/appprotect/syslog.yaml"
log_loc = "/var/log/messages"

create_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)

syslog_dst = f"syslog-svc.{test_namespace}"

# items[-1] because syslog pod is last one to spin-up
syslog_pod = kube_apis.v1.list_namespaced_pod(test_namespace).items[-1].metadata.name
syslog_pod = get_pod_name_that_contains(kube_apis.v1, test_namespace, "syslog-")

create_ingress_with_ap_annotations(
kube_apis, src_ing_yaml, test_namespace, ap_policy, "True", "True", f"{syslog_dst}:514"
Expand All @@ -333,9 +333,9 @@ def test_ap_sec_logs_on(
appprotect_setup.req_url + "/<script>", headers={"host": ingress_host}, verify=False
)
print(response_block.text)
log_contents = ""
log_contents_block = ""
retry = 0
while "ASM:attack_type" not in log_contents and retry <= 60:
while "ASM:attack_type" not in log_contents_block and retry <= 30:
log_contents_block = get_file_contents(
kube_apis.v1, log_loc, syslog_pod, test_namespace
)
Expand All @@ -354,7 +354,7 @@ def test_ap_sec_logs_on(
log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace)

delete_items_from_yaml(kube_apis, src_ing_yaml, test_namespace)
delete_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)
clear_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace)

assert_invalid_responses(response_block)
assert (
Expand Down Expand Up @@ -384,15 +384,8 @@ def test_ap_pod_startup(
"""
Log pod startup time while scaling up from 0 to 1
"""
src_syslog_yaml = f"{TEST_DATA}/appprotect/syslog.yaml"
create_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)

syslog_dst = f"syslog-svc.{test_namespace}"

# FIXME this is not used
# items[-1] because syslog pod is last one to spin-up
# syslog_pod = kube_apis.v1.list_namespaced_pod(test_namespace).items[-1].metadata.name

create_ingress_with_ap_annotations(
kube_apis, src_ing_yaml, test_namespace, ap_policy, "True", "True", f"{syslog_dst}:514"
)
Expand All @@ -408,29 +401,27 @@ def test_ap_pod_startup(
wait_before_test()
num = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ns, 1)
delete_items_from_yaml(kube_apis, src_ing_yaml, test_namespace)
delete_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)

assert num is None

@pytest.mark.flaky(max_runs=3)
def test_ap_multi_sec_logs(
self, request, kube_apis, crd_ingress_controller_with_ap, appprotect_setup, test_namespace
):
"""
Test corresponding log entries with multiple log destinations (in this case, two syslog servers)
"""
src_syslog_yaml = f"{TEST_DATA}/appprotect/syslog.yaml"
src_syslog2_yaml = f"{TEST_DATA}/appprotect/syslog2.yaml"
log_loc = "/var/log/messages"

print("Create two syslog servers")
create_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)
print("Create a second syslog server")
create_items_from_yaml(kube_apis, src_syslog2_yaml, test_namespace)

syslog_dst = f"syslog-svc.{test_namespace}"
syslog2_dst = f"syslog2-svc.{test_namespace}"

syslog_pod = kube_apis.v1.list_namespaced_pod(test_namespace).items[-2].metadata.name
syslog2_pod = kube_apis.v1.list_namespaced_pod(test_namespace).items[-1].metadata.name
syslog_pod = get_pod_name_that_contains(kube_apis.v1, test_namespace, "syslog-")
syslog2_pod = get_pod_name_that_contains(kube_apis.v1, test_namespace, "syslog2")

with open(src_ing_yaml) as f:
doc = yaml.safe_load(f)
Expand All @@ -454,6 +445,7 @@ def test_ap_multi_sec_logs(

ingress_host = get_first_ingress_host_from_yaml(src_ing_yaml)

wait_before_test(30)
ensure_response_from_backend(appprotect_setup.req_url, ingress_host, check404=True)

print("----------------------- Send request ----------------------")
Expand All @@ -480,8 +472,8 @@ def test_ap_multi_sec_logs(
reload_times[f"{request.node.name}"] = f"last reload duration: {reload_ms} ms"

delete_items_from_yaml(kube_apis, src_ing_yaml, test_namespace)
delete_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace)
delete_items_from_yaml(kube_apis, src_syslog2_yaml, test_namespace)
clear_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace)

assert_invalid_responses(response)
# check logs in dest. #1 i.e. syslog server #1
Expand All @@ -501,6 +493,7 @@ def test_ap_multi_sec_logs(
and 'outcome="REJECTED"' in log2_contents
)

@pytest.mark.flaky(max_runs=3)
def test_ap_enable_true_policy_correct_uds(
self, request, kube_apis, crd_ingress_controller_with_ap, appprotect_setup, test_namespace
):
Expand Down
12 changes: 10 additions & 2 deletions tests/suite/test_app_protect_waf_policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ def test_ap_waf_policy_allow(
assert_valid_responses(response1)
assert_valid_responses(response2)

@pytest.mark.flaky(max_runs=3)
def test_ap_waf_policy_logs(
self,
kube_apis,
Expand Down Expand Up @@ -361,8 +362,15 @@ def test_ap_waf_policy_logs(
headers={"host": virtual_server_setup.vs_host},
)
print(response.text)
wait_before_test(5)
log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace)
log_contents = ""
retry = 0
while "ASM:attack_type" not in log_contents and retry <= 30:
log_contents = get_file_contents(
kube_apis.v1, log_loc, syslog_pod, test_namespace
)
retry += 1
wait_before_test(1)
print(f"Security log not updated, retrying... #{retry}")

delete_policy(kube_apis.custom_objects, "waf-policy", test_namespace)
self.restore_default_vs(kube_apis, virtual_server_setup)
Expand Down
10 changes: 5 additions & 5 deletions tests/suite/test_rl_policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ def test_rl_policy_1rs(
assert occur.count(200) <= 1

@pytest.mark.parametrize("src", [rl_vs_sec_src])
def test_rl_policy_10rs(
def test_rl_policy_5rs(
self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src,
):
"""
Test if rate-limiting policy is working with 10 rps
Test if rate-limiting policy is working with 5 rps
"""
rate_sec = 10
rate_sec = 5
print(f"Create rl policy")
pol_name = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_sec_src, test_namespace)
print(f"Patch vs with policy: {src}")
Expand Down Expand Up @@ -251,10 +251,10 @@ def test_rl_override_spec_route(
):
"""
List policies in vs spec and route resp. and test if route overrides spec
route:policy = secondary (10 rps)
route:policy = secondary (5 rps)
spec:policy = primary (1 rps)
"""
rate_sec = 10
rate_sec = 5
print(f"Create rl policy")
pol_name_pri = create_policy_from_yaml(
kube_apis.custom_objects, rl_pol_pri_src, test_namespace
Expand Down
Loading

0 comments on commit c4a38b1

Please sign in to comment.