github.com/nginxinc/kubernetes-ingress@v1.12.5/tests/suite/test_ac_policies.py (about) 1 import pytest, requests 2 from kubernetes.client.rest import ApiException 3 from suite.resources_utils import wait_before_test, replace_configmap_from_yaml 4 from suite.custom_resources_utils import ( 5 read_custom_resource, 6 delete_virtual_server, 7 create_virtual_server_from_yaml, 8 patch_virtual_server_from_yaml, 9 create_policy_from_yaml, 10 delete_policy, 11 read_policy, 12 ) 13 from settings import TEST_DATA, DEPLOYMENTS 14 15 std_cm_src = f"{DEPLOYMENTS}/common/nginx-config.yaml" 16 test_cm_src = f"{TEST_DATA}/access-control/configmap/nginx-config.yaml" 17 std_vs_src = f"{TEST_DATA}/access-control/standard/virtual-server.yaml" 18 deny_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-deny.yaml" 19 deny_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-deny.yaml" 20 allow_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-allow.yaml" 21 allow_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-allow.yaml" 22 override_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-override.yaml" 23 invalid_pol_src = f"{TEST_DATA}/access-control/policies/access-control-policy-invalid.yaml" 24 invalid_vs_src = f"{TEST_DATA}/access-control/spec/virtual-server-invalid.yaml" 25 allow_vs_src_route = f"{TEST_DATA}/access-control/route-subroute/virtual-server-allow-route.yaml" 26 deny_vs_src_route = f"{TEST_DATA}/access-control/route-subroute/virtual-server-deny-route.yaml" 27 invalid_vs_src_route = ( 28 f"{TEST_DATA}/access-control/route-subroute/virtual-server-invalid-route.yaml" 29 ) 30 override_vs_src_route = ( 31 f"{TEST_DATA}/access-control/route-subroute/virtual-server-override-route.yaml" 32 ) 33 override_vs_spec_route_src = ( 34 f"{TEST_DATA}/access-control/route-subroute/virtual-server-override-spec-route.yaml" 35 ) 36 37 38 @pytest.fixture(scope="class") 39 def config_setup(request, kube_apis, ingress_controller_prerequisites) -> None: 40 """ 41 Replace configmap to add "set-real-ip-from" 42 :param request: pytest fixture 43 :param kube_apis: client apis 44 :param ingress_controller_prerequisites: IC pre-requisites 45 """ 46 print(f"------------- Replace ConfigMap --------------") 47 replace_configmap_from_yaml( 48 kube_apis.v1, 49 ingress_controller_prerequisites.config_map["metadata"]["name"], 50 ingress_controller_prerequisites.namespace, 51 test_cm_src, 52 ) 53 54 def fin(): 55 print(f"------------- Restore ConfigMap --------------") 56 replace_configmap_from_yaml( 57 kube_apis.v1, 58 ingress_controller_prerequisites.config_map["metadata"]["name"], 59 ingress_controller_prerequisites.namespace, 60 std_cm_src, 61 ) 62 63 request.addfinalizer(fin) 64 65 66 @pytest.mark.policies 67 @pytest.mark.parametrize( 68 "crd_ingress_controller, virtual_server_setup", 69 [ 70 ( 71 { 72 "type": "complete", 73 "extra_args": [f"-enable-custom-resources", f"-enable-leader-election=false"], 74 }, 75 {"example": "access-control", "app_type": "simple",}, 76 ) 77 ], 78 indirect=True, 79 ) 80 class TestAccessControlPoliciesVs: 81 def restore_default_vs(self, kube_apis, virtual_server_setup) -> None: 82 """ 83 Restore VirtualServer without policy spec 84 """ 85 delete_virtual_server( 86 kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace 87 ) 88 create_virtual_server_from_yaml( 89 kube_apis.custom_objects, std_vs_src, virtual_server_setup.namespace 90 ) 91 wait_before_test() 92 93 @pytest.mark.parametrize("src", [deny_vs_src, deny_vs_src_route]) 94 @pytest.mark.smoke 95 def test_deny_policy( 96 self, 97 kube_apis, 98 crd_ingress_controller, 99 virtual_server_setup, 100 test_namespace, 101 config_setup, 102 src, 103 ): 104 """ 105 Test if ip (10.0.0.1) block-listing is working: default(no policy) -> deny 106 """ 107 resp = requests.get( 108 virtual_server_setup.backend_1_url, 109 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 110 ) 111 print(f"Response: {resp.status_code}\n{resp.text}") 112 assert resp.status_code == 200 113 114 print(f"Create deny policy") 115 pol_name = create_policy_from_yaml(kube_apis.custom_objects, deny_pol_src, test_namespace) 116 print(f"Patch vs with policy: {src}") 117 patch_virtual_server_from_yaml( 118 kube_apis.custom_objects, 119 virtual_server_setup.vs_name, 120 src, 121 virtual_server_setup.namespace, 122 ) 123 wait_before_test() 124 125 policy_info = read_custom_resource(kube_apis.custom_objects, test_namespace, "policies", pol_name) 126 print(f"\nUse IP listed in deny block: 10.0.0.1") 127 resp1 = requests.get( 128 virtual_server_setup.backend_1_url, 129 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 130 ) 131 print(f"Response: {resp1.status_code}\n{resp1.text}") 132 print(f"\nUse IP not listed in deny block: 10.0.0.2") 133 resp2 = requests.get( 134 virtual_server_setup.backend_1_url, 135 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.2"}, 136 ) 137 print(f"Response: {resp2.status_code}\n{resp2.text}") 138 139 delete_policy(kube_apis.custom_objects, pol_name, test_namespace) 140 self.restore_default_vs(kube_apis, virtual_server_setup) 141 142 assert ( 143 policy_info["status"] 144 and policy_info["status"]["reason"] == "AddedOrUpdated" 145 and policy_info["status"]["state"] == "Valid" 146 ) 147 148 assert ( 149 resp1.status_code == 403 150 and "403 Forbidden" in resp1.text 151 and resp2.status_code == 200 152 and "Server address:" in resp2.text 153 ) 154 155 @pytest.mark.parametrize("src", [allow_vs_src, allow_vs_src_route]) 156 @pytest.mark.smoke 157 def test_allow_policy( 158 self, 159 kube_apis, 160 crd_ingress_controller, 161 virtual_server_setup, 162 test_namespace, 163 config_setup, 164 src, 165 ): 166 """ 167 Test if ip (10.0.0.1) allow-listing is working: default(no policy) -> allow 168 """ 169 resp = requests.get( 170 virtual_server_setup.backend_1_url, 171 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 172 ) 173 print(f"Response: {resp.status_code}\n{resp.text}") 174 assert resp.status_code == 200 175 176 print(f"Create allow policy") 177 pol_name = create_policy_from_yaml(kube_apis.custom_objects, allow_pol_src, test_namespace) 178 patch_virtual_server_from_yaml( 179 kube_apis.custom_objects, 180 virtual_server_setup.vs_name, 181 src, 182 virtual_server_setup.namespace, 183 ) 184 wait_before_test() 185 186 policy_info = read_custom_resource(kube_apis.custom_objects, test_namespace, "policies", pol_name) 187 print(f"\nUse IP listed in allow block: 10.0.0.1") 188 resp1 = requests.get( 189 virtual_server_setup.backend_1_url, 190 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 191 ) 192 print(f"\nUse IP listed not in allow block: 10.0.0.2") 193 print(f"Response: {resp1.status_code}\n{resp1.text}") 194 resp2 = requests.get( 195 virtual_server_setup.backend_1_url, 196 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.2"}, 197 ) 198 print(f"Response: {resp2.status_code}\n{resp2.text}") 199 200 delete_policy(kube_apis.custom_objects, pol_name, test_namespace) 201 self.restore_default_vs(kube_apis, virtual_server_setup) 202 203 assert ( 204 policy_info["status"] 205 and policy_info["status"]["reason"] == "AddedOrUpdated" 206 and policy_info["status"]["state"] == "Valid" 207 ) 208 209 assert ( 210 resp1.status_code == 200 211 and "Server address:" in resp1.text 212 and resp2.status_code == 403 213 and "403 Forbidden" in resp2.text 214 ) 215 216 @pytest.mark.parametrize("src", [override_vs_src, override_vs_src_route]) 217 def test_override_policy( 218 self, 219 kube_apis, 220 crd_ingress_controller, 221 virtual_server_setup, 222 test_namespace, 223 config_setup, 224 src, 225 ): 226 """ 227 Test if ip allow-listing overrides block-listing: default(no policy) -> deny and allow 228 """ 229 resp = requests.get( 230 virtual_server_setup.backend_1_url, 231 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 232 ) 233 print(f"Response: {resp.status_code}\n{resp.text}") 234 assert resp.status_code == 200 235 236 print(f"Create deny policy") 237 deny_pol_name = create_policy_from_yaml( 238 kube_apis.custom_objects, deny_pol_src, test_namespace 239 ) 240 print(f"Create allow policy") 241 allow_pol_name = create_policy_from_yaml( 242 kube_apis.custom_objects, allow_pol_src, test_namespace 243 ) 244 patch_virtual_server_from_yaml( 245 kube_apis.custom_objects, 246 virtual_server_setup.vs_name, 247 src, 248 virtual_server_setup.namespace, 249 ) 250 wait_before_test() 251 252 print(f"Use IP listed in both deny and allow policies: 10.0.0.1") 253 resp = requests.get( 254 virtual_server_setup.backend_1_url, 255 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 256 ) 257 print(f"Response: {resp.status_code}\n{resp.text}") 258 259 delete_policy(kube_apis.custom_objects, deny_pol_name, test_namespace) 260 delete_policy(kube_apis.custom_objects, allow_pol_name, test_namespace) 261 self.restore_default_vs(kube_apis, virtual_server_setup) 262 263 assert resp.status_code == 200 and "Server address:" in resp.text 264 265 @pytest.mark.parametrize("src", [invalid_vs_src, invalid_vs_src_route]) 266 def test_invalid_policy( 267 self, 268 kube_apis, 269 crd_ingress_controller, 270 virtual_server_setup, 271 test_namespace, 272 config_setup, 273 src, 274 ): 275 """ 276 Test if invalid policy is applied then response is 500 277 """ 278 resp = requests.get( 279 virtual_server_setup.backend_1_url, 280 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 281 ) 282 print(f"Response: {resp.status_code}\n{resp.text}") 283 assert resp.status_code == 200 284 285 print(f"Create invalid policy") 286 invalid_pol_name = create_policy_from_yaml( 287 kube_apis.custom_objects, invalid_pol_src, test_namespace 288 ) 289 patch_virtual_server_from_yaml( 290 kube_apis.custom_objects, 291 virtual_server_setup.vs_name, 292 src, 293 virtual_server_setup.namespace, 294 ) 295 296 wait_before_test() 297 resp = requests.get( 298 virtual_server_setup.backend_1_url, 299 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 300 ) 301 print(f"Response: {resp.status_code}\n{resp.text}") 302 303 vs_info = read_custom_resource( 304 kube_apis.custom_objects, 305 virtual_server_setup.namespace, 306 "virtualservers", 307 virtual_server_setup.vs_name, 308 ) 309 policy_info = read_custom_resource( 310 kube_apis.custom_objects, test_namespace, "policies", invalid_pol_name 311 ) 312 delete_policy(kube_apis.custom_objects, invalid_pol_name, test_namespace) 313 self.restore_default_vs(kube_apis, virtual_server_setup) 314 315 assert resp.status_code == 500 and "500 Internal Server Error" in resp.text 316 assert ( 317 policy_info["status"] 318 and policy_info["status"]["reason"] == "Rejected" 319 and policy_info["status"]["state"] == "Invalid" 320 ) 321 assert ( 322 vs_info["status"]["state"] == "Warning" 323 and vs_info["status"]["reason"] == "AddedOrUpdatedWithWarning" 324 ) 325 326 @pytest.mark.parametrize("src", [deny_vs_src, deny_vs_src_route]) 327 def test_deleted_policy( 328 self, 329 kube_apis, 330 crd_ingress_controller, 331 virtual_server_setup, 332 test_namespace, 333 config_setup, 334 src, 335 ): 336 """ 337 Test if valid policy is deleted then response is 500 338 """ 339 resp = requests.get( 340 virtual_server_setup.backend_1_url, 341 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 342 ) 343 print(f"Response: {resp.status_code}\n{resp.text}") 344 assert resp.status_code == 200 345 346 print(f"Create deny policy") 347 pol_name = create_policy_from_yaml(kube_apis.custom_objects, deny_pol_src, test_namespace) 348 patch_virtual_server_from_yaml( 349 kube_apis.custom_objects, 350 virtual_server_setup.vs_name, 351 src, 352 virtual_server_setup.namespace, 353 ) 354 355 wait_before_test() 356 vs_info = read_custom_resource( 357 kube_apis.custom_objects, 358 virtual_server_setup.namespace, 359 "virtualservers", 360 virtual_server_setup.vs_name, 361 ) 362 assert vs_info["status"]["state"] == "Valid" 363 delete_policy(kube_apis.custom_objects, pol_name, test_namespace) 364 365 wait_before_test() 366 resp = requests.get( 367 virtual_server_setup.backend_1_url, 368 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 369 ) 370 print(f"Response: {resp.status_code}\n{resp.text}") 371 372 vs_info = read_custom_resource( 373 kube_apis.custom_objects, 374 virtual_server_setup.namespace, 375 "virtualservers", 376 virtual_server_setup.vs_name, 377 ) 378 self.restore_default_vs(kube_apis, virtual_server_setup) 379 380 assert resp.status_code == 500 and "500 Internal Server Error" in resp.text 381 assert ( 382 vs_info["status"]["state"] == "Warning" 383 and vs_info["status"]["reason"] == "AddedOrUpdatedWithWarning" 384 ) 385 386 def test_route_override_spec( 387 self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, config_setup, 388 ): 389 """ 390 Test allow policy specified under routes overrides block in spec 391 """ 392 resp = requests.get( 393 virtual_server_setup.backend_1_url, 394 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 395 ) 396 print(f"Response: {resp.status_code}\n{resp.text}") 397 assert resp.status_code == 200 398 399 print(f"Create deny policy") 400 deny_pol_name = create_policy_from_yaml( 401 kube_apis.custom_objects, deny_pol_src, test_namespace 402 ) 403 print(f"Create allow policy") 404 allow_pol_name = create_policy_from_yaml( 405 kube_apis.custom_objects, allow_pol_src, test_namespace 406 ) 407 408 patch_virtual_server_from_yaml( 409 kube_apis.custom_objects, 410 virtual_server_setup.vs_name, 411 override_vs_spec_route_src, 412 virtual_server_setup.namespace, 413 ) 414 wait_before_test() 415 416 print(f"Use IP listed in both deny and allow policies: 10.0.0.1") 417 resp = requests.get( 418 virtual_server_setup.backend_1_url, 419 headers={"host": virtual_server_setup.vs_host, "X-Real-IP": "10.0.0.1"}, 420 ) 421 print(f"Response: {resp.status_code}\n{resp.text}") 422 423 self.restore_default_vs(kube_apis, virtual_server_setup) 424 delete_policy(kube_apis.custom_objects, deny_pol_name, test_namespace) 425 delete_policy(kube_apis.custom_objects, allow_pol_name, test_namespace) 426 427 assert resp.status_code == 200 and "Server address:" in resp.text