diff --git a/README.md b/README.md index cdbdac0..45a7d90 100644 --- a/README.md +++ b/README.md @@ -46,11 +46,17 @@ This is a properties example that a user `foo@example.com` would use to try to c 'scalar.dl.client.server.port': 50051, 'scalar.dl.client.server.privileged_port': 50052, 'scalar.dl.client.cert_holder_id': 'foo@example.com', - 'scalar.dl.client.private_key_pem': "-----BEGIN EC PRIVATE KEY-----\nMHc...", - 'scalar.dl.client.cert_pem': "-----BEGIN CERTIFICATE-----\nMIICjTCCAj...\n", + 'scalar.dl.client.private_key_pem': '-----BEGIN EC PRIVATE KEY-----\nMHc...', + // scalar.dl.client.private_key_path is applied when scalar.dl.client.private_key_pem is not given + 'scalar.dl.client.private_key_path': 'path-to-key-file', + 'scalar.dl.client.cert_pem': '-----BEGIN CERTIFICATE-----\nMIICjTCCAj...\n', + // scalar.dl.client.cert_path is applied when scalar.dl.client.cert_pem is not given + 'scalar.dl.client.cert_path': 'path-to-certificate-file', 'scalar.dl.client.cert_version': 1, 'scalar.dl.client.tls.enabled': false, 'scalar.dl.client.tls.ca_root_cert_pem': '-----BEGIN CERTIFICATE-----\n...\n', + // scalar.dl.client.tls.ca_root_cert_path is applied when scalar.dl.client.tls.ca_root_cert_pem is not given + 'scalar.dl.client.tls.ca_root_cert_path': 'path-to-ca-root-certificate-file', 'scalar.dl.client.authorization.credential': '...', 'scalar.dl.client.proxy.server': '...', } diff --git a/scalardl-node-client-sdk.js b/scalardl-node-client-sdk.js index cabe89a..8821cdc 100644 --- a/scalardl-node-client-sdk.js +++ b/scalardl-node-client-sdk.js @@ -109,6 +109,31 @@ function _createMetadata(properties) { return metadata; } +/** + * Read the content of file-based properties + * @param {Object} properties + * @return {Object} + */ +function _resolveFileBasedProperties(properties) { + const fs = require('fs'); + + properties['scalar.dl.client.cert_pem'] = + properties['scalar.dl.client.cert_pem'] || + fs.readFileSync(properties['scalar.dl.client.cert_path']).toString(); + + properties['scalar.dl.client.private_key_pem'] = + properties['scalar.dl.client.private_key_pem'] || + fs.readFileSync(properties['scalar.dl.client.private_key_path']).toString(); + + properties['scalar.dl.client.tls.ca_root_cert_pem'] = + properties['scalar.dl.client.tls.ca_root_cert_pem'] || + fs.readFileSync( + properties['scalar.dl.client.tls.ca_root_cert_path'], + ).toString(); + + return properties; +} + /** * @class */ @@ -118,6 +143,7 @@ class ClientServiceWithBinary extends ClientServiceBase { * @param {Object} properties */ constructor(properties) { + properties = _resolveFileBasedProperties(properties); super( { ..._createGrpcServices(properties), @@ -217,6 +243,7 @@ class ClientService extends ClientServiceBase { * @param {Object} properties */ constructor(properties) { + properties = _resolveFileBasedProperties(properties); super( { ..._createGrpcServices(properties), diff --git a/test/fixture/ca.pem b/test/fixture/ca.pem new file mode 100644 index 0000000..cd2715c --- /dev/null +++ b/test/fixture/ca.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE/jCCAuagAwIBAgIJAJO8tpVEEORLMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAeFw0xOTAzMTMxMDUyMTFaFw0yMDAzMTIxMDUyMTFaMBQx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAKFeFSrXRh5jA+OodMPw0XFO4sd4G9wYERlxgCjDmd9eC+loLpjGwRwwO7os +/+rhW+Cg/NGhNn64xCmS/JtZf91SBD1QfQ4wk4094sAUIHsztaWtZTATl6aIy0BN +21A0ueFgVQGehwO1FdRKtS7X+45YV2vMMK/UQ69VSCwY82olBRgWp45TXLUmWVgC +UAJkE/V2Ch8WLyKpCggtaxYmn8YfzA1X20QDK1b2IW4YPDcPapQLtU6wqIjrXX1E +w992GgfERm//I14QEyu+qIPafsniDGYxiR6HK8nqeR70QcGHt+Qql24xyjwWHEA/ +43pn3jjrNVRhiVAD8tkVyRmfWjIngksRHPwEh3jG34gshOi9xAaID+mx2AWhThsk +XbuqSxHckPlvgWHugZmFOwKZAgU5/gpnWR7oHPOSYffhGwmc/+SK/SQ4UDeTFI2c +40Xw22P8CWbIq4gKi66kSvuFbLSeKQIRMJd50hf7kw3SqnkqEaeRXy5jBovut7CU +nwcgGPceYmWhKxhkg5urzk+CQZENf+9+pVvArOQemn9bMuaBPwtwXE42+fktQpQ2 +PG3k7ryVL5R0jhuVNXf9ioU2z1ONQ2IdsuFtCKnozfVBAhy9bPfm120rTV/UBOCD +zcmfRnv081lG9BN/KtZBo7hfFH/ZD2542yVRvibRIIdPWIkTAgMBAAGjUzBRMB0G +A1UdDgQWBBQ61fQAtAgd7sM/NDtIX4D8GSA/8DAfBgNVHSMEGDAWgBQ61fQAtAgd +7sM/NDtIX4D8GSA/8DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IC +AQCaYh1bxlj9Impoq3rmFHl5/9Fb2o2H2Ne8VjTHb8eSoHuLwXdWzKnw6UhiCaN4 +EZgrsqq1L2Tc8Y+eqT4gz3uDLc5Cj29HHC/suZezIo3lgyZ/A6stYQXE5Gy8e+to +Qhmf4u8RMZ8zt6i355un6mTJxJq7JxoVqpECf5tg6pMdOUzbcKLTmN6i50jH/PSO +NQsJhiSJg3caNdWviob+UwEuUineMF/X08dB3gphZ7kmfDeRjmONALMXS1uvPwk2 +3s8S45LmxETx+tcJSvckKRC9JaQf6dgHfKAWHpkIqvLKyqy9Dmvg2RSJi3kI9oaj +dm64zc6CAsqVaPvoMfWIN7JZq9jvzc8msGiilfhiYoc+M3jvnmM81FuGbAw7Utq4 +uuHtpCcpbxRMChD4WdlrPeBONyBKp+RRWTGfBY1GW5aGWVp/cbcpIc2RSgnZcrxb +6ef2iTMtUjRd76JlkobTyvgo0GKdLgnr8c711I2YNp+TabKIKZOEvw2X+oGbfxBN +1WvRB5YJo2rzwZj0fSvN9IwT9TGxSZIo5zcaQuwLEmDZBJShgXN5Ya71Vag1AP2i +mOwUJRvfTVPWg+wtF2JQwaPpK0+Kb7oCq9tl3PUW40FRgqWV1Tgp6Co/U1W/1BU6 +02Vmic/M/HmRMwWuX1PyVOVr8Mjyj+OMF1JsmdR5eL5Mtg== +-----END CERTIFICATE----- diff --git a/test/fixture/cert.pem b/test/fixture/cert.pem new file mode 100644 index 0000000..9440329 --- /dev/null +++ b/test/fixture/cert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUMEUDTdWsQpftFkqs6bCd6U++4nEwCgYIKoZIzj0EAwIw +bzELMAkGA1UEBhMCSlAxDjAMBgNVBAgTBVRva3lvMQ4wDAYDVQQHEwVUb2t5bzEf +MB0GA1UEChMWU2FtcGxlIEludGVybWVkaWF0ZSBDQTEfMB0GA1UEAxMWU2FtcGxl +IEludGVybWVkaWF0ZSBDQTAeFw0xODA5MTAwODA3MDBaFw0yMTA5MDkwODA3MDBa +MEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJ +bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AAQEa6Gq6bKHsFU2pw0oBBCKkMaihSlRG97Z07rqlAKCO1J+7uUlXbRdhZ2uCjRj +d5cSG8rSWxRE703Ses+JBZPgo4HVMIHSMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRDd2MS9Ndo68PJ +y9K/RNY6syZW0zAfBgNVHSMEGDAWgBR+Y+v8yByDNp39G7trYrTfZ0UjJzAxBggr +BgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGGFWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTAq +BgNVHR8EIzAhMB+gHaAbhhlodHRwOi8vbG9jYWxob3N0Ojg4ODgvY3JsMAoGCCqG +SM49BAMCA0cAMEQCIC/Bo4oNU6yHFLJeme5ApxoNdyu3rWyiqWPxJmJAr9L0AiBl +Gc/v+yh4dHIDhCrimajTQAYOG9n0kajULI70Gg7TNw== +-----END CERTIFICATE----- diff --git a/test/fixture/key.pem b/test/fixture/key.pem new file mode 100644 index 0000000..09d0f4c --- /dev/null +++ b/test/fixture/key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICcJGMEw3dyXUGFu/5a36HqY0ynZi9gLUfKgYWMYgr/IoAoGCCqGSM49 +AwEHoUQDQgAEBGuhqumyh7BVNqcNKAQQipDGooUpURve2dO66pQCgjtSfu7lJV20 +XYWdrgo0Y3eXEhvK0lsURO9N0nrPiQWT4A== +-----END EC PRIVATE KEY----- diff --git a/test/integration_test_file_based_properties.js b/test/integration_test_file_based_properties.js new file mode 100644 index 0000000..4b9f897 --- /dev/null +++ b/test/integration_test_file_based_properties.js @@ -0,0 +1,162 @@ +const {ClientService} = require('../scalardl-node-client-sdk'); +const fs = require('fs'); +const cassandra = require('cassandra-driver'); +const assert = require('assert'); +const path = require('path'); + +const properties = { + 'scalar.dl.client.server.host': 'localhost', + 'scalar.dl.client.server.port': 50051, + 'scalar.dl.client.server.privileged_port': 50052, + 'scalar.dl.client.cert_holder_id': `foo@${Date.now()}`, + 'scalar.dl.client.cert_version': 1, + 'scalar.dl.client.tls.enabled': false, + 'scalar.dl.client.cert_path': path.join(__dirname, 'fixture', 'cert.pem'), + 'scalar.dl.client.private_key_path': path.join( + __dirname, + 'fixture', + 'key.pem', + ), + 'scalar.dl.client.tls.ca_root_cert_path': path.join( + __dirname, + 'fixture', + 'cert.pem', + ), +}; + +let clientService; +let cassandraClient; + +describe('Integration test with File-based Properties', async () => { + const mockedFunctionId = `TestFunction${Date.now()}`; + const mockedContractId = `StateUpdater${Date.now()}`; + const mockedContractName = 'com.org1.contract.StateUpdater'; + const mockedFunctionName = 'com.org1.function.TestFunction'; + const mockedAssetId = `mockedAssetId${Date.now()}`; + const mockedState = 1; + const mockedContractArgument = { + asset_id: mockedAssetId, + state: mockedState, + }; + const contractProperty = { + properties: 'bar', + }; + const mockedByteContract = fs.readFileSync( + path.join( __dirname, 'StateUpdater.class'), + ); + const mockedByteFunction = fs.readFileSync( + path.join(__dirname, 'TestFunction.class'), + ); + + clientService = new ClientService(properties); + + describe('registerCertificate', () => { + it('should be successful', async () => { + const response = await clientService.registerCertificate(); + assert.deepEqual(response, undefined); + }); + }); + describe('registerFunction', () => { + it('should be successful', async () => { + const response = await clientService.registerFunction( + mockedFunctionId, + mockedFunctionName, + mockedByteFunction, + ); + assert.deepEqual(response, undefined); + }); + }); + describe('registerContract', () => { + it('should be successful', async () => { + const response = await clientService.registerContract( + mockedContractId, + mockedContractName, + mockedByteContract, + contractProperty, + ); + assert.deepEqual(response, undefined); + }); + }); + describe('listContracts', () => { + it( + 'should return contract metadata' + + 'when the correct contract id is specified', + async () => { + const response = await clientService.listContracts(); + assert.ok(response.hasOwnProperty(mockedContractId)); + }, + ); + }); + describe('executeContract', () => { + it( + 'should work as expected when executing a registered contract', + async () => { + const response = await clientService.executeContract( + mockedContractId, + mockedContractArgument, + {}, + ); + + const contractResult = response.result; + assert.equal(contractResult.asset_id, mockedAssetId); + assert.equal(contractResult.state, mockedState); + assert.equal(contractResult.properties, contractProperty.properties); + }, + ); + + it( + 'should execute the function properly and cassandra' + + 'query should return proper object when correct inputs are specified', + async () => { + const contractArgumentWithFunction = { + asset_id: mockedAssetId, + state: Date.now(), + _functions_: [mockedFunctionId], + }; + const mockedFunctionArgument = { + asset_id: mockedAssetId, + state: mockedState, + }; + const response = await clientService.executeContract( + mockedContractId, + contractArgumentWithFunction, + mockedFunctionArgument, + ); + assert.equal( + response.getResult().state, + contractArgumentWithFunction.state, + ); + cassandraClient = new cassandra.Client({ + contactPoints: ['localhost'], + localDataCenter: 'dc1', + }); + const cassandraResponse = await cassandraClient.execute( + `SELECT * FROM foo.bar WHERE column_a='${mockedAssetId}';`, + ); + assert.equal( + cassandraResponse.rows[0].column_a, + contractArgumentWithFunction.asset_id, + ); + await cassandraClient.shutdown(); + }, + ); + }); + describe('validateLedger', () => { + it('should return 200 when correct asset id is specified', async () => { + const response = await clientService.validateLedger(mockedAssetId); + assert.equal(response.getCode(), 200); + }); + it( + 'should return 200 when correct asset id, ' + + 'startAge and endAge are specified', + async () => { + const response = await clientService.validateLedger( + mockedAssetId, + 0, + 1, + ); + assert.equal(response.getCode(), 200); + }, + ); + }); +});