|
| 1 | +''' |
| 2 | +Verify remap.config acl behavior. |
| 3 | +''' |
| 4 | +# Licensed to the Apache Software Foundation (ASF) under one |
| 5 | +# or more contributor license agreements. See the NOTICE file |
| 6 | +# distributed with this work for additional information |
| 7 | +# regarding copyright ownership. The ASF licenses this file |
| 8 | +# to you under the Apache License, Version 2.0 (the |
| 9 | +# "License"); you may not use this file except in compliance |
| 10 | +# with the License. You may obtain a copy of the License at |
| 11 | +# |
| 12 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 13 | +# |
| 14 | +# Unless required by applicable law or agreed to in writing, software |
| 15 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 16 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 17 | +# See the License for the specific language governing permissions and |
| 18 | +# limitations under the License. |
| 19 | + |
| 20 | +import os |
| 21 | +import re |
| 22 | +from typing import List, Tuple |
| 23 | + |
| 24 | +Test.Summary = ''' |
| 25 | +Verify remap.config acl behavior. |
| 26 | +''' |
| 27 | + |
| 28 | + |
| 29 | +class Test_remap_acl: |
| 30 | + """Configure a test to verify remap.config acl behavior.""" |
| 31 | + |
| 32 | + _ts_counter: int = 0 |
| 33 | + _server_counter: int = 0 |
| 34 | + _client_counter: int = 0 |
| 35 | + |
| 36 | + def __init__( |
| 37 | + self, name: str, replay_file: str, ip_allow_content: str, deactivate_ip_allow: bool, acl_configuration: str, |
| 38 | + named_acls: List[Tuple[str, str]], expected_responses: list[int]): |
| 39 | + """Initialize the test. |
| 40 | +
|
| 41 | + :param name: The name of the test. |
| 42 | + :param replay_file: The replay file to be used. |
| 43 | + :param ip_allow_content: The ip_allow configuration to be used. |
| 44 | + :param deactivate_ip_allow: Whether to deactivate the ip_allow filter. |
| 45 | + :param acl_configuration: The ACL configuration to be used. |
| 46 | + :param named_acls: The set of named ACLs to configure and use. |
| 47 | + :param expect_responses: The in-order expected responses from the proxy. |
| 48 | + """ |
| 49 | + self._replay_file = replay_file |
| 50 | + self._ip_allow_content = ip_allow_content |
| 51 | + self._deactivate_ip_allow = deactivate_ip_allow |
| 52 | + self._acl_configuration = acl_configuration |
| 53 | + self._named_acls = named_acls |
| 54 | + self._expected_responses = expected_responses |
| 55 | + |
| 56 | + tr = Test.AddTestRun(name) |
| 57 | + self._configure_server(tr) |
| 58 | + self._configure_traffic_server(tr) |
| 59 | + self._configure_client(tr) |
| 60 | + |
| 61 | + def _configure_server(self, tr: 'TestRun') -> None: |
| 62 | + """Configure the server. |
| 63 | +
|
| 64 | + :param tr: The TestRun object to associate the server process with. |
| 65 | + """ |
| 66 | + name = f"server-{Test_remap_acl._server_counter}" |
| 67 | + server = tr.AddVerifierServerProcess(name, self._replay_file) |
| 68 | + Test_remap_acl._server_counter += 1 |
| 69 | + self._server = server |
| 70 | + |
| 71 | + def _configure_traffic_server(self, tr: 'TestRun') -> None: |
| 72 | + """Configure Traffic Server. |
| 73 | +
|
| 74 | + :param tr: The TestRun object to associate the Traffic Server process with. |
| 75 | + """ |
| 76 | + |
| 77 | + name = f"ts-{Test_remap_acl._ts_counter}" |
| 78 | + ts = tr.MakeATSProcess(name, enable_cache=False, enable_tls=True) |
| 79 | + Test_remap_acl._ts_counter += 1 |
| 80 | + self._ts = ts |
| 81 | + |
| 82 | + ts.addDefaultSSLFiles() |
| 83 | + ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key') |
| 84 | + ts.Disk.records_config.update( |
| 85 | + { |
| 86 | + 'proxy.config.diags.debug.enabled': 1, |
| 87 | + 'proxy.config.diags.debug.tags': 'http|url|remap', |
| 88 | + 'proxy.config.http.push_method_enabled': 1, |
| 89 | + 'proxy.config.ssl.server.cert.path': ts.Variables.SSLDir, |
| 90 | + 'proxy.config.quic.no_activity_timeout_in': 0, |
| 91 | + 'proxy.config.ssl.server.private_key.path': ts.Variables.SSLDir, |
| 92 | + 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', |
| 93 | + 'proxy.config.http.connect_ports': self._server.Variables.http_port, |
| 94 | + }) |
| 95 | + |
| 96 | + remap_config_lines = [] |
| 97 | + if self._deactivate_ip_allow: |
| 98 | + remap_config_lines.append('.deactivatefilter ip_allow') |
| 99 | + |
| 100 | + # First, define the name ACLs (filters). |
| 101 | + for name, definition in self._named_acls: |
| 102 | + remap_config_lines.append(f'.definefilter {name} {definition}') |
| 103 | + # Now activate them. |
| 104 | + for name, _ in self._named_acls: |
| 105 | + remap_config_lines.append(f'.activatefilter {name}') |
| 106 | + |
| 107 | + remap_config_lines.append(f'map / http://127.0.0.1:{self._server.Variables.http_port} {self._acl_configuration}') |
| 108 | + ts.Disk.remap_config.AddLines(remap_config_lines) |
| 109 | + ts.Disk.ip_allow_yaml.AddLines(self._ip_allow_content.split("\n")) |
| 110 | + |
| 111 | + def _configure_client(self, tr: 'TestRun') -> None: |
| 112 | + """Run the test. |
| 113 | +
|
| 114 | + :param tr: The TestRun object to associate the client process with. |
| 115 | + """ |
| 116 | + |
| 117 | + name = f"client-{Test_remap_acl._client_counter}" |
| 118 | + p = tr.AddVerifierClientProcess(name, self._replay_file, https_ports=[self._ts.Variables.ssl_port]) |
| 119 | + Test_remap_acl._client_counter += 1 |
| 120 | + p.StartBefore(self._server) |
| 121 | + p.StartBefore(self._ts) |
| 122 | + |
| 123 | + codes = [str(code) for code in self._expected_responses] |
| 124 | + p.Streams.stdout += Testers.ContainsExpression( |
| 125 | + '.*'.join(codes), "Verifying the expected order of responses", reflags=re.DOTALL | re.MULTILINE) |
| 126 | + |
| 127 | + |
| 128 | +IP_ALLOW_CONTENT = f''' |
| 129 | +ip_allow: |
| 130 | + - apply: in |
| 131 | + ip_addrs: 0/0 |
| 132 | + action: allow |
| 133 | +''' |
| 134 | + |
| 135 | +test_ip_allow_optional_methods = Test_remap_acl( |
| 136 | + "Verify non-allowed methods are blocked.", |
| 137 | + replay_file='remap_acl_get_post_allowed.replay.yaml', |
| 138 | + ip_allow_content=IP_ALLOW_CONTENT, |
| 139 | + deactivate_ip_allow=True, |
| 140 | + acl_configuration='@action=allow @src_ip=127.0.0.1 @method=GET @method=POST', |
| 141 | + named_acls=[], |
| 142 | + expected_responses=[200, 200, 403, 403, 403]) |
| 143 | + |
| 144 | +test_ip_allow_optional_methods = Test_remap_acl( |
| 145 | + "Verify denied methods are blocked.", |
| 146 | + replay_file='remap_acl_get_post_denied.replay.yaml', |
| 147 | + ip_allow_content=IP_ALLOW_CONTENT, |
| 148 | + deactivate_ip_allow=True, |
| 149 | + acl_configuration='@action=deny @src_ip=127.0.0.1 @method=GET @method=POST', |
| 150 | + named_acls=[], |
| 151 | + expected_responses=[403, 403, 200, 200, 400]) |
| 152 | + |
| 153 | +test_ip_allow_optional_methods = Test_remap_acl( |
| 154 | + "Verify defined filters are evaluated before remap lines.", |
| 155 | + replay_file='remap_acl_all_denied.replay.yaml', |
| 156 | + ip_allow_content=IP_ALLOW_CONTENT, |
| 157 | + deactivate_ip_allow=True, |
| 158 | + acl_configuration='@action=allow @src_ip=127.0.0.1 @method=GET @method=POST', |
| 159 | + named_acls=[('deny', '@action=deny @src_ip=0.0.0.0-255.255.255.255')], |
| 160 | + expected_responses=[403, 403, 403, 403, 403]) |
| 161 | + |
| 162 | +test_ip_allow_optional_methods = Test_remap_acl( |
| 163 | + "Verify a default deny filter rule works.", |
| 164 | + replay_file='remap_acl_all_denied.replay.yaml', |
| 165 | + ip_allow_content=IP_ALLOW_CONTENT, |
| 166 | + deactivate_ip_allow=True, |
| 167 | + acl_configuration='@action=allow @src_ip=1.2.3.4 @method=GET @method=POST', |
| 168 | + named_acls=[('deny', '@action=deny @src_ip=0.0.0.0-255.255.255.255')], |
| 169 | + expected_responses=[403, 403, 403, 403, 403]) |
0 commit comments