-
Notifications
You must be signed in to change notification settings - Fork 6
/
generate_http_client.go
132 lines (121 loc) · 3.56 KB
/
generate_http_client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package kv
import (
"crypto/tls"
"crypto/x509"
"errors"
"net"
"net/http"
"net/url"
"strings"
"time"
"github.com/trimble-oss/tierceron/buildopts/coreopts"
)
func IsUrlIp(address string) (bool, error) {
if strings.HasPrefix(address, "https://127.0.0.1") {
return true, nil
}
u, err := url.Parse(address)
if err != nil {
return false, err
}
host, _, _ := net.SplitHostPort(u.Host)
ipHost := net.ParseIP(host)
if ipHost.To4() != nil {
return true, nil
}
ips, err := net.LookupIP(host)
if err != nil {
return false, err
}
for _, ip := range ips {
if ip.String() == "127.0.0.1" {
return true, nil
}
}
return false, nil
}
// CreateHTTPClient reads from several .pem files to get the necessary keys and certs to configure the http client and returns the client.
func CreateHTTPClient(insecure bool, address string, env string, scan bool) (client *http.Client, err error) {
return CreateHTTPClientAllowNonLocal(insecure, address, env, scan, false)
}
// CreateHTTPClient reads from several .pem files to get the necessary keys and certs to configure the http client and returns the client.
func CreateHTTPClientAllowNonLocal(insecure bool, address string, env string, scan bool, allowNonLocal bool) (client *http.Client, err error) {
// // create a pool of trusted certs
certPath := "../../certs/cert_files/dcidevpublic.pem"
if strings.HasPrefix(env, "prod") || strings.HasPrefix(env, "staging") {
certPath = "../../certs/cert_files/dcipublic.pem"
}
cert, err := Asset(certPath)
//servCertPEM, err := os.ReadFile(certPath)
//servCertPEM := []byte(cert)
if err != nil {
return nil, err
}
certPool, _ := x509.SystemCertPool()
if certPool == nil {
certPool = x509.NewCertPool()
}
certPool.AppendCertsFromPEM(cert)
var tlsConfig = &tls.Config{RootCAs: certPool}
if insecure {
if isLocal, lookupErr := IsUrlIp(address); isLocal {
if lookupErr != nil {
return nil, lookupErr
}
tlsConfig = &tls.Config{RootCAs: certPool, InsecureSkipVerify: true}
} else {
if lookupErr != nil {
return nil, lookupErr
}
if allowNonLocal {
tlsConfig = &tls.Config{RootCAs: certPool, InsecureSkipVerify: true}
}
}
} else {
if coreopts.BuildOptions.IsLocalEndpoint(address) {
tlsConfig.VerifyPeerCertificate = func(certificates [][]byte, verifiedChains [][]*x509.Certificate) error {
if verifiedChains != nil {
serverIP := net.ParseIP("127.0.0.1") // Change to local IP for self signed cert local debugging
for _, certChain := range verifiedChains {
for _, cert := range certChain {
if cert.IPAddresses != nil {
for _, ip := range cert.IPAddresses {
if ip.Equal(serverIP) {
return nil
}
}
}
}
}
return errors.New("TLS certificate verification failed (IP SAN mismatch)")
}
return nil
}
}
}
dialTimeout := 30 * time.Second
tlsHandshakeTimeout := 30 * time.Second
if scan {
dialTimeout = 50 * time.Millisecond
tlsHandshakeTimeout = 50 * time.Millisecond
}
// create another test server and use the certificate
// configure a client to use trust those certificates
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
DialContext: (&net.Dialer{
Timeout: dialTimeout,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: tlsHandshakeTimeout,
ExpectContinueTimeout: 1 * time.Second,
DisableKeepAlives: false,
MaxConnsPerHost: 10,
},
}
return httpClient, nil
}