Add resource id and cc

This commit is contained in:
Owen
2025-10-21 21:42:53 -07:00
parent d392fb371e
commit 3662d42374
4 changed files with 85 additions and 39 deletions

View File

@@ -687,7 +687,6 @@ export const requestAuditLog = pgTable(
actorId: text("actorId"), actorId: text("actorId"),
resourceId: integer("resourceId"), resourceId: integer("resourceId"),
ip: text("ip"), ip: text("ip"),
type: text("type"),
location: text("location"), location: text("location"),
userAgent: text("userAgent"), userAgent: text("userAgent"),
metadata: text("details"), metadata: text("details"),

View File

@@ -732,7 +732,6 @@ export const requestAuditLog = sqliteTable(
actorId: text("actorId"), actorId: text("actorId"),
resourceId: integer("resourceId"), resourceId: integer("resourceId"),
ip: text("ip"), ip: text("ip"),
type: text("type"),
location: text("location"), location: text("location"),
userAgent: text("userAgent"), userAgent: text("userAgent"),
metadata: text("details"), metadata: text("details"),

View File

@@ -26,11 +26,10 @@ export async function logRequestAudit(
data: { data: {
action: boolean; action: boolean;
reason: number; reason: number;
resourceId?: number;
user?: { username: string; userId: string; orgId: string }; user?: { username: string; userId: string; orgId: string };
apiKey?: { name: string; apiKeyId: string; orgId: string }; apiKey?: { name: string; apiKeyId: string; orgId: string };
metadata?: any; metadata?: any;
resouceId?: number;
type?: string;
location?: string; location?: string;
// userAgent?: string; // userAgent?: string;
}, },
@@ -41,10 +40,10 @@ export async function logRequestAudit(
host: string; host: string;
method: string; method: string;
tls: boolean; tls: boolean;
sessions?: Record<string, string> | undefined; sessions?: Record<string, string>;
headers?: Record<string, string> | undefined; headers?: Record<string, string>;
query?: Record<string, string> | undefined; query?: Record<string, string>;
requestIp?: string | undefined; requestIp?: string;
} }
) { ) {
try { try {
@@ -93,8 +92,7 @@ export async function logRequestAudit(
actorId, actorId,
metadata, metadata,
action: data.action, action: data.action,
resourceId: data.resouceId, resourceId: data.resourceId,
type: data.type,
reason: data.reason, reason: data.reason,
location: data.location, location: data.location,
// userAgent: data.userAgent, // TODO: add this // userAgent: data.userAgent, // TODO: add this

View File

@@ -128,6 +128,10 @@ export async function verifyResourceSession(
logger.debug("Client IP:", { clientIp }); logger.debug("Client IP:", { clientIp });
const ipCC = clientIp
? await getCountryCodeFromIp(clientIp)
: undefined;
let cleanHost = host; let cleanHost = host;
// if the host ends with :port, strip it // if the host ends with :port, strip it
if (cleanHost.match(/:[0-9]{1,5}$/)) { if (cleanHost.match(/:[0-9]{1,5}$/)) {
@@ -154,7 +158,8 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 201 //resource not found reason: 201, //resource not found
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -174,7 +179,8 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 201 //resource not found reason: 201, //resource not found
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -190,7 +196,8 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 202 //resource blocked reason: 202, //resource blocked
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -203,7 +210,8 @@ export async function verifyResourceSession(
const action = await checkRules( const action = await checkRules(
resource.resourceId, resource.resourceId,
clientIp, clientIp,
path path,
ipCC
); );
if (action == "ACCEPT") { if (action == "ACCEPT") {
@@ -212,7 +220,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 100 // allowed by rule reason: 100, // allowed by rule
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -225,7 +235,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 203 // dropped by rules reason: 203, // dropped by rules
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -254,7 +266,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 101 // allowed no auth reason: 101, // allowed no auth
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -313,7 +327,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 102 // valid access token reason: 102, // valid access token
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -357,7 +373,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 102 // valid access token reason: 102, // valid access token
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -377,7 +395,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 103 // valid header auth reason: 103, // valid header auth
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -395,7 +415,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 103 // valid header auth reason: 103, // valid header auth
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -413,7 +435,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 299 // no more auth methods reason: 299, // no more auth methods
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -431,7 +455,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 299 // no more auth methods reason: 299, // no more auth methods
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -452,7 +478,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 204 // no sessions reason: 204, // no sessions
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -494,7 +522,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 205 // temporary request token reason: 205, // temporary request token
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -511,7 +541,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 104 // valid pincode reason: 104, // valid pincode
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -527,7 +559,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 105 // valid password reason: 105, // valid password
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -546,7 +580,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 106 // valid email reason: 106, // valid email
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -562,7 +598,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 102 // valid access token reason: 102, // valid access token
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -598,7 +636,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
reason: 107 // valid sso reason: 107, // valid sso
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -624,7 +664,9 @@ export async function verifyResourceSession(
logRequestAudit( logRequestAudit(
{ {
action: false, action: false,
reason: 299 // no more auth methods reason: 299, // no more auth methods
resourceId: resource.resourceId,
location: ipCC
}, },
parsedBody.data parsedBody.data
); );
@@ -799,7 +841,8 @@ async function isUserAllowedToAccessResource(
async function checkRules( async function checkRules(
resourceId: number, resourceId: number,
clientIp: string | undefined, clientIp: string | undefined,
path: string | undefined path: string | undefined,
ipCC?: string
): Promise<"ACCEPT" | "DROP" | "PASS" | undefined> { ): Promise<"ACCEPT" | "DROP" | "PASS" | undefined> {
const ruleCacheKey = `rules:${resourceId}`; const ruleCacheKey = `rules:${resourceId}`;
@@ -838,9 +881,9 @@ async function checkRules(
) { ) {
return rule.action as any; return rule.action as any;
} else if ( } else if (
clientIp && ipCC &&
rule.match == "GEOIP" && rule.match == "GEOIP" &&
(await isIpInGeoIP(clientIp, rule.value)) (await isIpInGeoIP(ipCC, rule.value))
) { ) {
return rule.action as any; return rule.action as any;
} }
@@ -968,11 +1011,20 @@ export function isPathAllowed(pattern: string, path: string): boolean {
return result; return result;
} }
async function isIpInGeoIP(ip: string, countryCode: string): Promise<boolean> { async function isIpInGeoIP(
if (countryCode == "ALL") { ipCountryCode: string,
checkCountryCode: string
): Promise<boolean> {
if (checkCountryCode == "ALL") {
return true; return true;
} }
logger.debug(`IP ${ipCountryCode} is in country: ${checkCountryCode}`);
return ipCountryCode?.toUpperCase() === checkCountryCode.toUpperCase();
}
async function getCountryCodeFromIp(ip: string): Promise<string | undefined> {
const geoIpCacheKey = `geoip:${ip}`; const geoIpCacheKey = `geoip:${ip}`;
let cachedCountryCode: string | undefined = cache.get(geoIpCacheKey); let cachedCountryCode: string | undefined = cache.get(geoIpCacheKey);
@@ -983,9 +1035,7 @@ async function isIpInGeoIP(ip: string, countryCode: string): Promise<boolean> {
cache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes cache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes
} }
logger.debug(`IP ${ip} is in country: ${cachedCountryCode}`); return cachedCountryCode;
return cachedCountryCode?.toUpperCase() === countryCode.toUpperCase();
} }
function extractBasicAuth( function extractBasicAuth(