2020-10-15 21:41:03 +00:00
|
|
|
package ingress
|
|
|
|
|
|
|
|
import (
|
2022-03-14 17:51:10 +00:00
|
|
|
"encoding/json"
|
2020-11-05 13:37:30 +00:00
|
|
|
"io"
|
|
|
|
"net/http/httptest"
|
2020-10-15 21:41:03 +00:00
|
|
|
"net/url"
|
|
|
|
"regexp"
|
|
|
|
"testing"
|
2020-11-04 18:22:21 +00:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
2022-03-14 17:51:10 +00:00
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/config"
|
2020-10-15 21:41:03 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func Test_rule_matches(t *testing.T) {
|
|
|
|
type args struct {
|
|
|
|
requestURL *url.URL
|
|
|
|
}
|
|
|
|
tests := []struct {
|
2022-09-22 23:19:06 +00:00
|
|
|
name string
|
|
|
|
rule Rule
|
|
|
|
args args
|
|
|
|
want bool
|
2020-10-15 21:41:03 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Just hostname, pass",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "example.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://example.com"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
2022-09-22 23:19:06 +00:00
|
|
|
{
|
|
|
|
name: "Unicode hostname with unicode request, pass",
|
|
|
|
rule: Rule{
|
|
|
|
Hostname: "môô.cloudflare.com",
|
|
|
|
punycodeHostname: "xn--m-xgaa.cloudflare.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://môô.cloudflare.com"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Unicode hostname with punycode request, pass",
|
|
|
|
rule: Rule{
|
|
|
|
Hostname: "môô.cloudflare.com",
|
|
|
|
punycodeHostname: "xn--m-xgaa.cloudflare.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://xn--m-xgaa.cloudflare.com"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
2020-10-15 21:41:03 +00:00
|
|
|
{
|
|
|
|
name: "Entire hostname is wildcard, should match everything",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "*",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://example.com"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Just hostname, fail",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "example.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://foo.bar"),
|
|
|
|
},
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Just wildcard hostname, pass",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "*.example.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://adam.example.com"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Just wildcard hostname, fail",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "*.example.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://tunnel.com"),
|
|
|
|
},
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Just wildcard outside of subdomain in hostname, fail",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "*example.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://www.example.com"),
|
|
|
|
},
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Wildcard over multiple subdomains",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "*.example.com",
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://adam.chalmers.example.com"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Hostname and path",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2020-10-15 21:41:03 +00:00
|
|
|
Hostname: "*.example.com",
|
2022-03-14 17:51:10 +00:00
|
|
|
Path: &Regexp{Regexp: regexp.MustCompile("/static/.*\\.html")},
|
2020-10-15 21:41:03 +00:00
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://www.example.com/static/index.html"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
2022-03-14 17:51:10 +00:00
|
|
|
{
|
|
|
|
name: "Hostname and empty Regex",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2022-03-14 17:51:10 +00:00
|
|
|
Hostname: "example.com",
|
|
|
|
Path: &Regexp{},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://example.com/"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Hostname and nil path",
|
2022-09-22 23:19:06 +00:00
|
|
|
rule: Rule{
|
2022-03-14 17:51:10 +00:00
|
|
|
Hostname: "example.com",
|
|
|
|
Path: nil,
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
requestURL: MustParseURL(t, "https://example.com/"),
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
2020-10-15 21:41:03 +00:00
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
u := tt.args.requestURL
|
2022-09-22 23:19:06 +00:00
|
|
|
if got := tt.rule.Matches(u.Hostname(), u.Path); got != tt.want {
|
2020-10-15 21:41:03 +00:00
|
|
|
t.Errorf("rule.matches() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2020-11-04 18:22:21 +00:00
|
|
|
|
|
|
|
func TestStaticHTTPStatus(t *testing.T) {
|
|
|
|
o := newStatusCode(404)
|
|
|
|
buf := make([]byte, 100)
|
|
|
|
|
|
|
|
sendReq := func() {
|
|
|
|
resp, err := o.RoundTrip(nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = resp.Body.Read(buf)
|
2020-11-05 13:37:30 +00:00
|
|
|
require.Equal(t, io.EOF, err)
|
2020-11-04 18:22:21 +00:00
|
|
|
require.NoError(t, resp.Body.Close())
|
|
|
|
require.Equal(t, 404, resp.StatusCode)
|
2020-11-05 13:37:30 +00:00
|
|
|
|
|
|
|
resp, err = o.RoundTrip(nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
n, err := io.Copy(w, resp.Body)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, int64(0), n)
|
2020-11-04 18:22:21 +00:00
|
|
|
}
|
|
|
|
sendReq()
|
|
|
|
sendReq()
|
|
|
|
}
|
2022-03-14 17:51:10 +00:00
|
|
|
|
|
|
|
func TestMarshalJSON(t *testing.T) {
|
|
|
|
localhost8000 := MustParseURL(t, "https://localhost:8000")
|
|
|
|
defaultConfig := setConfig(originRequestFromConfig(config.OriginRequestConfig{}), config.OriginRequestConfig{})
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
path *Regexp
|
|
|
|
expected string
|
|
|
|
want bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Nil",
|
|
|
|
path: nil,
|
2022-09-22 13:04:47 +00:00
|
|
|
expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
2022-03-14 17:51:10 +00:00
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Nil regex",
|
|
|
|
path: &Regexp{Regexp: nil},
|
2022-09-22 13:04:47 +00:00
|
|
|
expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
2022-03-14 17:51:10 +00:00
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Empty",
|
|
|
|
path: &Regexp{Regexp: regexp.MustCompile("")},
|
2022-09-22 13:04:47 +00:00
|
|
|
expected: `{"hostname":"example.com","path":"","service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
2022-03-14 17:51:10 +00:00
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Basic",
|
|
|
|
path: &Regexp{Regexp: regexp.MustCompile("/echo")},
|
2022-09-22 13:04:47 +00:00
|
|
|
expected: `{"hostname":"example.com","path":"/echo","service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
2022-03-14 17:51:10 +00:00
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
r := Rule{
|
|
|
|
Hostname: "example.com",
|
|
|
|
Service: &httpService{url: localhost8000},
|
|
|
|
Path: tt.path,
|
|
|
|
Config: defaultConfig,
|
|
|
|
}
|
|
|
|
bytes, err := json.Marshal(r)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tt.expected, string(bytes))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|