github.com/grafana/synthetic-monitoring-agent@v0.64.2/cmd/synthetic-monitoring-agent/grpc.go (about) 1 package main 2 3 import ( 4 "context" 5 "crypto/tls" 6 "log" 7 "strings" 8 9 "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring" 10 "google.golang.org/grpc" 11 "google.golang.org/grpc/credentials" 12 "google.golang.org/grpc/credentials/insecure" 13 "google.golang.org/grpc/keepalive" 14 ) 15 16 // newAPIServerClient creates a client connection to an API server. It does not 17 // block: grpc.NewClient returns immediately with the connection in IDLE and 18 // connects lazily in the background on the first RPC. 19 func newAPIServerClient(addr string, allowInsecure bool, apiToken string) (*grpc.ClientConn, error) { 20 apiCreds := creds{Token: apiToken} 21 22 opts := []grpc.DialOption{ 23 grpc.WithPerRPCCredentials(apiCreds), 24 // Keep-alive is necessary to detect network failures in absence of writes from the client. 25 // Without it, the agent would hang if the server disappears while waiting for a response. 26 // See https://github.com/grpc/grpc/blob/master/doc/keepalive.md 27 grpc.WithKeepaliveParams(keepalive.ClientParameters{ 28 // GRPC_ARG_KEEPALIVE_TIME_MS - Time between pings 29 Time: synthetic_monitoring.HealthCheckInterval, 30 // GRPC_ARG_KEEPALIVE_TIMEOUT_MS - Ping timeout 31 Timeout: synthetic_monitoring.HealthCheckTimeout, 32 // GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS - Allow pings even if no grpc calls are in place. 33 // It shouldn't be the case that the agent doesn't have any calls in place during 34 // a significant period of time. 35 PermitWithoutStream: true, 36 }), 37 } 38 39 transportCreds := insecure.NewCredentials() 40 if !allowInsecure { 41 transportCreds = credentials.NewTLS(&tls.Config{ServerName: grpcApiHost(addr)}) 42 } 43 44 opts = append(opts, grpc.WithTransportCredentials(transportCreds)) 45 46 return grpc.NewClient(addr, opts...) 47 } 48 49 func grpcApiHost(addr string) string { 50 colonPos := strings.LastIndex(addr, ":") 51 if colonPos == -1 { 52 colonPos = len(addr) 53 } 54 55 hostname := addr[:colonPos] 56 57 return hostname 58 } 59 60 type creds struct { 61 Token string 62 } 63 64 func (c creds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 65 return map[string]string{ 66 "authorization": "Bearer " + c.Token, 67 }, nil 68 } 69 70 func (c creds) RequireTransportSecurity() bool { 71 log.Printf("RequireTransportSecurity") 72 // XXX(mem): this is true 73 return false 74 }