forked from letsencrypt/boulder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
83 lines (73 loc) · 2.82 KB
/
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
package grpc
import (
"crypto/tls"
"errors"
"net"
"github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/jmhodges/clock"
"github.com/letsencrypt/boulder/cmd"
bcreds "github.com/letsencrypt/boulder/grpc/creds"
"github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
)
// ClientSetup creates a gRPC TransportCredentials that presents
// a client certificate and validates the the server certificate based
// on the provided *tls.Config.
// It dials the remote service and returns a grpc.ClientConn if successful.
func ClientSetup(c *cmd.GRPCClientConfig, tlsConfig *tls.Config, metrics clientMetrics, clk clock.Clock) (*grpc.ClientConn, error) {
if c == nil {
return nil, errors.New("nil gRPC client config provided. JSON config is probably missing a fooService section.")
}
if c.ServerAddress == "" {
return nil, errors.New("ServerAddress must not be empty")
}
if tlsConfig == nil {
return nil, errNilTLS
}
// Set the only acceptable TLS version to 1.2 and the only acceptable cipher suite
// to ECDHE-RSA-CHACHA20-POLY1305.
tlsConfig.MinVersion, tlsConfig.MaxVersion = tls.VersionTLS12, tls.VersionTLS12
tlsConfig.CipherSuites = []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}
ci := clientInterceptor{c.Timeout.Duration, metrics, clk}
host, _, err := net.SplitHostPort(c.ServerAddress)
if err != nil {
return nil, err
}
creds := bcreds.NewClientCredentials(tlsConfig.RootCAs, tlsConfig.Certificates, host)
return grpc.Dial(
"dns:///"+c.ServerAddress,
grpc.WithBalancerName("round_robin"),
grpc.WithTransportCredentials(creds),
grpc.WithUnaryInterceptor(ci.intercept),
)
}
type registry interface {
MustRegister(...prometheus.Collector)
}
// clientMetrics is a struct type used to return registered metrics from
// `NewClientMetrics`
type clientMetrics struct {
grpcMetrics *grpc_prometheus.ClientMetrics
// inFlightRPCs is a labelled gauge that slices by service/method the number
// of outstanding/in-flight RPCs.
inFlightRPCs *prometheus.GaugeVec
}
// NewClientMetrics constructs a *grpc_prometheus.ClientMetrics, registered with
// the given registry, with timing histogram enabled. It must be called a
// maximum of once per registry, or there will be conflicting names.
func NewClientMetrics(stats registry) clientMetrics {
// Create the grpc prometheus client metrics instance and register it
grpcMetrics := grpc_prometheus.NewClientMetrics()
grpcMetrics.EnableClientHandlingTimeHistogram()
stats.MustRegister(grpcMetrics)
// Create a gauge to track in-flight RPCs and register it.
inFlightGauge := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "grpc_in_flight",
Help: "Number of in-flight (sent, not yet completed) RPCs",
}, []string{"method", "service"})
stats.MustRegister(inFlightGauge)
return clientMetrics{
grpcMetrics: grpcMetrics,
inFlightRPCs: inFlightGauge,
}
}