@@ -17,17 +17,20 @@ limitations under the License.
17
17
package comm
18
18
19
19
import (
20
+ "crypto/tls"
20
21
"fmt"
21
22
"io/ioutil"
23
+ "net"
22
24
"path/filepath"
25
+ "sync/atomic"
23
26
"testing"
27
+ "time"
24
28
25
- "github.com/spf13/viper"
26
-
27
- "crypto/tls"
28
-
29
+ testpb "github.com/hyperledger/fabric/core/comm/testdata/grpc"
29
30
"github.com/hyperledger/fabric/core/testutil"
31
+ "github.com/spf13/viper"
30
32
"github.com/stretchr/testify/assert"
33
+ "golang.org/x/net/context"
31
34
"google.golang.org/grpc"
32
35
)
33
36
@@ -141,7 +144,7 @@ func TestCASupport(t *testing.T) {
141
144
casClone := GetCASupport ()
142
145
assert .Exactly (t , casClone , cas , "Expected GetCASupport to be a singleton" )
143
146
144
- creds := cas .GetDeliverServiceCredentials ()
147
+ creds , _ := cas .GetDeliverServiceCredentials ("channel1" )
145
148
assert .Equal (t , "1.2" , creds .Info ().SecurityVersion ,
146
149
"Expected Security version to be 1.2" )
147
150
creds = cas .GetPeerCredentials (tls.Certificate {})
@@ -151,11 +154,115 @@ func TestCASupport(t *testing.T) {
151
154
// append some bad certs and make sure things still work
152
155
cas .ServerRootCAs = append (cas .ServerRootCAs , []byte ("badcert" ))
153
156
cas .ServerRootCAs = append (cas .ServerRootCAs , []byte (badPEM ))
154
- creds = cas .GetDeliverServiceCredentials ()
157
+ creds , _ = cas .GetDeliverServiceCredentials ("channel1" )
155
158
assert .Equal (t , "1.2" , creds .Info ().SecurityVersion ,
156
159
"Expected Security version to be 1.2" )
157
160
creds = cas .GetPeerCredentials (tls.Certificate {})
158
161
assert .Equal (t , "1.2" , creds .Info ().SecurityVersion ,
159
162
"Expected Security version to be 1.2" )
160
163
161
164
}
165
+
166
+ type srv struct {
167
+ port int
168
+ GRPCServer
169
+ caCert []byte
170
+ serviced uint32
171
+ }
172
+
173
+ func (s * srv ) assertServiced (t * testing.T ) {
174
+ assert .Equal (t , uint32 (1 ), atomic .LoadUint32 (& s .serviced ))
175
+ atomic .StoreUint32 (& s .serviced , 0 )
176
+ }
177
+
178
+ func (s * srv ) EmptyCall (context.Context , * testpb.Empty ) (* testpb.Empty , error ) {
179
+ atomic .StoreUint32 (& s .serviced , 1 )
180
+ return & testpb.Empty {}, nil
181
+ }
182
+
183
+ func newServer (org string , port int ) * srv {
184
+ certs := map [string ][]byte {
185
+ "ca.crt" : nil ,
186
+ "server.crt" : nil ,
187
+ "server.key" : nil ,
188
+ }
189
+ for suffix := range certs {
190
+ fName := filepath .Join ("testdata" , "impersonation" , org , suffix )
191
+ cert , err := ioutil .ReadFile (fName )
192
+ if err != nil {
193
+ panic (fmt .Errorf ("Failed reading %s: %v" , fName , err ))
194
+ }
195
+ certs [suffix ] = cert
196
+ }
197
+ l , err := net .Listen ("tcp" , fmt .Sprintf (":%d" , port ))
198
+ if err != nil {
199
+ panic (fmt .Errorf ("Failed listening on port %d: %v" , port , err ))
200
+ }
201
+ gSrv , err := NewGRPCServerFromListener (l , SecureServerConfig {
202
+ ServerCertificate : certs ["server.crt" ],
203
+ ServerKey : certs ["server.key" ],
204
+ UseTLS : true ,
205
+ })
206
+ if err != nil {
207
+ panic (fmt .Errorf ("Failed starting gRPC server: %v" , err ))
208
+ }
209
+ s := & srv {
210
+ port : port ,
211
+ caCert : certs ["ca.crt" ],
212
+ GRPCServer : gSrv ,
213
+ }
214
+ testpb .RegisterTestServiceServer (gSrv .Server (), s )
215
+ go s .Start ()
216
+ return s
217
+ }
218
+
219
+ func TestImpersonation (t * testing.T ) {
220
+ // Scenario: We have 2 organizations: orgA, orgB
221
+ // and each of them are in their respected channels- A, B.
222
+ // The test would obtain credentials.TransportCredentials by calling GetDeliverServiceCredentials.
223
+ // Each organization would have its own gRPC server (srvA and srvB) with a TLS certificate
224
+ // signed by its root CA and with a SAN entry of 'localhost'.
225
+ // We test the following assertions:
226
+ // 1) Invocation with GetDeliverServiceCredentials("A") to srvA succeeds
227
+ // 2) Invocation with GetDeliverServiceCredentials("B") to srvB succeeds
228
+ // 3) Invocation with GetDeliverServiceCredentials("A") to srvB fails
229
+ // 4) Invocation with GetDeliverServiceCredentials("B") to srvA fails
230
+
231
+ osA := newServer ("orgA" , 7070 )
232
+ defer osA .Stop ()
233
+ osB := newServer ("orgB" , 7080 )
234
+ defer osB .Stop ()
235
+ time .Sleep (time .Second )
236
+
237
+ cas := GetCASupport ()
238
+ _ , err := GetCASupport ().GetDeliverServiceCredentials ("C" )
239
+ assert .Error (t , err )
240
+
241
+ cas .OrdererRootCAsByChain ["A" ] = [][]byte {osA .caCert }
242
+ cas .OrdererRootCAsByChain ["B" ] = [][]byte {osB .caCert }
243
+
244
+ testInvoke (t , "A" , osA , true )
245
+ testInvoke (t , "B" , osB , true )
246
+ testInvoke (t , "A" , osB , false )
247
+ testInvoke (t , "B" , osA , false )
248
+
249
+ }
250
+
251
+ func testInvoke (t * testing.T , channelID string , s * srv , shouldSucceed bool ) {
252
+ creds , err := GetCASupport ().GetDeliverServiceCredentials (channelID )
253
+ assert .NoError (t , err )
254
+ endpoint := fmt .Sprintf ("localhost:%d" , s .port )
255
+ conn , err := grpc .Dial (endpoint , grpc .WithTimeout (time .Second * 3 ), grpc .WithTransportCredentials (creds ), grpc .WithBlock ())
256
+ if shouldSucceed {
257
+ assert .NoError (t , err )
258
+ defer conn .Close ()
259
+ } else {
260
+ assert .Error (t , err )
261
+ assert .Contains (t , err .Error (), "certificate signed by unknown authority" )
262
+ return
263
+ }
264
+ client := testpb .NewTestServiceClient (conn )
265
+ _ , err = client .EmptyCall (context .Background (), & testpb.Empty {})
266
+ assert .NoError (t , err )
267
+ s .assertServiced (t )
268
+ }
0 commit comments