mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-09 12:16:36 +00:00
fix request ip port strip issue with badger >=1.3.0
This commit is contained in:
@@ -13,7 +13,8 @@ import {
|
|||||||
LoginPage,
|
LoginPage,
|
||||||
Org,
|
Org,
|
||||||
Resource,
|
Resource,
|
||||||
ResourceHeaderAuth, ResourceHeaderAuthExtendedCompatibility,
|
ResourceHeaderAuth,
|
||||||
|
ResourceHeaderAuthExtendedCompatibility,
|
||||||
ResourcePassword,
|
ResourcePassword,
|
||||||
ResourcePincode,
|
ResourcePincode,
|
||||||
ResourceRule,
|
ResourceRule,
|
||||||
@@ -39,6 +40,8 @@ import {
|
|||||||
} from "#dynamic/lib/checkOrgAccessPolicy";
|
} from "#dynamic/lib/checkOrgAccessPolicy";
|
||||||
import { logRequestAudit } from "./logRequestAudit";
|
import { logRequestAudit } from "./logRequestAudit";
|
||||||
import cache from "@server/lib/cache";
|
import cache from "@server/lib/cache";
|
||||||
|
import semver from "semver";
|
||||||
|
import { APP_VERSION } from "@server/lib/consts";
|
||||||
|
|
||||||
const verifyResourceSessionSchema = z.object({
|
const verifyResourceSessionSchema = z.object({
|
||||||
sessions: z.record(z.string(), z.string()).optional(),
|
sessions: z.record(z.string(), z.string()).optional(),
|
||||||
@@ -50,7 +53,8 @@ const verifyResourceSessionSchema = z.object({
|
|||||||
path: z.string(),
|
path: z.string(),
|
||||||
method: z.string(),
|
method: z.string(),
|
||||||
tls: z.boolean(),
|
tls: z.boolean(),
|
||||||
requestIp: z.string().optional()
|
requestIp: z.string().optional(),
|
||||||
|
badgerVersion: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type VerifyResourceSessionSchema = z.infer<
|
export type VerifyResourceSessionSchema = z.infer<
|
||||||
@@ -69,6 +73,7 @@ export type VerifyUserResponse = {
|
|||||||
headerAuthChallenged?: boolean;
|
headerAuthChallenged?: boolean;
|
||||||
redirectUrl?: string;
|
redirectUrl?: string;
|
||||||
userData?: BasicUserData;
|
userData?: BasicUserData;
|
||||||
|
pangolinVersion?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function verifyResourceSession(
|
export async function verifyResourceSession(
|
||||||
@@ -97,7 +102,8 @@ export async function verifyResourceSession(
|
|||||||
requestIp,
|
requestIp,
|
||||||
path,
|
path,
|
||||||
headers,
|
headers,
|
||||||
query
|
query,
|
||||||
|
badgerVersion
|
||||||
} = parsedBody.data;
|
} = parsedBody.data;
|
||||||
|
|
||||||
// Extract HTTP Basic Auth credentials if present
|
// Extract HTTP Basic Auth credentials if present
|
||||||
@@ -105,7 +111,15 @@ export async function verifyResourceSession(
|
|||||||
|
|
||||||
const clientIp = requestIp
|
const clientIp = requestIp
|
||||||
? (() => {
|
? (() => {
|
||||||
logger.debug("Request IP:", { requestIp });
|
const isNewerBadger =
|
||||||
|
badgerVersion &&
|
||||||
|
semver.valid(badgerVersion) &&
|
||||||
|
semver.gte(badgerVersion, "1.3.1");
|
||||||
|
|
||||||
|
if (isNewerBadger) {
|
||||||
|
return requestIp;
|
||||||
|
}
|
||||||
|
|
||||||
if (requestIp.startsWith("[") && requestIp.includes("]")) {
|
if (requestIp.startsWith("[") && requestIp.includes("]")) {
|
||||||
// if brackets are found, extract the IPv6 address from between the brackets
|
// if brackets are found, extract the IPv6 address from between the brackets
|
||||||
const ipv6Match = requestIp.match(/\[(.*?)\]/);
|
const ipv6Match = requestIp.match(/\[(.*?)\]/);
|
||||||
@@ -114,12 +128,17 @@ export async function verifyResourceSession(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ivp4
|
// Check if it looks like IPv4 (contains dots and matches IPv4 pattern)
|
||||||
// split at last colon
|
// IPv4 format: x.x.x.x where x is 0-255
|
||||||
const lastColonIndex = requestIp.lastIndexOf(":");
|
const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}/;
|
||||||
if (lastColonIndex !== -1) {
|
if (ipv4Pattern.test(requestIp)) {
|
||||||
return requestIp.substring(0, lastColonIndex);
|
const lastColonIndex = requestIp.lastIndexOf(":");
|
||||||
|
if (lastColonIndex !== -1) {
|
||||||
|
return requestIp.substring(0, lastColonIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return as is
|
||||||
return requestIp;
|
return requestIp;
|
||||||
})()
|
})()
|
||||||
: undefined;
|
: undefined;
|
||||||
@@ -130,9 +149,7 @@ export async function verifyResourceSession(
|
|||||||
? await getCountryCodeFromIp(clientIp)
|
? await getCountryCodeFromIp(clientIp)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const ipAsn = clientIp
|
const ipAsn = clientIp ? await getAsnFromIp(clientIp) : undefined;
|
||||||
? await getAsnFromIp(clientIp)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
let cleanHost = host;
|
let cleanHost = host;
|
||||||
// if the host ends with :port, strip it
|
// if the host ends with :port, strip it
|
||||||
@@ -178,7 +195,13 @@ export async function verifyResourceSession(
|
|||||||
cache.set(resourceCacheKey, resourceData, 5);
|
cache.set(resourceCacheKey, resourceData, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { resource, pincode, password, headerAuth, headerAuthExtendedCompatibility } = resourceData;
|
const {
|
||||||
|
resource,
|
||||||
|
pincode,
|
||||||
|
password,
|
||||||
|
headerAuth,
|
||||||
|
headerAuthExtendedCompatibility
|
||||||
|
} = resourceData;
|
||||||
|
|
||||||
if (!resource) {
|
if (!resource) {
|
||||||
logger.debug(`Resource not found ${cleanHost}`);
|
logger.debug(`Resource not found ${cleanHost}`);
|
||||||
@@ -474,8 +497,7 @@ export async function verifyResourceSession(
|
|||||||
|
|
||||||
return notAllowed(res);
|
return notAllowed(res);
|
||||||
}
|
}
|
||||||
}
|
} else if (headerAuth) {
|
||||||
else if (headerAuth) {
|
|
||||||
// if there are no other auth methods we need to return unauthorized if nothing is provided
|
// if there are no other auth methods we need to return unauthorized if nothing is provided
|
||||||
if (
|
if (
|
||||||
!sso &&
|
!sso &&
|
||||||
@@ -713,7 +735,11 @@ export async function verifyResourceSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If headerAuthExtendedCompatibility is activated but no clientHeaderAuth provided, force client to challenge
|
// If headerAuthExtendedCompatibility is activated but no clientHeaderAuth provided, force client to challenge
|
||||||
if (headerAuthExtendedCompatibility && headerAuthExtendedCompatibility.extendedCompatibilityIsActivated && !clientHeaderAuth){
|
if (
|
||||||
|
headerAuthExtendedCompatibility &&
|
||||||
|
headerAuthExtendedCompatibility.extendedCompatibilityIsActivated &&
|
||||||
|
!clientHeaderAuth
|
||||||
|
) {
|
||||||
return headerAuthChallenged(res, redirectPath, resource.orgId);
|
return headerAuthChallenged(res, redirectPath, resource.orgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -825,7 +851,7 @@ async function notAllowed(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
data: { valid: false, redirectUrl },
|
data: { valid: false, redirectUrl, pangolinVersion: APP_VERSION },
|
||||||
success: true,
|
success: true,
|
||||||
error: false,
|
error: false,
|
||||||
message: "Access denied",
|
message: "Access denied",
|
||||||
@@ -839,8 +865,8 @@ function allowed(res: Response, userData?: BasicUserData) {
|
|||||||
const data = {
|
const data = {
|
||||||
data:
|
data:
|
||||||
userData !== undefined && userData !== null
|
userData !== undefined && userData !== null
|
||||||
? { valid: true, ...userData }
|
? { valid: true, ...userData, pangolinVersion: APP_VERSION }
|
||||||
: { valid: true },
|
: { valid: true, pangolinVersion: APP_VERSION },
|
||||||
success: true,
|
success: true,
|
||||||
error: false,
|
error: false,
|
||||||
message: "Access allowed",
|
message: "Access allowed",
|
||||||
@@ -879,7 +905,12 @@ async function headerAuthChallenged(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
data: { headerAuthChallenged: true, valid: false, redirectUrl },
|
data: {
|
||||||
|
headerAuthChallenged: true,
|
||||||
|
valid: false,
|
||||||
|
redirectUrl,
|
||||||
|
pangolinVersion: APP_VERSION
|
||||||
|
},
|
||||||
success: true,
|
success: true,
|
||||||
error: false,
|
error: false,
|
||||||
message: "Access denied",
|
message: "Access denied",
|
||||||
|
|||||||
Reference in New Issue
Block a user