Skip to content

Commit a029b70

Browse files
authored
Fix proxy issue in new listener client (#3181)
1 parent 3fab744 commit a029b70

File tree

2 files changed

+171
-3
lines changed

2 files changed

+171
-3
lines changed

cmd/ghalistener/config/config.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"crypto/x509"
55
"encoding/json"
66
"fmt"
7+
"net/http"
8+
"net/url"
79
"os"
810

911
"github.com/actions/actions-runner-controller/build"
@@ -101,7 +103,7 @@ func (c *Config) Logger() (logr.Logger, error) {
101103
return logger, nil
102104
}
103105

104-
func (c *Config) ActionsClient(logger logr.Logger) (*actions.Client, error) {
106+
func (c *Config) ActionsClient(logger logr.Logger, clientOptions ...actions.ClientOption) (*actions.Client, error) {
105107
var creds actions.ActionsAuth
106108
switch c.Token {
107109
case "":
@@ -114,9 +116,9 @@ func (c *Config) ActionsClient(logger logr.Logger) (*actions.Client, error) {
114116
creds.Token = c.Token
115117
}
116118

117-
options := []actions.ClientOption{
119+
options := append([]actions.ClientOption{
118120
actions.WithLogger(logger),
119-
}
121+
}, clientOptions...)
120122

121123
if c.ServerRootCA != "" {
122124
systemPool, err := x509.SystemCertPool()
@@ -132,6 +134,11 @@ func (c *Config) ActionsClient(logger logr.Logger) (*actions.Client, error) {
132134
options = append(options, actions.WithRootCAs(pool))
133135
}
134136

137+
proxyFunc := httpproxy.FromEnvironment().ProxyFunc()
138+
options = append(options, actions.WithProxy(func(req *http.Request) (*url.URL, error) {
139+
return proxyFunc(req.URL)
140+
}))
141+
135142
client, err := actions.NewClient(c.ConfigureUrl, &creds, options...)
136143
if err != nil {
137144
return nil, fmt.Errorf("failed to create actions client: %w", err)
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package config_test
2+
3+
import (
4+
"context"
5+
"crypto/tls"
6+
"net/http"
7+
"net/http/httptest"
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/actions/actions-runner-controller/cmd/ghalistener/config"
13+
"github.com/actions/actions-runner-controller/github/actions"
14+
"github.com/actions/actions-runner-controller/github/actions/testserver"
15+
"github.com/go-logr/logr"
16+
"github.com/stretchr/testify/assert"
17+
"github.com/stretchr/testify/require"
18+
)
19+
20+
func TestCustomerServerRootCA(t *testing.T) {
21+
ctx := context.Background()
22+
certsFolder := filepath.Join(
23+
"../../../",
24+
"github",
25+
"actions",
26+
"testdata",
27+
)
28+
certPath := filepath.Join(certsFolder, "server.crt")
29+
keyPath := filepath.Join(certsFolder, "server.key")
30+
31+
serverCalledSuccessfully := false
32+
33+
server := testserver.NewUnstarted(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
34+
serverCalledSuccessfully = true
35+
w.WriteHeader(http.StatusOK)
36+
w.Write([]byte(`{"count": 0}`))
37+
}))
38+
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
39+
require.NoError(t, err)
40+
41+
server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
42+
server.StartTLS()
43+
44+
var certsString string
45+
rootCA, err := os.ReadFile(filepath.Join(certsFolder, "rootCA.crt"))
46+
require.NoError(t, err)
47+
certsString = string(rootCA)
48+
49+
intermediate, err := os.ReadFile(filepath.Join(certsFolder, "intermediate.pem"))
50+
require.NoError(t, err)
51+
certsString = certsString + string(intermediate)
52+
53+
config := config.Config{
54+
ConfigureUrl: server.ConfigURLForOrg("myorg"),
55+
ServerRootCA: certsString,
56+
Token: "token",
57+
}
58+
59+
client, err := config.ActionsClient(logr.Discard())
60+
require.NoError(t, err)
61+
_, err = client.GetRunnerScaleSet(ctx, 1, "test")
62+
require.NoError(t, err)
63+
assert.True(t, serverCalledSuccessfully)
64+
}
65+
66+
func TestProxySettings(t *testing.T) {
67+
t.Run("http", func(t *testing.T) {
68+
wentThroughProxy := false
69+
70+
proxy := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
71+
wentThroughProxy = true
72+
}))
73+
t.Cleanup(func() {
74+
proxy.Close()
75+
})
76+
77+
prevProxy := os.Getenv("http_proxy")
78+
os.Setenv("http_proxy", proxy.URL)
79+
defer os.Setenv("http_proxy", prevProxy)
80+
81+
config := config.Config{
82+
ConfigureUrl: "https://github.com/org/repo",
83+
Token: "token",
84+
}
85+
86+
client, err := config.ActionsClient(logr.Discard())
87+
require.NoError(t, err)
88+
89+
req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
90+
require.NoError(t, err)
91+
_, err = client.Do(req)
92+
require.NoError(t, err)
93+
94+
assert.True(t, wentThroughProxy)
95+
})
96+
97+
t.Run("https", func(t *testing.T) {
98+
wentThroughProxy := false
99+
100+
proxy := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
101+
wentThroughProxy = true
102+
}))
103+
t.Cleanup(func() {
104+
proxy.Close()
105+
})
106+
107+
prevProxy := os.Getenv("https_proxy")
108+
os.Setenv("https_proxy", proxy.URL)
109+
defer os.Setenv("https_proxy", prevProxy)
110+
111+
config := config.Config{
112+
ConfigureUrl: "https://github.com/org/repo",
113+
Token: "token",
114+
}
115+
116+
client, err := config.ActionsClient(logr.Discard(), actions.WithRetryMax(0))
117+
require.NoError(t, err)
118+
119+
req, err := http.NewRequest(http.MethodGet, "https://example.com", nil)
120+
require.NoError(t, err)
121+
122+
_, err = client.Do(req)
123+
// proxy doesn't support https
124+
assert.Error(t, err)
125+
assert.True(t, wentThroughProxy)
126+
})
127+
128+
t.Run("no_proxy", func(t *testing.T) {
129+
wentThroughProxy := false
130+
131+
proxy := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
132+
wentThroughProxy = true
133+
}))
134+
t.Cleanup(func() {
135+
proxy.Close()
136+
})
137+
138+
prevProxy := os.Getenv("http_proxy")
139+
os.Setenv("http_proxy", proxy.URL)
140+
defer os.Setenv("http_proxy", prevProxy)
141+
142+
prevNoProxy := os.Getenv("no_proxy")
143+
os.Setenv("no_proxy", "example.com")
144+
defer os.Setenv("no_proxy", prevNoProxy)
145+
146+
config := config.Config{
147+
ConfigureUrl: "https://github.com/org/repo",
148+
Token: "token",
149+
}
150+
151+
client, err := config.ActionsClient(logr.Discard())
152+
require.NoError(t, err)
153+
154+
req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
155+
require.NoError(t, err)
156+
157+
_, err = client.Do(req)
158+
require.NoError(t, err)
159+
assert.False(t, wentThroughProxy)
160+
})
161+
}

0 commit comments

Comments
 (0)