github.com/KinWaiYuen/client-go/v2@v2.5.4/config/security.go (about)

     1  // Copyright 2021 TiKV Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // NOTE: The code in this file is based on code from the
    16  // TiDB project, licensed under the Apache License v 2.0
    17  //
    18  // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/config/security.go
    19  //
    20  
    21  // Copyright 2021 PingCAP, Inc.
    22  //
    23  // Licensed under the Apache License, Version 2.0 (the "License");
    24  // you may not use this file except in compliance with the License.
    25  // You may obtain a copy of the License at
    26  //
    27  //     http://www.apache.org/licenses/LICENSE-2.0
    28  //
    29  // Unless required by applicable law or agreed to in writing, software
    30  // distributed under the License is distributed on an "AS IS" BASIS,
    31  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    32  // See the License for the specific language governing permissions and
    33  // limitations under the License.
    34  
    35  package config
    36  
    37  import (
    38  	"crypto/tls"
    39  	"crypto/x509"
    40  	"io/ioutil"
    41  
    42  	"github.com/pingcap/errors"
    43  )
    44  
    45  // Security is the security section of the config.
    46  type Security struct {
    47  	ClusterSSLCA    string   `toml:"cluster-ssl-ca" json:"cluster-ssl-ca"`
    48  	ClusterSSLCert  string   `toml:"cluster-ssl-cert" json:"cluster-ssl-cert"`
    49  	ClusterSSLKey   string   `toml:"cluster-ssl-key" json:"cluster-ssl-key"`
    50  	ClusterVerifyCN []string `toml:"cluster-verify-cn" json:"cluster-verify-cn"`
    51  }
    52  
    53  // NewSecurity creates a Security.
    54  func NewSecurity(sslCA, sslCert, sslKey string, verityCN []string) Security {
    55  	return Security{
    56  		ClusterSSLCA:    sslCA,
    57  		ClusterSSLCert:  sslCert,
    58  		ClusterSSLKey:   sslKey,
    59  		ClusterVerifyCN: verityCN,
    60  	}
    61  }
    62  
    63  // ToTLSConfig generates tls's config based on security section of the config.
    64  func (s *Security) ToTLSConfig() (tlsConfig *tls.Config, err error) {
    65  	if len(s.ClusterSSLCA) != 0 {
    66  		certPool := x509.NewCertPool()
    67  		// Create a certificate pool from the certificate authority
    68  		var ca []byte
    69  		ca, err = ioutil.ReadFile(s.ClusterSSLCA)
    70  		if err != nil {
    71  			err = errors.Errorf("could not read ca certificate: %s", err)
    72  			return
    73  		}
    74  		// Append the certificates from the CA
    75  		if !certPool.AppendCertsFromPEM(ca) {
    76  			err = errors.New("failed to append ca certs")
    77  			return
    78  		}
    79  		tlsConfig = &tls.Config{
    80  			RootCAs:   certPool,
    81  			ClientCAs: certPool,
    82  		}
    83  
    84  		if len(s.ClusterSSLCert) != 0 && len(s.ClusterSSLKey) != 0 {
    85  			getCert := func() (*tls.Certificate, error) {
    86  				// Load the client certificates from disk
    87  				cert, err := tls.LoadX509KeyPair(s.ClusterSSLCert, s.ClusterSSLKey)
    88  				if err != nil {
    89  					return nil, errors.Errorf("could not load client key pair: %s", err)
    90  				}
    91  				return &cert, nil
    92  			}
    93  			// pre-test cert's loading.
    94  			if _, err = getCert(); err != nil {
    95  				return
    96  			}
    97  			tlsConfig.GetClientCertificate = func(info *tls.CertificateRequestInfo) (certificate *tls.Certificate, err error) {
    98  				return getCert()
    99  			}
   100  			tlsConfig.GetCertificate = func(info *tls.ClientHelloInfo) (certificate *tls.Certificate, err error) {
   101  				return getCert()
   102  			}
   103  		}
   104  	}
   105  	return
   106  }