github.com/cactusblossom/fabric-ca@v0.0.0-20200611062428-0082fc643826/lib/tls/tls.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package tls 18 19 import ( 20 "crypto/tls" 21 "crypto/x509" 22 "io/ioutil" 23 "time" 24 25 "github.com/cloudflare/cfssl/log" 26 "github.com/hyperledger/fabric-ca/util" 27 "github.com/hyperledger/fabric/bccsp" 28 "github.com/hyperledger/fabric/bccsp/factory" 29 "github.com/pkg/errors" 30 ) 31 32 // DefaultCipherSuites is a set of strong TLS cipher suites 33 var DefaultCipherSuites = []uint16{ 34 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 35 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 36 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 37 tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 38 tls.TLS_RSA_WITH_AES_128_GCM_SHA256, 39 tls.TLS_RSA_WITH_AES_256_GCM_SHA384, 40 } 41 42 // ServerTLSConfig defines key material for a TLS server 43 type ServerTLSConfig struct { 44 Enabled bool `help:"Enable TLS on the listening port"` 45 CertFile string `def:"tls-cert.pem" help:"PEM-encoded TLS certificate file for server's listening port"` 46 KeyFile string `help:"PEM-encoded TLS key for server's listening port"` 47 ClientAuth ClientAuth 48 } 49 50 // ClientAuth defines the key material needed to verify client certificates 51 type ClientAuth struct { 52 Type string `def:"noclientcert" help:"Policy the server will follow for TLS Client Authentication."` 53 CertFiles []string `help:"A list of comma-separated PEM-encoded trusted certificate files (e.g. root1.pem,root2.pem)"` 54 } 55 56 // ClientTLSConfig defines the key material for a TLS client 57 type ClientTLSConfig struct { 58 Enabled bool `skip:"true"` 59 CertFiles []string `help:"A list of comma-separated PEM-encoded trusted certificate files (e.g. root1.pem,root2.pem)"` 60 Client KeyCertFiles 61 } 62 63 // KeyCertFiles defines the files need for client on TLS 64 type KeyCertFiles struct { 65 KeyFile string `help:"PEM-encoded key file when mutual authentication is enabled"` 66 CertFile string `help:"PEM-encoded certificate file when mutual authenticate is enabled"` 67 } 68 69 // GetClientTLSConfig creates a tls.Config object from certs and roots 70 func GetClientTLSConfig(cfg *ClientTLSConfig, csp bccsp.BCCSP) (*tls.Config, error) { 71 var certs []tls.Certificate 72 73 if csp == nil { 74 csp = factory.GetDefault() 75 } 76 77 log.Debugf("CA Files: %+v\n", cfg.CertFiles) 78 log.Debugf("Client Cert File: %s\n", cfg.Client.CertFile) 79 log.Debugf("Client Key File: %s\n", cfg.Client.KeyFile) 80 81 if cfg.Client.CertFile != "" { 82 err := checkCertDates(cfg.Client.CertFile) 83 if err != nil { 84 return nil, err 85 } 86 87 clientCert, err := util.LoadX509KeyPair(cfg.Client.CertFile, cfg.Client.KeyFile, csp) 88 if err != nil { 89 return nil, err 90 } 91 92 certs = append(certs, *clientCert) 93 } else { 94 log.Debug("Client TLS certificate and/or key file not provided") 95 } 96 rootCAPool := x509.NewCertPool() 97 if len(cfg.CertFiles) == 0 { 98 return nil, errors.New("No trusted root certificates for TLS were provided") 99 } 100 101 for _, cacert := range cfg.CertFiles { 102 caCert, err := ioutil.ReadFile(cacert) 103 if err != nil { 104 return nil, errors.Wrapf(err, "Failed to read '%s'", cacert) 105 } 106 ok := rootCAPool.AppendCertsFromPEM(caCert) 107 if !ok { 108 return nil, errors.Errorf("Failed to process certificate from file %s", cacert) 109 } 110 } 111 112 config := &tls.Config{ 113 Certificates: certs, 114 RootCAs: rootCAPool, 115 } 116 117 return config, nil 118 } 119 120 // AbsTLSClient makes TLS client files absolute 121 func AbsTLSClient(cfg *ClientTLSConfig, configDir string) error { 122 var err error 123 124 for i := 0; i < len(cfg.CertFiles); i++ { 125 cfg.CertFiles[i], err = util.MakeFileAbs(cfg.CertFiles[i], configDir) 126 if err != nil { 127 return err 128 } 129 130 } 131 132 cfg.Client.CertFile, err = util.MakeFileAbs(cfg.Client.CertFile, configDir) 133 if err != nil { 134 return err 135 } 136 137 cfg.Client.KeyFile, err = util.MakeFileAbs(cfg.Client.KeyFile, configDir) 138 if err != nil { 139 return err 140 } 141 142 return nil 143 } 144 145 // AbsTLSServer makes TLS client files absolute 146 func AbsTLSServer(cfg *ServerTLSConfig, configDir string) error { 147 var err error 148 149 for i := 0; i < len(cfg.ClientAuth.CertFiles); i++ { 150 cfg.ClientAuth.CertFiles[i], err = util.MakeFileAbs(cfg.ClientAuth.CertFiles[i], configDir) 151 if err != nil { 152 return err 153 } 154 155 } 156 157 cfg.CertFile, err = util.MakeFileAbs(cfg.CertFile, configDir) 158 if err != nil { 159 return err 160 } 161 162 cfg.KeyFile, err = util.MakeFileAbs(cfg.KeyFile, configDir) 163 if err != nil { 164 return err 165 } 166 167 return nil 168 } 169 170 func checkCertDates(certFile string) error { 171 log.Debug("Check client TLS certificate for valid dates") 172 certPEM, err := ioutil.ReadFile(certFile) 173 if err != nil { 174 return errors.Wrapf(err, "Failed to read file '%s'", certFile) 175 } 176 177 cert, err := util.GetX509CertificateFromPEM(certPEM) 178 if err != nil { 179 return err 180 } 181 182 notAfter := cert.NotAfter 183 currentTime := time.Now().UTC() 184 185 if currentTime.After(notAfter) { 186 return errors.New("Certificate provided has expired") 187 } 188 189 notBefore := cert.NotBefore 190 if currentTime.Before(notBefore) { 191 return errors.New("Certificate provided not valid until later date") 192 } 193 194 return nil 195 }