Working on remote nodes

This commit is contained in:
Owen
2025-12-22 21:53:57 -05:00
parent 5c67a1cb12
commit ab3be26790
7 changed files with 89 additions and 14 deletions

View File

@@ -23,10 +23,10 @@ import {
} from "@server/lib/checkOrgAccessPolicy";
import { UserType } from "@server/types/UserTypes";
export async function enforceResourceSessionLength(
export function enforceResourceSessionLength(
resourceSession: ResourceSession,
org: Org
): Promise<{ valid: boolean; error?: string }> {
): { valid: boolean; error?: string } {
if (org.maxSessionLengthHours) {
const sessionIssuedAt = resourceSession.issuedAt; // may be null
const maxSessionLengthHours = org.maxSessionLengthHours;

View File

@@ -71,7 +71,8 @@ export async function getTraefikConfig(
siteTypes: string[],
filterOutNamespaceDomains = false,
generateLoginPageRouters = false,
allowRawResources = true
allowRawResources = true,
allowMaintenancePage = true
): Promise<any> {
// Get resources with their targets and sites in a single optimized query
// Start from sites on this exit node, then join to targets and resources

View File

@@ -39,7 +39,8 @@ import {
resourceHeaderAuthExtendedCompatibility,
ResourceHeaderAuthExtendedCompatibility,
orgs,
requestAuditLog
requestAuditLog,
Org
} from "@server/db";
import {
resources,
@@ -79,6 +80,7 @@ import { maxmindLookup } from "@server/db/maxmind";
import { verifyResourceAccessToken } from "@server/auth/verifyResourceAccessToken";
import semver from "semver";
import { maxmindAsnLookup } from "@server/db/maxmindAsn";
import { checkOrgAccessPolicy } from "@server/lib/checkOrgAccessPolicy";
// Zod schemas for request validation
const getResourceByDomainParamsSchema = z.strictObject({
@@ -94,6 +96,12 @@ const getUserOrgRoleParamsSchema = z.strictObject({
orgId: z.string().min(1, "Organization ID is required")
});
const getUserOrgSessionVerifySchema = z.strictObject({
userId: z.string().min(1, "User ID is required"),
orgId: z.string().min(1, "Organization ID is required"),
sessionId: z.string().min(1, "Session ID is required")
});
const getRoleResourceAccessParamsSchema = z.strictObject({
roleId: z
.string()
@@ -178,6 +186,7 @@ export type ResourceWithAuth = {
password: ResourcePassword | null;
headerAuth: ResourceHeaderAuth | null;
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
org: Org
};
export type UserSessionWithUser = {
@@ -508,6 +517,7 @@ hybridRouter.get(
resources.resourceId
)
)
.innerJoin(orgs, eq(orgs.orgId, resources.orgId))
.where(eq(resources.fullDomain, domain))
.limit(1);
@@ -542,7 +552,8 @@ hybridRouter.get(
password: result.resourcePassword,
headerAuth: result.resourceHeaderAuth,
headerAuthExtendedCompatibility:
result.resourceHeaderAuthExtendedCompatibility
result.resourceHeaderAuthExtendedCompatibility,
org: result.orgs
};
return response<ResourceWithAuth>(res, {
@@ -822,6 +833,69 @@ hybridRouter.get(
}
);
// Get user organization role
hybridRouter.get(
"/user/:userId/org/:orgId/session/:sessionId/verify",
async (req: Request, res: Response, next: NextFunction) => {
try {
const parsedParams = getUserOrgSessionVerifySchema.safeParse(
req.params
);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString()
)
);
}
const { userId, orgId, sessionId } = parsedParams.data;
const remoteExitNode = req.remoteExitNode;
if (!remoteExitNode || !remoteExitNode.exitNodeId) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Remote exit node not found"
)
);
}
if (await checkExitNodeOrg(remoteExitNode.exitNodeId, orgId)) {
return next(
createHttpError(
HttpCode.UNAUTHORIZED,
"User is not authorized to access this organization"
)
);
}
const accessPolicy = await checkOrgAccessPolicy({
orgId,
userId,
sessionId
});
return response(res, {
data: accessPolicy,
success: true,
error: false,
message: "User org access policy retrieved successfully",
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to get user org role"
)
);
}
}
);
// Check if role has access to resource
hybridRouter.get(
"/role/:roleId/resource/:resourceId/access",