Skip to content

Commit 925f4d9

Browse files
ASHUTOSH KUMARmastersingh24
ASHUTOSH KUMAR
authored andcommitted
Allow TLS conn. between the client and the CA services
Fixes FAB-392 Supporting TLS between the ACA client the rest of the CA services. This feature requires changes to the configuration of the Membership Services (YAML file), adding the support for two newly added (YAML) configuration parameters under the security section of membersrvc.yaml. To enable this feature (TLS connectivity), one needs to specify that tls_enabled (=true) and a path to a PEM-encoded certificate file to use. There is also the option to use the serverhostname override, enforcing that the same TLS Server Certificate's Common Name to be used. Change-Id: I64444d0e21615a47662ba1388cd6901ff787b408 Signed-off-by: ASHUTOSH KUMAR <[email protected]> Signed-off-by: JonathanLevi <[email protected]> Signed-off-by: Gari Singh <[email protected]>
1 parent de2cade commit 925f4d9

File tree

5 files changed

+201
-8
lines changed

5 files changed

+201
-8
lines changed

docs/Setup/TLSSetup.md

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
### Steps to enable TLS for all sever (ECA , ACA , TLSCA , TCA) and between ACA client to server communications.
2+
3+
1. Go to **memebersrvc.yaml** file under the fabric/membersrvc directory and edit security section, that is:
4+
```
5+
security:
6+
serverhostoverride:
7+
tls_enabled: false
8+
client:
9+
cert:
10+
file:
11+
```
12+
To enable TLS between the ACA client and the rest of the CA Services set the `tls_enbabled` flag to `true`.
13+
14+
2. Next, set **serverhostoverride** field to match **CN** (Common Name) of TLS Server certificate. To extract the Common Name from TLS Server's certificate, for example using OpenSSL, you can use the following command:
15+
16+
```
17+
openssl x509 -in <<certificate.crt -text -noout
18+
```
19+
where `certficate.crt` is the Server Certificate. If you have openssl installed on the machine and everything went well, you should expect an output of the form:
20+
21+
```
22+
Certificate:
23+
Data:
24+
Version: 3 (0x2)
25+
Serial Number:
26+
4f:39:0f:ac:7b:ce:2b:9f:28:57:52:4a:bb:94:a6:e5:9c:69:99:56
27+
Signature Algorithm: ecdsa-with-SHA256
28+
Issuer: C=US, ST=California, L=San Francisco, O=Internet Widgets, Inc., OU=WWW
29+
Validity
30+
Not Before: Aug 24 16:27:00 2016 GMT
31+
Not After : Aug 24 16:27:00 2017 GMT
32+
**Subject**: C=US, ST=California, L=San Francisco, O=example.com, **CN=www.example.com**
33+
Subject Public Key Info:
34+
Public Key Algorithm: id-ecPublicKey
35+
EC Public Key:
36+
pub:
37+
04:38:d2:62:75:4a:18:d9:f7:fe:6a:e7:df:32:e2:
38+
15:0f:01:9c:1b:4f:dc:ff:22:97:5c:2a:d9:5c:c3:
39+
a3:ef:e3:90:3b:3c:8a:d2:45:b1:60:11:94:5e:a7:
40+
51:e8:e5:5d:be:38:39:da:66:e1:99:46:0c:d3:45:
41+
3d:76:7e:b7:8c
42+
ASN1 OID: prime256v1
43+
X509v3 extensions:
44+
X509v3 Key Usage: critical
45+
Digital Signature, Key Encipherment
46+
X509v3 Extended Key Usage:
47+
TLS Web Server Authentication
48+
X509v3 Basic Constraints: critical
49+
CA:FALSE
50+
X509v3 Subject Key Identifier:
51+
E8:9C:86:81:59:D4:D7:76:43:C7:2E:92:88:30:1B:30:A5:B3:A4:5C
52+
X509v3 Authority Key Identifier:
53+
keyid:5E:33:AC:E0:9D:B9:F9:71:5F:1F:96:B5:84:85:35:BE:89:8C:35:C2
54+
55+
X509v3 Subject Alternative Name:
56+
DNS:www.example.com
57+
Signature Algorithm: ecdsa-with-SHA256
58+
30:45:02:21:00:9f:7e:93:93:af:3d:cf:7b:77:f0:55:2d:57:
59+
9d:a9:bf:b0:8c:9c:2e:cf:b2:b4:d8:de:f3:79:c7:66:7c:e7:
60+
4d:02:20:7e:9b:36:d1:3a:df:e4:d2:d7:3b:9d:73:c7:61:a8:
61+
2e:a5:b1:23:10:65:81:96:b1:3b:79:d4:a6:12:fe:f2:69
62+
```
63+
64+
Now you can use that CN value (**www.example.com** above, for example) from the output and use it in the **serverhostoverride** field (under the security section of the membersrvc.yaml file)
65+
66+
3. Last, make sure that path to the corresponding TLS Server Certificate is specified under `security.client.cert.file`

membersrvc/ca/client_grpc.go

+111-3
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,132 @@
11
package ca
22

33
import (
4+
"crypto/tls"
5+
"crypto/x509"
6+
"encoding/pem"
7+
"io/ioutil"
48
"time"
59

610
pb "github.com/hyperledger/fabric/membersrvc/protos"
7-
"google.golang.org/grpc"
8-
911
"github.com/spf13/viper"
12+
"google.golang.org/grpc"
13+
"google.golang.org/grpc/credentials"
1014
)
1115

16+
/** Performs Certificate type validation **/
17+
/*
18+
* Checks for valid Cert format type
19+
* Cert expiration
20+
*
21+
*/
22+
func isValidCertFormatted(certLocation string) bool {
23+
24+
var isvalidCert = false
25+
certificate, err := ioutil.ReadFile(certLocation)
26+
if err != nil {
27+
return false
28+
}
29+
block, _ := pem.Decode(certificate)
30+
if block == nil {
31+
certificates, err := x509.ParseCertificates(certificate)
32+
if err != nil {
33+
caLogger.Error("Not a valid Certificate")
34+
} else {
35+
validCert := validateCert(certificates[0])
36+
if !validCert {
37+
caLogger.Error("Certificate has expired")
38+
}
39+
return validCert
40+
}
41+
} else {
42+
certificates, err := x509.ParseCertificates(block.Bytes)
43+
if err != nil {
44+
caLogger.Error("Not a valid Certificate")
45+
} else {
46+
validCert := validateCert(certificates[0])
47+
if !validCert {
48+
caLogger.Error("Certificate has expired")
49+
}
50+
return validCert
51+
}
52+
}
53+
54+
return isvalidCert
55+
56+
}
57+
58+
/** Given the cert , it checks for expiry
59+
* Does not check for revocation
60+
*/
61+
func validateCert(cert *x509.Certificate) bool {
62+
63+
notBefore := cert.NotBefore
64+
notAfter := cert.NotAfter
65+
66+
currentTime := time.Now()
67+
diffFromExpiry := notAfter.Sub(currentTime)
68+
diffFromStart := currentTime.Sub(notBefore)
69+
70+
return ((diffFromExpiry > 0) && (diffFromStart > 0))
71+
72+
}
73+
74+
// NewClientTLSFromFile creates Client TLS connection credentials
75+
// @certFile : TLS Server Certificate in PEM format
76+
// @serverNameOverride : Common Name (CN) of the TLS Server Certificate
77+
// returns Secure Transport Credentials
78+
//
79+
func NewClientTLSFromFile(certFile, serverNameOverride string) (credentials.TransportCredentials, error) {
80+
caLogger.Debug("upgrading to TLS1.2")
81+
b, err := ioutil.ReadFile(certFile)
82+
83+
if err != nil {
84+
caLogger.Errorf("Certificate could not be found in the [%s] path", certFile)
85+
return nil, err
86+
}
87+
88+
if !isValidCertFormatted(certFile) {
89+
return nil, nil
90+
}
91+
92+
cp := x509.NewCertPool()
93+
94+
ok := cp.AppendCertsFromPEM(b)
95+
if !ok {
96+
caLogger.Error("credentials: failed to append certificates: ")
97+
return nil, nil
98+
}
99+
return credentials.NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp, MinVersion: 0, MaxVersion: 0}), nil
100+
}
101+
12102
//GetClientConn returns a connection to the server located on *address*.
13103
func GetClientConn(address string, serverName string) (*grpc.ClientConn, error) {
104+
105+
caLogger.Debug("GetACAClient: using the given gRPC client connection to return a new ACA client")
14106
var opts []grpc.DialOption
15-
opts = append(opts, grpc.WithInsecure())
107+
108+
if viper.GetBool("security.tls_enabled") {
109+
caLogger.Debug("TLS was enabled [security.tls_enabled == true]")
110+
111+
creds, err := NewClientTLSFromFile(viper.GetString("security.client.cert.file"), viper.GetString("security.serverhostoverride"))
112+
113+
if err != nil {
114+
caLogger.Error("Could not establish TLS client connection in GetClientConn while getting creds:")
115+
caLogger.Error(err)
116+
return nil, err
117+
}
118+
opts = append(opts, grpc.WithTransportCredentials(creds))
119+
} else {
120+
caLogger.Debug("TLS was not enabled [security.tls_enabled == false]")
121+
opts = append(opts, grpc.WithInsecure())
122+
}
16123
opts = append(opts, grpc.WithTimeout(time.Second*3))
17124
return grpc.Dial(address, opts...)
18125
}
19126

20127
//GetACAClient returns a client to Attribute Certificate Authority.
21128
func GetACAClient() (*grpc.ClientConn, pb.ACAPClient, error) {
129+
caLogger.Debug("GetACAClient: Trying to create a new ACA Client from the connection provided")
22130
conn, err := GetClientConn(viper.GetString("aca.address"), viper.GetString("aca.server-name"))
23131
if err != nil {
24132
return nil, nil, err

membersrvc/membersrvc.yaml

+16-4
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,26 @@ server:
2121
file:
2222

2323
security:
24-
# Can be 256 or 384
25-
# Must be the same as in core.yaml
24+
# Either 256 or 384 (note: must be the exact same value as specified in the core.yaml file)
2625
level: 256
2726

28-
# Can be SHA2 or SHA3
29-
# Must be the same as in core.yaml
27+
# Either SHA2 or SHA3 (note: must be the exact same value as specified in the core.yaml file)
3028
hashAlgorithm: SHA3
3129

30+
# The server host CN (Common Name) to be used (needs to match the TLS Server Certificate)
31+
serverhostoverride:
32+
33+
# Boolean (true/false) value indicating whether TLS should be used between the client and
34+
# the various CA services (ECA, TCA, TLSCA, ACA)
35+
tls_enabled: false
36+
37+
# A PEM-encoded (X509 v3, Base64) certificate to use for establishing the TLS connection
38+
# between the client and the ACA service
39+
client:
40+
cert:
41+
file:
42+
43+
3244
# Enabling/disabling different logging levels of the CA.
3345
#
3446
logging:

membersrvc/server.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,22 @@ func main() {
8585
runtime.GOMAXPROCS(viper.GetInt("server.gomaxprocs"))
8686

8787
var opts []grpc.ServerOption
88-
if viper.GetString("server.tls.cert.file") != "" {
88+
89+
if viper.GetBool("security.tls_enabled") {
90+
logger.Debug("TLS was enabled [security.tls_enabled == true]")
8991
creds, err := credentials.NewServerTLSFromFile(viper.GetString("server.tls.cert.file"), viper.GetString("server.tls.key.file"))
9092
if err != nil {
9193
logger.Panic(err)
9294
}
9395
opts = []grpc.ServerOption{grpc.Creds(creds)}
96+
} else {
97+
logger.Debug("TLS was not enabled [security.tls_enabled == false]")
9498
}
99+
95100
srv := grpc.NewServer(opts...)
96101

97102
if viper.GetBool("aca.enabled") {
103+
logger.Debug("ACA was enabled [aca.enabled == true]")
98104
aca.Start(srv)
99105
}
100106
eca.Start(srv)

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pages:
1919
- Fabric Network Setup: Setup/Network-setup.md
2020
- NodeSDK Setup: Setup/NodeSDK-setup.md
2121
- CA Setup: Setup/ca-setup.md
22+
- TLS Setup: Setup/TLSSetup.md
2223
- Logging: Setup/logging-control.md
2324

2425
- APIs:

0 commit comments

Comments
 (0)