Skip to content

Commit 0cdbaca

Browse files
furkansenharputlumustafaiman
authored andcommitted
refactor ssl behavior and add tests
1 parent 490e605 commit 0cdbaca

31 files changed

+331
-245
lines changed

code_samples/ssl_authentication.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,11 @@
1717
var Config = require('hazelcast-client').Config;
1818
var HazelcastClient = require('hazelcast-client').Client;
1919

20-
if (process.argv.length < 5) {
21-
console.log('Usage: \n' +
22-
'node ssl_authentication.js [servername] [trusted-ca] [private-key] [certificate-file] ');
23-
return
24-
}
2520

2621
var cfg = new Config.ClientConfig();
27-
cfg.networkConfig.sslOptions = {
28-
servername: process.argv[2],
29-
ca: process.argv[3],
30-
key: process.argv[4],
31-
cert: process.argv[5],
32-
33-
};
22+
cfg.networkConfig.sslConfig.enabled = true;
3423

3524
HazelcastClient.newHazelcastClient(cfg).then(function (client) {
36-
console.log('This client is authenticated using ssl.');
25+
console.log('This client is authenticated using SSL.');
3726
client.shutdown();
3827
});

src/config/ClientNetworkConfig.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@
1414
* limitations under the License.
1515
*/
1616

17-
import {ImportConfig} from './ImportConfig';
18-
import {Properties} from './Properties';
19-
import {SSLOptions} from './SSLOptions';
2017
import {ClientCloudConfig} from './ClientCloudConfig';
18+
import {SSLConfig} from './SSLConfig';
2119

2220
/**
23-
* Network configuration
21+
* Network configuration.
2422
*/
2523
export class ClientNetworkConfig {
2624
/**
@@ -59,12 +57,7 @@ export class ClientNetworkConfig {
5957
smartRouting: boolean = true;
6058

6159
/**
62-
* sslOptions is by default null which disables Ssl. A none null {@link SSLOptions} value enables Ssl.
63-
* @type {SSLOptions}
60+
* SSL configuration.
6461
*/
65-
sslOptions: SSLOptions = null;
66-
67-
sslOptionsFactoryConfig: ImportConfig = null;
68-
69-
sslOptionsFactoryProperties: Properties = null;
62+
sslConfig: SSLConfig = new SSLConfig();
7063
}

src/config/ConfigBuilder.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class ConfigBuilder {
4949
this.handleConfig(this.loadedJson);
5050
return this.clientConfig;
5151
} catch (e) {
52-
throw new HazelcastError('Error parsing config.', e);
52+
throw new HazelcastError('Error parsing config: ' + e.message, e);
5353
}
5454
}
5555

@@ -99,7 +99,7 @@ export class ConfigBuilder {
9999
} else if (key === 'connectionAttemptLimit') {
100100
this.clientConfig.networkConfig.connectionAttemptLimit = tryGetNumber(jsonObject[key]);
101101
} else if (key === 'ssl') {
102-
this.handleSsl(jsonObject[key]);
102+
this.handleSSL(jsonObject[key]);
103103
} else if (key === 'hazelcastCloud') {
104104
this.handleHazelcastCloud(jsonObject[key]);
105105
}
@@ -133,19 +133,25 @@ export class ConfigBuilder {
133133
return importConfig;
134134
}
135135

136-
private handleSsl(jsonObject: any): void {
136+
private handleSSL(jsonObject: any): void {
137137
const sslEnabled = tryGetBoolean(jsonObject.enabled);
138-
if (sslEnabled) {
138+
this.clientConfig.networkConfig.sslConfig.enabled = sslEnabled;
139+
140+
if (jsonObject.sslOptions) {
139141
if (jsonObject.factory) {
140-
const factory = jsonObject.factory;
141-
const importConfig = this.parseImportConfig(factory);
142-
if (importConfig.path == null && importConfig.exportedName !== BasicSSLOptionsFactory.name) {
143-
throw new RangeError('Invalid configuration. Either ssl factory path should be set or exportedName ' +
144-
' should be ' + BasicSSLOptionsFactory.name);
145-
} else {
146-
this.clientConfig.networkConfig.sslOptionsFactoryConfig = this.parseImportConfig(factory);
147-
this.clientConfig.networkConfig.sslOptionsFactoryProperties = this.parseProperties(factory.properties);
148-
}
142+
throw new RangeError('Invalid configuration. Either SSL options should be set manually or SSL factory' +
143+
' should be used.');
144+
}
145+
this.clientConfig.networkConfig.sslConfig.sslOptions = jsonObject.sslOptions;
146+
} else if (jsonObject.factory) {
147+
const factory = jsonObject.factory;
148+
const importConfig = this.parseImportConfig(factory);
149+
if (importConfig.path == null && importConfig.exportedName !== BasicSSLOptionsFactory.name) {
150+
throw new RangeError('Invalid configuration. Either SSL factory path should be set or exportedName' +
151+
' should be ' + BasicSSLOptionsFactory.name + '.');
152+
} else {
153+
this.clientConfig.networkConfig.sslConfig.sslOptionsFactoryConfig = this.parseImportConfig(factory);
154+
this.clientConfig.networkConfig.sslConfig.sslOptionsFactoryProperties = this.parseProperties(factory.properties);
149155
}
150156
}
151157
}

src/config/SSLConfig.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2008-2018, Hazelcast, Inc. 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+
import {ConnectionOptions} from 'tls';
18+
import {Properties} from './Properties';
19+
import {ImportConfig} from './ImportConfig';
20+
21+
/**
22+
* SSL configuration.
23+
*/
24+
export class SSLConfig {
25+
26+
/**
27+
* If it is true, SSL is enabled.
28+
*/
29+
enabled: boolean = false;
30+
31+
/**
32+
* sslOptions is by default null which means the following default configuration
33+
* is used while connecting to the server.
34+
*
35+
* {
36+
* checkServerIdentity: (): any => null,
37+
* rejectUnauthorized: true,
38+
* };
39+
*
40+
* If you want to override the default behavior, you can write your own connection sslOptions.
41+
*/
42+
sslOptions: ConnectionOptions = null;
43+
44+
/**
45+
* sslOptionsFactoryConfig is config for ssl options factory. If you don't specify the path, BasicSSLOptionsFactory is used
46+
* by default.
47+
*/
48+
sslOptionsFactoryConfig: ImportConfig = null;
49+
50+
/**
51+
* sslOptionsFactoryProperties is the properties to be set for ssl options.
52+
*/
53+
sslOptionsFactoryProperties: Properties = null;
54+
}

src/config/SSLOptions.ts

Lines changed: 0 additions & 54 deletions
This file was deleted.

src/invocation/ClientConnectionManager.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {BasicSSLOptionsFactory} from '../connection/BasicSSLOptionsFactory';
2828
import {AddressTranslator} from '../connection/AddressTranslator';
2929
import {AddressProvider} from '../connection/AddressProvider';
3030
import Address = require('../Address');
31+
import {SSLOptionsFactory} from '../connection/SSLOptionsFactory';
3132

3233
const EMIT_CONNECTION_CLOSED = 'connectionClosed';
3334
const EMIT_CONNECTION_OPENED = 'connectionOpened';
@@ -149,21 +150,31 @@ export class ClientConnectionManager extends EventEmitter {
149150
return Promise.reject(error);
150151
}
151152
}
152-
if (this.client.getConfig().networkConfig.sslOptions) {
153-
const opts = this.client.getConfig().networkConfig.sslOptions;
154-
return this.connectTLSSocket(address, opts);
155-
} else if (this.client.getConfig().networkConfig.sslOptionsFactoryConfig) {
156-
const factoryConfig = this.client.getConfig().networkConfig.sslOptionsFactoryConfig;
157-
const factoryProperties = this.client.getConfig().networkConfig.sslOptionsFactoryProperties;
158-
let factory: any;
159-
if (factoryConfig.path) {
160-
factory = new (loadNameFromPath(factoryConfig.path, factoryConfig.exportedName))();
153+
154+
if (this.client.getConfig().networkConfig.sslConfig.enabled) {
155+
if (this.client.getConfig().networkConfig.sslConfig.sslOptions) {
156+
const opts = this.client.getConfig().networkConfig.sslConfig.sslOptions;
157+
return this.connectTLSSocket(address, opts);
158+
} else if (this.client.getConfig().networkConfig.sslConfig.sslOptionsFactoryConfig) {
159+
const factoryConfig = this.client.getConfig().networkConfig.sslConfig.sslOptionsFactoryConfig;
160+
const factoryProperties = this.client.getConfig().networkConfig.sslConfig.sslOptionsFactoryProperties;
161+
let factory: SSLOptionsFactory;
162+
if (factoryConfig.path) {
163+
factory = new (loadNameFromPath(factoryConfig.path, factoryConfig.exportedName))();
164+
} else {
165+
factory = new BasicSSLOptionsFactory();
166+
}
167+
return factory.init(factoryProperties).then(() => {
168+
return this.connectTLSSocket(address, factory.getSSLOptions());
169+
});
161170
} else {
162-
factory = new BasicSSLOptionsFactory();
171+
// the default behavior when ssl is enabled
172+
const opts = this.client.getConfig().networkConfig.sslConfig.sslOptions = {
173+
checkServerIdentity: (): any => null,
174+
rejectUnauthorized: true,
175+
};
176+
return this.connectTLSSocket(address, opts);
163177
}
164-
return factory.init(factoryProperties).then(() => {
165-
return this.connectTLSSocket(address, factory.getSSLOptions());
166-
});
167178
} else {
168179
return this.connectNetSocket(address);
169180
}

test/config/ConfigBuilderSSLTest.js

Lines changed: 0 additions & 50 deletions
This file was deleted.

test/config/hazelcast-client-ssl-false.json

Lines changed: 0 additions & 14 deletions
This file was deleted.

test/config/ConfigBuilderHazelcastCloudTest.js renamed to test/declarative_config/ConfigBuilderHazelcastCloudTest.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ describe('ConfigBuilderHazelcastCloud Test', function () {
3737
}
3838

3939
it('cloudConfig', function () {
40-
return loadJson('hazelcast-client-full.json').then(function () {
40+
return loadJson('configurations/full.json').then(function () {
4141
var networkConfig = configFull.networkConfig;
4242
expect(networkConfig.cloudConfig.enabled).to.be.false;
4343
expect(networkConfig.cloudConfig.discoveryToken).to.be.equal('EXAMPLE_TOKEN');
4444
});
4545
});
4646

4747
it('cloudConfig_enabled_nullToken', function () {
48-
return expect(loadJson('hazelcast-client-invalid-cloud-config.json')).to.be.rejectedWith(Error);
48+
return expect(loadJson('configurations/invalid-cloud.json')).to.be.rejectedWith(Error);
4949
});
5050

5151
it('cloudConfig_defaults', function () {
@@ -56,7 +56,7 @@ describe('ConfigBuilderHazelcastCloud Test', function () {
5656
});
5757

5858
it('cloudConfig_enabled', function () {
59-
return loadJson('hazelcast-client-cloud-config-enabled.json').then(function () {
59+
return loadJson('configurations/cloud-enabled.json').then(function () {
6060
var networkConfig = configFull.networkConfig;
6161
expect(networkConfig.cloudConfig.enabled).to.be.true;
6262
expect(networkConfig.cloudConfig.discoveryToken).to.be.equal('EXAMPLE_TOKEN');

0 commit comments

Comments
 (0)