blob: 3d0b38fd52d92dc3d900b428b1c888f664eff67f [file] [log] [blame]
murgatroid99153b09d2015-09-25 16:04:03 -07001/*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34'use strict';
35
36var assert = require('assert');
37var fs = require('fs');
38var path = require('path');
39
40var grpc = require('..');
41
murgatroid999c43b002015-09-28 16:31:16 -070042/**
43 * This is used for testing functions with multiple asynchronous calls that
44 * can happen in different orders. This should be passed the number of async
45 * function invocations that can occur last, and each of those should call this
46 * function's return value
47 * @param {function()} done The function that should be called when a test is
48 * complete.
49 * @param {number} count The number of calls to the resulting function if the
50 * test passes.
51 * @return {function()} The function that should be called at the end of each
52 * sequence of asynchronous functions.
53 */
54function multiDone(done, count) {
55 return function() {
56 count -= 1;
57 if (count <= 0) {
58 done();
59 }
60 };
61}
62
murgatroid997cfee082015-10-13 13:49:55 -070063var fakeSuccessfulGoogleCredentials = {
64 getRequestMetadata: function(service_url, callback) {
65 setTimeout(function() {
66 callback(null, {Authorization: 'success'});
67 }, 0);
68 }
69};
70
71var fakeFailingGoogleCredentials = {
72 getRequestMetadata: function(service_url, callback) {
73 setTimeout(function() {
74 callback(new Error("Authorization failure"));
75 }, 0);
76 }
77};
78
murgatroid99a5a897d2015-09-28 16:38:38 -070079describe('client credentials', function() {
murgatroid99153b09d2015-09-25 16:04:03 -070080 var Client;
81 var server;
82 var port;
83 var client_ssl_creds;
84 var client_options = {};
85 before(function() {
86 var proto = grpc.load(__dirname + '/test_service.proto');
87 server = new grpc.Server();
88 server.addProtoService(proto.TestService.service, {
89 unary: function(call, cb) {
90 call.sendMetadata(call.metadata);
91 cb(null, {});
92 },
93 clientStream: function(stream, cb){
94 stream.on('data', function(data) {});
95 stream.on('end', function() {
96 stream.sendMetadata(stream.metadata);
97 cb(null, {});
98 });
99 },
100 serverStream: function(stream) {
101 stream.sendMetadata(stream.metadata);
102 stream.end();
103 },
104 bidiStream: function(stream) {
105 stream.on('data', function(data) {});
106 stream.on('end', function() {
107 stream.sendMetadata(stream.metadata);
108 stream.end();
109 });
110 }
111 });
112 var key_path = path.join(__dirname, './data/server1.key');
113 var pem_path = path.join(__dirname, './data/server1.pem');
114 var key_data = fs.readFileSync(key_path);
115 var pem_data = fs.readFileSync(pem_path);
116 var creds = grpc.ServerCredentials.createSsl(null,
117 [{private_key: key_data,
118 cert_chain: pem_data}]);
119 //creds = grpc.ServerCredentials.createInsecure();
120 port = server.bind('localhost:0', creds);
121 server.start();
122
123 Client = proto.TestService;
124 var ca_path = path.join(__dirname, '../test/data/ca.pem');
125 var ca_data = fs.readFileSync(ca_path);
126 client_ssl_creds = grpc.credentials.createSsl(ca_data);
127 var host_override = 'foo.test.google.fr';
128 client_options['grpc.ssl_target_name_override'] = host_override;
129 client_options['grpc.default_authority'] = host_override;
130 });
131 after(function() {
132 server.forceShutdown();
133 });
murgatroid999c43b002015-09-28 16:31:16 -0700134 it('Should accept SSL creds for a client', function(done) {
135 var client = new Client('localhost:' + port, client_ssl_creds,
136 client_options);
137 client.unary({}, function(err, data) {
138 assert.ifError(err);
139 done();
140 });
141 });
142 it('Should update metadata with SSL creds', function(done) {
murgatroid99153b09d2015-09-25 16:04:03 -0700143 var metadataUpdater = function(service_url, callback) {
144 var metadata = new grpc.Metadata();
145 metadata.set('plugin_key', 'plugin_value');
146 callback(null, metadata);
147 };
148 var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
murgatroid99be13d812015-10-09 14:45:30 -0700149 var combined_creds = grpc.credentials.combineChannelCredentials(
150 client_ssl_creds, creds);
murgatroid99153b09d2015-09-25 16:04:03 -0700151 var client = new Client('localhost:' + port, combined_creds,
152 client_options);
153 var call = client.unary({}, function(err, data) {
154 assert.ifError(err);
murgatroid99153b09d2015-09-25 16:04:03 -0700155 });
156 call.on('metadata', function(metadata) {
157 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
158 done();
159 });
160 });
murgatroid999c43b002015-09-28 16:31:16 -0700161 it('Should update metadata for two simultaneous calls', function(done) {
162 done = multiDone(done, 2);
163 var metadataUpdater = function(service_url, callback) {
164 var metadata = new grpc.Metadata();
165 metadata.set('plugin_key', 'plugin_value');
166 callback(null, metadata);
167 };
168 var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
murgatroid99be13d812015-10-09 14:45:30 -0700169 var combined_creds = grpc.credentials.combineChannelCredentials(
170 client_ssl_creds, creds);
murgatroid999c43b002015-09-28 16:31:16 -0700171 var client = new Client('localhost:' + port, combined_creds,
172 client_options);
173 var call = client.unary({}, function(err, data) {
174 assert.ifError(err);
175 });
176 call.on('metadata', function(metadata) {
177 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
178 done();
179 });
180 var call2 = client.unary({}, function(err, data) {
181 assert.ifError(err);
182 });
183 call2.on('metadata', function(metadata) {
184 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
185 done();
186 });
187 });
murgatroid996fe015e2015-10-12 13:18:06 -0700188 it.skip('should propagate errors that the updater emits', function(done) {
189 var metadataUpdater = function(service_url, callback) {
190 var error = new Error('Authentication error');
191 error.code = grpc.status.UNAUTHENTICATED;
192 callback(error);
193 };
194 var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
195 var combined_creds = grpc.credentials.combineChannelCredentials(
196 client_ssl_creds, creds);
197 var client = new Client('localhost:' + port, combined_creds,
198 client_options);
199 client.unary({}, function(err, data) {
200 assert(err);
201 assert.strictEqual(err.message, 'Authentication error');
202 assert.strictEqual(err.code, grpc.status.UNAUTHENTICATED);
203 done();
204 });
205 });
murgatroid997cfee082015-10-13 13:49:55 -0700206 it('should successfully wrap a Google credential', function(done) {
207 var creds = grpc.credentials.createFromGoogleCredential(
208 fakeSuccessfulGoogleCredentials);
209 var combined_creds = grpc.credentials.combineChannelCredentials(
210 client_ssl_creds, creds);
211 var client = new Client('localhost:' + port, combined_creds,
212 client_options);
213 var call = client.unary({}, function(err, data) {
214 assert.ifError(err);
215 });
216 call.on('metadata', function(metadata) {
murgatroid99c52dfac2015-10-13 15:37:34 -0700217 assert.deepEqual(metadata.get('authorization'), ['success']);
murgatroid997cfee082015-10-13 13:49:55 -0700218 done();
219 });
220 });
221 it.skip('should get an error from a Google credential', function(done) {
222 var creds = grpc.credentials.createFromGoogleCredential(
223 fakeFailingGoogleCredentials);
224 var combined_creds = grpc.credentials.combineChannelCredentials(
225 client_ssl_creds, creds);
226 var client = new Client('localhost:' + port, combined_creds,
227 client_options);
228 client.unary({}, function(err, data) {
229 assert(err);
230 assert.strictEqual(err.message, 'Authorization failure');
231 done();
232 });
233 });
murgatroid999c43b002015-09-28 16:31:16 -0700234 describe('Per-rpc creds', function() {
235 var client;
236 var updater_creds;
237 before(function() {
238 client = new Client('localhost:' + port, client_ssl_creds,
239 client_options);
240 var metadataUpdater = function(service_url, callback) {
241 var metadata = new grpc.Metadata();
242 metadata.set('plugin_key', 'plugin_value');
243 callback(null, metadata);
244 };
245 updater_creds = grpc.credentials.createFromMetadataGenerator(
246 metadataUpdater);
247 });
248 it('Should update metadata on a unary call', function(done) {
249 var call = client.unary({}, function(err, data) {
250 assert.ifError(err);
251 }, null, {credentials: updater_creds});
252 call.on('metadata', function(metadata) {
253 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
254 done();
255 });
256 });
257 it('should update metadata on a client streaming call', function(done) {
258 var call = client.clientStream(function(err, data) {
259 assert.ifError(err);
260 }, null, {credentials: updater_creds});
261 call.on('metadata', function(metadata) {
262 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
263 done();
264 });
265 call.end();
266 });
267 it('should update metadata on a server streaming call', function(done) {
268 var call = client.serverStream({}, null, {credentials: updater_creds});
269 call.on('data', function() {});
270 call.on('metadata', function(metadata) {
271 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
272 done();
273 });
274 });
275 it('should update metadata on a bidi streaming call', function(done) {
276 var call = client.bidiStream(null, {credentials: updater_creds});
277 call.on('data', function() {});
278 call.on('metadata', function(metadata) {
279 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
280 done();
281 });
282 call.end();
283 });
murgatroid995f709ca2015-09-30 14:22:54 -0700284 it('should be able to use multiple plugin credentials', function(done) {
285 var altMetadataUpdater = function(service_url, callback) {
286 var metadata = new grpc.Metadata();
287 metadata.set('other_plugin_key', 'other_plugin_value');
288 callback(null, metadata);
289 };
290 var alt_updater_creds = grpc.credentials.createFromMetadataGenerator(
291 altMetadataUpdater);
292 var combined_updater = grpc.credentials.combineCallCredentials(
293 updater_creds, alt_updater_creds);
294 var call = client.unary({}, function(err, data) {
295 assert.ifError(err);
murgatroid99be13d812015-10-09 14:45:30 -0700296 }, null, {credentials: combined_updater});
murgatroid995f709ca2015-09-30 14:22:54 -0700297 call.on('metadata', function(metadata) {
298 assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
299 assert.deepEqual(metadata.get('other_plugin_key'),
300 ['other_plugin_value']);
301 done();
302 });
303 });
murgatroid999c43b002015-09-28 16:31:16 -0700304 });
murgatroid99153b09d2015-09-25 16:04:03 -0700305});