Skip to content

Commit 9c26033

Browse files
fix(fsccli): Fix TLS config for fsccli
Signed-off-by: Marcus Brandenburger <bur@zurich.ibm.com>
1 parent aa23760 commit 9c26033

File tree

7 files changed

+115
-50
lines changed

7 files changed

+115
-50
lines changed

integration/benchmark/node/bench_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,13 @@ func setupClient(tb testing.TB, confPath string) (*benchmark.ViewClient, error)
183183
return nil, err
184184
}
185185

186+
tlsEnabled := config.TLSConfig.Enabled
187+
tlsRootCACert := path.Clean(config.TLSConfig.RootCACertPath)
188+
186189
cc := &grpc.ConnectionConfig{
187190
Address: config.Address,
188-
TLSEnabled: true,
189-
TLSRootCertFile: path.Join(config.TLSConfig.PeerCACertPath),
191+
TLSEnabled: tlsEnabled,
192+
TLSRootCertFile: tlsRootCACert,
190193
ConnectionTimeout: 10 * time.Second,
191194
}
192195

integration/nwo/fsc/fsc.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,18 @@ func (p *Platform) GenerateArtifacts() {
151151
p.GenerateRoutingConfig()
152152
}
153153

154+
// TLS settings
155+
var tlsConfig view2.TLSClientConfig
156+
tlsConfig.RootCACertPath = path.Join(p.NodeLocalTLSDir(peer.Peer), "ca.crt")
157+
tlsConfig.Enabled = len(tlsConfig.RootCACertPath) > 0
158+
159+
// TODO: note that NWO does not yet support mTLS
160+
tlsConfig.ClientAuthRequired = p.ClientAuthRequired()
161+
154162
c := view2.Config{
155-
Version: 0,
156-
Address: p.PeerAddress(peer, ListenPort),
157-
TLSConfig: view2.TLSConfig{
158-
PeerCACertPath: path.Join(p.NodeLocalTLSDir(peer.Peer), "ca.crt"),
159-
Timeout: 10 * time.Minute,
160-
},
163+
Version: 0,
164+
Address: p.PeerAddress(peer, ListenPort),
165+
TLSConfig: tlsConfig,
161166
SignerConfig: view2.SignerConfig{
162167
IdentityPath: p.LocalMSPIdentityCert(peer.Peer),
163168
KeyPath: p.LocalMSPPrivateKey(peer.Peer),

integration/nwo/fsc/node/core_template.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ fsc:
5050
# Private key used for TLS server
5151
key:
5252
file: {{ .NodeLocalTLSDir Peer }}/server.key
53+
{{- if .ClientAuthRequired }}
5354
# If mutual TLS is enabled, clientRootCAs.files contains a list of additional root certificates
5455
# used for verifying certificates of client connections.
55-
{{- if .ClientAuthRequired }}
5656
clientRootCAs:
5757
files:
5858
- {{ .NodeLocalTLSDir Peer }}/ca.crt
@@ -122,20 +122,25 @@ fsc:
122122
# HTTPS server listener address
123123
address: 0.0.0.0:{{ .NodePort Replica "Web" }}
124124
tls:
125+
# Require server-side TLS
125126
enabled: true
127+
# Require client certificates / mutual TLS for inbound connections.
128+
# Note that clients that are not configured to use a certificate will
129+
# fail to connect to the node.
130+
clientAuthRequired: {{ .ClientAuthRequired }}
131+
# X.509 certificate used for TLS server
126132
cert:
127133
file: {{ .NodeLocalTLSDir Peer }}/server.crt
134+
# Private key used for TLS server
128135
key:
129136
file: {{ .NodeLocalTLSDir Peer }}/server.key
130-
# Require client certificates / mutual TLS for inbound connections.
131-
# Note that clients that are not configured to use a certificate will
132-
# fail to connect to the node.
133-
clientAuthRequired: false
137+
{{- if .ClientAuthRequired }}
134138
# If mutual TLS is enabled, clientRootCAs.files contains a list of additional root certificates
135139
# used for verifying certificates of client connections.
136140
clientRootCAs:
137141
files:
138142
- {{ .NodeLocalTLSDir Peer }}/ca.crt
143+
{{- end }}
139144
tracing:
140145
# Type of provider to be used: none (default), file, otlp, console
141146
provider: {{ Topology.Monitoring.TracingType }}

platform/view/services/view/grpc/client/cmd/config.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package view
88

99
import (
1010
"os"
11-
"time"
1211

1312
"github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
1413
"gopkg.in/yaml.v2"
@@ -20,19 +19,20 @@ type SignerConfig struct {
2019
KeyPath string
2120
}
2221

23-
// TLSConfig defines configuration of a Client
24-
type TLSConfig struct {
25-
CertPath string
26-
KeyPath string
27-
PeerCACertPath string
28-
Timeout time.Duration
22+
// TLSClientConfig defines configuration of a Client
23+
type TLSClientConfig struct {
24+
Enabled bool `yaml:"enabled"`
25+
RootCACertPath string `yaml:"rootCACertPath,omitempty"`
26+
ClientAuthRequired bool `yaml:"clientAuthRequired,omitempty"`
27+
ClientCertPath string `yaml:"clientCertPath,omitempty"`
28+
ClientKeyPath string `yaml:"clientKeyPath,omitempty"`
2929
}
3030

3131
// Config aggregates configuration of TLS and signing
3232
type Config struct {
3333
Version int
3434
Address string
35-
TLSConfig TLSConfig
35+
TLSConfig TLSClientConfig
3636
SignerConfig SignerConfig
3737
}
3838

@@ -76,3 +76,31 @@ func validateConfig(conf Config) error {
7676
}
7777
return nil
7878
}
79+
80+
func ValidateTLSConfig(config TLSClientConfig) error {
81+
isEmpty := func(val string) bool {
82+
return len(val) == 0
83+
}
84+
85+
if !config.Enabled {
86+
return nil
87+
}
88+
89+
if isEmpty(config.RootCACertPath) {
90+
return errors.New("rootCACertPath not set")
91+
}
92+
93+
if !config.ClientAuthRequired {
94+
return nil
95+
}
96+
97+
if isEmpty(config.ClientKeyPath) {
98+
return errors.New("clientKeyPath not set")
99+
}
100+
101+
if isEmpty(config.ClientCertPath) {
102+
return errors.New("ClientCertPath not set")
103+
}
104+
105+
return nil
106+
}

platform/view/services/view/grpc/client/cmd/config_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ func TestConfig(t *testing.T) {
2424
fmt.Println(configFilePath)
2525
t.Run("save and load a config", func(t *testing.T) {
2626
c := Config{
27-
TLSConfig: TLSConfig{
28-
CertPath: "foo",
29-
KeyPath: "foo",
30-
PeerCACertPath: "foo",
31-
Timeout: time.Second * 3,
27+
TLSConfig: TLSClientConfig{
28+
Enabled: true,
29+
ClientAuthRequired: true,
30+
ClientCertPath: "foo",
31+
ClientKeyPath: "foo",
32+
RootCACertPath: "foo",
3233
},
3334
SignerConfig: SignerConfig{
3435
KeyPath: "foo",

platform/view/services/view/grpc/client/cmd/view.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,12 @@ func parseFlagsToConfig() Config {
110110
IdentityPath: userCert,
111111
KeyPath: userKey,
112112
},
113-
TLSConfig: TLSConfig{
114-
KeyPath: tlsKey,
115-
CertPath: tlsCert,
116-
PeerCACertPath: tlsCA,
113+
TLSConfig: TLSClientConfig{
114+
Enabled: len(tlsCA) > 0,
115+
RootCACertPath: tlsCA,
116+
ClientAuthRequired: len(tlsCert) > 0 && len(tlsKey) > 0,
117+
ClientCertPath: tlsCert,
118+
ClientKeyPath: tlsKey,
117119
},
118120
}
119121
return conf
@@ -145,10 +147,25 @@ func invoke() error {
145147
return err
146148
}
147149

150+
if err := ValidateTLSConfig(config.TLSConfig); err != nil {
151+
return err
152+
}
153+
154+
// parse TLS configuration
155+
tlsEnabled := config.TLSConfig.Enabled
156+
tlsRootCACert := path.Clean(config.TLSConfig.RootCACertPath)
157+
158+
// TODO:
159+
// parse mTLS configuration
160+
//mtlsEnabled := config.TLSConfig.ClientAuthRequired
161+
//tlsClientCert := path.Clean(config.TLSConfig.ClientCertPath)
162+
//tlsClientKey := path.Clean(config.TLSConfig.ClientKeyPath)
163+
148164
cc := &grpc.ConnectionConfig{
149-
Address: config.Address,
150-
TLSEnabled: true,
151-
TLSRootCertFile: path.Join(config.TLSConfig.PeerCACertPath),
165+
Address: config.Address,
166+
TLSEnabled: tlsEnabled,
167+
TLSRootCertFile: tlsRootCACert,
168+
//TLSClientSideAuth: mtlsEnabled,
152169
ConnectionTimeout: 10 * time.Second,
153170
}
154171

platform/view/services/web/server/server.go

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,13 @@ func (t TLS) Config() (*tls.Config, error) {
4040
if !t.Enabled {
4141
return tlsConfig, nil
4242
}
43+
44+
// setup TLS
4345
cert, err := tls.LoadX509KeyPair(t.CertFile, t.KeyFile)
4446
if err != nil {
4547
return nil, err
4648
}
4749

48-
if len(t.ClientCACertFiles) == 0 {
49-
return nil, errors.Errorf("client TLS CA certificate pool must not be empty")
50-
}
51-
52-
caCertPool := x509.NewCertPool()
53-
for _, caPath := range t.ClientCACertFiles {
54-
caPem, err := os.ReadFile(caPath)
55-
if err != nil {
56-
return nil, err
57-
}
58-
caCertPool.AppendCertsFromPEM(caPem)
59-
}
6050
tlsConfig = &tls.Config{
6151
Certificates: []tls.Certificate{cert},
6252
CipherSuites: []uint16{
@@ -71,13 +61,29 @@ func (t TLS) Config() (*tls.Config, error) {
7161
},
7262
MinVersion: tls.VersionTLS12,
7363
MaxVersion: tls.VersionTLS13,
74-
ClientCAs: caCertPool,
64+
ClientAuth: tls.VerifyClientCertIfGiven,
7565
}
76-
if t.ClientAuth {
77-
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
78-
} else {
79-
tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven
66+
67+
if !t.ClientAuth {
68+
return tlsConfig, nil
69+
}
70+
71+
// setup mTLS
72+
if len(t.ClientCACertFiles) == 0 {
73+
return nil, errors.Errorf("client TLS CA certificate pool must not be empty")
8074
}
75+
76+
caCertPool := x509.NewCertPool()
77+
for _, caPath := range t.ClientCACertFiles {
78+
caPem, err := os.ReadFile(caPath)
79+
if err != nil {
80+
return nil, err
81+
}
82+
caCertPool.AppendCertsFromPEM(caPem)
83+
}
84+
tlsConfig.ClientCAs = caCertPool
85+
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
86+
8187
return tlsConfig, nil
8288
}
8389

0 commit comments

Comments
 (0)