Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add automated tests for -watch-secret-namespace #3245

Merged
merged 9 commits into from
Nov 15, 2022
20 changes: 20 additions & 0 deletions tests/data/watch-secret-namespace/route-multiple.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: k8s.nginx.org/v1
kind: VirtualServerRoute
metadata:
name: backends
spec:
host: virtual-server-route.example.com
upstreams:
- name: backend1
service: backend1-svc
port: 80
- name: backend3
service: backend3-svc
port: 80
subroutes:
- path: "/backends/backend1"
action:
pass: backend1
- path: "/backends/backend3"
action:
pass: backend3
14 changes: 14 additions & 0 deletions tests/data/watch-secret-namespace/route-single.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: k8s.nginx.org/v1
kind: VirtualServerRoute
metadata:
name: backend2
spec:
host: virtual-server-route.example.com
upstreams:
- name: backend2
service: backend2-svc
port: 80
subroutes:
- path: "/backend2"
action:
pass: backend2
13 changes: 13 additions & 0 deletions tests/data/watch-secret-namespace/standard/virtual-server.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: virtual-server-route
spec:
host: virtual-server-route.example.com
tls:
secret: virtual-server-tls-secret
routes:
- path: "/backends"
route: backends # implicit namespace
- path: "/backend2"
route: backend2-namespace/backend2
8 changes: 8 additions & 0 deletions tests/data/watch-secret-namespace/tls-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: virtual-server-tls-secret
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQ4RENDQXRpZ0F3SUJBZ0lKQU9jbHdCelprYmlhTUEwR0NTcUdTSWIzRFFFQkJRVUFNRmd4Q3pBSkJnTlYKQkFZVEFsVlRNUXN3Q1FZRFZRUUlFd0pEUVRFaE1COEdBMVVFQ2hNWVNXNTBaWEp1WlhRZ1YybGtaMmwwY3lCUQpkSGtnVEhSa01Sa3dGd1lEVlFRREV4QmpZV1psTG1WNFlXMXdiR1V1WTI5dE1CNFhEVEUzTURnek1URXdNVGN5Ck1Gb1hEVEU0TURnek1URXdNVGN5TUZvd1dERUxNQWtHQTFVRUJoTUNWVk14Q3pBSkJnTlZCQWdUQWtOQk1TRXcKSHdZRFZRUUtFeGhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXhHVEFYQmdOVkJBTVRFR05oWm1VdQpaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQzdIT0xJCm5oZjE1aUcxOE16RXBzN0lvZmxHQmovMi9NVjA0OWtBS0hrTnZOem1XaXRXWDV2QU1yRkF5THY0dXBIWDI5b0IKa3l6YUhlYyt2TlFibEh1bStINUtkUWZXWHFXNkJ6UnVhMzBreEkrcG91cnhpNy9jaDJORS92djBhRGtvaTJ0RAovOUI2aHAyVkoxWXFJdm9hQ2wwSmFYWDd0WEc4SGU1S1BSZzBYMm1Mblcwa29tay9ZVGRPbS9xOVRjUDRnUmhrCms3bUhJMDlSME5vNUhTbURydmVBWFEyY3lGWVJQVUNjWkNPd0h6UUdVUVB1UU0wNVArWUNnVlNRcElKWFV0b0kKbGdEMHhZZUw4UU1rZjZ0TWpYcXpTVVRhQlhzNkRKU2x1YWN1aHpkV212UnFPUVNNYlVpZ3dVUEZCRDVLRUFIcwozM0hHeVZ5dkI4cVlrYUczQWdNQkFBR2pnYnd3Z2Jrd0hRWURWUjBPQkJZRUZOdTQvMTdpSituRGxPMkoyVisvCitqM2x5SzVZTUlHSkJnTlZIU01FZ1lFd2Y0QVUyN2ovWHVJbjZjT1U3WW5aWDcvNlBlWElybGloWEtSYU1GZ3gKQ3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSUV3SkRRVEVoTUI4R0ExVUVDaE1ZU1c1MFpYSnVaWFFnVjJsawpaMmwwY3lCUWRIa2dUSFJrTVJrd0Z3WURWUVFERXhCallXWmxMbVY0WVcxd2JHVXVZMjl0Z2drQTV5WEFITm1SCnVKb3dEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQUtGUHJBcXA3a3lzTDVGNnMKWFhWdXZkZzAyc0srUlpzb2F3QWVxbHlSRmpJeUlQL2VTajBhQjQwQmNOcWFyRHhwNjhBd1pZNG4yQk9EVmo5WgphOFlvV1YyOFpwamloaThxNnBPSElOa0MrOXpCY1hsZ2lvVUZBTERCcXFPTXFUZkw1cjNGejNUTGN1clozajhuCnUzL2hRVHNXZG5TZENWbmN0aXhaUHJ5cnhJSFlWSERiVHF4ZWdTQUN6WkU1MHMwdlRpMFJkNUkrcVdubVpIUloKL0hLNVZnNWlNS2E1clBPRTFaT2M3L2VnVjZ6R2p4THJiNEdlQ2JyTjBBb01tazNpL2d2K2kzL0N6aTlXOVhNNApwa2hQSjJUcEtMSjVaOHgxUVhjUW5Dem5yOEdtL2FuVzV4b3lDdWhjZzlXMlVSYzRKVTZ1UXh0WU9tczYrc0RxCjBBN1Y3UT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdXh6aXlKNFg5ZVlodGZETXhLYk95S0g1UmdZLzl2ekZkT1BaQUNoNURiemM1bG9yClZsK2J3REt4UU1pNytMcVIxOXZhQVpNczJoM25QcnpVRzVSN3B2aCtTblVIMWw2bHVnYzBibXQ5Sk1TUHFhTHEKOFl1LzNJZGpSUDc3OUdnNUtJdHJRLy9RZW9hZGxTZFdLaUw2R2dwZENXbDErN1Z4dkIzdVNqMFlORjlwaTUxdApKS0pwUDJFM1RwdjZ2VTNEK0lFWVpKTzVoeU5QVWREYU9SMHBnNjczZ0YwTm5NaFdFVDFBbkdRanNCODBCbEVECjdrRE5PVC9tQW9GVWtLU0NWMUxhQ0pZQTlNV0hpL0VESkgrclRJMTZzMGxFMmdWN09neVVwYm1uTG9jM1ZwcjAKYWprRWpHMUlvTUZEeFFRK1NoQUI3Tjl4eHNsY3J3ZkttSkdodHdJREFRQUJBb0lCQUVuZHpXbUZmOUFEV2F1Sgp0RXl0elZSSEhURVhwb2pLb09qVVNnWlY4L1FJYXV4RkRIYThwNi9vVXpGUURXVFR3bCtFMnp0ajdvRHM3UzFIClBqVGxHU3VCVGRuMitYRVhURFYwUXE2VW9JS3pWa09SblU1ZDdSQVNJbzVLV3d6UldEODVTczg5WGdBQXhKVHQKUW9hLzZCdi9tMXJyMXpmWEdWODZNYWY5Rm1FVjI5bmpCcHZ3cUpzOFlUaFU5VE5BRUdnbkxBWGFJYTJZSUJTSgozcVhJd1RrdFBHUUZyZUowdnBiOVlaTkRxWk0rMmI1K3BBVEVXclpyeTQxTlpvdzhNUnVOYnoxVU5sWXkyazZKCjlXclUxUDVYM2l3dEZmcXA3TzREakNOMFR2Y1Y1Nm5QczJoYldDeHp4RmxFalJwNW5KQ3Bsdi9yNCt4eHJVRWQKd0NjU0x3RUNnWUVBOGVDUGM2S2JpSXVFUWxwVjcxTXRQMjdBZzhkMzN5aWZKajAvQ3R3RlF6dlhWcHZCSHFRagphUE1ZaEswZ3o0MzFHMGtqVUpTeUU2STJYVWhFU3gxZUw2TU5sVS9xc29Uc0JaZEV3N0cvMFRhdW1TQUJWemZPCkIvckdtbEZkZitxWVpiR3pIdGtvbVJWb1JqVWtPcGRJL3RnL1ZlSmJ3K1RIS2dYS01NU2V5cjhDZ1lFQXhnbTkKWXN5dVZVUGlEdDhuL1JXeEJwZ1Zqazk0M3BFOVFjK2FVK0VPcGROK2NNQjkvaGJiWUpMZEZ2WUUwd2s1cEQ1SQpibktscjZycndEVUJKNWY2TXM0L3gyS3JISjlCQ3VNT3JyTEVTVm42ZG9NdDhWdEtpQkVLTVFuSnIzYmM4UDV3CnpvVmNhRGl1dCtISjcySG83cG5QQTFhaS9QV1ZwM2pZUTlCSXZ3a0NnWUJRNzkzUXlmYlZxQ25uc2liVFlMZmgKWkFRVGxLbXVDUC9JWWZJNGhndFV4aTkya2NQN3B0MGFmMDRUQjRQVk1DRjJzZkNaUkVpYWZVdEh4Nmppb2I4awpuYUVyOTRRSG5LY0Y3K3BZdWFBQU9CWVFzejcvbW5MZEJMTjBiQW1uaGk3Y3lLdXhoT1VxNUpqeDlWSmNNTWVDClQ0WlNETjY4SEUvdzVlTVVrcGE0TFFLQmdGM0piUXhtUE1XYW9XdERtYytNdjBxTktlQThtTlJtMmlqWnBZL0YKek1jUnN4YTR3ckpicHNkRXBqbmlod1Jlb1JLOGdGYjJLcXRYK2RBTUNpRHpJNFYrRWN4ZVdRVDBFcnlTTFhqawpwbnJLaHdnck5jM1EyeW8zVDZsTHBsMVhvR2p0UndVM09UME9Zd2dvZ1JiQ09xc000bklGVEtrWnNTY2YzdU8yCnQwenBBb0dCQU5Fc1V4Yit6UHpKbEgwL2hOTlhteisvNGx4aXlJb1ZQQXgzaEtBemtjOGtkZzhoS25XWkZhK0YKTjZMOXZjTDhNbnRjNHpmVDdDanNxWGJ2cGUzRUFOeGk4TWRSZzd1Z093L2NiZWdLVklZY3hTdXdRKzYrNUZYOApKRzlhbGxzdXovTk40b2RpMzRvblpEVmRZcURnY2xaZnZucXZKMHZWSzc1VXhQZ3F3aUJQCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
112 changes: 112 additions & 0 deletions tests/suite/test_watch_secret_namespace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from unittest import mock

import pytest
import requests
from kubernetes.client.rest import ApiException
from settings import TEST_DATA
from suite.utils.resources_utils import create_secret_from_yaml, ensure_response_from_backend, wait_before_test
from suite.utils.ssl_utils import create_sni_session


@pytest.mark.vsr
@pytest.mark.parametrize(
"crd_ingress_controller, v_s_route_setup",
[
(
{
"type": "complete",
"extra_args": [
f"-enable-custom-resources",
f"-watch-namespace=nginx-ingress,backends,backend2-namespace",
f"-watch-secret-namespace=backends",
],
},
{"example": "watch-secret-namespace"},
)
],
indirect=True,
)
class TestVSRWatchSecretNamespacesValid:
def test_responses(
self,
kube_apis,
ingress_controller_prerequisites,
crd_ingress_controller,
v_s_route_setup,
v_s_route_app_setup,
):
"""Creates 3 tests 1). watching specific ns and secret ns, 2). watching only specific secret ns, 3). watching all ns"""
src_vs_sec_yaml = f"{TEST_DATA}/watch-secret-namespace/tls-secret.yaml"
create_secret_from_yaml(kube_apis.v1, "backends", src_vs_sec_yaml)
req_url = f"https://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port_ssl}"
session = create_sni_session()
exception = ""
resp = mock.Mock()
resp.status_code = "None"
resp.text = "None"
retry = 0
while resp.status_code == "None" and retry < 10:
wait_before_test()
try:
resp = session.get(
f"{req_url}{v_s_route_setup.route_m.paths[0]}",
headers={"host": v_s_route_setup.vs_host},
allow_redirects=False,
verify=False,
)
except requests.exceptions.SSLError as e:
exception = str(e)
print(f"SSL certificate exception: {exception}")
retry = +1

assert resp.status_code == 200


@pytest.mark.vsr
@pytest.mark.parametrize(
"crd_ingress_controller, v_s_route_setup",
[
(
{
"type": "complete",
"extra_args": [
f"-enable-custom-resources",
f"-watch-namespace=nginx-ingress,backends,backend2-namespace",
f"-watch-secret-namespace=invalid",
],
},
{"example": "watch-secret-namespace"},
)
],
indirect=True,
)
class TestVSRWatchSecretNamespacesInvalid:
def test_responses(
self,
kube_apis,
ingress_controller_prerequisites,
crd_ingress_controller,
v_s_route_setup,
v_s_route_app_setup,
):
"""Creates 2 tests 1). watching specific ns and invalid secret ns, 2). watching only invalid secret ns"""
src_vs_sec_yaml = f"{TEST_DATA}/watch-secret-namespace/tls-secret.yaml"
create_secret_from_yaml(kube_apis.v1, "backends", src_vs_sec_yaml)
req_url = f"https://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port_ssl}"
session = create_sni_session()
exception = ""
wait_before_test()
try:
resp = session.get(
f"{req_url}{v_s_route_setup.route_m.paths[0]}",
headers={"host": v_s_route_setup.vs_host},
allow_redirects=False,
verify=False,
)
except requests.exceptions.SSLError as e:
exception = str(e)
print(f"SSL certificate exception: {exception}")
resp = mock.Mock()
resp.status_code = "None"
resp.text = "None"
assert "[SSL: TLSV1_UNRECOGNIZED_NAME]" in exception and "None" in resp.status_code
27 changes: 26 additions & 1 deletion tests/suite/utils/resources_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import re
import time
from unittest import mock

import pytest
import requests
Expand All @@ -12,6 +13,7 @@
from kubernetes.stream import stream
from more_itertools import first
from settings import DEPLOYMENTS, PROJECT_ROOT, RECONFIGURATION_DELAY, TEST_DATA
from suite.utils.ssl_utils import create_sni_session


class RBACAuthorization:
Expand Down Expand Up @@ -1429,7 +1431,7 @@ def get_events(v1: CoreV1Api, namespace) -> []:
return res.items


def ensure_response_from_backend(req_url, host, additional_headers=None, check404=False) -> None:
def ensure_response_from_backend(req_url, host, additional_headers=None, check404=False, sni=False) -> None:
"""
Wait for 502|504|404 to disappear.

Expand All @@ -1442,6 +1444,29 @@ def ensure_response_from_backend(req_url, host, additional_headers=None, check40
if additional_headers:
headers.update(additional_headers)

if sni and check404:
session = create_sni_session()
for _ in range(60):
try:
resp = session.get(
req_url,
headers=headers,
allow_redirects=False,
verify=False,
)
if resp.status_code != 502 and resp.status_code != 504 and resp.status_code != 404:
print(
f"After {_} retries at 1 second interval, got {resp.status_code} response. Continue with tests..."
)
return
time.sleep(1)
except requests.exceptions.SSLError as e:
exception = str(e)
print(f"SSL certificate exception: {exception}")
resp = mock.Mock()
resp.status_code = "None"
pytest.fail(f"Keep getting {resp.status_code} from {req_url} after 60 seconds. Exiting...")

if check404:
for _ in range(60):
resp = requests.get(req_url, headers=headers, verify=False)
Expand Down