Skip to content

Commit

Permalink
Add idPattern to payload options
Browse files Browse the repository at this point in the history
  • Loading branch information
jason-fox committed Aug 18, 2021
1 parent 08f30df commit fd0d99b
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 56 deletions.
63 changes: 33 additions & 30 deletions controllers/oauth2/oauth2.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ function oauth_authorize(req, res, next) {
.catch(next);
}


// Read in parameters in Open Policy Agent JSON format and make
// a Permit/Deny adjudication
exports.auth_opa_policy = function (req, res) {
Expand All @@ -380,11 +379,12 @@ exports.auth_opa_policy = function (req, res) {
payload_entity_ids: req.body.ids,
payload_attributes: req.body.attrs,
payload_types: req.body.types,
}
payload_id_patterns: req.body.idPatterns
};
return user_permissions(options.roles, options.application, options.action, options.resource, options)
.then(function (permit) {
const result = {
allow: permit,
allow: permit
};
return res.status(200).json(result);
})
Expand All @@ -407,60 +407,63 @@ exports.auth_xacml_policy = function (req, res) {
const resource = obj.Request.Resource.Attribute;

const mapping = {
"urn:oasis:names:tc:xacml:2.0:subject:role" : "roles",
"urn:oasis:names:tc:xacml:1.0:resource:resource-id": "application",
"urn:thales:xacml:2.0:resource:sub-resource-id": "resource",
"urn:ngsi-ld:resource:tenant": "service_header",
"urn:ngsi-ld:resource:types": "payload_types",
"urn:ngsi-ld:resource:attrs": "payload_attributes",
"urn:ngsi-ld:resource:ids": "payload_entity_ids",
"urn:oasis:names:tc:xacml:1.0:action:action-id": "action"
'urn:oasis:names:tc:xacml:2.0:subject:role': 'roles',
'urn:oasis:names:tc:xacml:1.0:resource:resource-id': 'application',
'urn:thales:xacml:2.0:resource:sub-resource-id': 'resource',
'urn:ngsi-ld:resource:tenant': 'service_header',
'urn:ngsi-ld:resource:types': 'payload_types',
'urn:ngsi-ld:resource:attrs': 'payload_attributes',
'urn:ngsi-ld:resource:ids': 'payload_entity_ids',
'urn:ngsi-ld:resource:id-patterns': 'payload_id_patterns',
'urn:oasis:names:tc:xacml:1.0:action:action-id': 'action'
};

access.forEach((elem) =>{
access.forEach((elem) => {
options[mapping[elem.AttributeId]] = elem.Value;
});
action.forEach((elem) =>{
action.forEach((elem) => {
options[mapping[elem.AttributeId]] = elem.Value;
});
resource.forEach((elem) =>{
resource.forEach((elem) => {
options[mapping[elem.AttributeId]] = elem.Value;
});

return user_permissions(options.roles, options.application, options.action, options.resource, options)
.then(function (permit) {
/* eslint-disable snakecase/snakecase */
const result = {
Response: [{
Decision: (permit ? "Permit": "Deny"),
/* eslint-disable snakecase/snakecase */
const result = {
Response: [
{
Decision: permit ? 'Permit' : 'Deny',
Status: {
StatusCode:{
Value: "urn:oasis:names:tc:xacml:1.0:status:ok",
StatusCode: {"Value": "urn:oasis:names:tc:xacml:1.0:status:ok"}
StatusCode: {
Value: 'urn:oasis:names:tc:xacml:1.0:status:ok',
StatusCode: { Value: 'urn:oasis:names:tc:xacml:1.0:status:ok' }
}
}
}]};
/* eslint-enable snakecase/snakecase */
}
]
};
/* eslint-enable snakecase/snakecase */
return res.status(200).json(result);
})
.catch(function (error) {
debug('Error ', error);
// Request is not authorized.
return res.status(error.code || 500).json(error.message || error);
});

}
};

// GET /user -- Function to handle token authentication
exports.authenticate_token = function (req, res) {
debug(' --> authenticate_token');

const options = {
action: req.query.action,
resource: req.query.resource,
authzforce: req.query.authzforce,
application: req.query.app_id,
service_header: req.query.authorization_service_header
action: req.query.action,
resource: req.query.resource,
authzforce: req.query.authzforce,
application: req.query.app_id,
service_header: req.query.authorization_service_header
};

if (options.authzforce && (options.action || options.resource || options.service_header)) {
Expand Down
70 changes: 44 additions & 26 deletions models/model_oauth_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ function search_user_info(user_info, options) {
}

if (action && resource) {
user_info.authorization_decision = values[2] ? 'Permit' :'Deny';
user_info.authorization_decision = values[2] ? 'Permit' : 'Deny';
} else if (config_authzforce.enabled && authzforce) {
const authzforce_domain = values[2];
if (authzforce_domain) {
Expand Down Expand Up @@ -785,6 +785,9 @@ function user_roles(user_id, app_id) {
});
}

// A payload ids are allowed if all values pass the permission id regex
// A payload types are allowed if all values pass the permission type regex
// A payload attributes are allowed if all values pass the permission attrs regex
function payload_permission(payload, permissionRegex) {
let permitted = true;
if (permissionRegex && payload) {
Expand All @@ -796,6 +799,18 @@ function payload_permission(payload, permissionRegex) {
return permitted;
}

// A payload idPattern is allowed only if all idPatterns are equal to the permission id regex.
// This is a weird edge case since idPatterns are only applicable to NGSI subscriptions.
function id_pattern_permission(payload, permissionRegex) {
let permitted = true;
if (permissionRegex && payload) {
permitted = payload.every((str) => {
return permissionRegex === str;
});
}
return permitted;
}

// Search user permissions in application whose action and resource are recieved from Pep Proxy
function user_permissions(roles_id, app_id, action, resource, options) {
debug('-------user_permissions-------');
Expand All @@ -804,54 +819,57 @@ function user_permissions(roles_id, app_id, action, resource, options) {
const ids = options.payload_entity_ids;
const attributes = options.payload_attributes;
const types = options.payload_types;
const id_patterns = options.payload_id_patterns;

const isPermitted = (permission) =>{
const isPermitted = (permission) => {
const check = {
resource: (permission.is_regex === 1
? new RegExp(permission.resource, 'i').test(resource)
: permission.resource === resource),
service_header: true,
resource:
permission.is_regex === 1
? new RegExp(permission.resource, 'i').test(resource)
: permission.resource === resource,
service_header: true,
payload: true
};

if (check.resource === false){
if (check.resource === false) {
return false;
}

if (permission.use_authorization_service_header === 1){
check.service_header = (permission.authorization_service_header === authorization_service_header);
if (permission.use_authorization_service_header === 1) {
check.service_header = permission.authorization_service_header === authorization_service_header;
}
if (config.authorization.level === 'payload') {
check.payload =
payload_permission(ids, permission.regex_entity_ids) &&
payload_permission(attributes, permission.regex_attributes) &&
payload_permission(types, permission.regex_types);
payload_permission(types, permission.regex_types) &&
id_pattern_permission(id_patterns, permission.regex_entity_ids);
}

//debug(JSON.stringify(permission));
//debug(JSON.stringify(check));
return ( check.service_header && check.payload);
}
return check.service_header && check.payload;
};

return models.role_permission
.findAll({
where: { role_id: roles_id },
attributes: ['permission_id']
})
.then(function (permissions) {
return (permissions.length === 0) ? false :
models.permission
.findAll({
where: {
id: permissions.map((elem) => elem.permission_id),
oauth_client_id: app_id,
action
}
})
.then((permissions) => {
return (_.some(permissions, isPermitted));
});
});
return permissions.length === 0
? false
: models.permission
.findAll({
where: {
id: permissions.map((elem) => elem.permission_id),
oauth_client_id: app_id,
action
}
})
.then((permissions) => {
return _.some(permissions, isPermitted);
});
});
}

// Search Trusted applications
Expand Down

0 comments on commit fd0d99b

Please sign in to comment.