feat(federation): Add bridge support to Lysand

This commit is contained in:
Jesse Wierzbinski 2024-05-17 07:56:13 -10:00
parent a603b602e6
commit 7a591a024e
No known key found for this signature in database
3 changed files with 47 additions and 2 deletions

View file

@ -288,6 +288,16 @@ reactions = []
banners = []
avatars = []
# For bridge software, such as lysand-org/activitypub
# Bridges must be hosted separately from the main Lysand process
[federation.bridge]
enabled = false
# Only lysand-ap exists for now
software = "lysand-ap"
# WARNING: These IPs will have signature checks disabled.
# Only use the bridge software if you trust it.
allowed_ips = ["192.168.1.0/24"]
[instance]
name = "Lysand"
description = "A Lysand instance"

View file

@ -430,6 +430,17 @@ export const configValidator = z.object({
banners: z.array(zUrl).default([]),
avatars: z.array(zUrl).default([]),
}),
bridge: z
.object({
enabled: z.boolean().default(false),
software: z.enum(["lysand-ap"]).or(z.string()),
allowed_ips: z.array(z.string().trim()).default([]),
})
.default({
enabled: false,
software: "lysand-ap",
allowed_ips: [],
}),
})
.default({
blocked: [],
@ -445,6 +456,11 @@ export const configValidator = z.object({
banners: [],
avatars: [],
},
bridge: {
enabled: false,
software: "lysand-ap",
allowed_ips: [],
},
}),
instance: z
.object({

View file

@ -3,8 +3,10 @@ import { zValidator } from "@hono/zod-validator";
import { dualLogger } from "@loggers";
import { EntityValidator, SignatureValidator } from "@lysand-org/federation";
import { errorResponse, jsonResponse, response } from "@response";
import type { SocketAddress } from "bun";
import { eq } from "drizzle-orm";
import type { Hono } from "hono";
import { matches } from "ip-matching";
import { z } from "zod";
import { isValidationError } from "zod-validation-error";
import { resolveNote } from "~database/entities/Status";
@ -14,6 +16,7 @@ import {
} from "~database/entities/User";
import { db } from "~drizzle/db";
import { Notifications, Relationships } from "~drizzle/schema";
import { config } from "~packages/config-manager";
import { User } from "~packages/database-interface/user";
import { LogLevel } from "~packages/log-manager";
@ -57,11 +60,27 @@ export default (app: Hono) =>
return errorResponse("User not found", 404);
}
// @ts-expect-error IP attribute is not in types
const request_ip = context.env?.ip as
| SocketAddress
| undefined
| null;
let checkSignature = true;
if (request_ip?.address && config.federation.bridge.enabled) {
for (const ip of config.federation.bridge.allowed_ips) {
if (matches(ip, request_ip?.address)) {
checkSignature = false;
break;
}
}
}
// Verify request signature
// TODO: Check if instance is defederated
// TODO: Reverse DNS lookup with Origin header
// biome-ignore lint/correctness/noConstantCondition: Temporary
if (true) {
if (checkSignature) {
if (!signature) {
return errorResponse("Missing Signature header", 400);
}