trpc.group/trpc-go/trpc-go@v1.0.3/internal/tls/tls.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  // Package tls provides some utility functions to get TLS config.
    15  package tls
    16  
    17  import (
    18  	"crypto/tls"
    19  	"crypto/x509"
    20  	"errors"
    21  	"fmt"
    22  	"os"
    23  )
    24  
    25  // GetServerConfig gets TLS config for server.
    26  // If you do not need to verify the client's certificate, set the caCertFile to empty.
    27  // CertFile and keyFile should not be empty.
    28  func GetServerConfig(caCertFile, certFile, keyFile string) (*tls.Config, error) {
    29  	tlsConf := &tls.Config{}
    30  	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    31  	if err != nil {
    32  		return nil, fmt.Errorf("server load cert file error: %w", err)
    33  	}
    34  	tlsConf.Certificates = []tls.Certificate{cert}
    35  
    36  	if caCertFile == "" { // no need to verify client certificate.
    37  		return tlsConf, nil
    38  	}
    39  	tlsConf.ClientAuth = tls.RequireAndVerifyClientCert
    40  	pool, err := GetCertPool(caCertFile)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	tlsConf.ClientCAs = pool
    45  	return tlsConf, nil
    46  }
    47  
    48  // GetClientConfig gets TLS config for client.
    49  // If you do not need to verify the server's certificate, set the caCertFile to "none".
    50  // If only one-way authentication, set the certFile and keyFile to empty.
    51  func GetClientConfig(serverName, caCertFile, certFile, keyFile string) (*tls.Config, error) {
    52  	tlsConf := &tls.Config{}
    53  	if caCertFile == "none" { // no need to verify server certificate.
    54  		tlsConf.InsecureSkipVerify = true
    55  		return tlsConf, nil
    56  	}
    57  	// need to verify server certification.
    58  	tlsConf.ServerName = serverName
    59  	certPool, err := GetCertPool(caCertFile)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	tlsConf.RootCAs = certPool
    64  	if certFile == "" {
    65  		return tlsConf, nil
    66  	}
    67  	// enable two-way authentication and needs to send the
    68  	// client's own certificate to the server.
    69  	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    70  	if err != nil {
    71  		return nil, fmt.Errorf("client load cert file error: %w", err)
    72  	}
    73  	tlsConf.Certificates = []tls.Certificate{cert}
    74  	return tlsConf, nil
    75  }
    76  
    77  // GetCertPool gets CertPool information.
    78  func GetCertPool(caCertFile string) (*x509.CertPool, error) {
    79  	// root means to use the root ca certificate installed on the machine to
    80  	// verify the peer, if not root, use the input ca file to verify peer.
    81  	if caCertFile == "root" {
    82  		return nil, nil
    83  	}
    84  	ca, err := os.ReadFile(caCertFile)
    85  	if err != nil {
    86  		return nil, fmt.Errorf("read ca file error: %w", err)
    87  	}
    88  	certPool := x509.NewCertPool()
    89  	if !certPool.AppendCertsFromPEM(ca) {
    90  		return nil, errors.New("AppendCertsFromPEM fail")
    91  	}
    92  	return certPool, nil
    93  }