mirror of
https://github.com/fosrl/pangolin.git
synced 2025-07-28 22:55:07 +02:00
Get new api endpoints working
This commit is contained in:
parent
6e1bfdac58
commit
b1f4971f25
13 changed files with 79 additions and 51 deletions
|
@ -35,7 +35,8 @@ gerbil:
|
||||||
wg_site:
|
wg_site:
|
||||||
start_port: 51820
|
start_port: 51820
|
||||||
block_size: 24
|
block_size: 24
|
||||||
subnet_group: 100.89.137.0/20
|
subnet_group: 100.89.138.0/20
|
||||||
|
site_block_size: 30
|
||||||
|
|
||||||
rate_limits:
|
rate_limits:
|
||||||
global:
|
global:
|
||||||
|
|
|
@ -173,7 +173,7 @@ export const olmSessions = sqliteTable("clientSession", {
|
||||||
sessionId: text("id").primaryKey(),
|
sessionId: text("id").primaryKey(),
|
||||||
olmId: text("olmId")
|
olmId: text("olmId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => newts.newtId, { onDelete: "cascade" }),
|
.references(() => olms.olmId, { onDelete: "cascade" }),
|
||||||
expiresAt: integer("expiresAt").notNull()
|
expiresAt: integer("expiresAt").notNull()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,8 @@ const configSchema = z.object({
|
||||||
wg_site: z.object({
|
wg_site: z.object({
|
||||||
block_size: z.number().positive().gt(0),
|
block_size: z.number().positive().gt(0),
|
||||||
subnet_group: z.string(),
|
subnet_group: z.string(),
|
||||||
start_port: portSchema
|
start_port: portSchema,
|
||||||
|
site_block_size: z.number().positive().gt(0)
|
||||||
}),
|
}),
|
||||||
rate_limits: z.object({
|
rate_limits: z.object({
|
||||||
global: z.object({
|
global: z.object({
|
||||||
|
|
|
@ -37,10 +37,10 @@ const createClientSchema = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().min(1).max(255),
|
name: z.string().min(1).max(255),
|
||||||
siteId: z.number().int().positive(),
|
siteId: z.number().int().positive(),
|
||||||
pubKey: z.string(),
|
pubKey: z.string().optional(),
|
||||||
subnet: z.string(),
|
subnet: z.string().optional(),
|
||||||
olmId: z.string(),
|
olmId: z.string().optional(),
|
||||||
secret: z.string(),
|
secret: z.string().optional(),
|
||||||
type: z.enum(["olm"])
|
type: z.enum(["olm"])
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { fromError } from "zod-validation-error";
|
||||||
|
|
||||||
const getSiteSchema = z
|
const getSiteSchema = z
|
||||||
.object({
|
.object({
|
||||||
siteId: z.number().int().positive()
|
siteId: z.string().transform(Number).pipe(z.number())
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
|
@ -92,12 +92,16 @@ export async function pickClientDefaults(
|
||||||
subnets.push(
|
subnets.push(
|
||||||
address.replace(
|
address.replace(
|
||||||
/\/\d+$/,
|
/\/\d+$/,
|
||||||
`/${config.getRawConfig().wg_site.block_size}`
|
`/${config.getRawConfig().wg_site.site_block_size}`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
logger.debug(`Subnets: ${subnets}`);
|
||||||
|
logger.debug(`Address: ${address}`);
|
||||||
|
logger.debug(`Block size: ${config.getRawConfig().wg_site.block_size}`);
|
||||||
|
logger.debug(`Site block size: ${config.getRawConfig().wg_site.site_block_size}`);
|
||||||
const newSubnet = findNextAvailableCidr(
|
const newSubnet = findNextAvailableCidr(
|
||||||
subnets,
|
subnets,
|
||||||
config.getRawConfig().wg_site.block_size,
|
config.getRawConfig().wg_site.site_block_size,
|
||||||
address
|
address
|
||||||
);
|
);
|
||||||
if (!newSubnet) {
|
if (!newSubnet) {
|
||||||
|
|
|
@ -28,7 +28,8 @@ import {
|
||||||
import { verifyUserHasAction } from "../middlewares/verifyUserHasAction";
|
import { verifyUserHasAction } from "../middlewares/verifyUserHasAction";
|
||||||
import { ActionsEnum } from "@server/auth/actions";
|
import { ActionsEnum } from "@server/auth/actions";
|
||||||
import { verifyUserIsOrgOwner } from "../middlewares/verifyUserIsOrgOwner";
|
import { verifyUserIsOrgOwner } from "../middlewares/verifyUserIsOrgOwner";
|
||||||
import { createNewt, getToken } from "./newt";
|
import { createNewt, getNewtToken } from "./newt";
|
||||||
|
import { getOlmToken } from "./olm";
|
||||||
import rateLimit from "express-rate-limit";
|
import rateLimit from "express-rate-limit";
|
||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
|
|
||||||
|
@ -501,7 +502,8 @@ authRouter.use(
|
||||||
authRouter.put("/signup", auth.signup);
|
authRouter.put("/signup", auth.signup);
|
||||||
authRouter.post("/login", auth.login);
|
authRouter.post("/login", auth.login);
|
||||||
authRouter.post("/logout", auth.logout);
|
authRouter.post("/logout", auth.logout);
|
||||||
authRouter.post("/newt/get-token", getToken);
|
authRouter.post("/newt/get-token", getNewtToken);
|
||||||
|
authRouter.post("/olm/get-token", getOlmToken);
|
||||||
|
|
||||||
authRouter.post("/2fa/enable", verifySessionUserMiddleware, auth.verifyTotp);
|
authRouter.post("/2fa/enable", verifySessionUserMiddleware, auth.verifyTotp);
|
||||||
authRouter.post(
|
authRouter.post(
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const newtGetTokenBodySchema = z.object({
|
||||||
|
|
||||||
export type NewtGetTokenBody = z.infer<typeof newtGetTokenBodySchema>;
|
export type NewtGetTokenBody = z.infer<typeof newtGetTokenBodySchema>;
|
||||||
|
|
||||||
export async function getToken(
|
export async function getNewtToken(
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
next: NextFunction
|
next: NextFunction
|
|
@ -10,8 +10,7 @@ import config from "@server/lib/config";
|
||||||
|
|
||||||
const inputSchema = z.object({
|
const inputSchema = z.object({
|
||||||
publicKey: z.string(),
|
publicKey: z.string(),
|
||||||
endpoint: z.string(),
|
endpoint: z.string()
|
||||||
listenPort: z.number()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
type Input = z.infer<typeof inputSchema>;
|
type Input = z.infer<typeof inputSchema>;
|
||||||
|
@ -20,6 +19,9 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
|
||||||
const { message, client, sendToClient } = context;
|
const { message, client, sendToClient } = context;
|
||||||
const newt = client as Newt;
|
const newt = client as Newt;
|
||||||
|
|
||||||
|
logger.debug(JSON.stringify(message.data));
|
||||||
|
|
||||||
|
|
||||||
logger.debug("Handling Newt get config message!");
|
logger.debug("Handling Newt get config message!");
|
||||||
|
|
||||||
if (!newt) {
|
if (!newt) {
|
||||||
|
@ -99,8 +101,8 @@ export const handleGetConfigMessage: MessageHandler = async (context) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const configResponse = {
|
const configResponse = {
|
||||||
listenPort: site.listenPort, // ?????
|
listenPort: site.listenPort,
|
||||||
// ipAddress: exitNode[0].address,
|
ipAddress: site.address,
|
||||||
peers
|
peers
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,12 @@ interface PeerBandwidth {
|
||||||
|
|
||||||
export const handleReceiveBandwidthMessage: MessageHandler = async (context) => {
|
export const handleReceiveBandwidthMessage: MessageHandler = async (context) => {
|
||||||
const { message, client, sendToClient } = context;
|
const { message, client, sendToClient } = context;
|
||||||
const newt = client as Newt;
|
|
||||||
|
|
||||||
const bandwidthData: PeerBandwidth[] = message.data;
|
if (!message.data.bandwidthData) {
|
||||||
|
logger.warn("No bandwidth data provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
const bandwidthData: PeerBandwidth[] = message.data.bandwidthData;
|
||||||
|
|
||||||
if (!Array.isArray(bandwidthData)) {
|
if (!Array.isArray(bandwidthData)) {
|
||||||
throw new Error("Invalid bandwidth data");
|
throw new Error("Invalid bandwidth data");
|
||||||
|
@ -63,6 +66,4 @@ export const handleReceiveBandwidthMessage: MessageHandler = async (context) =>
|
||||||
.where(eq(clients.clientId, client.clientId));
|
.where(eq(clients.clientId, client.clientId));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info("Handling register olm message!");
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export * from "./createNewt";
|
export * from "./createNewt";
|
||||||
export * from "./getToken";
|
export * from "./getNewtToken";
|
||||||
export * from "./handleNewtRegisterMessage";
|
export * from "./handleNewtRegisterMessage";
|
||||||
export* from "./handleReceiveBandwidthMessage";
|
export* from "./handleReceiveBandwidthMessage";
|
|
@ -1,6 +1,6 @@
|
||||||
import { generateSessionToken } from "@server/auth/sessions/app";
|
import { generateSessionToken } from "@server/auth/sessions/app";
|
||||||
import db from "@server/db";
|
import db from "@server/db";
|
||||||
import { newts } from "@server/db/schema";
|
import { olms } from "@server/db/schema";
|
||||||
import HttpCode from "@server/types/HttpCode";
|
import HttpCode from "@server/types/HttpCode";
|
||||||
import response from "@server/lib/response";
|
import response from "@server/lib/response";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
|
@ -9,27 +9,27 @@ import createHttpError from "http-errors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { fromError } from "zod-validation-error";
|
import { fromError } from "zod-validation-error";
|
||||||
import {
|
import {
|
||||||
createNewtSession,
|
createOlmSession,
|
||||||
validateNewtSessionToken
|
validateOlmSessionToken
|
||||||
} from "@server/auth/sessions/newt";
|
} from "@server/auth/sessions/olm";
|
||||||
import { verifyPassword } from "@server/auth/password";
|
import { verifyPassword } from "@server/auth/password";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import config from "@server/lib/config";
|
import config from "@server/lib/config";
|
||||||
|
|
||||||
export const newtGetTokenBodySchema = z.object({
|
export const olmGetTokenBodySchema = z.object({
|
||||||
newtId: z.string(),
|
olmId: z.string(),
|
||||||
secret: z.string(),
|
secret: z.string(),
|
||||||
token: z.string().optional()
|
token: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type NewtGetTokenBody = z.infer<typeof newtGetTokenBodySchema>;
|
export type OlmGetTokenBody = z.infer<typeof olmGetTokenBodySchema>;
|
||||||
|
|
||||||
export async function getToken(
|
export async function getOlmToken(
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
next: NextFunction
|
next: NextFunction
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const parsedBody = newtGetTokenBodySchema.safeParse(req.body);
|
const parsedBody = olmGetTokenBodySchema.safeParse(req.body);
|
||||||
|
|
||||||
if (!parsedBody.success) {
|
if (!parsedBody.success) {
|
||||||
return next(
|
return next(
|
||||||
|
@ -40,15 +40,15 @@ export async function getToken(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { newtId, secret, token } = parsedBody.data;
|
const { olmId, secret, token } = parsedBody.data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (token) {
|
if (token) {
|
||||||
const { session, newt } = await validateNewtSessionToken(token);
|
const { session, olm } = await validateOlmSessionToken(token);
|
||||||
if (session) {
|
if (session) {
|
||||||
if (config.getRawConfig().app.log_failed_attempts) {
|
if (config.getRawConfig().app.log_failed_attempts) {
|
||||||
logger.info(
|
logger.info(
|
||||||
`Newt session already valid. Newt ID: ${newtId}. IP: ${req.ip}.`
|
`Olm session already valid. Olm ID: ${olmId}. IP: ${req.ip}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return response<null>(res, {
|
return response<null>(res, {
|
||||||
|
@ -61,29 +61,31 @@ export async function getToken(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingNewtRes = await db
|
const existingOlmRes = await db
|
||||||
.select()
|
.select()
|
||||||
.from(newts)
|
.from(olms)
|
||||||
.where(eq(newts.newtId, newtId));
|
.where(eq(olms.olmId, olmId));
|
||||||
if (!existingNewtRes || !existingNewtRes.length) {
|
if (!existingOlmRes || !existingOlmRes.length) {
|
||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(
|
||||||
HttpCode.BAD_REQUEST,
|
HttpCode.BAD_REQUEST,
|
||||||
"No newt found with that newtId"
|
"No olm found with that olmId"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingNewt = existingNewtRes[0];
|
logger.debug("Existing olm: ", existingOlmRes);
|
||||||
|
|
||||||
|
const existingOlm = existingOlmRes[0];
|
||||||
|
|
||||||
const validSecret = await verifyPassword(
|
const validSecret = await verifyPassword(
|
||||||
secret,
|
secret,
|
||||||
existingNewt.secretHash
|
existingOlm.secretHash
|
||||||
);
|
);
|
||||||
if (!validSecret) {
|
if (!validSecret) {
|
||||||
if (config.getRawConfig().app.log_failed_attempts) {
|
if (config.getRawConfig().app.log_failed_attempts) {
|
||||||
logger.info(
|
logger.info(
|
||||||
`Newt id or secret is incorrect. Newt: ID ${newtId}. IP: ${req.ip}.`
|
`Olm id or secret is incorrect. Olm: ID ${olmId}. IP: ${req.ip}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return next(
|
return next(
|
||||||
|
@ -91,8 +93,12 @@ export async function getToken(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.debug("Creating new olm session token");
|
||||||
|
|
||||||
const resToken = generateSessionToken();
|
const resToken = generateSessionToken();
|
||||||
await createNewtSession(resToken, existingNewt.newtId);
|
await createOlmSession(resToken, existingOlm.olmId);
|
||||||
|
|
||||||
|
logger.debug("Token created successfully");
|
||||||
|
|
||||||
return response<{ token: string }>(res, {
|
return response<{ token: string }>(res, {
|
||||||
data: {
|
data: {
|
||||||
|
@ -103,12 +109,12 @@ export async function getToken(
|
||||||
message: "Token created successfully",
|
message: "Token created successfully",
|
||||||
status: HttpCode.OK
|
status: HttpCode.OK
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
console.error(e);
|
logger.error(error);
|
||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(
|
||||||
HttpCode.INTERNAL_SERVER_ERROR,
|
HttpCode.INTERNAL_SERVER_ERROR,
|
||||||
"Failed to authenticate newt"
|
"Failed to authenticate olm"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -1 +1,3 @@
|
||||||
export * from "./handleOlmRegisterMessage";
|
export * from "./handleOlmRegisterMessage";
|
||||||
|
export * from "./getOlmToken";
|
||||||
|
export * from "./createOlm";
|
|
@ -45,7 +45,7 @@ export async function pickSiteDefaults(
|
||||||
// list all of the sites on that exit node
|
// list all of the sites on that exit node
|
||||||
const sitesQuery = await db
|
const sitesQuery = await db
|
||||||
.select({
|
.select({
|
||||||
subnet: sites.subnet,
|
subnet: sites.subnet
|
||||||
})
|
})
|
||||||
.from(sites)
|
.from(sites)
|
||||||
.where(eq(sites.exitNodeId, exitNode.exitNodeId));
|
.where(eq(sites.exitNodeId, exitNode.exitNodeId));
|
||||||
|
@ -53,8 +53,17 @@ export async function pickSiteDefaults(
|
||||||
// TODO: we need to lock this subnet for some time so someone else does not take it
|
// TODO: we need to lock this subnet for some time so someone else does not take it
|
||||||
let subnets = sitesQuery.map((site) => site.subnet);
|
let subnets = sitesQuery.map((site) => site.subnet);
|
||||||
// exclude the exit node address by replacing after the / with a site block size
|
// exclude the exit node address by replacing after the / with a site block size
|
||||||
subnets.push(exitNode.address.replace(/\/\d+$/, `/${config.getRawConfig().gerbil.site_block_size}`));
|
subnets.push(
|
||||||
const newSubnet = findNextAvailableCidr(subnets, config.getRawConfig().gerbil.site_block_size, exitNode.address);
|
exitNode.address.replace(
|
||||||
|
/\/\d+$/,
|
||||||
|
`/${config.getRawConfig().gerbil.site_block_size}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const newSubnet = findNextAvailableCidr(
|
||||||
|
subnets,
|
||||||
|
config.getRawConfig().gerbil.site_block_size,
|
||||||
|
exitNode.address
|
||||||
|
);
|
||||||
if (!newSubnet) {
|
if (!newSubnet) {
|
||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(
|
||||||
|
@ -77,12 +86,12 @@ export async function pickSiteDefaults(
|
||||||
endpoint: exitNode.endpoint,
|
endpoint: exitNode.endpoint,
|
||||||
subnet: newSubnet,
|
subnet: newSubnet,
|
||||||
newtId,
|
newtId,
|
||||||
newtSecret: secret,
|
newtSecret: secret
|
||||||
},
|
},
|
||||||
success: true,
|
success: true,
|
||||||
error: false,
|
error: false,
|
||||||
message: "Organization retrieved successfully",
|
message: "Organization retrieved successfully",
|
||||||
status: HttpCode.OK,
|
status: HttpCode.OK
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue