86 lines
1.6 KiB
Go
86 lines
1.6 KiB
Go
package cloud
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
_ "embed"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
)
|
|
|
|
var Host = "cloud.evcc.io:8080"
|
|
|
|
var (
|
|
conn *grpc.ClientConn
|
|
)
|
|
|
|
//go:embed ca-cert.pem
|
|
var caCert []byte
|
|
|
|
func caPEM() []byte {
|
|
copy := bytes.NewBuffer(caCert)
|
|
return copy.Bytes()
|
|
}
|
|
|
|
func loadTLSCredentials() (*tls.Config, error) {
|
|
certPool, err := x509.SystemCertPool()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !certPool.AppendCertsFromPEM(caPEM()) {
|
|
return nil, fmt.Errorf("failed to add CA certificate")
|
|
}
|
|
|
|
// create the credentials and return it
|
|
config := &tls.Config{
|
|
RootCAs: certPool,
|
|
}
|
|
|
|
return config, nil
|
|
}
|
|
|
|
func verifyConnection(host string) func(conn tls.ConnectionState) error {
|
|
return func(conn tls.ConnectionState) error {
|
|
if len(conn.PeerCertificates) > 0 {
|
|
peer := conn.PeerCertificates[0]
|
|
return peer.VerifyHostname(host)
|
|
}
|
|
|
|
return errors.New("missing host certificate")
|
|
}
|
|
}
|
|
|
|
func Connection(hostPort string) (*grpc.ClientConn, error) {
|
|
var err error
|
|
if conn == nil {
|
|
creds := insecure.NewCredentials()
|
|
|
|
if !strings.HasPrefix(hostPort, "localhost") {
|
|
host, _, err := net.SplitHostPort(hostPort)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tlsConfig *tls.Config
|
|
if tlsConfig, err = loadTLSCredentials(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// make sure it matches the hostname
|
|
tlsConfig.VerifyConnection = verifyConnection(host)
|
|
|
|
creds = credentials.NewTLS(tlsConfig)
|
|
}
|
|
conn, err = grpc.Dial(hostPort, grpc.WithTransportCredentials(creds))
|
|
}
|
|
|
|
return conn, err
|
|
}
|