diff --git a/authorize/evaluator/opa/policy/authz.rego b/authorize/evaluator/opa/policy/authz.rego index e9f18735b..6933c4ac8 100644 --- a/authorize/evaluator/opa/policy/authz.rego +++ b/authorize/evaluator/opa/policy/authz.rego @@ -153,7 +153,7 @@ allowed_route_regex(input_url_obj, policy) { parse_url(str) = { "scheme": scheme, "host": host, "path": path } { [_, scheme, host, rawpath] = regex.find_all_string_submatch_n( - `(?:(http[s]?)://)?([^/]+)([^?#]*)`, + `(?:((?:tcp[+])?http[s]?)://)?([^/]+)([^?#]*)`, str, 1)[0] path = normalize_url_path(rawpath) } diff --git a/authorize/evaluator/opa/policy/authz_test.rego b/authorize/evaluator/opa/policy/authz_test.rego index d7720b12d..b3b4eb79a 100644 --- a/authorize/evaluator/opa/policy/authz_test.rego +++ b/authorize/evaluator/opa/policy/authz_test.rego @@ -301,6 +301,13 @@ test_parse_url { url.path == "/some/path" } +test_parse_tcp_url { + url := parse_url("tcp+http://example.com/some/path?qs") + url.scheme == "tcp+http" + url.host == "example.com" + url.path == "/some/path" +} + test_allowed_route_source { allowed_route("http://example.com", {"source": "example.com"}) allowed_route("http://example.com", {"source": "http://example.com"}) diff --git a/authorize/evaluator/opa/policy/statik.go b/authorize/evaluator/opa/policy/statik.go index b188e78d9..9aad7978c 100644 --- a/authorize/evaluator/opa/policy/statik.go +++ b/authorize/evaluator/opa/policy/statik.go @@ -9,6 +9,6 @@ import ( const Rego = "rego" // static asset namespace func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\xa5\x92eQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01\x96B\xa4_\xacXOw\x9c6\x10?\xc3\xa7\x98\x92\x0b\xb4\x18'\xfds\xe8\xe6Q\xd7/\xa7\x1eZ\xe7%\xcd\x89G\x14\x01\xda]\xc5 QI8\xde8\xf9\xee}\xfa\xc3.\xb0\x0bv\xec\xf8\xe0\xdd\x1d\xcd\xfc\xe67\xa3a4\xa2\xc5\xe55\xde\x10hyC\x04\xed\x9a\x04wj\xfb\xd9\xf7+\xb2\xc6]\xad\x00\xd75\xff\x04)\xacq-\x89\xef\xfb\x82w\x8a\xa0\x96\xd7\xb4\xdc!Z\xdd\xc2*\x855\x15R!\xa3I*4\xd5\x08)k;\x95l\x95j\x93N\xd4\xd1\x08B\x9bWX\xe1d \xa4DfS\x90\xdc\x97DJ\xca\x996\xb0\x80\xda\xac\x10\xfc\x9a\x08d\x10\x9c\x82\xdfI\"\xe6\xb5\xf4\xaa\xbf\x11\xbck\xe5\xbc\x92]\xf7}\\\xd7\xfb\xb0*\xde`\xca\x8c\xd1\x86\xa8\xa98\x1c\x12\x8eF\x86\x07gC;+]0\xd3D\x8f\xac\x8cp\xc1\x88V-*kL\x9b#\xcb\xc3\xca\xc4\xdc\x7f\xe6\xf6\xb8\xed\x8a\x9a\x96\xbe\xfdq\xe7{C\xb5\xe4RK_\x1b\x8dwL\x97\x08a\x8a\x96X\x91\xea\xb2,\x89\x94\x90\xa6\xa0DG\xfc\xaf\x07\xc0\x92\x0b \xad \xeb\x9an\xb6j\x06\xf8\xd5\xd5\x9b\xb7\x16\xbcW\xdcCy\x83\xc2i\x88\xda\xf2J/\x05W\xaf\xff\xfd\xeb\xea\x9f\xb7\x81\xef\x95\xbcc*\xe4\xc5GR\xaadC\xd4\xb0\xd2\xb6\x04WD\xc8\x18\x02K\xf0\xec\x15gJ\xf0\xfa\xec\x0d\xf9\xaf#R\x9d\xfdm\x10\x83\x18\xb2<\x8a\xe0\x0fx\xfeP\xbc+A7\x94\x0d\x0d\x071c\xb6\x83Qz\xc0\x14\\\x1f;\x00\xc0q^/\xd9\xeerh\xf3NWp\x9f\x05m\xe2J\xdb\x14/\xa2\x15\xfc\x90B\x10\x0c\xdd\x16; \x0d\xa6\xf5!\xc9Z512\x8dtTX\x19\xca\xfb\xfc\xf6\xe0\xb4i\x89\x90\x9caE\xd0\xdep\xec\xc6\x14\xed\xc1\x87\xe4\x0dq2\xcf\xd6s\x86rH{\xd1\xf1C0Z\x9e\xf7\xee\x9e\x984\x05\xd6\xd5\xf5$\xce\x81\xe24\xe6SQB\xff\x8c\xcf\x86\xb9\x80\xbf\x10\xef}\xec\xbf!\x13c\xff\xb6\xa1L\x9c:\xa1g\x08#\xca\\\xdb \x0f\xbb\x1c\xc3\x89f\x95\xd9\xcf\x10c\x08\xce\x93\xde\xe4<\x88|\x8fq\x05\x0fR\xc6UCY0\xf2mN?*\xc1,\x1d|\x93\x9a4\x84)\xbdG5\x95*4\xc7\x9c\xd1\x91.\x0e\xb33\xd1\x12\xcb\x19\xbf\x15a;`\x9c\x9d\x19)\xd8sk-x\x03Xw^\xca6\x96\x8cm|\xd2\xd7\xfa\x99 Xr\x96\x9b\xe3\xc0|\x85\x14\xb2_\x9f\xff\x12C\xd0G\xa0\xb3`\x1d\xe56%O\x8f\xe1t\x08\x0b\x84~\xff-\x86\x80\xb2\x1b\\\xd3\n\xca\x9a\x12\xa6\xa0$B\xd1\xb5\xe9\xd4\x9a\x19\x95\xa8\xe0\xbc&\xb8/{*\x91\xd1GV\x1f\x0d\xf4\xdd\xde\xde\xabg\x13+\x88\xea\x04\x93\xa0\xb6\xc4\x8eX\xd0`UnuBM*\xfd\x87\xcc]H\x8f\\\xd0\xcfh\x83\xb9\xed\xce\xf7\x8ed\xab\x142\xfd\xf9\x05\xcc\xe3M\xab\xdb\x18\xec\xf2K\xf7 \xa7\xc75=\xa1\xbd\x84\x11\x93\xa3\xfaq\x03G\x9e=\xcfu|'\x94\xd1P\xef\xce\xf5,-D\xbc\xf8\xa8\xc9\xb5XH\xa2\x05\x83\xd8Lw\x1d$@\xf2N\x94\x03@m\xbb\x07\x9d*\xeb\xe9\x84\xde>T\x19\xab\xed\x03U\x05\xd9\x90Y\xd8i\xf0\xcb\x94\xf5F\x0dF\x12+\x8d!\xb0FA\x0cA\x10\xed\xbb\xf7\xf7\xc6\xb5\x83\x86ge\xa7w\xc2\x0d2V%\x9alZ\xb2\xe5\xd2\x0ctc\x04#>\xce\xc3\xe2n\xcc\xf1\xb5F\x8byx:n\x9f\x07\x85\x85\x92\x9f\xe8\xb4\x0e\x12]\x1a=bb-O\xec\xf3B\x01\xcd\xb2\xc0j\xbb\x1c\xdb\x930]\\=q\xac\xb6\xda\xcdql\xc7\xb1,U\xf8\x9ccc\xb3\x18\xcdSQ]<\x82 \xd3*\xfb\xe24*\xf1\x89\xb8\xcc&\x1djY*\xa1{\xe5\x1d\x04\xb2\xdc\x92\x86\x04+\xb0_b\x08t\xc9\x06+\xd0\x1f}\x0eW`2\xf6U3\xcbP\xbc\xd7\xb5:\x02\x7f\xd2\xcbz\xce3\xfe\x935e\x95\xee\xd6H*A\xd9\x06\xc9\xae0,\x11\x0b}\xcf\xfb\x10^\xacB\xdd-3\x99_D\xab\xf3\xf3\xe8\"\xcc\xde\x9f\xe7?Ea\xf6\xfe\xe2Y\xfec\xf4!\xf6=O*\x11\xc3\x8bH7Q\xcf\xee\x170.\x1a\\\xd3\xcf\xf6\xf12\x05\xe1|\x9b\xf0N,\xbb8\x83\xf3\xc0\x8crJ\xec\xb7c^Yk9\xe5\xfd\xf5c:\xf7\xb9\xe9\xce\xfe2\x1bf\xce\x14\xd9\xd6T\xf5\x8b\xc1\x9fA\xd4_\xb5nM\x1d\xfc\xec{\xb7\xd9\x8b\\\x7fu\x03\xa5\x86\x9e\x1c\xf6\xfa_lF\x80\xc8\xccj\xfa\xb7\x1d\xa2\xb5L[\x1c\xdf\x93\xfb\xc2I\xe1\xc6\xcdw\xb2+&\x17\xec\x142\xd9&c\xd9\x17\x90\xadir\xae\xb5u\xc5\xe1\xa4Cyn\x90n\xb4\xc2\x1d\xe8\xb3\xf2\x16R\xc0B\xe0]RrVb\x15\x1a\x05\xfd\xe7\x00F\xe8\xf1~5\xeb\xe0\x0bt\xf3\x8e\xc6v{\xcf\x91\x0e\xfb\xeb4\xe2\xfe=\xc4q\xcc\x8fa\xea\xd0\x1e\xc1\xb5\x9f\xe6\x97\xd9\xba\xb7\x1f\xdf\x87\xac\x05{\x04\xd7\xfdUl\x89\xea\xe0\xc5\xc9\x0c\xdd\xd3$\xb3 \xcb\x03N\xfe\x08\xaa\x03kkl\x8f\x97\x13\xd7\x95\x18\x8a\xc8\xb1\xa3\x12\xd9\x86\x19\xe2h\"(\xac\x00\xdf\x98\x17E8\xc3\xd7\x16\xb7\xb0\x82A\x9f-b\xc0\xd7\xb1\xb9\x89G~\x8fbB\x0e\xf1\x8d\x8c\xc6\x92\xa2\x97\xe0\x1b{\xc5M5b\x86\xf4\xc4\xf7\x7f\x00\x00\x00\xff\xffPK\x07\x08\xe1\x91\x85!x\x05\x00\x00j\x14\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\xa5\x92eQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00authz_test.regoUT\x05\x00\x01\x96B\xa4_\xecY[o\xdb6\x14~\xb6~\x05\xc1\xa7fpd$\xed\xf6\x10 X\x82b\x18\xf6\xb0\xa5\xe8\xe5)0\x04Zbm\xae\x92\xa8R\x14j\xc7\xf0\x7f\x1fxHJ\x94-\xc9\xb2\x1a;\x01f=\xb4\x16u\xae\xdfw\x0eo\xc9H\xf8\x8d\xcc)\xcaxB\x05+\x12\x9f\x14r\xf1\xe4y\x92\xe62\xa0 aq@\xe2\x98\xff\xa0\x11Z{#\xf8\x89~0\xb9\xf0F\xa3\x88H\xe2\x0b^H\x1ad\xc2\xcaj\xc0\"\xe5Z\xfd\xbc\xc2jx\xa3=\xab\x81J\x12\xf2Sru\xf7 \xafB\xa8G\xb0\x902\x03\xb7\x08\x17\x02\xd4\xd4\xc8\xcdd\xe2\xea\xa2-%\x13\x9d\xd1\xd3Q\x99\xb1+\xc4\xce\xe4\xb9\x0c\xed\xb73\xe9g\xa8GD\xdaR\xd9\x86\xad\xd6\xb8\x98w\xd3\xd5\\\x0dz\x03\xd0\xbf\x1a\x9c\x0dC\xcf\x14a\xae\x87\xb2\x84\xaa\xdc2\xa2W\x82~)6\xc4P\xaa\xb7d\xa7\xda\xa2\x7fnv\xc7\xdf3\xb3\x06\xa5^I4BR\x9ej\x86\x00\xb2\xa3\xdc\x0c\x87\xa0sz\x00\xd7 \xae\xec\xfa\xbf\xf4D\xa4!\xb1\xd2\x88\xf9hl\xf5O\xae4\xf0\xb8\\=M\xdd\xe4\xf2b\xa6\xd7\xa0\x95\xcai\xa9\xa6\xda9\xadr\x86u\xe6Mu\xdc\xde{\xa5\xd0\xb0B\x15p\xda(\xae\xd5\xc2P\xd9\xb1~\x19\x05\xa9\xda\xb1|\xdda\xe6-\x9e\xa2\xcd\xb8\x87\xf85\x88\xbf\x83\xfbb+\xa9\xef\x03\x14vK5\xd3\xaf\xab\xd8\xb4i\xad\xb1\xf1\xe2\xcc\xd5\xe9*\xa8\x9d\x8baF8\xc2y\x07\x8e0\xf7\xe9\xea\xdeu\xf6E_A\xb7\x9cf\xfeO\xd7\xdc\xcei\xbb\x85\x92\xa3\x1c\x8f\x06\xb0rjL\xfe\x0b\x00\x00\xff\xffPK\x07\x088\xf7w\xee\xf1\x04\x00\x00\xab&\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xa5\x92eQ\xe1\x91\x85!x\x05\x00\x00j\x14\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\x96B\xa4_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xa5\x92eQ8\xf7w\xee\xf1\x04\x00\x00\xab&\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xb9\x05\x00\x00authz_test.regoUT\x05\x00\x01\x96B\xa4_PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\xf0\n\x00\x00\x00\x00" + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00q\x82\x8fQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01\x16\xe2\xd8_\xacX]w\x9b8\x13\xbe\x86_1/\xbd\x81\xb7\x84\xb4\xfbq\xb1\xeea\xb39\xbd\xda\x8b\xdd\xf4\xb4\xdb+\x0eU\x05\xc8\xb6\x1a\x90XI\xa4q\xd3\xfe\xf7=\xfa\xc0\x06lH\x9a4\x17\xb1=\x9ay\xe6\x99\xd10\x1a\xd1\xe2\xf2\x1ao\x08\xb4\xbc!\x82vM\x82;\xb5\xfd\xe2\xfb\x15Y\xe3\xaeV\x80\xeb\x9a\x7f\x86\x14\xd6\xb8\x96\xc4\xf7}\xc1;EP\xcbkZ\xee\x10\xadna\x95\xc2\x9a\n\xa9\x90\xd1$\x15\x9aj\x84\x94\xb5\x9dJ\xb6J\xb5I'\xeah\x04\xa1\xcd+\xacp2\x10R\"\xb3)H\xeeK\"%\xe5L\x1bX@mV\x08~M\x042\x08N\xc1\xef$\x11\xf3Zz\xd5\xdf\x08\xde\xb5r^\xc9\xae\xfb>\xae\xeb}X\x15o0e\xc6hC\xd4T\x1c\x0e G#\xc3\x83\xb3\xa1\x9d\x95.\x98i\xa2GVF\xb8`D\xab\x16\x955\xa6\xcd\x91\xe5aeb\xee?s{\xdcvEMK\xdf\xfe\xb8\xf3\xbd\xa1Zr\xa9\xa5o\x8c\xc6{\xa6K\x840EK\xacHuY\x96DJHSP\xa2#\xfe\xb7\x03`\xc9\x85\x84V\x90uM7[5\x03\xfc\xfa\xea\xed;\x0b\xde+\xee\xa1\xbcA\xe14Dmy\xa5\x97\x82\xab7\xff\xfcy\xf5\xf7\xbb\xc0\xf7J\xde1\x15\xf2\xe2\x13)U\xb2!jXi[\x82+\"d\x0c\x81%x\xf6\x9a3%x}\xf6\x96\xfc\xdb\x11\xa9\xce\xfe2\x88A\x0cY\x1eE\xf0;\xbcx(\xde\x95\xa0\x1b\xca\x86\x86\x83\x981\xdb\xc1(=`\n\xae\x8f\x1d\x00\xe08\xaf\x97lw9\xb4y\xaf+\xb8\xcf\x826q\xa5m\x8a\x17\xd1\n\xfe\x97B\x10\x0c\xdd\x16; \x0d\xa6\xf5!\xc9Z512\x8dtTX\x19\xca\xfb\xfc\xf6\xe0\xb4i\x89\x90\x9caE\xd0\xdep\xec\xc6\x14\xed\xc1\x87\xe4\x0dq2\xcf\xd6s\x86rH{\xd1\xf1C0Z\x9e\xf7\xee\x9e\x984\x05\xd6\xd5\xf5$\xce\x81\xe24\xe6SQB\xff\x8c\xcf\x86\xb9\x80\xbf\x10\xef}\xec\xbf#\x13c\xff\xb6\xa1L\x9c:\xa1g\x08#\xca\\\xdb \x0f\xbb\x1c\xc3\x89f\x95\xd9\xcf\x10c\x08\xce\x93\xde\xe4<\x88|\x8fq\x05\x0fR\xc6UCY0\xf2mN?*\xc1,\x1d|\x93\x9a4\x84)\xbdG5\x95*4\xc7\x9c\xd1\x91.\x0e\xb33\xd1\x12\xcb\x19\xbf\x15a;`\x9c\x9d\x19)\xd8sk-x\x03Xw^\xca6\x96\x8cm|\xd2\xd7\xfa\x99 Xr\x96\x9b\xe3\xc0|\x85\x14\xb2_^\xfc\x1cC\xd0G\xa0\xb3`\x1d\xe56%O\x8f\xe1t\x08\x0b\x84~\xfb5\x86\x80\xb2\x1b\\\xd3\n\xca\x9a\x12\xa6\xa0$B\xd1\xb5\xe9\xd4\x9a\x19\x95\xa8\xe0\xbc&\xb8/{*\x91\xd1GV\x1f\x0d\xf4\xdd\xde\xde\xabg\x13+\x88\xea\x04\x93\xa0\xb6\xc4\x8eX\xd0`UnuBM*\xfd\x87\xcc]H\x8f\\\xd0\xcfh\x83\xb9\xed\xce\xf7\x8ed\xab\x142\xfd\xf9\x15\xcc\xe3M\xab\xdb\x18\xec\xf2+\xf7 \xa7\xc75=\xa1\xbd\x82\x11\x93\xa3\xfaq\x03G\x9e\xbd\xc8u|'\x94\xd1P\xef\xce\xf5,-D\xbc\xf8\xa4\xc9\xb5XH\xa2\x05\x83\xd8Lw\x1d$@\xf2N\x94\x03@m\xbb\x07\x9d*\xeb\xe9\x84\xde>T\x19\xab\xed\x03U\x05\xd9\x90Y\xd8i\xf0\xcb\x94\xf5F\x0dF\x12+\x8d!\xb0FA\x0cA\x10\xed\xbb\xf7\x8f\xc6\xb5\x83\x86ge\xa7w\xc2\x0d2V%\x9alZ\xb2\xe5\xd2\x0ctc\x04#>\xce\xc3\xe2n\xcc\xf1\xb5F\x8byx:n\x9f\x07\x85\x85\x92\x9f\xe9\xb4\x0e\x12]\x1a=bb-O\xec\xf3B\x01\xcd\xb2\xc0j\xbb\x1c\xdb\x930]\\=q\xac\xb6\xda\xcdql\xc7\xb1,U\xf8\x9ccc\xb3\x18\xcdSQ]<\x82 \xd3*\xfb\xe24*\xf1\x89\xb8\xcc&\x1djY*\xa1{\xe5\x1d\x04\xb2\xdc\x92\x86\x04+\xb0_b\x08t\xc9\x06+\xd0\x1f}\x0eW`2\xf6M3\xcbP\xbc\xd7\xb5:\x02\x7f\xd6\xcbz\xce3\xfe\x935e\x95\xee\xd6H*A\xd9\x06\xc9\xae0,\x11\x0b}\xcf\xfb\x18^\xac\xc2\xf0b\xa5\xca6{\x9eG\x17\xbaqf2\xbf\x88V\xe7\xe7\xd1E\x98}8\xcf\x9fGa\xf6\xe1\xe2Y\xfe\xff\xe8c\xec{\x9eT\"\x86\x97\x91\xee\xa7\x9e\xdd:`\\4\xb8\xa6_\xec\x93fj\xc3\xd10\x91\x9eXv!\x07\xe7\x81\x99\xea\x94\xd8\xef\xcc\xbc\xb2\xd6r\xca\xfb\x9b\xc8t\x04t\x83\x9e\xfde\xf6\xce\x1c/\xb2\xad\xa9\xea\x17\x83?\x82\xa8\xbfu\xdd\x9a\x92\xf8\xc9\xf7n\xb3\x97\xb9\xfe\xeafK\x0d=9\xf7\xf5\xbf\xd8L\x03\x91\x19\xdb\xf4o;Ok\x99\xb68\xbe2\xf75\x94\xc2\x8d\x1b\xf5dWL\xee\xda)d\xb2M\xc6\xb2\xaf [\xd3\xef\\\x97\xeb\x8a\xc3\xa1\x87\xf2\xdc \xddh\x85;\xd0\xc7\xe6-\xa4\x80\x85\xc0\xbb\xa4\xe4\xac\xc4*4\n\xfa\xcf\x01\x8c\xd0\xe3\xfdj\xd6\xc1W\xe8\xe6\x1d\x8d\xed\xf6\x9e#\x1d\xf6\xb7i\xc4\xfd+\x89\xe3\x98\x1f\xc3\xd4\xa1=\x82k?\xd8/\xb3u/B~\x0cY\x0b\xf6\x08\xae\xfb[\xd9\x12\xd5\xc1;\x94\x19\xba\xa7If\x13\x96\x07\x9c\xfc\x11T\x07\xd6\xd6\xd8\x9e4'n.1\x14\x91cG%\xb2\xbd3\xc4\xd1DPX\x01\xbe1\xef\x8cp\x86\xaf-na\x05\x83\x96[\xc4\x80\xafcs)\x8f\xfc\x1e\xc5\x84\x1c\xe2\x1b\x19\x8d%E/\xc17\xf6\xb6\x9bj\xc4\x0c\xe9\xe1\xef\xbf\x00\x00\x00\xff\xffPK\x07\x08ogu\xb0\x82\x05\x00\x00u\x14\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00 \x93wQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00authz_test.regoUT\x05\x00\x01}\xfe\xbb_\xecY[o\xdb6\x14~\xb6~\x05\xc1\xa7fpd$\xed\xf6\x10 X\x82b\x18\xf6\xb0\xa5\xe8\xe5)0\x04Zbm\xae\x92\xa8R\x14j\xc7\xf0\x7f\x1fxHJ\x94-\xc9\xb2\x1a;\x01f=\xb4\x16u\xae\xdfw\x0eo\xc9H\xf8\x8d\xcc)\xcaxB\x05+\x12\x9f\x14r\xf1\xe4y\x92\xe62\xa0 aq@\xe2\x98\xff\xa0\x11Z{#\xf8\x89~0\xb9\xf0F\xa3\x88H\xe2\x0b^H\x1ad\xc2\xcaj\xc0\"\xe5Z\xfd\xbc\xc2jx\xa3=\xab\x81J\x12\xf2Sru\xf7 \xafB\xa8G\xb0\x902\x03\xb7\x08\x17\x02\xd4\xd4\xc8\xcdd\xe2\xea\xa2-%\x13\x9d\xd1\xd3Q\x99\xb1+\xc4\xce\xe4\xb9\x0c\xed\xb73\xe9g\xa8GD\xdaR\xd9\x86\xad\xd6\xb8\x98w\xd3\xd5\\\x0dz\x03\xd0\xbf\x1a\x9c\x0dC\xcf\x14a\xae\x87\xb2\x84\xaa\xdc2\xa2W\x82~)6\xc4P\xaa\xb7d\xa7\xda\xa2\x7fnv\xc7\xdf3\xb3\x06\xa5^I4BR\x9ej\x86\x00\xb2\xa3\xdc\x0c\x87\xa0sz\x00\xd7 \xae\xec\xfa\xbf\xf4D\xa4!\xb1\xd2\x88\xf9hl\xf5O\xae4\xf0\xb8\\=M\xdd\xe4\xf2b\xa6\xd7\xa0\x95\xcai\xa9\xa6\xda9\xadr\x86u\xe6Mu\xdc\xde{\xa5\xd0\xb0B\x15p\xda(\xae\xd5\xc2P\xd9\xb1~\x19\x05\xa9\xda\xb1|\xdda\xe6-\x9e\xa2\xcd\xb8\x87\xf85\x88\xbf\x83\xfbb+\xa9\xef\x03\x14vK5\xd3\xaf\xab\xd8\xb4i\xad\xb1\xf1\xe2\xcc\xd5\xe9*\xa8\x9d\x8baF8\xc2y\x07\x8e0\xf7\xe9\xea\xdeu\xf6E_A\xb7\x9cf\xfeO\xd7\xdc\xcei\xbb\x85\x92\xa3\x1c\x8f\x06\xb0rjL\xfe\x0b\x00\x00\xff\xffPK\x07\x088\xf7w\xee\xf1\x04\x00\x00\xab&\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00q\x82\x8fQogu\xb0\x82\x05\x00\x00u\x14\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\x16\xe2\xd8_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00 \x93wQ8\xf7w\xee\xf1\x04\x00\x00\xab&\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xc3\x05\x00\x00authz_test.regoUT\x05\x00\x01}\xfe\xbb_PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\xfa\n\x00\x00\x00\x00" fs.RegisterWithNamespace("rego", data) } diff --git a/config/policy.go b/config/policy.go index c5467b978..da879de50 100644 --- a/config/policy.go +++ b/config/policy.go @@ -257,7 +257,7 @@ func (p *Policy) Validate() error { } // Make sure there's no path set on the from url - if !(source.Path == "" || source.Path == "/") { + if (source.Scheme == "http" || source.Scheme == "https") && !(source.Path == "" || source.Path == "/") { return fmt.Errorf("config: policy source url (%s) contains a path, but it should be set using the path field instead", source.String()) } diff --git a/internal/controlplane/xds_routes.go b/internal/controlplane/xds_routes.go index a6b066335..778f76ed1 100644 --- a/internal/controlplane/xds_routes.go +++ b/internal/controlplane/xds_routes.go @@ -192,20 +192,29 @@ func buildPolicyRoutes(options *config.Options, domain string) []*envoy_config_r routeTimeout := getRouteTimeout(options, &policy) prefixRewrite, regexRewrite := getRewriteOptions(&policy) + upgradeConfigs := []*envoy_config_route_v3.RouteAction_UpgradeConfig{ + { + UpgradeType: "websocket", + Enabled: &wrappers.BoolValue{Value: policy.AllowWebsockets}, + }, + { + UpgradeType: "spdy/3.1", + Enabled: &wrappers.BoolValue{Value: policy.AllowSPDY}, + }, + } + if urlutil.IsTCP(policy.Source.URL) { + upgradeConfigs = append(upgradeConfigs, &envoy_config_route_v3.RouteAction_UpgradeConfig{ + UpgradeType: "CONNECT", + Enabled: &wrappers.BoolValue{Value: true}, + ConnectConfig: &envoy_config_route_v3.RouteAction_UpgradeConfig_ConnectConfig{}, + }) + } + routeAction := &envoy_config_route_v3.RouteAction{ ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{ Cluster: clusterName, }, - UpgradeConfigs: []*envoy_config_route_v3.RouteAction_UpgradeConfig{ - { - UpgradeType: "websocket", - Enabled: &wrappers.BoolValue{Value: policy.AllowWebsockets}, - }, - { - UpgradeType: "spdy/3.1", - Enabled: &wrappers.BoolValue{Value: policy.AllowSPDY}, - }, - }, + UpgradeConfigs: upgradeConfigs, HostRewriteSpecifier: &envoy_config_route_v3.RouteAction_AutoHostRewrite{ AutoHostRewrite: &wrappers.BoolValue{Value: !policy.PreserveHostHeader}, }, @@ -271,6 +280,10 @@ func toEnvoyHeaders(headers map[string]string) []*envoy_config_core_v3.HeaderVal func mkRouteMatch(policy *config.Policy) *envoy_config_route_v3.RouteMatch { match := &envoy_config_route_v3.RouteMatch{} switch { + case urlutil.IsTCP(policy.Source.URL): + match.PathSpecifier = &envoy_config_route_v3.RouteMatch_ConnectMatcher_{ + ConnectMatcher: &envoy_config_route_v3.RouteMatch_ConnectMatcher{}, + } case policy.Regex != "": match.PathSpecifier = &envoy_config_route_v3.RouteMatch_SafeRegex{ SafeRegex: &envoy_type_matcher_v3.RegexMatcher{ diff --git a/internal/controlplane/xds_routes_test.go b/internal/controlplane/xds_routes_test.go index 8aafe1456..92a1c8078 100644 --- a/internal/controlplane/xds_routes_test.go +++ b/internal/controlplane/xds_routes_test.go @@ -464,6 +464,50 @@ func Test_buildPolicyRoutes(t *testing.T) { } ] `, routes) + + t.Run("tcp", func(t *testing.T) { + routes = buildPolicyRoutes(&config.Options{ + CookieName: "pomerium", + DefaultUpstreamTimeout: time.Second * 3, + Policies: []config.Policy{ + { + Source: &config.StringURL{URL: mustParseURL("tcp+https://example.com:22")}, + PassIdentityHeaders: true, + }, + }, + }, "example.com:22") + + testutil.AssertProtoJSONEqual(t, ` + [ + { + "name": "policy-0", + "match": { + "connectMatcher": {} + }, + "metadata": { + "filterMetadata": { + "envoy.filters.http.lua": { + "remove_impersonate_headers": false, + "remove_pomerium_authorization": true, + "remove_pomerium_cookie": "pomerium" + } + } + }, + "route": { + "autoHostRewrite": true, + "cluster": "policy-9", + "timeout": "3s", + "upgradeConfigs": [ + { "enabled": false, "upgradeType": "websocket"}, + { "enabled": false, "upgradeType": "spdy/3.1"}, + { "enabled": true, "upgradeType": "CONNECT", "connectConfig": {} } + ] + } + } + ] + `, routes) + + }) } // Make sure default Headers are set for response. diff --git a/internal/urlutil/url.go b/internal/urlutil/url.go index f23bd3b80..b5a3506f2 100644 --- a/internal/urlutil/url.go +++ b/internal/urlutil/url.go @@ -84,6 +84,10 @@ func GetAbsoluteURL(r *http.Request) *url.URL { // For standard HTTP (80)/HTTPS (443) ports, it returns `example.com` and `example.com:`. // Otherwise, return the URL.Host value. func GetDomainsForURL(u *url.URL) []string { + if IsTCP(u) { + return []string{u.Host} + } + var defaultPort string if u.Scheme == "http" { defaultPort = "80" @@ -102,6 +106,11 @@ func GetDomainsForURL(u *url.URL) []string { return []string{u.Hostname(), net.JoinHostPort(u.Hostname(), defaultPort)} } +// IsTCP returns whether or not the given URL is for TCP via HTTP Connect. +func IsTCP(u *url.URL) bool { + return u.Scheme == "tcp+http" || u.Scheme == "tcp+https" +} + // ParseEnvoyQueryParams returns a new URL with queryparams parsed from envoy format. func ParseEnvoyQueryParams(u *url.URL) *url.URL { nu := &url.URL{