Adjust rule processing

This commit is contained in:
Owen 2025-02-09 10:50:43 -05:00
parent 42434ca832
commit 874c67345e
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD

View file

@ -151,12 +151,22 @@ export async function verifyResourceSession(
} }
// check the rules // check the rules
if ( if (resource.applyRules) {
resource.applyRules && const action = await checkRules(
(await checkRules(resource.resourceId, clientIp, path)) resource.resourceId,
) { clientIp,
logger.debug("Resource allowed because rules are satisfied"); path
return allowed(res); );
if (action == "ACCEPT") {
logger.debug("Resource allowed by rule");
return allowed(res);
} else if (action == "DROP") {
logger.debug("Resource denied by rule");
return notAllowed(res);
}
// otherwise its undefined and we pass
} }
const redirectUrl = `${config.getRawConfig().app.dashboard_url}/auth/resource/${encodeURIComponent(resource.resourceId)}?redirect=${encodeURIComponent(originalRequestURL)}`; const redirectUrl = `${config.getRawConfig().app.dashboard_url}/auth/resource/${encodeURIComponent(resource.resourceId)}?redirect=${encodeURIComponent(originalRequestURL)}`;
@ -456,7 +466,7 @@ async function checkRules(
resourceId: number, resourceId: number,
clientIp: string | undefined, clientIp: string | undefined,
path: string | undefined path: string | undefined
): Promise<boolean> { ): Promise<"ACCEPT" | "DROP" | undefined> {
const ruleCacheKey = `rules:${resourceId}`; const ruleCacheKey = `rules:${resourceId}`;
let rules: ResourceRule[] | undefined = cache.get(ruleCacheKey); let rules: ResourceRule[] | undefined = cache.get(ruleCacheKey);
@ -472,36 +482,40 @@ async function checkRules(
if (rules.length === 0) { if (rules.length === 0) {
logger.debug("No rules found for resource", resourceId); logger.debug("No rules found for resource", resourceId);
return false; return;
} }
for (const rule of rules) { for (const rule of rules) {
if (clientIp && rule.match == "IP" && isIpInCidr(clientIp, rule.value)) { if (
return rule.action == "ACCEPT"; clientIp &&
rule.match == "IP" &&
isIpInCidr(clientIp, rule.value)
) {
return rule.action as "ACCEPT" | "DROP";
} else if (path && rule.match == "PATH") { } else if (path && rule.match == "PATH") {
// rule.value is a regex, match on the path and see if it matches // rule.value is a regex, match on the path and see if it matches
const re = urlGlobToRegex(rule.value); const re = urlGlobToRegex(rule.value);
if (re.test(path)) { if (re.test(path)) {
return rule.action == "ACCEPT"; return rule.action as "ACCEPT" | "DROP";
} }
} }
} }
return false; return;
} }
function urlGlobToRegex(pattern: string): RegExp { function urlGlobToRegex(pattern: string): RegExp {
// Remove leading slash if present (we'll add it to the regex pattern) // Remove leading slash if present (we'll add it to the regex pattern)
pattern = pattern.startsWith('/') ? pattern.slice(1) : pattern; pattern = pattern.startsWith("/") ? pattern.slice(1) : pattern;
// Escape special regex characters except * // Escape special regex characters except *
const escapedPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&'); const escapedPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
// Replace * with regex pattern for any valid URL segment characters // Replace * with regex pattern for any valid URL segment characters
const regexPattern = escapedPattern.replace(/\*/g, '[a-zA-Z0-9_-]+'); const regexPattern = escapedPattern.replace(/\*/g, "[a-zA-Z0-9_-]+");
// Create the final pattern that: // Create the final pattern that:
// 1. Optionally matches leading slash // 1. Optionally matches leading slash
// 2. Matches the entire string // 2. Matches the entire string
return new RegExp(`^/?${regexPattern}$`); return new RegExp(`^/?${regexPattern}$`);
} }