@sap/hdi-deploy
Advanced tools
Comparing version 5.0.1 to 5.1.0
@@ -0,1 +1,9 @@ | ||
## 5.1.0 | ||
Features: | ||
- validation checks to ensure the correctness of privilege names and their properties in .hdbgrants and .hdbrevokes files. | ||
- enhanced global object privileges with additional support | ||
Fixes: | ||
- fixed accessing undefined data from readableBuffer when using the --optimise-file-upload option | ||
## 5.0.1 | ||
@@ -2,0 +10,0 @@ Fixes: |
@@ -13,2 +13,3 @@ 'use strict'; | ||
const censor_string = require('./utils').censor_string; | ||
const areAllowedGlobalObjectPrivileges = require('./utils').areAllowedGlobalObjectPrivileges; | ||
const is_hdb_enabled = logger.getHDBValue(); | ||
@@ -244,2 +245,3 @@ let hana_client; | ||
/** | ||
@@ -767,6 +769,4 @@ * Constructor function for a hana-helper instance. | ||
*/ | ||
grantGlobalObjectPrivileges: function (privileges, obj, type, grantee, withGrantOption) { | ||
if (type !== 'REMOTE SOURCE') { | ||
throw new Error(`${obj} must be of type REMOTE SOURCE`); | ||
} | ||
grantGlobalObjectPrivileges: function (privileges, obj, type, grantee, ishanacloud, withGrantOption) { | ||
areAllowedGlobalObjectPrivileges(privileges, type, obj, ishanacloud); | ||
const sql = withGrantOption ? `GRANT ${privileges.map(identifier).join(',')} ON ${type} ${identifier(obj)} TO ${identifier(grantee)} WITH GRANT OPTION` : `GRANT ${privileges.map(identifier).join(',')} ON ${type} ${identifier(obj)} TO ${identifier(grantee)}`; | ||
@@ -960,7 +960,4 @@ | ||
*/ | ||
revokeGlobalObjectPrivileges: function (privileges, obj, type, grantee) { | ||
if (type !== 'REMOTE SOURCE') { | ||
throw new Error(`${obj} must be of type REMOTE SOURCE`); | ||
} | ||
revokeGlobalObjectPrivileges: function (privileges, obj, type, grantee, ishanacloud) { | ||
areAllowedGlobalObjectPrivileges(privileges, type, obj, ishanacloud); | ||
const sql = `REVOKE ${privileges.map(identifier).join(',')} ON ${type} ${identifier(obj)} FROM ${identifier(grantee)}`; | ||
@@ -967,0 +964,0 @@ return execute(sql); |
@@ -46,4 +46,4 @@ 'use strict'; | ||
*/ | ||
function grantPrivileges (client, grantor_type, privileges, grantee, grantor_schema, grantor_remote, grantor_procedure, grantor_procedure_schema, cb) { | ||
return handlePrivileges(strategy_function(grantor_type, client, grantor_schema, grantor_procedure, grantor_procedure_schema), privileges, grantee, grantor_schema, grantor_remote, cb); | ||
function grantPrivileges (client, grantor_type, privileges, grantee, grantor_schema, grantor_remote, grantor_procedure, grantor_procedure_schema, ishanacloud, cb) { | ||
return handlePrivileges(strategy_function(grantor_type, client, grantor_schema, grantor_procedure, grantor_procedure_schema), privileges, grantee, grantor_schema, grantor_remote, ishanacloud, cb); | ||
} | ||
@@ -64,3 +64,3 @@ | ||
*/ | ||
function grantUsers (privileges, grantor, fileName, creds, targetCreds, container, grantee, cb) { | ||
function grantUsers (privileges, grantor, fileName, creds, targetCreds, container, grantee, ishanacloud, cb) { | ||
/** | ||
@@ -91,7 +91,7 @@ * Get the grantor type from the credentials. | ||
handleUsers(true, type_function, grantPrivileges, privileges, grantor, fileName, creds, targetCreds, container, grantee, cb); | ||
handleUsers(true, type_function, grantPrivileges, privileges, grantor, fileName, creds, targetCreds, container, grantee, ishanacloud, cb); | ||
} | ||
module.exports = function (services, root, fileName, container, grantee, cb) { | ||
return handleFile(true, grantUsers, services, root, fileName, container, grantee, cb); | ||
module.exports = function (services, root, fileName, container, grantee, ishanacloud, cb) { | ||
return handleFile(true, grantUsers, services, root, fileName, container, grantee, ishanacloud, cb); | ||
}; |
@@ -46,2 +46,43 @@ 'use strict'; | ||
/** | ||
* Validate typos in .hdbgrants. Prints error and exits if invalid. | ||
* @param {Object} privileges privileges Object | ||
* @param {Boolean} isPrivilage is it a privilege example system_privileges to check or user to check example object_owner or application_user | ||
*/ | ||
function validateGrants (content) { | ||
const valid_users = ['object_owner', 'application_user']; | ||
const valid_entry_names = ['system_privileges', 'schema_privileges', 'global_roles', 'schema_roles', 'object_privileges', 'global_object_privileges', 'roles', 'container_roles']; | ||
const valid_entry_properties = ['roles', 'privileges', 'privileges_with_admin_option', 'roles_with_admin_option', 'name', 'type', 'schema', 'privileges_with_grant_option', 'names']; | ||
function onFail (error) { | ||
const pjson = require('../../package.json'); | ||
logger.error(`${error}\nFor help with *.hdbgrants and *.hdbrevokes files look at the documentation: https://www.npmjs.com/package/@sap/hdi-deploy/v/${pjson.version}#permissions-to-container-external-objects`); | ||
process.exit(1); | ||
} | ||
for (const user in content) { | ||
if (valid_users.indexOf(user) === -1) { | ||
onFail(`Invalid user - '${user}'`); | ||
} else { | ||
for (const entry in content[user]) { | ||
if (valid_entry_names.indexOf(entry) === -1) { | ||
onFail(`Unrecognized token - '${entry}'`); | ||
} else { | ||
const entry_array = content[user][entry]; | ||
for (let i=0; i<entry_array.length; i++) { | ||
if (typeof(entry_array[i]) === 'object') { | ||
const properties = Object.keys(entry_array[i]); | ||
for (let j=0; j<properties.length; j++) { | ||
if (valid_entry_properties.indexOf(properties[j]) === -1) { | ||
onFail(`Invalid property - '${properties[j]}' in '${entry}' at index ${i}`); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
/** | ||
* Handle Privileges. | ||
@@ -55,6 +96,5 @@ * | ||
*/ | ||
module.exports.handlePrivileges = function (get_strategy_fn, privileges, grantee, grantor_schema, grantor_remote, cb) { | ||
module.exports.handlePrivileges = function (get_strategy_fn, privileges, grantee, grantor_schema, grantor_remote, ishanacloud, cb) { | ||
try { | ||
const tasks = []; | ||
const strategy = get_strategy_fn(tasks); | ||
@@ -206,3 +246,3 @@ | ||
if (check_array_is_array_and_not_empty(obj.privileges, 'privileges')) { | ||
strategy.handleGlobalObjectPrivileges(obj.privileges, name, obj.type, grantee, false); | ||
strategy.handleGlobalObjectPrivileges(obj.privileges, name, obj.type, grantee, ishanacloud, false); | ||
} | ||
@@ -212,3 +252,3 @@ } | ||
if (check_array_is_array_and_not_empty(obj.privileges_with_grant_option, 'privileges_with_grant_option')) { | ||
strategy.handleGlobalObjectPrivileges(obj.privileges_with_grant_option, name, obj.type, grantee, true); | ||
strategy.handleGlobalObjectPrivileges(obj.privileges_with_grant_option, name, obj.type, grantee, ishanacloud, true); | ||
} | ||
@@ -266,3 +306,3 @@ } | ||
module.exports.handleUsers = function (isGrantAction, type_function, privileges_function, privileges, grantor, fileName, creds, targetCreds, container, grantee, cb) { | ||
module.exports.handleUsers = function (isGrantAction, type_function, privileges_function, privileges, grantor, fileName, creds, targetCreds, container, grantee, ishanacloud, cb) { | ||
try { | ||
@@ -324,3 +364,3 @@ const tasks = []; | ||
tasks.push(function (callback) { | ||
privileges_function(client, type, privileges.object_owner, container, creds.schema, creds.remote, creds.procedure, creds.procedure_schema, callback); | ||
privileges_function(client, type, privileges.object_owner, container, creds.schema, creds.remote, creds.procedure, creds.procedure_schema, ishanacloud, callback); | ||
}); | ||
@@ -331,6 +371,7 @@ } | ||
tasks.push(function (callback) { | ||
privileges_function(client, type, privileges.application_user, grantee, creds.schema, creds.remote, creds.procedure, creds.procedure_schema, callback); | ||
privileges_function(client, type, privileges.application_user, grantee, creds.schema, creds.remote, creds.procedure, creds.procedure_schema, ishanacloud, callback); | ||
}); | ||
} | ||
tasks.push(client.disconnect()); | ||
@@ -363,3 +404,3 @@ | ||
module.exports.handleFile = function (isGrantAction, handle_users_fn, services, root, fileName, container, grantee, cb) { | ||
module.exports.handleFile = function (isGrantAction, handle_users_fn, services, root, fileName, container, grantee, ishanacloud, cb) { | ||
const tasks = []; | ||
@@ -386,3 +427,4 @@ try { | ||
logger.trace(trace_string, file[grantor]); | ||
handle_users_fn(file[grantor], grantor, fileName, creds, targetCreds, container, grantee, callback); | ||
validateGrants(file[grantor]); | ||
handle_users_fn(file[grantor], grantor, fileName, creds, targetCreds, container, grantee, ishanacloud, callback); | ||
}); | ||
@@ -389,0 +431,0 @@ }); |
@@ -25,3 +25,3 @@ 'use strict'; | ||
tasks.push(function (callback) { | ||
grantor(services, content.root, fileName, container, grantee, callback); | ||
grantor(services, content.root, fileName, container, grantee, options.isHanaCloud, callback); | ||
}); | ||
@@ -57,3 +57,3 @@ tasks.push(logger.logfn(` Processing "${fileName}"... ok`)); | ||
tasks.push(function (callback) { | ||
revoker(services, content.root, fileName, container, grantee, callback); | ||
revoker(services, content.root, fileName, container, grantee, options.isHanaCloud, callback); | ||
}); | ||
@@ -60,0 +60,0 @@ tasks.push(logger.logfn(` Processing "${fileName}"... ok`)); |
@@ -46,4 +46,4 @@ 'use strict'; | ||
*/ | ||
function revokePrivileges (client, revoker_type, privileges, revokee, revoker_schema, revoker_remote, revoker_procedure, revoker_procedure_schema, cb) { | ||
return handlePrivileges(strategy_function(revoker_type, client, revoker_schema, revoker_procedure, revoker_procedure_schema), privileges, revokee, revoker_schema, revoker_remote, cb); | ||
function revokePrivileges (client, revoker_type, privileges, revokee, revoker_schema, revoker_remote, revoker_procedure, revoker_procedure_schema, ishanacloud, cb) { | ||
return handlePrivileges(strategy_function(revoker_type, client, revoker_schema, revoker_procedure, revoker_procedure_schema), privileges, revokee, revoker_schema, revoker_remote, ishanacloud, cb); | ||
} | ||
@@ -64,3 +64,3 @@ | ||
*/ | ||
function revokeUsers (privileges, revoker, fileName, creds, targetCreds, container, revokee, cb) { | ||
function revokeUsers (privileges, revoker, fileName, creds, targetCreds, container, revokee, ishanacloud, cb) { | ||
/** | ||
@@ -91,7 +91,7 @@ * Get the revoker type from the credentials. | ||
handleUsers(false, type_function, revokePrivileges, privileges, revoker, fileName, creds, targetCreds, container, revokee, cb); | ||
handleUsers(false, type_function, revokePrivileges, privileges, revoker, fileName, creds, targetCreds, container, revokee, ishanacloud, cb); | ||
} | ||
module.exports = function (services, root, fileName, container, revokee, cb) { | ||
return handleFile(false, revokeUsers, services, root, fileName, container, revokee, cb); | ||
module.exports = function (services, root, fileName, container, revokee, ishanacloud, cb) { | ||
return handleFile(false, revokeUsers, services, root, fileName, container, revokee, ishanacloud, cb); | ||
}; |
@@ -86,4 +86,4 @@ 'use strict'; | ||
*/ | ||
handleGlobalObjectPrivileges (privileges, name, type, grantee, grantable) { | ||
this.tasks.push(this.client.grantGlobalObjectPrivileges(privileges, name, type, grantee, grantable)); | ||
handleGlobalObjectPrivileges (privileges, name, type, grantee, ishanacloud, grantable) { | ||
this.tasks.push(this.client.grantGlobalObjectPrivileges(privileges, name, type, grantee, ishanacloud, grantable)); | ||
} | ||
@@ -405,3 +405,3 @@ | ||
*/ | ||
handleGlobalObjectPrivileges (privileges, name, type, grantee, grantable) { | ||
handleGlobalObjectPrivileges (privileges, name, type, grantee, ishanacloud, grantable) { | ||
privileges.forEach((privilege) => { | ||
@@ -578,4 +578,4 @@ this.grant_privileges.push([ | ||
*/ | ||
handleGlobalObjectPrivileges (privileges, name, type, revokee) { | ||
this.tasks.push(this.client.revokeGlobalObjectPrivileges(privileges, name, type, revokee)); | ||
handleGlobalObjectPrivileges (privileges, name, type, revokee, ishanacloud) { | ||
this.tasks.push(this.client.revokeGlobalObjectPrivileges(privileges, name, type, revokee, ishanacloud)); | ||
} | ||
@@ -582,0 +582,0 @@ |
@@ -41,4 +41,9 @@ /* eslint-disable no-unused-vars */ | ||
emptyStream = false; | ||
} else if (deployFileContent[1].readableBuffer.head !== null && deployFileContent[1].readableBuffer.head.data !== null) { | ||
content = deployFileContent[1].readableBuffer.head.data; | ||
} else if (deployFileContent[1].readableBuffer.head !== undefined && deployFileContent[1].readableBuffer.head.data !== undefined) { | ||
if (deployFileContent[1].readableBuffer.head !== null && deployFileContent[1].readableBuffer.head.data !== null) { | ||
content = deployFileContent[1].readableBuffer.head.data; | ||
emptyStream = false; | ||
} | ||
} else if (deployFileContent[1].readableBuffer.length > 0 && Buffer.isBuffer(deployFileContent[1].readableBuffer[0])) { | ||
content = deployFileContent[1].readableBuffer[0]; | ||
emptyStream = false; | ||
@@ -51,3 +56,3 @@ } | ||
} else { | ||
sum = checksum(fs.readFileSync(deployFileContent[1].path, 'utf8')); //with node 16 the deployconent is not carrying data in readstream for few files. | ||
sum = checksum(fs.readFileSync(deployFileContent[1].path, 'utf8')); //with node 16 the deploycontent is not carrying data in readstream for few files. | ||
//we are getting head = null in readstream so for that reason using the local file to calculate sha256 instead of deployfilecontent. | ||
@@ -54,0 +59,0 @@ } |
@@ -242,3 +242,41 @@ 'use strict'; | ||
exports.mask_passwords_and_certificates_in_vcaps = mask_passwords_and_certificates_in_vcaps; | ||
const allowedPrivilegesInOnPremise = { | ||
'PSE': ['ALTER', 'REFERENCES'], | ||
'USERGROUP': ['USERGROUP OPERATOR'], | ||
'REMOTE SUBSCRIPTION': ['ALTER', 'PROCESS REMOTE SUBSCRIPTION EXCEPTION'], | ||
'AGENT': ['AGENT MESSAGING'], | ||
'REMOTE SOURCE': ['ALTER', 'CREATE REMOTE SUBSCRIPTION', 'CREATE VIRTUAL FUNCTION', 'CREATE VIRTUAL PROCEDURE', 'CREATE VIRTUAL TABLE', 'LINKED DATABASE', 'PROCESS REMOTE SUBSCRIPTION EXCEPTION', 'REMOTE EXECUTE', 'REMOTE TABLE ADMIN'] | ||
}; | ||
const allowedPrivilegesInCloud = { | ||
...allowedPrivilegesInOnPremise, | ||
'JWT PROVIDER': ['ALTER', 'REFERENCES'], | ||
'SAML PROVIDER': ['ALTER', 'REFERENCES'], | ||
'X509 PROVIDER': ['ALTER', 'REFERENCES'], | ||
'ROLEGROUP': ['GRANTOR', 'OPERATOR'], | ||
'USERGROUP': ['GRANTOR', 'OPERATOR'], | ||
}; | ||
/** | ||
* Validates the allowed global object privileges based on db type (on premise or cloud) | ||
* @param {Array} privileges privileges need to be granted | ||
* @param {String} type type of privileges | ||
* @param {String} obj name of object | ||
* @param {Boolean} ishanacloud is hana db or not | ||
*/ | ||
function areAllowedGlobalObjectPrivileges (privileges, type, obj, ishanacloud) { | ||
const allowedPrivileges = ishanacloud ? allowedPrivilegesInCloud : allowedPrivilegesInOnPremise; | ||
if (allowedPrivileges.hasOwnProperty(type)) { | ||
for (let i =0;i<privileges.length;i++) { | ||
if (!allowedPrivileges[type].includes(privileges[i])) { | ||
throw new Error(`Invalid privilege ${privileges[i]}.\n${obj} of type ${type} is allowed to have only these privileges [${allowedPrivileges[type]}]`); | ||
} | ||
} | ||
} else { | ||
throw new Error(`Invalid object type ${type}.\nObject type must be one of the types in [${Object.keys(allowedPrivileges)}]`); | ||
} | ||
} | ||
exports.areAllowedGlobalObjectPrivileges = areAllowedGlobalObjectPrivileges; | ||
/** | ||
* Generates current date and time | ||
@@ -245,0 +283,0 @@ * |
{ | ||
"name": "@sap/hdi-deploy", | ||
"version": "5.0.1", | ||
"version": "5.1.0", | ||
"lockfileVersion": 2, | ||
@@ -9,3 +9,3 @@ "requires": true, | ||
"name": "@sap/hdi-deploy", | ||
"version": "5.0.1", | ||
"version": "5.1.0", | ||
"hasInstallScript": true, | ||
@@ -12,0 +12,0 @@ "license": "See LICENSE file", |
{ | ||
"name": "@sap/hdi-deploy", | ||
"description": "HDI content deployment", | ||
"version": "5.0.1", | ||
"version": "5.1.0", | ||
"license": "See LICENSE file", | ||
@@ -6,0 +6,0 @@ "repository": {}, |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
522648
11165