@prosopo/user-access-policy 3.10.1 → 3.10.3
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/.turbo/turbo-build$colon$cjs.log +2 -2
- package/.turbo/turbo-build$colon$tsc.log +14 -14
- package/.turbo/turbo-build.log +36 -36
- package/CHANGELOG.md +24 -0
- package/dist/cjs/redis/reader/redisRulesReader.cjs +32 -1
- package/dist/redis/reader/redisRulesReader.d.ts.map +1 -1
- package/dist/redis/reader/redisRulesReader.js +33 -2
- package/dist/redis/reader/redisRulesReader.js.map +1 -1
- package/dist/tests/redis/redisRulesStorage.integration.test.js +159 -0
- package/dist/tests/redis/redisRulesStorage.integration.test.js.map +1 -1
- package/package.json +4 -4
- package/src/redis/reader/redisRulesReader.ts +52 -5
- package/src/tests/redis/redisRulesStorage.integration.test.ts +295 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/user-access-policy@3.10.
|
|
2
|
+
> @prosopo/user-access-policy@3.10.3 build:cjs
|
|
3
3
|
> NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
|
|
4
4
|
|
|
5
5
|
ViteCommonJSConfig: .
|
|
@@ -67,5 +67,5 @@ rendering chunks...
|
|
|
67
67
|
[2mdist/cjs/[22m[36mredis/redisRulesWriter.cjs [39m[1m[2m 3.44 kB[22m[1m[22m
|
|
68
68
|
[2mdist/cjs/[22m[36mredis/reader/redisRulesQuery.cjs [39m[1m[2m 4.34 kB[22m[1m[22m
|
|
69
69
|
[2mdist/cjs/[22m[36mapi/ruleApiRoutes.cjs [39m[1m[2m 4.55 kB[22m[1m[22m
|
|
70
|
-
[2mdist/cjs/[22m[36mredis/reader/redisRulesReader.cjs [39m[1m[
|
|
70
|
+
[2mdist/cjs/[22m[36mredis/reader/redisRulesReader.cjs [39m[1m[2m11.57 kB[22m[1m[22m
|
|
71
71
|
[32m✓ built in 437ms[39m
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/user-access-policy@3.10.
|
|
2
|
+
> @prosopo/user-access-policy@3.10.3 build:tsc
|
|
3
3
|
> tsc --build --verbose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
12:05:45 PM - Projects in this build:
|
|
6
6
|
* ../../dev/config/tsconfig.json
|
|
7
7
|
* ../locale/tsconfig.json
|
|
8
8
|
* ../util/tsconfig.json
|
|
@@ -15,27 +15,27 @@
|
|
|
15
15
|
* ../api/tsconfig.json
|
|
16
16
|
* tsconfig.json
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
12:05:45 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/vite/NodejsPolarsNativeFilePlugin.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
12:05:45 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
12:05:45 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
12:05:45 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/logger.ts' is older than output '../logger/tsconfig.tsbuildinfo'
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
12:05:45 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
12:05:45 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/keyring/keyring/types.ts' is older than output '../types/tsconfig.tsbuildinfo'
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
12:05:45 PM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/error.ts' is older than output '../common/tsconfig.tsbuildinfo'
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
12:05:45 PM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/apiRoutes.ts' is older than output '../api-route/tsconfig.tsbuildinfo'
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
12:05:45 PM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/tsconfig.tsbuildinfo'
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
12:05:45 PM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
12:05:45 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
12:05:45 PM - Building project '/home/runner/work/captcha/captcha/packages/user-access-policy/tsconfig.json'...
|
|
41
41
|
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/user-access-policy@3.10.
|
|
2
|
+
> @prosopo/user-access-policy@3.10.3 build
|
|
3
3
|
> npm run build:cross-env -- --mode ${NODE_ENV:-development}
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @prosopo/user-access-policy@3.10.
|
|
6
|
+
> @prosopo/user-access-policy@3.10.3 build:cross-env
|
|
7
7
|
> vite build --config vite.esm.config.ts --mode production
|
|
8
8
|
|
|
9
9
|
ViteEsmConfig: .
|
|
@@ -39,37 +39,37 @@ transforming...
|
|
|
39
39
|
Build end
|
|
40
40
|
[32m✓[39m 33 modules transformed.
|
|
41
41
|
rendering chunks...
|
|
42
|
-
[2mdist/[22m[36mapi/delete/.export.js [39m[1m[
|
|
43
|
-
[2mdist/[22m[36mapi/read/.export.js [39m[1m[
|
|
44
|
-
[2mdist/[22m[36mapi/write/.export.js [39m[1m[
|
|
45
|
-
[2mdist/[22m[36mmongoose/.export.js [39m[1m[
|
|
46
|
-
[2mdist/[22m[36mredis/.export.js [39m[1m[
|
|
47
|
-
[2mdist/[22m[36mrulesStorage.js [39m[1m[
|
|
48
|
-
[2mdist/[22m[36mrule.js [39m[1m[
|
|
49
|
-
[2mdist/[22m[36mruleInput/.export.js [39m[1m[
|
|
50
|
-
[2mdist/[22m[36mapi/.export.js [39m[1m[
|
|
51
|
-
[2mdist/[22m[36mruleRecord.js [39m[1m[
|
|
52
|
-
[2mdist/[22m[36mapi/delete/deleteAllRules.js [39m[1m[
|
|
53
|
-
[2mdist/[22m[36m.export.js [39m[1m[
|
|
54
|
-
[2mdist/[22m[36mapi/read/getMissingIds.js [39m[1m[
|
|
55
|
-
[2mdist/[22m[36mapi/read/fetchRules.js [39m[1m[
|
|
56
|
-
[2mdist/[22m[36mredis/redisRulesStorage.js [39m[1m[
|
|
57
|
-
[2mdist/[22m[36mmongoose/mongooseRuleSchema.js [39m[1m[
|
|
58
|
-
[2mdist/[22m[36mapi/delete/deleteRules.js [39m[1m[
|
|
59
|
-
[2mdist/[22m[36mapi/delete/deleteRuleGroups.js [39m[1m[
|
|
60
|
-
[2mdist/[22m[36mruleInput/policyInput.js [39m[1m[
|
|
61
|
-
[2mdist/[22m[36mapi/read/findRuleIds.js [39m[1m[
|
|
62
|
-
[2mdist/[22m[36mapi/write/rehashRules.js [39m[1m[
|
|
63
|
-
[2mdist/[22m[36mruleInput/ruleInput.js [39m[1m[
|
|
64
|
-
[2mdist/[22m[36mredis/redisClient.js [39m[1m[
|
|
65
|
-
[2mdist/[22m[36mredis/redisRuleIndex.js [39m[1m[
|
|
66
|
-
[2mdist/[22m[36mruleInput/userScopeInput.js [39m[1m[
|
|
67
|
-
[2mdist/[22m[36mapi/rulesApiClient.js [39m[1m[
|
|
68
|
-
[2mdist/[22m[36mredis/reader/redisAggregate.js [39m[1m[
|
|
69
|
-
[2mdist/[22m[36mtransformRule.js [39m[1m[
|
|
70
|
-
[2mdist/[22m[36mapi/write/insertRules.js [39m[1m[
|
|
71
|
-
[2mdist/[22m[36mredis/redisRulesWriter.js [39m[1m[
|
|
72
|
-
[2mdist/[22m[36mredis/reader/redisRulesQuery.js [39m[1m[
|
|
73
|
-
[2mdist/[22m[36mapi/ruleApiRoutes.js [39m[1m[
|
|
74
|
-
[2mdist/[22m[36mredis/reader/redisRulesReader.js [39m[1m[
|
|
75
|
-
[32m✓ built in
|
|
42
|
+
[2mdist/[22m[36mapi/delete/.export.js [39m[1m[2m 0.00 kB[22m[1m[22m
|
|
43
|
+
[2mdist/[22m[36mapi/read/.export.js [39m[1m[2m 0.00 kB[22m[1m[22m
|
|
44
|
+
[2mdist/[22m[36mapi/write/.export.js [39m[1m[2m 0.00 kB[22m[1m[22m
|
|
45
|
+
[2mdist/[22m[36mmongoose/.export.js [39m[1m[2m 0.11 kB[22m[1m[22m
|
|
46
|
+
[2mdist/[22m[36mredis/.export.js [39m[1m[2m 0.20 kB[22m[1m[22m
|
|
47
|
+
[2mdist/[22m[36mrulesStorage.js [39m[1m[2m 0.23 kB[22m[1m[22m
|
|
48
|
+
[2mdist/[22m[36mrule.js [39m[1m[2m 0.24 kB[22m[1m[22m
|
|
49
|
+
[2mdist/[22m[36mruleInput/.export.js [39m[1m[2m 0.27 kB[22m[1m[22m
|
|
50
|
+
[2mdist/[22m[36mapi/.export.js [39m[1m[2m 0.37 kB[22m[1m[22m
|
|
51
|
+
[2mdist/[22m[36mruleRecord.js [39m[1m[2m 0.61 kB[22m[1m[22m
|
|
52
|
+
[2mdist/[22m[36mapi/delete/deleteAllRules.js [39m[1m[2m 0.67 kB[22m[1m[22m
|
|
53
|
+
[2mdist/[22m[36m.export.js [39m[1m[2m 0.85 kB[22m[1m[22m
|
|
54
|
+
[2mdist/[22m[36mapi/read/getMissingIds.js [39m[1m[2m 1.01 kB[22m[1m[22m
|
|
55
|
+
[2mdist/[22m[36mapi/read/fetchRules.js [39m[1m[2m 1.08 kB[22m[1m[22m
|
|
56
|
+
[2mdist/[22m[36mredis/redisRulesStorage.js [39m[1m[2m 1.21 kB[22m[1m[22m
|
|
57
|
+
[2mdist/[22m[36mmongoose/mongooseRuleSchema.js [39m[1m[2m 1.37 kB[22m[1m[22m
|
|
58
|
+
[2mdist/[22m[36mapi/delete/deleteRules.js [39m[1m[2m 1.44 kB[22m[1m[22m
|
|
59
|
+
[2mdist/[22m[36mapi/delete/deleteRuleGroups.js [39m[1m[2m 1.44 kB[22m[1m[22m
|
|
60
|
+
[2mdist/[22m[36mruleInput/policyInput.js [39m[1m[2m 1.50 kB[22m[1m[22m
|
|
61
|
+
[2mdist/[22m[36mapi/read/findRuleIds.js [39m[1m[2m 1.54 kB[22m[1m[22m
|
|
62
|
+
[2mdist/[22m[36mapi/write/rehashRules.js [39m[1m[2m 1.54 kB[22m[1m[22m
|
|
63
|
+
[2mdist/[22m[36mruleInput/ruleInput.js [39m[1m[2m 1.72 kB[22m[1m[22m
|
|
64
|
+
[2mdist/[22m[36mredis/redisClient.js [39m[1m[2m 1.90 kB[22m[1m[22m
|
|
65
|
+
[2mdist/[22m[36mredis/redisRuleIndex.js [39m[1m[2m 2.01 kB[22m[1m[22m
|
|
66
|
+
[2mdist/[22m[36mruleInput/userScopeInput.js [39m[1m[2m 2.22 kB[22m[1m[22m
|
|
67
|
+
[2mdist/[22m[36mapi/rulesApiClient.js [39m[1m[2m 2.36 kB[22m[1m[22m
|
|
68
|
+
[2mdist/[22m[36mredis/reader/redisAggregate.js [39m[1m[2m 2.46 kB[22m[1m[22m
|
|
69
|
+
[2mdist/[22m[36mtransformRule.js [39m[1m[2m 2.76 kB[22m[1m[22m
|
|
70
|
+
[2mdist/[22m[36mapi/write/insertRules.js [39m[1m[2m 3.22 kB[22m[1m[22m
|
|
71
|
+
[2mdist/[22m[36mredis/redisRulesWriter.js [39m[1m[2m 3.22 kB[22m[1m[22m
|
|
72
|
+
[2mdist/[22m[36mredis/reader/redisRulesQuery.js [39m[1m[2m 4.15 kB[22m[1m[22m
|
|
73
|
+
[2mdist/[22m[36mapi/ruleApiRoutes.js [39m[1m[2m 4.33 kB[22m[1m[22m
|
|
74
|
+
[2mdist/[22m[36mredis/reader/redisRulesReader.js [39m[1m[2m10.68 kB[22m[1m[22m
|
|
75
|
+
[32m✓ built in 437ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @prosopo/user-access-policy
|
|
2
2
|
|
|
3
|
+
## 3.10.3
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- Updated dependencies [3a46191]
|
|
7
|
+
- Updated dependencies [dde23e8]
|
|
8
|
+
- @prosopo/types@4.7.0
|
|
9
|
+
- @prosopo/api@3.5.0
|
|
10
|
+
|
|
11
|
+
## 3.10.2
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 6962179: fix(user-access-policy): make findRulesRanked robust to typeless candidates and IPv6 numericIp
|
|
15
|
+
|
|
16
|
+
Two production-fatal bugs in `findRulesRanked`, both surfacing as `failed to execute ranked search query` with empty results — i.e. no rules match the request and a Block rule that should fire is silently skipped.
|
|
17
|
+
|
|
18
|
+
1. **Typeless candidates abort the aggregate.** `SEVERITY_EXPR = '(@type == "block")'` dereferenced `@type` directly, so any candidate document missing `type` triggered `Could not find the value for a parameter name, consider using EXISTS if applicable for type`. Sources of typeless candidates in production: stale RediSearch index entries pointing at a hash whose `type` was `HDEL`'d or whose key was `DEL`'d (visible after mass cleanups), and partial-write races in the writer. Fix: `FILTER exists(@type)` step at the start of the pipeline drops malformed candidates before any APPLY runs.
|
|
19
|
+
|
|
20
|
+
2. **`FT.AGGREGATE LOAD` returns NUMERIC fields as doubles.** RediSearch stores NUMERIC values in the index as 8-byte doubles, so any `numericIp` / `numericIpMaskMin` / `numericIpMaskMax` past `Number.MAX_SAFE_INTEGER` (every IPv6 rule) round-tripped as scientific notation (`5.59112965392e+37`) and `z.coerce.bigint()` threw `Cannot convert … to a BigInt`. The hash itself preserves the full 38-digit string. Fix: use the aggregate purely as a ranker (it returns top-N keys by spec/severity); read the field values via `HGETALL` over those keys, same pattern as `findRulesGreedy`. One extra round-trip over ≤20 keys.
|
|
21
|
+
|
|
22
|
+
Adds three regression tests: two simulate the typeless candidate via `HDEL` (single rule + co-resident valid rule), one inserts an IPv6 `numericIp` past `2**53` and asserts the bigint comes back intact. All three fail without the respective fix.
|
|
23
|
+
- Updated dependencies [4626340]
|
|
24
|
+
- @prosopo/types@4.6.1
|
|
25
|
+
- @prosopo/api@3.4.14
|
|
26
|
+
|
|
3
27
|
## 3.10.1
|
|
4
28
|
### Patch Changes
|
|
5
29
|
|
|
@@ -109,6 +109,19 @@ class RedisRulesReader {
|
|
|
109
109
|
DIALECT: redisRulesQuery.REDIS_QUERY_DIALECT,
|
|
110
110
|
LOAD: [...RULE_LOAD_FIELDS],
|
|
111
111
|
STEPS: [
|
|
112
|
+
// Drop candidates whose hash is missing `type` before
|
|
113
|
+
// any APPLY runs. SEVERITY_EXPR dereferences `@type`
|
|
114
|
+
// directly, and RediSearch throws
|
|
115
|
+
// "Could not find the value for a parameter name,
|
|
116
|
+
// consider using EXISTS if applicable for type"
|
|
117
|
+
// when the LOAD pulls an undefined @type, aborting
|
|
118
|
+
// the whole aggregate. The undefined @type can come
|
|
119
|
+
// from a partial-write race in the writer or a
|
|
120
|
+
// stale RediSearch index entry pointing at a hash
|
|
121
|
+
// whose `type` field has been removed; in both
|
|
122
|
+
// cases the doc is malformed and not a valid
|
|
123
|
+
// AccessRule, so dropping it is correct.
|
|
124
|
+
{ type: "FILTER", expression: "exists(@type)" },
|
|
112
125
|
{ type: "APPLY", expression: SPECIFICITY_EXPR, AS: "_spec" },
|
|
113
126
|
{ type: "APPLY", expression: SEVERITY_EXPR, AS: "_sev" },
|
|
114
127
|
{ type: "APPLY", expression: RANK_EXPR, AS: "_rank" },
|
|
@@ -145,7 +158,25 @@ class RedisRulesReader {
|
|
|
145
158
|
)
|
|
146
159
|
}
|
|
147
160
|
}));
|
|
148
|
-
|
|
161
|
+
const ruleKeys = [];
|
|
162
|
+
for (const result of reply.results) {
|
|
163
|
+
const key = result.__key;
|
|
164
|
+
if (typeof key === "string") {
|
|
165
|
+
ruleKeys.push(key);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (ruleKeys.length === 0) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
const { records } = await redisClient.fetchRedisHashRecords(
|
|
172
|
+
this.client,
|
|
173
|
+
ruleKeys,
|
|
174
|
+
this.logger
|
|
175
|
+
);
|
|
176
|
+
const nonEmptyRecords = records.filter(
|
|
177
|
+
(record) => Object.keys(record).length > 0
|
|
178
|
+
);
|
|
179
|
+
return redisClient.parseRedisRecords(nonEmptyRecords, ruleInput.accessRuleInput, this.logger);
|
|
149
180
|
} catch (e) {
|
|
150
181
|
this.logger.error(() => ({
|
|
151
182
|
err: e,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redisRulesReader.d.ts","sourceRoot":"","sources":["../../../src/redis/reader/redisRulesReader.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAe7C,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,KAAK,EACX,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,yBAAyB,CAAC;AAoBjC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAoEzC,qBAAa,gBAAiB,YAAW,iBAAiB;IAExD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,MAAM;IAG1B,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAcvD,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAazD,SAAS,CACd,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,UAAQ,EAC1B,mBAAmB,UAAO,GACxB,OAAO,CAAC,UAAU,EAAE,CAAC;YAuBV,eAAe;
|
|
1
|
+
{"version":3,"file":"redisRulesReader.d.ts","sourceRoot":"","sources":["../../../src/redis/reader/redisRulesReader.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAe7C,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,KAAK,EACX,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,yBAAyB,CAAC;AAoBjC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAoEzC,qBAAa,gBAAiB,YAAW,iBAAiB;IAExD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,MAAM;IAG1B,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAcvD,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAazD,SAAS,CACd,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,UAAQ,EAC1B,mBAAmB,UAAO,GACxB,OAAO,CAAC,UAAU,EAAE,CAAC;YAuBV,eAAe;YA0Hf,eAAe;IAuDvB,WAAW,CAChB,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,UAAQ,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC;IAgDd,eAAe,CACpB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC;cAYA,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA8B5E,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;CAGlD;AAED,qBAAa,qBAAsB,YAAW,iBAAiB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAErC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWvD,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAWzD,SAAS,CACd,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,UAAQ,EAC1B,mBAAmB,UAAO,GACxB,OAAO,CAAC,UAAU,EAAE,CAAC;IAWlB,WAAW,CAChB,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,UAAQ,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC;IAWd,eAAe,CACpB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC;CAKhB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as util from "node:util";
|
|
2
2
|
import { chunkIntoBatches, executeBatchesSequentially } from "@prosopo/common";
|
|
3
3
|
import { getRulesRedisQuery, REDIS_QUERY_DIALECT } from "./redisRulesQuery.js";
|
|
4
|
-
import { REDIS_BATCH_SIZE, getMissingRedisKeys,
|
|
4
|
+
import { REDIS_BATCH_SIZE, getMissingRedisKeys, fetchRedisHashRecords, parseRedisRecords } from "../redisClient.js";
|
|
5
5
|
import { ACCESS_RULE_REDIS_KEY_PREFIX, ACCESS_RULES_REDIS_INDEX_NAME } from "../redisRuleIndex.js";
|
|
6
6
|
import { AccessPolicyType } from "../../rule.js";
|
|
7
7
|
import { accessRuleInput } from "../../ruleInput/ruleInput.js";
|
|
@@ -90,6 +90,19 @@ class RedisRulesReader {
|
|
|
90
90
|
DIALECT: REDIS_QUERY_DIALECT,
|
|
91
91
|
LOAD: [...RULE_LOAD_FIELDS],
|
|
92
92
|
STEPS: [
|
|
93
|
+
// Drop candidates whose hash is missing `type` before
|
|
94
|
+
// any APPLY runs. SEVERITY_EXPR dereferences `@type`
|
|
95
|
+
// directly, and RediSearch throws
|
|
96
|
+
// "Could not find the value for a parameter name,
|
|
97
|
+
// consider using EXISTS if applicable for type"
|
|
98
|
+
// when the LOAD pulls an undefined @type, aborting
|
|
99
|
+
// the whole aggregate. The undefined @type can come
|
|
100
|
+
// from a partial-write race in the writer or a
|
|
101
|
+
// stale RediSearch index entry pointing at a hash
|
|
102
|
+
// whose `type` field has been removed; in both
|
|
103
|
+
// cases the doc is malformed and not a valid
|
|
104
|
+
// AccessRule, so dropping it is correct.
|
|
105
|
+
{ type: "FILTER", expression: "exists(@type)" },
|
|
93
106
|
{ type: "APPLY", expression: SPECIFICITY_EXPR, AS: "_spec" },
|
|
94
107
|
{ type: "APPLY", expression: SEVERITY_EXPR, AS: "_sev" },
|
|
95
108
|
{ type: "APPLY", expression: RANK_EXPR, AS: "_rank" },
|
|
@@ -126,7 +139,25 @@ class RedisRulesReader {
|
|
|
126
139
|
)
|
|
127
140
|
}
|
|
128
141
|
}));
|
|
129
|
-
|
|
142
|
+
const ruleKeys = [];
|
|
143
|
+
for (const result of reply.results) {
|
|
144
|
+
const key = result.__key;
|
|
145
|
+
if (typeof key === "string") {
|
|
146
|
+
ruleKeys.push(key);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (ruleKeys.length === 0) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
const { records } = await fetchRedisHashRecords(
|
|
153
|
+
this.client,
|
|
154
|
+
ruleKeys,
|
|
155
|
+
this.logger
|
|
156
|
+
);
|
|
157
|
+
const nonEmptyRecords = records.filter(
|
|
158
|
+
(record) => Object.keys(record).length > 0
|
|
159
|
+
);
|
|
160
|
+
return parseRedisRecords(nonEmptyRecords, accessRuleInput, this.logger);
|
|
130
161
|
} catch (e) {
|
|
131
162
|
this.logger.error(() => ({
|
|
132
163
|
err: e,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redisRulesReader.js","sourceRoot":"","sources":["../../../src/redis/reader/redisRulesReader.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"redisRulesReader.js","sourceRoot":"","sources":["../../../src/redis/reader/redisRulesReader.ts"],"names":[],"mappings":"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"}
|
|
@@ -854,6 +854,165 @@ describe("redisAccessRulesStorage", () => {
|
|
|
854
854
|
}, true);
|
|
855
855
|
expect(foundAccessRules).toEqual([accessRule]);
|
|
856
856
|
});
|
|
857
|
+
test("findRulesRanked does not throw when a matched candidate is missing @type", async () => {
|
|
858
|
+
const clientId = getUniqueString();
|
|
859
|
+
const userId = getUniqueString();
|
|
860
|
+
const accessRule = {
|
|
861
|
+
type: AccessPolicyType.Block,
|
|
862
|
+
clientId: clientId,
|
|
863
|
+
userId: userId,
|
|
864
|
+
};
|
|
865
|
+
await insertRules([accessRule]);
|
|
866
|
+
const ruleKey = getAccessRuleRedisKey(accessRule);
|
|
867
|
+
await redisClient.hDel(ruleKey, "type");
|
|
868
|
+
const foundAccessRules = await accessRulesReader.findRules({
|
|
869
|
+
policyScope: { clientId: clientId },
|
|
870
|
+
policyScopeMatch: FilterScopeMatch.Exact,
|
|
871
|
+
userScope: { userId: userId },
|
|
872
|
+
userScopeMatch: FilterScopeMatch.Exact,
|
|
873
|
+
}, true);
|
|
874
|
+
expect(foundAccessRules).toEqual([]);
|
|
875
|
+
});
|
|
876
|
+
test("findRulesRanked returns the valid rule and skips a typeless ghost candidate", async () => {
|
|
877
|
+
const clientId = getUniqueString();
|
|
878
|
+
const userId = getUniqueString();
|
|
879
|
+
const validRule = {
|
|
880
|
+
type: AccessPolicyType.Block,
|
|
881
|
+
clientId: clientId,
|
|
882
|
+
userId: userId,
|
|
883
|
+
ja4Hash: "t13d1313h2_valid",
|
|
884
|
+
};
|
|
885
|
+
const ghostRule = {
|
|
886
|
+
type: AccessPolicyType.Block,
|
|
887
|
+
clientId: clientId,
|
|
888
|
+
userId: userId,
|
|
889
|
+
ja4Hash: "t13d1313h2_ghost",
|
|
890
|
+
};
|
|
891
|
+
await insertRules([validRule, ghostRule]);
|
|
892
|
+
const ghostKey = getAccessRuleRedisKey(ghostRule);
|
|
893
|
+
await redisClient.hDel(ghostKey, "type");
|
|
894
|
+
const foundAccessRules = await accessRulesReader.findRules({
|
|
895
|
+
policyScope: { clientId: clientId },
|
|
896
|
+
policyScopeMatch: FilterScopeMatch.Exact,
|
|
897
|
+
userScope: { userId: userId },
|
|
898
|
+
userScopeMatch: FilterScopeMatch.Greedy,
|
|
899
|
+
}, true);
|
|
900
|
+
expect(foundAccessRules).toEqual([validRule]);
|
|
901
|
+
});
|
|
902
|
+
test("findRulesRanked preserves bigint precision for IPv6 numericIp values", async () => {
|
|
903
|
+
const clientId = getUniqueString();
|
|
904
|
+
const userId = getUniqueString();
|
|
905
|
+
const ipv6NumericIp = 55878094658432211238406371356040233102n;
|
|
906
|
+
const accessRule = {
|
|
907
|
+
type: AccessPolicyType.Block,
|
|
908
|
+
clientId: clientId,
|
|
909
|
+
userId: userId,
|
|
910
|
+
numericIp: ipv6NumericIp,
|
|
911
|
+
};
|
|
912
|
+
await insertRules([accessRule]);
|
|
913
|
+
const foundAccessRules = await accessRulesReader.findRules({
|
|
914
|
+
policyScope: { clientId: clientId },
|
|
915
|
+
policyScopeMatch: FilterScopeMatch.Exact,
|
|
916
|
+
userScope: { userId: userId, numericIp: ipv6NumericIp },
|
|
917
|
+
userScopeMatch: FilterScopeMatch.Greedy,
|
|
918
|
+
}, true);
|
|
919
|
+
expect(foundAccessRules).toEqual([accessRule]);
|
|
920
|
+
expect(foundAccessRules[0]?.numericIp).toBe(ipv6NumericIp);
|
|
921
|
+
});
|
|
922
|
+
test("findRulesRanked preserves rank order over multiple candidates", async () => {
|
|
923
|
+
const clientId = getUniqueString();
|
|
924
|
+
const userId = getUniqueString();
|
|
925
|
+
const ja4 = `t13d1313h2_${getUniqueString()}`;
|
|
926
|
+
const moreSpecificRule = {
|
|
927
|
+
type: AccessPolicyType.Restrict,
|
|
928
|
+
clientId: clientId,
|
|
929
|
+
userId: userId,
|
|
930
|
+
ja4Hash: ja4,
|
|
931
|
+
countryCode: "GB",
|
|
932
|
+
};
|
|
933
|
+
const lessSpecificRule = {
|
|
934
|
+
type: AccessPolicyType.Restrict,
|
|
935
|
+
clientId: clientId,
|
|
936
|
+
ja4Hash: ja4,
|
|
937
|
+
};
|
|
938
|
+
await insertRules([lessSpecificRule, moreSpecificRule]);
|
|
939
|
+
const foundAccessRules = await accessRulesReader.findRules({
|
|
940
|
+
policyScope: { clientId: clientId },
|
|
941
|
+
policyScopeMatch: FilterScopeMatch.Exact,
|
|
942
|
+
userScope: {
|
|
943
|
+
userId: userId,
|
|
944
|
+
ja4Hash: ja4,
|
|
945
|
+
countryCode: "GB",
|
|
946
|
+
},
|
|
947
|
+
userScopeMatch: FilterScopeMatch.Greedy,
|
|
948
|
+
}, true);
|
|
949
|
+
expect(foundAccessRules).toHaveLength(2);
|
|
950
|
+
expect(foundAccessRules[0]).toEqual(moreSpecificRule);
|
|
951
|
+
expect(foundAccessRules[1]).toEqual(lessSpecificRule);
|
|
952
|
+
});
|
|
953
|
+
test("findRulesRanked ranks Block over Restrict at equal specificity", async () => {
|
|
954
|
+
const clientId = getUniqueString();
|
|
955
|
+
const userId = getUniqueString();
|
|
956
|
+
const blockRule = {
|
|
957
|
+
type: AccessPolicyType.Block,
|
|
958
|
+
clientId: clientId,
|
|
959
|
+
userId: userId,
|
|
960
|
+
};
|
|
961
|
+
const restrictRule = {
|
|
962
|
+
type: AccessPolicyType.Restrict,
|
|
963
|
+
clientId: clientId,
|
|
964
|
+
userId: userId,
|
|
965
|
+
description: "tiebreaker-restrict",
|
|
966
|
+
};
|
|
967
|
+
await insertRules([restrictRule, blockRule]);
|
|
968
|
+
const foundAccessRules = await accessRulesReader.findRules({
|
|
969
|
+
policyScope: { clientId: clientId },
|
|
970
|
+
policyScopeMatch: FilterScopeMatch.Exact,
|
|
971
|
+
userScope: { userId: userId },
|
|
972
|
+
userScopeMatch: FilterScopeMatch.Greedy,
|
|
973
|
+
}, true);
|
|
974
|
+
expect(foundAccessRules).toHaveLength(2);
|
|
975
|
+
expect(foundAccessRules[0]?.type).toBe(AccessPolicyType.Block);
|
|
976
|
+
expect(foundAccessRules[1]?.type).toBe(AccessPolicyType.Restrict);
|
|
977
|
+
});
|
|
978
|
+
test("findRulesRanked: keys DEL'd between aggregate and HGETALL drop out without reordering survivors", async () => {
|
|
979
|
+
const clientId = getUniqueString();
|
|
980
|
+
const userId = getUniqueString();
|
|
981
|
+
const topRule = {
|
|
982
|
+
type: AccessPolicyType.Block,
|
|
983
|
+
clientId: clientId,
|
|
984
|
+
userId: userId,
|
|
985
|
+
ja4Hash: "t13d_top",
|
|
986
|
+
countryCode: "GB",
|
|
987
|
+
};
|
|
988
|
+
const middleRule = {
|
|
989
|
+
type: AccessPolicyType.Restrict,
|
|
990
|
+
clientId: clientId,
|
|
991
|
+
userId: userId,
|
|
992
|
+
ja4Hash: "t13d_mid",
|
|
993
|
+
};
|
|
994
|
+
const bottomRule = {
|
|
995
|
+
type: AccessPolicyType.Restrict,
|
|
996
|
+
clientId: clientId,
|
|
997
|
+
userId: userId,
|
|
998
|
+
};
|
|
999
|
+
await insertRules([topRule, middleRule, bottomRule]);
|
|
1000
|
+
const middleKey = getAccessRuleRedisKey(middleRule);
|
|
1001
|
+
await redisClient.del(middleKey);
|
|
1002
|
+
const foundAccessRules = await accessRulesReader.findRules({
|
|
1003
|
+
policyScope: { clientId: clientId },
|
|
1004
|
+
policyScopeMatch: FilterScopeMatch.Exact,
|
|
1005
|
+
userScope: {
|
|
1006
|
+
userId: userId,
|
|
1007
|
+
ja4Hash: "t13d_top",
|
|
1008
|
+
countryCode: "GB",
|
|
1009
|
+
},
|
|
1010
|
+
userScopeMatch: FilterScopeMatch.Greedy,
|
|
1011
|
+
}, true);
|
|
1012
|
+
expect(foundAccessRules).toHaveLength(2);
|
|
1013
|
+
expect(foundAccessRules[0]).toEqual(topRule);
|
|
1014
|
+
expect(foundAccessRules[1]).toEqual(bottomRule);
|
|
1015
|
+
});
|
|
857
1016
|
});
|
|
858
1017
|
afterAll(async () => {
|
|
859
1018
|
await redisClient.flushAll();
|