package ingress import ( "flag" "testing" "time" "github.com/cloudflare/cloudflared/cmd/cloudflared/config" "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" "gopkg.in/yaml.v2" ) // Ensure that the nullable config from `config` package and the // non-nullable config from `ingress` package have the same number of // fields. // This test ensures that programmers didn't add a new field to // one struct and forget to add it to the other ;) func TestCorrespondingFields(t *testing.T) { require.Equal( t, CountFields(t, config.OriginRequestConfig{}), CountFields(t, OriginRequestConfig{}), ) } func CountFields(t *testing.T, val interface{}) int { b, err := yaml.Marshal(val) require.NoError(t, err) m := make(map[string]interface{}, 0) err = yaml.Unmarshal(b, &m) require.NoError(t, err) return len(m) } func TestOriginRequestConfigOverrides(t *testing.T) { rulesYAML := ` originRequest: connectTimeout: 1m tlsTimeout: 1s noHappyEyeballs: true tcpKeepAlive: 1s keepAliveConnections: 1 keepAliveTimeout: 1s httpHostHeader: abc originServerName: a1 caPool: /tmp/path0 noTLSVerify: true disableChunkedEncoding: true bastionMode: True proxyAddress: 127.1.2.3 proxyPort: 100 proxyType: socks5 ingress: - hostname: tun.example.com service: https://localhost:8000 - hostname: "*" service: https://localhost:8001 originRequest: connectTimeout: 2m tlsTimeout: 2s noHappyEyeballs: false tcpKeepAlive: 2s keepAliveConnections: 2 keepAliveTimeout: 2s httpHostHeader: def originServerName: b2 caPool: /tmp/path1 noTLSVerify: false disableChunkedEncoding: false bastionMode: false proxyAddress: interface proxyPort: 200 proxyType: "" ` ing, err := ParseIngress(MustReadIngress(rulesYAML)) if err != nil { t.Error(err) } // Rule 0 didn't override anything, so it inherits the user-specified // root-level configuration. actual0 := ing.Rules[0].Config expected0 := OriginRequestConfig{ ConnectTimeout: 1 * time.Minute, TLSTimeout: 1 * time.Second, NoHappyEyeballs: true, TCPKeepAlive: 1 * time.Second, KeepAliveConnections: 1, KeepAliveTimeout: 1 * time.Second, HTTPHostHeader: "abc", OriginServerName: "a1", CAPool: "/tmp/path0", NoTLSVerify: true, DisableChunkedEncoding: true, BastionMode: true, ProxyAddress: "127.1.2.3", ProxyPort: uint(100), ProxyType: "socks5", } require.Equal(t, expected0, actual0) // Rule 1 overrode all the root-level config. actual1 := ing.Rules[1].Config expected1 := OriginRequestConfig{ ConnectTimeout: 2 * time.Minute, TLSTimeout: 2 * time.Second, NoHappyEyeballs: false, TCPKeepAlive: 2 * time.Second, KeepAliveConnections: 2, KeepAliveTimeout: 2 * time.Second, HTTPHostHeader: "def", OriginServerName: "b2", CAPool: "/tmp/path1", NoTLSVerify: false, DisableChunkedEncoding: false, BastionMode: false, ProxyAddress: "interface", ProxyPort: uint(200), ProxyType: "", } require.Equal(t, expected1, actual1) } func TestOriginRequestConfigDefaults(t *testing.T) { rulesYAML := ` ingress: - hostname: tun.example.com service: https://localhost:8000 - hostname: "*" service: https://localhost:8001 originRequest: connectTimeout: 2m tlsTimeout: 2s noHappyEyeballs: false tcpKeepAlive: 2s keepAliveConnections: 2 keepAliveTimeout: 2s httpHostHeader: def originServerName: b2 caPool: /tmp/path1 noTLSVerify: false disableChunkedEncoding: false bastionMode: false proxyAddress: interface proxyPort: 200 proxyType: "" ` ing, err := ParseIngress(MustReadIngress(rulesYAML)) if err != nil { t.Error(err) } // Rule 0 didn't override anything, so it inherits the cloudflared defaults actual0 := ing.Rules[0].Config expected0 := OriginRequestConfig{ ConnectTimeout: defaultConnectTimeout, TLSTimeout: defaultTLSTimeout, TCPKeepAlive: defaultTCPKeepAlive, KeepAliveConnections: defaultKeepAliveConnections, KeepAliveTimeout: defaultKeepAliveTimeout, ProxyAddress: defaultProxyAddress, } require.Equal(t, expected0, actual0) // Rule 1 overrode all defaults. actual1 := ing.Rules[1].Config expected1 := OriginRequestConfig{ ConnectTimeout: 2 * time.Minute, TLSTimeout: 2 * time.Second, NoHappyEyeballs: false, TCPKeepAlive: 2 * time.Second, KeepAliveConnections: 2, KeepAliveTimeout: 2 * time.Second, HTTPHostHeader: "def", OriginServerName: "b2", CAPool: "/tmp/path1", NoTLSVerify: false, DisableChunkedEncoding: false, BastionMode: false, ProxyAddress: "interface", ProxyPort: uint(200), ProxyType: "", } require.Equal(t, expected1, actual1) } func TestDefaultConfigFromCLI(t *testing.T) { set := flag.NewFlagSet("contrive", 0) c := cli.NewContext(nil, set, nil) expected := OriginRequestConfig{ ConnectTimeout: defaultConnectTimeout, TLSTimeout: defaultTLSTimeout, TCPKeepAlive: defaultTCPKeepAlive, KeepAliveConnections: defaultKeepAliveConnections, KeepAliveTimeout: defaultKeepAliveTimeout, ProxyAddress: defaultProxyAddress, } actual := originRequestFromSingeRule(c) require.Equal(t, expected, actual) }