@restorecommerce/acs-client 0.4.18 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/lib/acs/authz.d.ts +8 -7
- package/lib/acs/authz.js +76 -88
- package/lib/acs/authz.js.map +1 -1
- package/lib/acs/interfaces.d.ts +70 -16
- package/lib/acs/interfaces.js +16 -1
- package/lib/acs/interfaces.js.map +1 -1
- package/lib/acs/resolver.d.ts +14 -17
- package/lib/acs/resolver.js +75 -96
- package/lib/acs/resolver.js.map +1 -1
- package/lib/utils.d.ts +32 -3
- package/lib/utils.js +169 -3
- package/lib/utils.js.map +1 -1
- package/package.json +8 -11
- package/tsconfig.json +0 -1
package/lib/acs/resolver.js
CHANGED
|
@@ -12,7 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.whatIsAllowed = exports.isAllowed = exports.accessRequest = exports.isAllowedRequest = void 0;
|
|
13
13
|
const _ = require("lodash");
|
|
14
14
|
const interfaces_1 = require("./interfaces");
|
|
15
|
-
const interfaces_2 = require("./interfaces");
|
|
16
15
|
const logger_1 = require("../logger");
|
|
17
16
|
const config_1 = require("../config");
|
|
18
17
|
const utils_1 = require("../utils");
|
|
@@ -22,82 +21,80 @@ const subjectIsUnauthenticated = (subject) => {
|
|
|
22
21
|
return !!subject
|
|
23
22
|
&& 'unauthenticated' in subject && subject['unauthenticated'];
|
|
24
23
|
};
|
|
25
|
-
const whatIsAllowedRequest = (subject,
|
|
24
|
+
const whatIsAllowedRequest = (subject, resource, action, ctx, useCache) => __awaiter(void 0, void 0, void 0, function* () {
|
|
26
25
|
if (subjectIsUnauthenticated(subject)) {
|
|
27
26
|
const grpcConfig = config_1.cfg.get('client:acs-srv');
|
|
28
27
|
const acsClient = new grpc_client_1.GrpcClient(grpcConfig, logger_1.default);
|
|
29
28
|
const acs = acsClient['acs-srv'];
|
|
30
29
|
return yield new authz_1.UnAuthZ(acs).whatIsAllowed({
|
|
31
30
|
target: {
|
|
32
|
-
|
|
31
|
+
subject: subject, resource, action
|
|
33
32
|
},
|
|
34
33
|
context: {
|
|
35
34
|
security: {}
|
|
36
35
|
}
|
|
37
|
-
}, useCache);
|
|
36
|
+
}, ctx, useCache);
|
|
38
37
|
}
|
|
39
38
|
else {
|
|
40
|
-
return yield authZ.whatIsAllowed({
|
|
39
|
+
return yield authz_1.authZ.whatIsAllowed({
|
|
41
40
|
context: {
|
|
42
41
|
security: {}
|
|
43
42
|
},
|
|
44
43
|
target: {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
subject,
|
|
45
|
+
resource,
|
|
46
|
+
action
|
|
48
47
|
}
|
|
49
|
-
}, useCache);
|
|
48
|
+
}, ctx, useCache);
|
|
50
49
|
}
|
|
51
50
|
});
|
|
52
|
-
const
|
|
53
|
-
return 'entity' in object;
|
|
54
|
-
};
|
|
55
|
-
const isAllowedRequest = (subject, resources, action, authZ, useCache) => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
const isAllowedRequest = (subject, resource, action, ctx, useCache) => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
52
|
if (subjectIsUnauthenticated(subject)) {
|
|
57
53
|
const grpcConfig = config_1.cfg.get('client:acs-srv');
|
|
58
54
|
const acsClient = new grpc_client_1.GrpcClient(grpcConfig, logger_1.default);
|
|
59
55
|
const acs = acsClient['acs-srv'];
|
|
60
56
|
return yield new authz_1.UnAuthZ(acs).isAllowed({
|
|
61
57
|
target: {
|
|
62
|
-
|
|
58
|
+
subject: subject, resource, action
|
|
63
59
|
},
|
|
64
60
|
context: {
|
|
65
61
|
security: {}
|
|
66
62
|
}
|
|
67
|
-
}, useCache);
|
|
63
|
+
}, ctx, useCache);
|
|
68
64
|
}
|
|
69
65
|
else {
|
|
70
|
-
return yield authZ.isAllowed({
|
|
66
|
+
return yield authz_1.authZ.isAllowed({
|
|
71
67
|
context: {
|
|
72
68
|
security: {}
|
|
73
69
|
},
|
|
74
70
|
target: {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
subject,
|
|
72
|
+
resource,
|
|
73
|
+
action
|
|
78
74
|
}
|
|
79
|
-
}, useCache);
|
|
75
|
+
}, ctx, useCache);
|
|
80
76
|
}
|
|
81
77
|
});
|
|
82
78
|
exports.isAllowedRequest = isAllowedRequest;
|
|
83
79
|
/**
|
|
84
80
|
* It turns an API request as can be found in typical Web frameworks like express, koa etc.
|
|
85
|
-
* into a proper ACS request. For
|
|
86
|
-
* it uses `whatIsAllowed()`. For the latter it extends the filter provided in the `ReadRequst`
|
|
81
|
+
* into a proper ACS request. For `whatIsAllowed` operation it returns the filters
|
|
87
82
|
* to enforce the applicapble poilicies. The response is `Decision`
|
|
88
83
|
* or policy set reverse query `PolicySetRQ` depending on the requeste operation `isAllowed()` or
|
|
89
84
|
* `whatIsAllowed()` respectively.
|
|
90
|
-
* @param {Subject
|
|
91
|
-
* @param {
|
|
85
|
+
* @param {Subject} subject Contains subject information or ApiKey
|
|
86
|
+
* @param {Resource[]} resource Contains resource name, resource instance and optional resource properties
|
|
92
87
|
* @param {AuthZAction} action Action to be performed on resource
|
|
93
|
-
* @param {
|
|
94
|
-
* @param {
|
|
95
|
-
*
|
|
88
|
+
* @param {ACSClientContext} ctx Context containing Subject and Context Resources for ACS
|
|
89
|
+
* @param {Operation} operation Operation to perform `isAllowed` or `whatIsAllowed`,
|
|
90
|
+
* if this param is missing defaults to `isAllowed` operation
|
|
91
|
+
* @param {Database} database database used either `arangoDB` or `postgres`,
|
|
92
|
+
* if this param is missing defaults to `arangoDB`
|
|
96
93
|
* @param {boolean} useCache by default ACS caching is used, if set to false then ACS cache
|
|
97
94
|
* is not used and ACS request is made to `access-control-srv`
|
|
98
95
|
* @returns {DecisionResponse | PolicySetRQResponse}
|
|
99
96
|
*/
|
|
100
|
-
const accessRequest = (subject,
|
|
97
|
+
const accessRequest = (subject, resource, action, ctx, operation, database, useCache = true) => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
98
|
// when subject is not passed (if auth header is not set)
|
|
102
99
|
if (_.isEmpty(subject)) {
|
|
103
100
|
subject = { unauthenticated: true };
|
|
@@ -131,40 +128,53 @@ const accessRequest = (subject, request, action, authZ, entity, resourceNameSpac
|
|
|
131
128
|
if (_.isEmpty(subject)) {
|
|
132
129
|
return { decision: interfaces_1.Decision.DENY, operation_status: utils_1.generateOperationStatus(config_1.errors.USER_NOT_LOGGED_IN.code, config_1.errors.USER_NOT_LOGGED_IN.message) };
|
|
133
130
|
}
|
|
134
|
-
let resources = [];
|
|
135
131
|
let subjectID;
|
|
136
132
|
let targetScope = subject.scope;
|
|
137
133
|
// resolve userID by token
|
|
138
134
|
if (subject && subject.id) {
|
|
139
135
|
subjectID = subject.id;
|
|
140
136
|
}
|
|
141
|
-
if (!
|
|
142
|
-
|
|
137
|
+
if (!_.isArray(resource)) {
|
|
138
|
+
resource = [resource];
|
|
139
|
+
}
|
|
140
|
+
if (_.isEmpty(resource)) {
|
|
141
|
+
const msg = `Access not allowed for request with subject:${subjectID}, ` +
|
|
142
|
+
`resource:${resource}, action:${action}, target_scope:${targetScope}; the response was INDETERMINATE`;
|
|
143
|
+
const details = 'Entity missing';
|
|
144
|
+
logger_1.default.verbose(msg);
|
|
145
|
+
logger_1.default.verbose('Details:', { details });
|
|
146
|
+
return { decision: interfaces_1.Decision.DENY, operation_status: utils_1.generateOperationStatus(Number(config_1.errors.ACTION_NOT_ALLOWED.code), msg) };
|
|
147
|
+
}
|
|
148
|
+
// default ACS operation is isAllowed
|
|
149
|
+
if (!operation) {
|
|
150
|
+
operation = interfaces_1.Operation.isAllowed;
|
|
151
|
+
}
|
|
152
|
+
// default database is arangoDB
|
|
153
|
+
if (!database) {
|
|
154
|
+
database = 'arangoDB';
|
|
155
|
+
}
|
|
156
|
+
// ctx.resources
|
|
157
|
+
if (ctx.resources && !_.isArray(ctx.resources)) {
|
|
158
|
+
ctx.resources = [ctx.resources];
|
|
143
159
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
// for action create or modify with read request to get policySetRQ
|
|
148
|
-
|| ((action == interfaces_2.AuthZAction.CREATE || action == interfaces_2.AuthZAction.MODIFY) && isReadRequest(request))) {
|
|
149
|
-
const resourceName = request.entity;
|
|
160
|
+
// whatIsAllowed Operation
|
|
161
|
+
if (operation === interfaces_1.Operation.whatIsAllowed) {
|
|
162
|
+
// const resourceName = request.entity;
|
|
150
163
|
let policySetResponse;
|
|
151
164
|
try {
|
|
152
165
|
// retrieving set of applicable policies/rules from ACS
|
|
153
166
|
// Note: it is assumed that there is only one policy set
|
|
154
|
-
policySetResponse = yield whatIsAllowedRequest(subClone,
|
|
155
|
-
type: resourceName,
|
|
156
|
-
namespace: request.namespace
|
|
157
|
-
}], [action], authZ, useCache);
|
|
167
|
+
policySetResponse = yield whatIsAllowedRequest(subClone, resource, action, ctx, useCache);
|
|
158
168
|
}
|
|
159
169
|
catch (err) {
|
|
160
|
-
logger_1.default.error('Error calling whatIsAllowed
|
|
170
|
+
logger_1.default.error('Error calling whatIsAllowed operation', { message: err.message });
|
|
161
171
|
logger_1.default.error('Error stack', err.stack);
|
|
162
172
|
return { decision: interfaces_1.Decision.DENY, operation_status: utils_1.generateOperationStatus(err.code, err.message) };
|
|
163
173
|
}
|
|
164
174
|
// handle case if policySet is empty
|
|
165
175
|
if ((!policySetResponse || _.isEmpty(policySetResponse.policy_sets)) && authzEnforced) {
|
|
166
176
|
const msg = `Access not allowed for request with subject:${subjectID}, ` +
|
|
167
|
-
`resource:${
|
|
177
|
+
`resource:${resource}, action:${action}, target_scope:${targetScope}; the response was INDETERMINATE`;
|
|
168
178
|
const details = 'no matching policy/rule could be found';
|
|
169
179
|
logger_1.default.verbose(msg);
|
|
170
180
|
logger_1.default.verbose('Details:', { details });
|
|
@@ -172,74 +182,43 @@ const accessRequest = (subject, request, action, authZ, entity, resourceNameSpac
|
|
|
172
182
|
}
|
|
173
183
|
if ((!policySetResponse || _.isEmpty(policySetResponse.policy_sets)) && !authzEnforced) {
|
|
174
184
|
logger_1.default.verbose(`The Access response was INDETERMIATE for a request with subject:` +
|
|
175
|
-
`${subjectID}, resource:${
|
|
185
|
+
`${subjectID}, resource:${resource}, action:${action}, target_scope:${targetScope} ` +
|
|
176
186
|
`as no matching policy/rule could be found, but since ACS enforcement ` +
|
|
177
187
|
`config is disabled overriding the ACS result`);
|
|
178
188
|
}
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
`resource:${resourceWithNS}, action:${action}, target_scope:${targetScope}; the response was DENY`;
|
|
184
|
-
const details = `Subject:${subjectID} does not have access to target scope ${targetScope}}`;
|
|
185
|
-
logger_1.default.verbose(msg);
|
|
186
|
-
logger_1.default.verbose('Details:', { details });
|
|
187
|
-
return { decision: interfaces_1.Decision.DENY, operation_status: utils_1.generateOperationStatus(Number(config_1.errors.ACTION_NOT_ALLOWED.code), msg) };
|
|
188
|
-
}
|
|
189
|
-
if (!permissionArguments && !authzEnforced) {
|
|
190
|
-
logger_1.default.verbose(`The Access response was DENY for a request from subject:${subjectID}, ` +
|
|
191
|
-
`resource:${resourceWithNS}, action:${action}, target_scope:${targetScope}, ` +
|
|
192
|
-
`but since ACS enforcement config is disabled overriding the ACS result`);
|
|
189
|
+
// create filters to enforce applicable policies and custom query / args if applicable
|
|
190
|
+
const resourceFilters = yield utils_1.createEntityFilterMap(resource, policySetResponse, ctx.resources, action, subClone, subjectID, authzEnforced, targetScope, database);
|
|
191
|
+
if (resourceFilters.decision) {
|
|
192
|
+
return resourceFilters;
|
|
193
193
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (request.args && request.args.filters && !_.isEmpty(request.args.filters)) {
|
|
197
|
-
if (_.isArray(request.args.filters)) {
|
|
198
|
-
for (let filter of request.args.filters) {
|
|
199
|
-
if (!_.isArray(permissionArguments.filters)) {
|
|
200
|
-
permissionArguments.filters = [filter];
|
|
201
|
-
}
|
|
202
|
-
permissionArguments.filters.push(filter);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
if (!_.isArray(permissionArguments.filters)) {
|
|
207
|
-
permissionArguments.filters = [permissionArguments.filters];
|
|
208
|
-
}
|
|
209
|
-
permissionArguments.filters.push(request.args.filters);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
Object.assign(request.args, permissionArguments);
|
|
194
|
+
policySetResponse.filters = resourceFilters.entityFilterMap;
|
|
195
|
+
policySetResponse.custom_query_args = resourceFilters.customQueryArgs;
|
|
213
196
|
policySetResponse.decision = interfaces_1.Decision.PERMIT; // Adding Permit to read response (since we no longer throw errorrs)
|
|
214
197
|
policySetResponse.operation_status = utils_1.generateOperationStatus(200, 'success');
|
|
215
198
|
return policySetResponse;
|
|
216
199
|
}
|
|
217
|
-
|
|
218
|
-
|
|
200
|
+
let resourceList = [];
|
|
201
|
+
resource.forEach((resourceObj) => {
|
|
202
|
+
resourceList.push(resourceObj.resource);
|
|
203
|
+
});
|
|
204
|
+
let resourceString;
|
|
205
|
+
if (resourceList.length === 1) {
|
|
206
|
+
resourceString = resourceList[0];
|
|
219
207
|
}
|
|
220
208
|
else {
|
|
221
|
-
|
|
209
|
+
resourceString = JSON.stringify(resourceList);
|
|
222
210
|
}
|
|
223
211
|
// default deny
|
|
224
212
|
let decisionResponse = { decision: interfaces_1.Decision.DENY, operation_status: { code: 0, message: '' } };
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (!_.isEmpty(resources) || action === interfaces_2.AuthZAction.DELETE ||
|
|
228
|
-
action === interfaces_2.AuthZAction.EXECUTE || action === interfaces_2.AuthZAction.DROP) {
|
|
229
|
-
// add type and namespace
|
|
230
|
-
for (let resource of resources) {
|
|
231
|
-
resourceList.push({
|
|
232
|
-
fields: _.keys(resource),
|
|
233
|
-
instance: resource,
|
|
234
|
-
type: entity,
|
|
235
|
-
namespace: resourceNameSpace
|
|
236
|
-
});
|
|
237
|
-
}
|
|
213
|
+
// isAllowed operation
|
|
214
|
+
if (operation === interfaces_1.Operation.isAllowed) {
|
|
238
215
|
// authorization
|
|
239
216
|
try {
|
|
240
|
-
decisionResponse = yield exports.isAllowedRequest(subClone,
|
|
217
|
+
decisionResponse = yield exports.isAllowedRequest(subClone, resource, action, ctx, useCache);
|
|
241
218
|
}
|
|
242
219
|
catch (err) {
|
|
220
|
+
logger_1.default.error('Error calling isAllowed operation', { message: err.message });
|
|
221
|
+
logger_1.default.error('Error stack', err.stack);
|
|
243
222
|
return { decision: interfaces_1.Decision.DENY, operation_status: utils_1.generateOperationStatus(err.code, err.message) };
|
|
244
223
|
}
|
|
245
224
|
if (decisionResponse && decisionResponse.decision != interfaces_1.Decision.PERMIT && authzEnforced) {
|
|
@@ -251,7 +230,7 @@ const accessRequest = (subject, request, action, authZ, entity, resourceNameSpac
|
|
|
251
230
|
details = `Subject:${subjectID} does not have access to requested target scope ${targetScope}`;
|
|
252
231
|
}
|
|
253
232
|
const msg = `Access not allowed for request with subject:${subjectID}, ` +
|
|
254
|
-
`resource:${
|
|
233
|
+
`resource:${resourceString}, action:${action}, target_scope:${targetScope}; the response was ${decisionResponse.decision}`;
|
|
255
234
|
logger_1.default.verbose(msg);
|
|
256
235
|
logger_1.default.verbose('Details:', { details });
|
|
257
236
|
return { decision: interfaces_1.Decision.DENY, operation_status: utils_1.generateOperationStatus(Number(config_1.errors.ACTION_NOT_ALLOWED.code), msg) };
|
|
@@ -266,7 +245,7 @@ const accessRequest = (subject, request, action, authZ, entity, resourceNameSpac
|
|
|
266
245
|
details = `Subject:${subjectID} does not have access to requested target scope ${targetScope}`;
|
|
267
246
|
}
|
|
268
247
|
logger_1.default.verbose(`Access not allowed for request with subject:${subjectID}, ` +
|
|
269
|
-
`resource:${
|
|
248
|
+
`resource:${resourceString}, action:${action}, target_scope:${targetScope}; the response was ${decisionResponse.decision}`);
|
|
270
249
|
logger_1.default.verbose(`${details}, Overriding the ACS result as ACS enforce config is disabled`);
|
|
271
250
|
decisionResponse.decision = interfaces_1.Decision.PERMIT;
|
|
272
251
|
}
|
package/lib/acs/resolver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/acs/resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4BAA4B;AAC5B,6CAGsB;
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/acs/resolver.ts"],"names":[],"mappings":"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"}
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,10 +1,39 @@
|
|
|
1
|
-
import { RoleAssociation, UserScope, Subject, PolicySetRQ } from './acs/interfaces';
|
|
1
|
+
import { RoleAssociation, UserScope, Subject, PolicySetRQ, PolicySetRQResponse, Attribute, EnityFilterMap, CustomQueryArgs, DecisionResponse, Resource, AuthZAction, ResolvedSubject } from './acs/interfaces';
|
|
2
2
|
import { QueryArguments, UserQueryArguments } from './acs/resolver';
|
|
3
|
-
import { ACSAuthZ } from './acs/authz';
|
|
4
3
|
export declare const reduceRoleAssociations: (roleAssociations: RoleAssociation[], scopeID: string) => Promise<UserScope>;
|
|
5
4
|
export declare const handleError: (err: string | Error | any) => any;
|
|
6
|
-
export declare const buildFilterPermissions: (policySet: PolicySetRQ, subject:
|
|
5
|
+
export declare const buildFilterPermissions: (policySet: PolicySetRQ, subject: ResolvedSubject, reqResources: any, database: string) => Promise<QueryArguments | UserQueryArguments>;
|
|
7
6
|
export declare const generateOperationStatus: (code?: number, message?: string) => {
|
|
8
7
|
code: number;
|
|
9
8
|
message: string;
|
|
10
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Check if the attributes of a resources from a rule, policy
|
|
12
|
+
* or policy set match the attributes from a request.
|
|
13
|
+
*
|
|
14
|
+
* @param ruleAttributes
|
|
15
|
+
* @param requestAttributes
|
|
16
|
+
*/
|
|
17
|
+
export declare const attributesMatch: (ruleAttributes: Attribute[], requestAttributes: Attribute[]) => boolean;
|
|
18
|
+
export interface FilterMapResponse {
|
|
19
|
+
entityFilterMap: EnityFilterMap[];
|
|
20
|
+
customQueryArgs: CustomQueryArgs[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* creates entity filters and custom query / arguments for the entity list provided
|
|
24
|
+
* It iterates through each entity and filter the applicable policies and
|
|
25
|
+
* provide them to buildFilterPermissions to create filters for each of the entities requested
|
|
26
|
+
*
|
|
27
|
+
* @param {Entity[]} entity Contains entity name, entity instance and optional entity properties
|
|
28
|
+
* @param {PolicSetResponse} policySetResponse contains set of applicable policies for entities list
|
|
29
|
+
* @param {any} resources context resources
|
|
30
|
+
* @param {AuthZAction} action Action to be performed on resource
|
|
31
|
+
* @param {Subject} subject Contains subject information or ApiKey
|
|
32
|
+
* @param {string} subjectID resolved subject identifier from token
|
|
33
|
+
* @param {boolean} authzEnforced authorization enforcement flag
|
|
34
|
+
* @param {string} targetScope target scope
|
|
35
|
+
* @param {Database} database database used either `arangoDB` or `postgres`,
|
|
36
|
+
* if this param is missing defaults to `arangoDB`
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
export declare const createEntityFilterMap: (resource: Resource[], policySetResponse: PolicySetRQResponse, resources: any, action: AuthZAction, subject: Subject, subjectID: string, authzEnforced: boolean, targetScope: string, database: 'arangoDB' | 'postgres') => Promise<FilterMapResponse | DecisionResponse>;
|
package/lib/utils.js
CHANGED
|
@@ -9,13 +9,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.generateOperationStatus = exports.buildFilterPermissions = exports.handleError = exports.reduceRoleAssociations = void 0;
|
|
12
|
+
exports.createEntityFilterMap = exports.attributesMatch = exports.generateOperationStatus = exports.buildFilterPermissions = exports.handleError = exports.reduceRoleAssociations = void 0;
|
|
13
13
|
const interfaces_1 = require("./acs/interfaces");
|
|
14
14
|
const _ = require("lodash");
|
|
15
15
|
const config_1 = require("./config");
|
|
16
16
|
const nodeEval = require("node-eval");
|
|
17
17
|
const logger_1 = require("./logger");
|
|
18
18
|
const cache_1 = require("./acs/cache");
|
|
19
|
+
const authz_1 = require("./acs/authz");
|
|
19
20
|
const reduceRoleAssociations = (roleAssociations, scopeID) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
21
|
const urns = config_1.cfg.get('authorization:urns');
|
|
21
22
|
const scope = {
|
|
@@ -232,7 +233,7 @@ const buildQueryFromTarget = (target, effect, userTotalScope, urns, userConditio
|
|
|
232
233
|
}
|
|
233
234
|
}
|
|
234
235
|
const scopingAttribute = _.find(subject, (attribute) => attribute.id == urns.roleScopingEntity);
|
|
235
|
-
if (!!scopingAttribute && effect == interfaces_1.Effect.PERMIT &&
|
|
236
|
+
if (!!scopingAttribute && effect == interfaces_1.Effect.PERMIT && database === 'arangoDB') { // note: there is currently no query to exclude scopes
|
|
236
237
|
// userTotalScope is an array accumulated scopes for each rule
|
|
237
238
|
if (userCondition) {
|
|
238
239
|
filter = [];
|
|
@@ -305,7 +306,7 @@ const buildQueryFromTarget = (target, effect, userTotalScope, urns, userConditio
|
|
|
305
306
|
query.userCondition = userCondition;
|
|
306
307
|
return query;
|
|
307
308
|
};
|
|
308
|
-
const buildFilterPermissions = (policySet, subject, reqResources,
|
|
309
|
+
const buildFilterPermissions = (policySet, subject, reqResources, database) => __awaiter(void 0, void 0, void 0, function* () {
|
|
309
310
|
let hierarchical_scopes = subject && subject.hierarchical_scopes ? subject.hierarchical_scopes : [];
|
|
310
311
|
let role_associations = subject && subject.role_associations ? subject.role_associations : [];
|
|
311
312
|
if (_.isEmpty(role_associations) || _.isEmpty(hierarchical_scopes)) {
|
|
@@ -461,4 +462,169 @@ const generateOperationStatus = (code, message) => {
|
|
|
461
462
|
};
|
|
462
463
|
};
|
|
463
464
|
exports.generateOperationStatus = generateOperationStatus;
|
|
465
|
+
/**
|
|
466
|
+
* Check if the attributes of a resources from a rule, policy
|
|
467
|
+
* or policy set match the attributes from a request.
|
|
468
|
+
*
|
|
469
|
+
* @param ruleAttributes
|
|
470
|
+
* @param requestAttributes
|
|
471
|
+
*/
|
|
472
|
+
const attributesMatch = (ruleAttributes, requestAttributes) => {
|
|
473
|
+
for (let attribute of ruleAttributes) {
|
|
474
|
+
const id = attribute.id;
|
|
475
|
+
const value = attribute.value;
|
|
476
|
+
const match = !!requestAttributes.find((requestAttribute) => {
|
|
477
|
+
// return requestAttribute.id == id && requestAttribute.value == value;
|
|
478
|
+
if (requestAttribute.id == id && requestAttribute.value == value) {
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
else if (requestAttribute.id == id) {
|
|
482
|
+
// rule entity
|
|
483
|
+
let pattern = value.substring(value.lastIndexOf(':') + 1);
|
|
484
|
+
let nsEntityArray = pattern.split('.');
|
|
485
|
+
// firstElement could be either entity or namespace
|
|
486
|
+
let nsOrEntity = nsEntityArray[0];
|
|
487
|
+
let entityRegexValue = nsEntityArray[nsEntityArray.length - 1];
|
|
488
|
+
let reqNS, ruleNS;
|
|
489
|
+
if (nsOrEntity.toUpperCase() != entityRegexValue.toUpperCase()) {
|
|
490
|
+
// rule name space is present
|
|
491
|
+
ruleNS = nsOrEntity.toUpperCase();
|
|
492
|
+
}
|
|
493
|
+
// request entity
|
|
494
|
+
let reqValue = requestAttribute.value;
|
|
495
|
+
const reqAttributeNS = reqValue.substring(0, reqValue.lastIndexOf(':'));
|
|
496
|
+
const ruleAttributeNS = value.substring(0, value.lastIndexOf(':'));
|
|
497
|
+
// verify namespace before entity name
|
|
498
|
+
if (reqAttributeNS != ruleAttributeNS) {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
let reqPattern = reqValue.substring(reqValue.lastIndexOf(':') + 1);
|
|
502
|
+
let reqNSEntityArray = reqPattern.split('.');
|
|
503
|
+
// firstElement could be either entity or namespace
|
|
504
|
+
let reqNSOrEntity = reqNSEntityArray[0];
|
|
505
|
+
let requestEntityValue = reqNSEntityArray[reqNSEntityArray.length - 1];
|
|
506
|
+
if (reqNSOrEntity.toUpperCase() != requestEntityValue.toUpperCase()) {
|
|
507
|
+
// request name space is present
|
|
508
|
+
reqNS = reqNSOrEntity.toUpperCase();
|
|
509
|
+
}
|
|
510
|
+
if ((reqNS && ruleNS && (reqNS === ruleNS)) || (!reqNS && !ruleNS)) {
|
|
511
|
+
const reExp = new RegExp(entityRegexValue);
|
|
512
|
+
if (requestEntityValue.match(reExp)) {
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
if (!match) {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return true;
|
|
526
|
+
};
|
|
527
|
+
exports.attributesMatch = attributesMatch;
|
|
528
|
+
/**
|
|
529
|
+
* creates entity filters and custom query / arguments for the entity list provided
|
|
530
|
+
* It iterates through each entity and filter the applicable policies and
|
|
531
|
+
* provide them to buildFilterPermissions to create filters for each of the entities requested
|
|
532
|
+
*
|
|
533
|
+
* @param {Entity[]} entity Contains entity name, entity instance and optional entity properties
|
|
534
|
+
* @param {PolicSetResponse} policySetResponse contains set of applicable policies for entities list
|
|
535
|
+
* @param {any} resources context resources
|
|
536
|
+
* @param {AuthZAction} action Action to be performed on resource
|
|
537
|
+
* @param {Subject} subject Contains subject information or ApiKey
|
|
538
|
+
* @param {string} subjectID resolved subject identifier from token
|
|
539
|
+
* @param {boolean} authzEnforced authorization enforcement flag
|
|
540
|
+
* @param {string} targetScope target scope
|
|
541
|
+
* @param {Database} database database used either `arangoDB` or `postgres`,
|
|
542
|
+
* if this param is missing defaults to `arangoDB`
|
|
543
|
+
*
|
|
544
|
+
*/
|
|
545
|
+
const createEntityFilterMap = (resource, policySetResponse, resources, action, subject, subjectID, authzEnforced, targetScope, database) => __awaiter(void 0, void 0, void 0, function* () {
|
|
546
|
+
let entityFilterMap = [];
|
|
547
|
+
let customQueryArgs = [];
|
|
548
|
+
for (let resourceObj of resource) {
|
|
549
|
+
let resourcenameNameSpace = resourceObj.resource;
|
|
550
|
+
let resourceNameSpace, resourceName;
|
|
551
|
+
if (resourcenameNameSpace && resourcenameNameSpace.indexOf('.') > -1) {
|
|
552
|
+
resourceNameSpace = resourcenameNameSpace.slice(0, resourcenameNameSpace.lastIndexOf('.'));
|
|
553
|
+
// resource name from `.` till end, when no end index is specified for
|
|
554
|
+
// slice api it returns till end of string
|
|
555
|
+
resourceName = resourcenameNameSpace.slice(resourcenameNameSpace.lastIndexOf('.') + 1);
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
resourceName = resourcenameNameSpace;
|
|
559
|
+
}
|
|
560
|
+
const resourceType = authz_1.formatResourceType(resourceName, resourceNameSpace);
|
|
561
|
+
const urns = config_1.cfg.get('authorization:urns');
|
|
562
|
+
const resourceValueURN = (urns === null || urns === void 0 ? void 0 : urns.model) + `:${resourceType}`;
|
|
563
|
+
let resourcePolicies = { policy_sets: [{ policies: [] }] };
|
|
564
|
+
const resourceAttributes = [{ id: urns === null || urns === void 0 ? void 0 : urns.entity, value: resourceValueURN }];
|
|
565
|
+
if (policySetResponse && policySetResponse.policy_sets && policySetResponse.policy_sets.length > 0) {
|
|
566
|
+
policySetResponse.policy_sets.forEach((policySet) => {
|
|
567
|
+
var _a, _b, _c;
|
|
568
|
+
const policies = policySet.policies;
|
|
569
|
+
// check if the policy and rule set is applicable to the enitity
|
|
570
|
+
if (policies && policies.length > 0) {
|
|
571
|
+
for (let policy of policies) {
|
|
572
|
+
const policyTargetResources = (_a = policy === null || policy === void 0 ? void 0 : policy.target) === null || _a === void 0 ? void 0 : _a.resources;
|
|
573
|
+
if (policyTargetResources) {
|
|
574
|
+
const policyMatch = exports.attributesMatch(policyTargetResources, resourceAttributes);
|
|
575
|
+
if (policyMatch && policy.rules && policy.rules.length > 0) {
|
|
576
|
+
for (let rule of policy.rules) {
|
|
577
|
+
const ruleMatch = exports.attributesMatch((_b = rule === null || rule === void 0 ? void 0 : rule.target) === null || _b === void 0 ? void 0 : _b.resources, resourceAttributes);
|
|
578
|
+
if (ruleMatch) {
|
|
579
|
+
resourcePolicies.policy_sets[0].policies.push(policy);
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
else if (policy === null || policy === void 0 ? void 0 : policy.rules) {
|
|
586
|
+
// check for rule
|
|
587
|
+
for (let rule of policy.rules) {
|
|
588
|
+
const ruleMatch = exports.attributesMatch((_c = rule === null || rule === void 0 ? void 0 : rule.target) === null || _c === void 0 ? void 0 : _c.resources, resourceAttributes);
|
|
589
|
+
if (ruleMatch) {
|
|
590
|
+
resourcePolicies.policy_sets[0].policies.push(policy);
|
|
591
|
+
break;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
let permissionArguments = yield exports.buildFilterPermissions(resourcePolicies.policy_sets[0], subject, resources, database);
|
|
600
|
+
if (!permissionArguments && authzEnforced) {
|
|
601
|
+
const msg = `Access not allowed for request with subject:${subjectID}, ` +
|
|
602
|
+
`resource:${resourceName}, action:${action}, target_scope:${targetScope}; the response was DENY`;
|
|
603
|
+
const details = `Subject:${subjectID} does not have access to target scope ${targetScope}}`;
|
|
604
|
+
logger_1.default.verbose(msg);
|
|
605
|
+
logger_1.default.verbose('Details:', { details });
|
|
606
|
+
return { decision: interfaces_1.Decision.DENY, operation_status: exports.generateOperationStatus(Number(config_1.errors.ACTION_NOT_ALLOWED.code), msg) };
|
|
607
|
+
}
|
|
608
|
+
if (!permissionArguments && !authzEnforced) {
|
|
609
|
+
logger_1.default.verbose(`The Access response was DENY for a request from subject:${subjectID}, ` +
|
|
610
|
+
`resource:${resourceName}, action:${action}, target_scope:${targetScope}, ` +
|
|
611
|
+
`but since ACS enforcement config is disabled overriding the ACS result`);
|
|
612
|
+
}
|
|
613
|
+
if (!_.isArray(permissionArguments.filters)) {
|
|
614
|
+
permissionArguments.filters = [permissionArguments.filters];
|
|
615
|
+
}
|
|
616
|
+
entityFilterMap.push({ resource: resourceName, filters: permissionArguments.filters });
|
|
617
|
+
if (permissionArguments.custom_queries && permissionArguments.custom_arguments) {
|
|
618
|
+
customQueryArgs.push({
|
|
619
|
+
resource: resourceName,
|
|
620
|
+
custom_queries: permissionArguments.custom_queries,
|
|
621
|
+
custom_arguments: permissionArguments.custom_arguments
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
entityFilterMap, customQueryArgs
|
|
627
|
+
};
|
|
628
|
+
});
|
|
629
|
+
exports.createEntityFilterMap = createEntityFilterMap;
|
|
464
630
|
//# sourceMappingURL=utils.js.map
|