Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable http and https proxy addrs #208

Merged
merged 5 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
on: [push, pull_request]
name: Test
# Workaround for coveralls error "Can't add a job to a build that is already closed"
# See https://github.com/lemurheavy/coveralls-public/issues/1716
env:
COVERALLS_SERVICE_NUMBER: ${{ github.run_id }}-${{ github.run_attempt }}
jobs:
test:
strategy:
Expand All @@ -23,6 +27,7 @@ jobs:
go test -race -v -timeout 2m -failfast -covermode atomic -coverprofile=.covprofile ./... -tags=nointegration
# Run integration tests hermetically to avoid nondeterministic races on environment variables
go test -race -v -timeout 2m -failfast ./cmd/... -run TestSmokescreenIntegration
go test -race -v -timeout 2m -failfast ./cmd/... -run TestInvalidUpstreamProxyConfiguratedFromEnv
go test -race -v -timeout 2m -failfast ./cmd/... -run TestInvalidUpstreamProxyConfiguration
go test -race -v -timeout 2m -failfast ./cmd/... -run TestClientHalfCloseConnection
- name: Install goveralls
Expand Down
67 changes: 62 additions & 5 deletions cmd/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func TestSmokescreenIntegration(t *testing.T) {

for _, useTLS := range []bool{true, false} {
// Smokescreen instances
_, proxyServer, err := startSmokescreen(t, useTLS, &logHook)
_, proxyServer, err := startSmokescreen(t, useTLS, &logHook, "")
require.NoError(t, err)
defer proxyServer.Close()
proxyServers[useTLS] = proxyServer
Expand Down Expand Up @@ -449,13 +449,13 @@ func validateProxyResponseWithUpstream(t *testing.T, test *TestCase, resp *http.

// This test must be run with a separate test command as the environment variables
// required can race with the test above.
func TestInvalidUpstreamProxyConfiguration(t *testing.T) {
func TestInvalidUpstreamProxyConfiguratedFromEnv(t *testing.T) {
var logHook logrustest.Hook
servers := map[bool]*httptest.Server{}

// Create TLS and non-TLS instances of Smokescreen
for _, useTLS := range []bool{true, false} {
_, server, err := startSmokescreen(t, useTLS, &logHook)
_, server, err := startSmokescreen(t, useTLS, &logHook, "")
require.NoError(t, err)
defer server.Close()
servers[useTLS] = server
Expand Down Expand Up @@ -500,6 +500,58 @@ func TestInvalidUpstreamProxyConfiguration(t *testing.T) {
}
}

func TestInvalidUpstreamProxyConfiguration(t *testing.T) {
var logHook logrustest.Hook
servers := map[bool]*httptest.Server{}

// Create TLS and non-TLS instances of Smokescreen
for _, useTLS := range []bool{true, false} {
var httpProxyAddr string
if useTLS {
httpProxyAddr = "https://notaproxy.prxy.svc:443"
} else {
httpProxyAddr = "http://notaproxy.prxy.svc:80"
}
_, server, err := startSmokescreen(t, useTLS, &logHook, httpProxyAddr)
require.NoError(t, err)
defer server.Close()
servers[useTLS] = server
}

// Passing an illegal upstream proxy value is not designed to be an especially well
// handled error so it would fail many of the checks in our other tests. We really
// only care to ensure that these requests never succeed.
for _, overConnect := range []bool{true, false} {
t.Run(fmt.Sprintf("illegal proxy with CONNECT %t", overConnect), func(t *testing.T) {
var proxyTarget string
var upstreamProxy string

// These proxy targets don't actually matter as the requests won't be sent.
// because the resolution of the upstream proxy will fail.
if overConnect {
upstreamProxy = "https://notaproxy.prxy.svc:443"
proxyTarget = "https://api.stripe.com:443"
} else {
upstreamProxy = "http://notaproxy.prxy.svc:80"
proxyTarget = "http://checkip.amazonaws.com:80"
}

testCase := &TestCase{
OverConnect: overConnect,
OverTLS: overConnect,
ProxyURL: servers[overConnect].URL,
TargetURL: proxyTarget,
UpstreamProxy: upstreamProxy,
RoleName: generateRoleForPolicy(acl.Open),
ExpectStatus: http.StatusBadGateway,
}
resp, err := executeRequestForTest(t, testCase, &logHook)
validateProxyResponseWithUpstream(t, testCase, resp, err, logHook.AllEntries())

})
}
}

func TestClientHalfCloseConnection(t *testing.T) {
a := assert.New(t)

Expand All @@ -510,7 +562,7 @@ func TestClientHalfCloseConnection(t *testing.T) {

var logHook logrustest.Hook

conf, server, err := startSmokescreen(t, false, &logHook)
conf, server, err := startSmokescreen(t, false, &logHook, "")
require.NoError(t, err)
defer server.Close()

Expand Down Expand Up @@ -577,7 +629,7 @@ func findLogEntry(entries []*logrus.Entry, msg string) *logrus.Entry {
return nil
}

func startSmokescreen(t *testing.T, useTLS bool, logHook logrus.Hook) (*smokescreen.Config, *httptest.Server, error) {
func startSmokescreen(t *testing.T, useTLS bool, logHook logrus.Hook, httpProxyAddr string) (*smokescreen.Config, *httptest.Server, error) {
args := []string{
"smokescreen",
"--listen-ip=127.0.0.1",
Expand All @@ -596,6 +648,11 @@ func startSmokescreen(t *testing.T, useTLS bool, logHook logrus.Hook) (*smokescr
)
}

if httpProxyAddr != ""{
args = append(args, fmt.Sprintf("--upstream-http-proxy-addr=%s", httpProxyAddr))
args = append(args, fmt.Sprintf("--upstream-https-proxy-addr=%s", httpProxyAddr))
}

conf, err := NewConfiguration(args, nil)
if err != nil {
t.Fatalf("Failed to create configuration: %v", err)
Expand Down
28 changes: 23 additions & 5 deletions cmd/smokescreen.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ func NewConfiguration(args []string, logger *log.Logger) (*smokescreen.Config, e
Value: "/metrics",
Usage: "Expose prometheus metrics on `ENDPOINT`. Requires --expose-prometheus-metrics to be set. Defaults to \"/metrics\"",
},
cli.StringFlag{
Name: "prometheus-listen-ip",
Value: "0.0.0.0",
Usage: "Listen for prometheus metrics on interface with address IP. Requires --expose-prometheus-metrics to be set. Defaults to \"0.0.0.0\"",
},
cli.StringFlag{
Name: "prometheus-listen-ip",
Value: "0.0.0.0",
Usage: "Listen for prometheus metrics on interface with address IP. Requires --expose-prometheus-metrics to be set. Defaults to \"0.0.0.0\"",
},
cli.StringFlag{
Name: "prometheus-port",
Value: "9810",
Expand Down Expand Up @@ -146,6 +146,16 @@ func NewConfiguration(args []string, logger *log.Logger) (*smokescreen.Config, e
Name: "unsafe-allow-private-ranges",
Usage: "Allow private ip ranges by default",
},
cli.StringFlag{
Name: "upstream-http-proxy-addr",
Value: "",
Usage: "Set Smokescreen's upstream HTTP proxy address",
},
cli.StringFlag{
Name: "upstream-https-proxy-addr",
Value: "",
Usage: "Set Smokescreen's upstream HTTPS proxy address",
},
}

app.Action = func(c *cli.Context) error {
Expand Down Expand Up @@ -287,6 +297,14 @@ func NewConfiguration(args []string, logger *log.Logger) (*smokescreen.Config, e
}
}

if c.IsSet("upstream-http-proxy-addr") {
conf.UpstreamHttpProxyAddr = c.String("upstream-http-proxy-addr")
}

if c.IsSet("upstream-https-proxy-addr") {
conf.UpstreamHttpsProxyAddr = c.String("upstream-https-proxy-addr")
}

// Setup the connection tracker if there is not yet one in the config
if conf.ConnTracker == nil {
conf.ConnTracker = conntrack.NewTracker(conf.IdleTimeout, conf.MetricsClient, conf.Log, conf.ShuttingDown, nil)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/rs/xid v1.2.1
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.0
github.com/stripe/goproxy v0.0.0-20230801191332-fabc3ecb7251
github.com/stripe/goproxy v0.0.0-20231113215313-dbbdf2f6d709
golang.org/x/net v0.17.0
gopkg.in/urfave/cli.v1 v1.20.0
gopkg.in/yaml.v2 v2.4.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stripe/goproxy v0.0.0-20230801191332-fabc3ecb7251 h1:wR1exp7OglR0ctk8yWPVp1oTOuyaLUlJv3/Wlbvbw64=
github.com/stripe/goproxy v0.0.0-20230801191332-fabc3ecb7251/go.mod h1:hF2CVgH4++5ijZiy9grGVP8Fsi4u+SMOtbnIKYbMUjY=
github.com/stripe/goproxy v0.0.0-20231113215313-dbbdf2f6d709 h1:b0AttHAJ5f9rIK2frq9Q4WEeeBNQccr1j+cjQCmOl6s=
github.com/stripe/goproxy v0.0.0-20231113215313-dbbdf2f6d709/go.mod h1:hF2CVgH4++5ijZiy9grGVP8Fsi4u+SMOtbnIKYbMUjY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
4 changes: 4 additions & 0 deletions pkg/smokescreen/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ type Config struct {
TransportMaxIdleConns int
TransportMaxIdleConnsPerHost int

// These are the http and https address for the upstream proxy
UpstreamHttpProxyAddr string
UpstreamHttpsProxyAddr string

// Used for logging connection time
TimeConnect bool

Expand Down
2 changes: 1 addition & 1 deletion pkg/smokescreen/smokescreen.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func newContext(cfg *Config, proxyType string, req *http.Request) *SmokescreenCo
}

func BuildProxy(config *Config) *goproxy.ProxyHttpServer {
proxy := goproxy.NewProxyHttpServer()
proxy := goproxy.NewProxyHttpServer(goproxy.WithHttpProxyAddr(config.UpstreamHttpProxyAddr), goproxy.WithHttpsProxyAddr(config.UpstreamHttpsProxyAddr))
proxy.Verbose = false
configureTransport(proxy.Tr, config)

Expand Down
31 changes: 22 additions & 9 deletions vendor/github.com/stripe/goproxy/https.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 61 additions & 2 deletions vendor/github.com/stripe/goproxy/proxy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ github.com/sirupsen/logrus/hooks/test
## explicit; go 1.13
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
# github.com/stripe/goproxy v0.0.0-20230801191332-fabc3ecb7251
# github.com/stripe/goproxy v0.0.0-20231113215313-dbbdf2f6d709
## explicit; go 1.13
github.com/stripe/goproxy
# golang.org/x/mod v0.8.0
Expand Down