This is an automated email from the ASF dual-hosted git repository.

eze pushed a commit to branch 9.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/9.2.x by this push:
     new ce942e0aca Add a setting to choose the data source of IP address for 
ACL (#12294)
ce942e0aca is described below

commit ce942e0acacd5cc9f38bd07565a1dfc5ffed0e33
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Mon Jun 16 15:30:56 2025 -0600

    Add a setting to choose the data source of IP address for ACL (#12294)
    
    * Add a setting to choose the data source of IP address for ACL
---
 .../configuration/proxy-protocol.en.rst            |   4 +
 doc/admin-guide/files/records.config.en.rst        |  14 ++
 iocore/net/P_SNIActionPerformer.h                  |  17 ++-
 iocore/net/libinknet_stub.cc                       |   2 +
 mgmt/RecordsConfig.cc                              |   8 ++
 proxy/IPAllow.cc                                   |  33 ++++-
 proxy/IPAllow.h                                    |   4 +
 proxy/http/HttpSessionAccept.cc                    |  10 ++
 proxy/http/remap/UrlRewrite.cc                     |  28 +++-
 proxy/http2/Http2SessionAccept.cc                  |  16 ++-
 .../gold_tests/autest-site/trafficserver.test.ext  |  14 +-
 tests/gold_tests/remap/remap_acl.test.py           |  39 +++++-
 .../remap_acl_get_post_allowed_pp.replay.yaml      | 152 +++++++++++++++++++++
 13 files changed, 322 insertions(+), 19 deletions(-)

diff --git a/doc/admin-guide/configuration/proxy-protocol.en.rst 
b/doc/admin-guide/configuration/proxy-protocol.en.rst
index a83fe5b137..bb25a6f47d 100644
--- a/doc/admin-guide/configuration/proxy-protocol.en.rst
+++ b/doc/admin-guide/configuration/proxy-protocol.en.rst
@@ -47,6 +47,10 @@ configured with 
:ts:cv:`proxy.config.http.proxy_protocol_allowlist`.
        If the allowlist is configured, requests will only be accepted from 
these
        IP addresses and must be prefaced with the PROXY v1/v2 header.
 
+By default, |TS| uses client's IP address that is from the peer when it 
applies ACL. If you configure a port to
+enable PROXY protocol and want to apply ACL against the IP address delivered 
by PROXY protocol, you need to have ``PROXY`` in
+:ts:cv:`proxy.config.acl.subjects`.
+
 1. HTTP Forwarded Header
 
 The client IP address in the PROXY protocol header is passed to the origin 
server via an HTTP `Forwarded:
diff --git a/doc/admin-guide/files/records.config.en.rst 
b/doc/admin-guide/files/records.config.en.rst
index 7db9e6a9f6..44e857da91 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -2102,6 +2102,20 @@ Security
    policies is set in the corresponding :file:`sni.yaml` file entry and the 
:file:`sni.yaml` entry does not override
    this value via a :ref:`host_sni_policy<override-host-sni-policy>` attribute.
 
+.. ts:cv:: CONFIG proxy.config.acl.subjects STRING PEER
+
+   Specifies the list of data sources for getting client's IP address for ACL.
+   The value is a comma separated string, and the first available data source
+   will be used. If you configure a port to enable PROXY protocol, you probably
+   need to adjust this setting to have ``PROXY`` in the list.
+
+   ============= 
======================================================================
+   Value         Description
+   ============= 
======================================================================
+   ``PEER``      Use the IP address of the peer
+   ``PROXY``     Use the IP address from PROXY protocol
+   ============= 
======================================================================
+
 
 Cache Control
 =============
diff --git a/iocore/net/P_SNIActionPerformer.h 
b/iocore/net/P_SNIActionPerformer.h
index eebe44b75a..aaa7627aad 100644
--- a/iocore/net/P_SNIActionPerformer.h
+++ b/iocore/net/P_SNIActionPerformer.h
@@ -35,6 +35,7 @@
 #include "SSLTypes.h"
 
 #include "tscore/ink_inet.h"
+#include "../../proxy/IPAllow.h"
 
 #include <vector>
 
@@ -442,15 +443,25 @@ public:
       return SSL_TLSEXT_ERR_OK;
     }
 
-    auto ssl_vc = dynamic_cast<SSLNetVConnection *>(snis);
-    auto ip     = ssl_vc->get_remote_endpoint();
+    auto ssl_vc        = dynamic_cast<SSLNetVConnection *>(snis);
+    const sockaddr *ip = nullptr;
+    for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+      if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+        ip = ssl_vc->get_remote_addr();
+        break;
+      } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] &&
+                 ssl_vc->get_proxy_protocol_version() != 
ProxyProtocolVersion::UNDEFINED) {
+        ip = ssl_vc->get_proxy_protocol_src_addr();
+        break;
+      }
+    }
 
     // check the allowed ips
     if (ip_map.contains(ip)) {
       return SSL_TLSEXT_ERR_OK;
     } else {
       char buff[256];
-      ats_ip_ntop(&ip.sa, buff, sizeof(buff));
+      ats_ip_ntop(ip, buff, sizeof(buff));
       Debug("ssl_sni", "%s is not allowed. Denying connection", buff);
       return SSL_TLSEXT_ERR_ALERT_FATAL;
     }
diff --git a/iocore/net/libinknet_stub.cc b/iocore/net/libinknet_stub.cc
index a48273372a..76d1629b81 100644
--- a/iocore/net/libinknet_stub.cc
+++ b/iocore/net/libinknet_stub.cc
@@ -192,3 +192,5 @@ PreWarmManager::reconfigure()
 }
 
 PreWarmManager prewarmManager;
+
+uint8_t IpAllow::subjects[Subject::MAX_SUBJECTS];
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index e645bb6c6f..c127d1eafa 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -147,6 +147,14 @@ static const RecordElement RecordsConfig[] =
   {RECT_CONFIG, "proxy.config.srv_enabled", RECD_INT, "0", RECU_DYNAMIC, 
RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
   ,
 
+  
//##############################################################################
+  //#
+  //# ACL
+  //#
+  
//##############################################################################
+  {RECT_CONFIG, "proxy.config.acl.subjects", RECD_STRING, "PEER", 
RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+  ,
+
   
//##############################################################################
   //#
   //# Support for disabling check for Accept-* / Content-* header mismatch
diff --git a/proxy/IPAllow.cc b/proxy/IPAllow.cc
index 9f0976d4b1..0ed85d6ccc 100644
--- a/proxy/IPAllow.cc
+++ b/proxy/IPAllow.cc
@@ -25,6 +25,8 @@
  */
 
 #include <sstream>
+#include <string_view>
+
 #include "IPAllow.h"
 #include "tscore/BufferWriter.h"
 #include "tscore/ts_file.h"
@@ -114,6 +116,7 @@ const IpAllow::ACL IpAllow::DENY_ALL_ACL;
 
 size_t IpAllow::configid     = 0;
 bool IpAllow::accept_check_p = true; // initializing global flag for fast deny
+uint8_t IpAllow::subjects[Subject::MAX_SUBJECTS];
 
 static ConfigUpdateHandler<IpAllow> *ipAllowUpdate;
 
@@ -202,7 +205,35 @@ IpAllow::match(sockaddr const *ip, match_key_t key)
 //   End API functions
 //
 
-IpAllow::IpAllow(const char *config_var) : 
config_file(ats_scoped_str(RecConfigReadConfigPath(config_var)).get()) {}
+IpAllow::IpAllow(const char *config_var) : 
config_file(ats_scoped_str(RecConfigReadConfigPath(config_var)).get())
+{
+  RecString subjects_char;
+  REC_ReadConfigStringAlloc(subjects_char, "proxy.config.acl.subjects");
+  std::string_view subjects_sv{subjects_char};
+  int i = 0;
+  std::string_view::size_type s, e;
+
+  for (s = 0, e = 0; s < subjects_sv.size() && e != subjects_sv.npos; s = e + 
1) {
+    e                           = subjects_sv.find(",", s);
+    std::string_view subject_sv = subjects_sv.substr(s, e);
+    if (i >= MAX_SUBJECTS) {
+      Error("Too many ACL subjects were provided");
+    }
+    if (subject_sv == "PEER") {
+      subjects[i] = Subject::PEER;
+      ++i;
+    } else if (subject_sv == "PROXY") {
+      subjects[i] = Subject::PROXY;
+      ++i;
+    } else {
+      Debug("ip-allow", "Unknown subject %.*s was ignored", 
static_cast<int>(subject_sv.length()), subject_sv.data());
+    }
+  }
+  if (i < Subject::MAX_SUBJECTS) {
+    subjects[i] = Subject::MAX_SUBJECTS;
+  }
+  ats_free(subjects_char);
+}
 
 void
 IpAllow::PrintMap(const IpMap *map) const
diff --git a/proxy/IPAllow.h b/proxy/IPAllow.h
index 9221e7525b..8b1b2e75d9 100644
--- a/proxy/IPAllow.h
+++ b/proxy/IPAllow.h
@@ -102,6 +102,8 @@ public:
 
   static constexpr const char *MODULE_NAME = "IPAllow";
 
+  enum Subject { PEER, PROXY, MAX_SUBJECTS };
+
   /** An access control record and support data.
    * The primary point of this is to hold the backing configuration in memory 
while the ACL
    * is in use.
@@ -182,6 +184,8 @@ public:
 
   const ts::file::path &get_config_file() const;
 
+  static uint8_t subjects[Subject::MAX_SUBJECTS];
+
 private:
   static size_t configid;               ///< Configuration ID for update 
management.
   static const Record ALLOW_ALL_RECORD; ///< Static record that allows all 
access.
diff --git a/proxy/http/HttpSessionAccept.cc b/proxy/http/HttpSessionAccept.cc
index 29416da112..2bc19a1fb5 100644
--- a/proxy/http/HttpSessionAccept.cc
+++ b/proxy/http/HttpSessionAccept.cc
@@ -33,6 +33,16 @@ HttpSessionAccept::accept(NetVConnection *netvc, MIOBuffer 
*iobuf, IOBufferReade
   IpAllow::ACL acl;
   ip_port_text_buffer ipb;
 
+  for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+    if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+      client_ip = netvc->get_remote_addr();
+      break;
+    } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] &&
+               netvc->get_proxy_protocol_version() != 
ProxyProtocolVersion::UNDEFINED) {
+      client_ip = netvc->get_proxy_protocol_src_addr();
+      break;
+    }
+  }
   acl = IpAllow::match(client_ip, IpAllow::SRC_ADDR);
   if (!acl.isValid()) { // if there's no ACL, it's a hard deny.
     Warning("client '%s' prohibited by ip-allow policy", 
ats_ip_ntop(client_ip, ipb, sizeof(ipb)));
diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc
index cddc865a65..78dd61d9c2 100644
--- a/proxy/http/remap/UrlRewrite.cc
+++ b/proxy/http/remap/UrlRewrite.cc
@@ -402,6 +402,26 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s, 
url_mapping *map)
     bool client_enabled_flag = true;
 
     ink_release_assert(ats_is_ip(&s->client_info.src_addr));
+    const IpEndpoint *src_addr   = nullptr;
+    const IpEndpoint *local_addr = nullptr;
+    const ProxyProtocol &pp_info = 
s->state_machine->get_ua_txn()->get_netvc()->get_proxy_protocol_info();
+    for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+      if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+        src_addr   = &s->client_info.src_addr;
+        local_addr = &s->client_info.dst_addr;
+        break;
+      } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] && 
pp_info.version != ProxyProtocolVersion::UNDEFINED) {
+        src_addr   = &pp_info.src_addr;
+        local_addr = &pp_info.dst_addr;
+        break;
+      }
+    }
+
+    if (src_addr == nullptr) {
+      // Use addresses from peer if none of the configured sources are 
avaialable
+      src_addr   = &s->client_info.src_addr;
+      local_addr = &s->client_info.dst_addr;
+    }
 
     for (acl_filter_rule *rp = map->filter; rp && client_enabled_flag; rp = 
rp->next) {
       bool match = true;
@@ -421,7 +441,7 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s, 
url_mapping *map)
       if (match && rp->src_ip_valid) {
         match = false;
         for (int j = 0; j < rp->src_ip_cnt && !match; j++) {
-          bool in_range = 
rp->src_ip_array[j].contains(s->client_info.src_addr);
+          bool in_range = rp->src_ip_array[j].contains(*src_addr);
           if (rp->src_ip_array[j].invert) {
             if (!in_range) {
               match = true;
@@ -438,16 +458,14 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s, 
url_mapping *map)
         Debug("url_rewrite", "match was true and we have specified a in_ip 
field");
         match = false;
         for (int j = 0; j < rp->in_ip_cnt && !match; j++) {
-          IpEndpoint incoming_addr;
-          
incoming_addr.assign(s->state_machine->ua_txn->get_netvc()->get_local_addr());
           if (is_debug_tag_set("url_rewrite")) {
             char buf1[128], buf2[128], buf3[128];
-            ats_ip_ntop(incoming_addr, buf1, sizeof(buf1));
+            ats_ip_ntop(local_addr, buf1, sizeof(buf1));
             rp->in_ip_array[j].start.toString(buf2, sizeof(buf2));
             rp->in_ip_array[j].end.toString(buf3, sizeof(buf3));
             Debug("url_rewrite", "Trying to match incoming address %s in range 
%s - %s.", buf1, buf2, buf3);
           }
-          bool in_range = rp->in_ip_array[j].contains(incoming_addr);
+          bool in_range = rp->in_ip_array[j].contains(*local_addr);
           if (rp->in_ip_array[j].invert) {
             if (!in_range) {
               match = true;
diff --git a/proxy/http2/Http2SessionAccept.cc 
b/proxy/http2/Http2SessionAccept.cc
index f0226fdee8..6cf0ae775f 100644
--- a/proxy/http2/Http2SessionAccept.cc
+++ b/proxy/http2/Http2SessionAccept.cc
@@ -36,8 +36,20 @@ Http2SessionAccept::~Http2SessionAccept() = default;
 bool
 Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, 
IOBufferReader *reader)
 {
-  sockaddr const *client_ip = netvc->get_remote_addr();
-  IpAllow::ACL session_acl  = IpAllow::match(client_ip, IpAllow::SRC_ADDR);
+  sockaddr const *client_ip = nullptr;
+
+  for (int i = 0; i < IpAllow::Subject::MAX_SUBJECTS; ++i) {
+    if (IpAllow::Subject::PEER == IpAllow::subjects[i]) {
+      client_ip = netvc->get_remote_addr();
+      break;
+    } else if (IpAllow::Subject::PROXY == IpAllow::subjects[i] &&
+               netvc->get_proxy_protocol_version() != 
ProxyProtocolVersion::UNDEFINED) {
+      client_ip = netvc->get_proxy_protocol_src_addr();
+      break;
+    }
+  }
+
+  IpAllow::ACL session_acl = IpAllow::match(client_ip, IpAllow::SRC_ADDR);
   if (!session_acl.isValid()) {
     ip_port_text_buffer ipb;
     Warning("HTTP/2 client '%s' prohibited by ip-allow policy", 
ats_ip_ntop(client_ip, ipb, sizeof(ipb)));
diff --git a/tests/gold_tests/autest-site/trafficserver.test.ext 
b/tests/gold_tests/autest-site/trafficserver.test.ext
index 80848aa2cf..6979523508 100755
--- a/tests/gold_tests/autest-site/trafficserver.test.ext
+++ b/tests/gold_tests/autest-site/trafficserver.test.ext
@@ -44,7 +44,7 @@ def MakeATSProcess(
         enable_quic=False,
         block_for_debug=False,
         log_data=default_log_data,
-        use_traffic_out=True):
+        use_traffic_out=True, enable_proxy_protocol=False):
     #####################################
     # common locations
 
@@ -328,6 +328,14 @@ def MakeATSProcess(
         if enable_tls:
             get_port(p, "ssl_port")
             get_port(p, "ssl_portv6")
+
+        if enable_proxy_protocol:
+            get_port(p, "proxy_protocol_port")
+            get_port(p, "proxy_protocol_portv6")
+
+            if enable_tls:
+                get_port(p, "proxy_protocol_ssl_port")
+                get_port(p, "proxy_protocol_ssl_portv6")
     else:
         p.Variables.port = 8080
         p.Variables.portv6 = 8080
@@ -381,6 +389,10 @@ def MakeATSProcess(
         if enable_quic:
             port_str += " {ssl_port}:quic {ssl_portv6}:quic:ipv6".format(
                 ssl_port=p.Variables.ssl_port, 
ssl_portv6=p.Variables.ssl_portv6)
+        if enable_proxy_protocol:
+            port_str += f" {p.Variables.proxy_protocol_port}:pp 
{p.Variables.proxy_protocol_portv6}:pp:ipv6"
+            if enable_tls:
+                port_str += f" {p.Variables.proxy_protocol_ssl_port}:pp:ssl 
{p.Variables.proxy_protocol_ssl_portv6}:pp:ssl:ipv6"
         #p.Env['PROXY_CONFIG_HTTP_SERVER_PORTS'] = port_str
         p.Disk.records_config.update({
             'proxy.config.http.server_ports': port_str,
diff --git a/tests/gold_tests/remap/remap_acl.test.py 
b/tests/gold_tests/remap/remap_acl.test.py
index 288c8d7de2..08c913cba2 100644
--- a/tests/gold_tests/remap/remap_acl.test.py
+++ b/tests/gold_tests/remap/remap_acl.test.py
@@ -43,7 +43,7 @@ class Test_remap_acl:
 
     def __init__(
             self, name: str, replay_file: str, ip_allow_content: str, 
deactivate_ip_allow: bool,
-            acl_configuration: str, named_acls: List[Tuple[str, str]], 
expected_responses: List[int]):
+            acl_configuration: str, named_acls: List[Tuple[str, str]], 
expected_responses: List[int], proxy_protocol: bool):
         """Initialize the test.
 
         :param name: The name of the test.
@@ -64,7 +64,7 @@ class Test_remap_acl:
         tr = Test.AddTestRun(name)
         self._configure_server(tr)
         self._configure_traffic_server(tr)
-        self._configure_client(tr)
+        self._configure_client(tr, proxy_protocol)
 
     def _configure_server(self, tr: 'TestRun') -> None:
         """Configure the server.
@@ -83,16 +83,17 @@ class Test_remap_acl:
         """
 
         name = f"ts-{Test_remap_acl._ts_counter}"
-        ts = tr.MakeATSProcess(name, enable_cache=False, enable_tls=True)
+        ts = tr.MakeATSProcess(name, enable_cache=False, enable_tls=True, 
enable_proxy_protocol=True)
         Test_remap_acl._ts_counter += 1
         self._ts = ts
 
         ts.Disk.records_config.update(
             {
                 'proxy.config.diags.debug.enabled': 1,
-                'proxy.config.diags.debug.tags': 'http|url|remap|ip_allow',
+                'proxy.config.diags.debug.tags': 
'http|url|remap|ip-allow|proxyprotocol',
                 'proxy.config.http.push_method_enabled': 1,
                 'proxy.config.http.connect_ports': 
self._server.Variables.http_port,
+                'proxy.config.acl.subjects': 'PROXY,PEER',
             })
 
         remap_config_lines = []
@@ -111,14 +112,15 @@ class Test_remap_acl:
         ts.Disk.remap_config.AddLines(remap_config_lines)
         ts.Disk.ip_allow_yaml.AddLines(self._ip_allow_content.split("\n"))
 
-    def _configure_client(self, tr: 'TestRun') -> None:
+    def _configure_client(self, tr: 'TestRun', proxy_protocol: bool) -> None:
         """Run the test.
 
         :param tr: The TestRun object to associate the client process with.
         """
 
         name = f"client-{Test_remap_acl._client_counter}"
-        p = tr.AddVerifierClientProcess(name, self._replay_file, 
http_ports=[self._ts.Variables.port])
+        port = self._ts.Variables.port if proxy_protocol == False else 
self._ts.Variables.proxy_protocol_port
+        p = tr.AddVerifierClientProcess(name, self._replay_file, 
http_ports=[port])
         Test_remap_acl._client_counter += 1
         p.StartBefore(self._server)
         p.StartBefore(self._ts)
@@ -159,6 +161,25 @@ def replay_proxy_response(filename, replay_file, 
get_proxy_response, post_proxy_
     with open(replay_file, "w") as f:
         f.write(dump(data))
 
+IP_ALLOW_CONTENT = f'''
+ip_allow:
+  - apply: in
+    ip_addrs: 0/0
+    action: allow
+    methods:
+      - GET
+'''
+
+test_ip_allow_optional_methods_pp = Test_remap_acl(
+    "Verify non-allowed methods are blocked (PP).",
+    replay_file='remap_acl_get_post_allowed_pp.replay.yaml',
+    ip_allow_content=IP_ALLOW_CONTENT,
+    deactivate_ip_allow=True,
+    acl_configuration='@action=allow @src_ip=1.2.3.4 @method=GET @method=POST',
+    named_acls=[],
+    expected_responses=[200, 200, 403, 403, 403],
+    proxy_protocol=True)
+
 """
 Test all acl combinations
 # """
@@ -178,6 +199,7 @@ for idx, test in enumerate(all_acl_combination_tests):
         acl_configuration=test["inline"],
         named_acls=[("acl", test["named_acl"])] if test["named_acl"] != "" 
else [],
         expected_responses=[test["GET response"], test["POST response"]],
+        proxy_protocol=False,
     )
 
 """
@@ -202,7 +224,9 @@ for idx, test in enumerate(all_deactivate_ip_allow_tests):
         deactivate_ip_allow=test["deactivate_ip_allow"],
         acl_configuration=test["inline"],
         named_acls=[("acl", test["named_acl"])] if test["named_acl"] != "" 
else [],
-        expected_responses=[test["GET response"], test["POST response"]])
+        expected_responses=[test["GET response"], test["POST response"]],
+        proxy_protocol=False,
+    )
 
 """
 Test combination of named filters
@@ -223,4 +247,5 @@ for idx, test in enumerate(named_filter_combination_tests):
         acl_configuration="",
         named_acls=[("acl_1", test["named_acl_1"]), ("acl_2", 
test["named_acl_2"])],
         expected_responses=[test["GET response"], test["POST response"]],
+        proxy_protocol=False,
     )
diff --git a/tests/gold_tests/remap/remap_acl_get_post_allowed_pp.replay.yaml 
b/tests/gold_tests/remap/remap_acl_get_post_allowed_pp.replay.yaml
new file mode 100644
index 0000000000..5d2eb68c67
--- /dev/null
+++ b/tests/gold_tests/remap/remap_acl_get_post_allowed_pp.replay.yaml
@@ -0,0 +1,152 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+# This expects a remap.config that allows GET and POST, but denies all other
+# methods.
+
+meta:
+  version: "1.0"
+
+  blocks:
+  - standard_response: &standard_response
+      server-response:
+        status: 200
+        reason: OK
+        headers:
+          fields:
+          - [ Content-Length, 20 ]
+
+sessions:
+- protocol:
+  - name: http
+    version: 1
+  - name: proxy-protocol
+    version: 2
+    src-addr: "1.2.3.4:1111"
+    dst-addr: "5.6.7.8:2222"
+  transactions:
+
+  - client-request:
+      method: "GET"
+      version: "1.1"
+      url: /test/ip_allow/test_get
+      headers:
+        fields:
+        - [ Content-Length, 0 ]
+        - [ uuid, get ]
+        - [ X-Request, get ]
+
+    <<: *standard_response
+
+    proxy-response:
+      status: 200
+
+  # POST also is in the allow list.
+  - client-request:
+      method: "POST"
+      version: "1.1"
+      url: /test/ip_allow/test_post
+      headers:
+        fields:
+        - [Content-Length, 10]
+        - [ uuid, post ]
+        - [ X-Request, post ]
+
+    <<: *standard_response
+
+    proxy-response:
+      status: 200
+
+  # PUT rejected
+  - client-request:
+      method: "PUT"
+      version: "1.1"
+      url: /test/ip_allow/test_put
+      headers:
+        fields:
+        - [ Host, example.com ]
+        - [ uuid, put ]
+        - [ X-Request, put ]
+        - [ Content-Length, 113 ]
+      content:
+        encoding: plain
+        data: "HTTP/1.1 200 OK\nServer: ATS/10.0.0\nAccept-Ranges: 
bytes\nContent-Length: 6\nCache-Control: public,max-age=2\n\nCACHED"
+
+    # Not received.
+    <<: *standard_response
+
+    # Verify that ATS rejected the PUSH.
+    proxy-response:
+      status: 403
+
+- protocol:
+  - name: http
+    version: 1
+  - name: proxy-protocol
+    version: 2
+    src-addr: "1.2.3.4:1111"
+    dst-addr: "5.6.7.8:2222"
+  delay: 2s
+  transactions:
+
+  # DELETE rejected
+  - client-request:
+      method: "DELETE"
+      version: "1.1"
+      url: /test/ip_allow/test_delete
+      headers:
+        fields:
+        - [ Host, example.com ]
+        - [ uuid, delete ]
+        - [ X-Request, delete ]
+        - [ Content-Length, 0 ]
+
+    <<: *standard_response
+
+    # Verify that ATS rejects the DELETE.
+    proxy-response:
+      status: 403
+
+- protocol:
+  - name: http
+    version: 1
+  - name: proxy-protocol
+    version: 2
+    src-addr: "1.2.3.4:1111"
+    dst-addr: "5.6.7.8:2222"
+  delay: 4s
+  transactions:
+
+  # PUSH rejected
+  - client-request:
+      method: "PUSH"
+      version: "1.1"
+      url: /test/ip_allow/test_push
+      headers:
+        fields:
+        - [ Host, example.com ]
+        - [ uuid, push ]
+        - [ X-Request, push ]
+        - [ Content-Length, 113 ]
+      content:
+        encoding: plain
+        data: "HTTP/1.1 200 OK\nServer: ATS/10.0.0\nAccept-Ranges: 
bytes\nContent-Length: 6\nCache-Control: public,max-age=2\n\nCACHED"
+
+    <<: *standard_response
+
+    # Verify that ATS rejected the PUSH.
+    proxy-response:
+      status: 403

Reply via email to