Skip to content

Commit afc0848

Browse files
authored
Introduce GRPC_PROXY EnvVar Support (#2364)
Introduce the ability to specify a dial context for GRPC connections. Signed-off-by: Alexander Greene <[email protected]>
1 parent 41261fc commit afc0848

File tree

4 files changed

+438
-1
lines changed

4 files changed

+438
-1
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ require (
3636
github.com/spf13/cobra v1.1.3
3737
github.com/spf13/pflag v1.0.5
3838
github.com/stretchr/testify v1.7.0
39+
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023
3940
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
4041
google.golang.org/grpc v1.38.0
4142
gopkg.in/yaml.v2 v2.4.0

pkg/controller/registry/grpc/source.go

+67-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ package grpc
22

33
import (
44
"context"
5+
"net"
6+
"net/url"
7+
"os"
58
"sync"
69
"time"
710

811
"github.com/operator-framework/operator-registry/pkg/client"
912

1013
"github.com/sirupsen/logrus"
14+
"golang.org/x/net/http/httpproxy"
15+
"golang.org/x/net/proxy"
1116
"google.golang.org/grpc"
1217
"google.golang.org/grpc/connectivity"
1318

@@ -100,10 +105,71 @@ func (s *SourceStore) Get(key registry.CatalogKey) *SourceConn {
100105
return &source
101106
}
102107

108+
func grpcProxyURL(addr string) (*url.URL, error) {
109+
// Handle ip addresses
110+
host, _, err := net.SplitHostPort(addr)
111+
if err != nil {
112+
return nil, err
113+
}
114+
115+
url, err := url.Parse(host)
116+
if err != nil {
117+
return nil, err
118+
}
119+
120+
// Hardcode fields required for proxy resolution
121+
url.Host = addr
122+
url.Scheme = "http"
123+
124+
// Override HTTPS_PROXY and HTTP_PROXY with GRPC_PROXY
125+
proxyConfig := &httpproxy.Config{
126+
HTTPProxy: getGRPCProxyEnv(),
127+
HTTPSProxy: getGRPCProxyEnv(),
128+
NoProxy: getEnvAny("NO_PROXY", "no_proxy"),
129+
CGI: os.Getenv("REQUEST_METHOD") != "",
130+
}
131+
132+
// Check if a proxy should be used based on environment variables
133+
return proxyConfig.ProxyFunc()(url)
134+
}
135+
136+
func getGRPCProxyEnv() string {
137+
return getEnvAny("GRPC_PROXY", "grpc_proxy")
138+
}
139+
140+
func getEnvAny(names ...string) string {
141+
for _, n := range names {
142+
if val := os.Getenv(n); val != "" {
143+
return val
144+
}
145+
}
146+
return ""
147+
}
148+
149+
func grpcConnection(address string) (*grpc.ClientConn, error) {
150+
dialOptions := []grpc.DialOption{grpc.WithInsecure()}
151+
proxyURL, err := grpcProxyURL(address)
152+
if err != nil {
153+
return nil, err
154+
}
155+
156+
if proxyURL != nil {
157+
dialOptions = append(dialOptions, grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
158+
dialer, err := proxy.FromURL(proxyURL, &net.Dialer{})
159+
if err != nil {
160+
return nil, err
161+
}
162+
return dialer.Dial("tcp", addr)
163+
}))
164+
}
165+
166+
return grpc.Dial(address, dialOptions...)
167+
}
168+
103169
func (s *SourceStore) Add(key registry.CatalogKey, address string) (*SourceConn, error) {
104170
_ = s.Remove(key)
105171

106-
conn, err := grpc.Dial(address, grpc.WithInsecure())
172+
conn, err := grpcConnection(address)
107173
if err != nil {
108174
return nil, err
109175
}

0 commit comments

Comments
 (0)