// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package client import ( "fmt" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "github.com/hashicorp/consul/proto-public/pbresource" ) type GRPCClient struct { Client pbresource.ResourceServiceClient Config *GRPCConfig Conn *grpc.ClientConn } func NewGRPCClient(config *GRPCConfig) (*GRPCClient, error) { conn, err := dial(config) if err != nil { return nil, fmt.Errorf("error dialing grpc: %+v", err) } return &GRPCClient{ Client: pbresource.NewResourceServiceClient(conn), Config: config, Conn: conn, }, nil } func dial(c *GRPCConfig) (*grpc.ClientConn, error) { err := checkCertificates(c) if err != nil { return nil, err } var dialOpts []grpc.DialOption if c.GRPCTLS { tlsConfig, err := SetupTLSConfig(c) if err != nil { return nil, fmt.Errorf("failed to setup tls config when tried to establish grpc call: %w", err) } dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) } else { dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials())) } return grpc.Dial(c.Address, dialOpts...) } func checkCertificates(c *GRPCConfig) error { if c.GRPCTLS { certFileEmpty := c.CertFile == "" keyFileEmpty := c.KeyFile == "" // both files need to be empty or both files need to be provided if certFileEmpty != keyFileEmpty { return fmt.Errorf("you have to provide client certificate file and key file at the same time " + "if you intend to communicate in TLS/SSL mode") } } return nil }