feat: implement `attachLdSignatureForRelays` to control signing of Relayed activities

This commit is contained in:
Hazel K 2024-07-25 10:37:23 -04:00
parent c344705d67
commit 32872181dd
6 changed files with 89 additions and 39 deletions

View File

@ -198,8 +198,10 @@ proxyRemoteFiles: true
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4 # https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
#videoThumbnailGenerator: https://example.com #videoThumbnailGenerator: https://example.com
# Sign to ActivityPub GET request (default: true) # Sign outgoing ActivityPub GET request (default: true)
signToActivityPubGet: true signToActivityPubGet: true
# Sign outgoing ActivityPub Activities (default: true)
attachLdSignatureForRelays: true
# check that inbound ActivityPub GET requests are signed ("authorized fetch") # check that inbound ActivityPub GET requests are signed ("authorized fetch")
checkActivityPubGetSignature: false checkActivityPubGetSignature: false

View File

@ -270,8 +270,10 @@ proxyRemoteFiles: true
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4 # https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
#videoThumbnailGenerator: https://example.com #videoThumbnailGenerator: https://example.com
# Sign to ActivityPub GET request (default: true) # Sign outgoing ActivityPub GET request (default: true)
signToActivityPubGet: true signToActivityPubGet: true
# Sign outgoing ActivityPub Activities (default: true)
attachLdSignatureForRelays: true
# check that inbound ActivityPub GET requests are signed ("authorized fetch") # check that inbound ActivityPub GET requests are signed ("authorized fetch")
checkActivityPubGetSignature: false checkActivityPubGetSignature: false

View File

@ -285,8 +285,10 @@ proxyRemoteFiles: true
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4 # https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
#videoThumbnailGenerator: https://example.com #videoThumbnailGenerator: https://example.com
# Sign to ActivityPub GET request (default: true) # Sign outgoing ActivityPub GET request (default: true)
signToActivityPubGet: true signToActivityPubGet: true
# Sign outgoing ActivityPub Activities (default: true)
attachLdSignatureForRelays: true
# check that inbound ActivityPub GET requests are signed ("authorized fetch") # check that inbound ActivityPub GET requests are signed ("authorized fetch")
checkActivityPubGetSignature: false checkActivityPubGetSignature: false

View File

@ -208,8 +208,10 @@ id: "aidx"
# Media Proxy # Media Proxy
#mediaProxy: https://example.com/proxy #mediaProxy: https://example.com/proxy
# Sign to ActivityPub GET request (default: true) # Sign outgoing ActivityPub GET request (default: true)
signToActivityPubGet: true signToActivityPubGet: true
# Sign outgoing ActivityPub Activities (default: true)
attachLdSignatureForRelays: true
# check that inbound ActivityPub GET requests are signed ("authorized fetch") # check that inbound ActivityPub GET requests are signed ("authorized fetch")
checkActivityPubGetSignature: false checkActivityPubGetSignature: false

View File

@ -95,6 +95,7 @@ type Source = {
customMOTD?: string[]; customMOTD?: string[];
signToActivityPubGet?: boolean; signToActivityPubGet?: boolean;
attachLdSignatureForRelays?: boolean;
checkActivityPubGetSignature?: boolean; checkActivityPubGetSignature?: boolean;
perChannelMaxNoteCacheCount?: number; perChannelMaxNoteCacheCount?: number;
@ -161,6 +162,7 @@ export type Config = {
proxyRemoteFiles: boolean | undefined; proxyRemoteFiles: boolean | undefined;
customMOTD: string[] | undefined; customMOTD: string[] | undefined;
signToActivityPubGet: boolean; signToActivityPubGet: boolean;
attachLdSignatureForRelays: boolean;
checkActivityPubGetSignature: boolean | undefined; checkActivityPubGetSignature: boolean | undefined;
version: string; version: string;
@ -291,6 +293,7 @@ export function loadConfig(): Config {
proxyRemoteFiles: config.proxyRemoteFiles, proxyRemoteFiles: config.proxyRemoteFiles,
customMOTD: config.customMOTD, customMOTD: config.customMOTD,
signToActivityPubGet: config.signToActivityPubGet ?? true, signToActivityPubGet: config.signToActivityPubGet ?? true,
attachLdSignatureForRelays: config.attachLdSignatureForRelays ?? true,
checkActivityPubGetSignature: config.checkActivityPubGetSignature, checkActivityPubGetSignature: config.checkActivityPubGetSignature,
mediaProxy: externalMediaProxy ?? internalMediaProxy, mediaProxy: externalMediaProxy ?? internalMediaProxy,
externalMediaProxyEnabled: externalMediaProxy !== null && externalMediaProxy !== internalMediaProxy, externalMediaProxyEnabled: externalMediaProxy !== null && externalMediaProxy !== internalMediaProxy,

View File

@ -9,7 +9,7 @@ import { In } from 'typeorm';
import * as mfm from '@transfem-org/sfm-js'; import * as mfm from '@transfem-org/sfm-js';
import {DI} from '@/di-symbols.js'; import {DI} from '@/di-symbols.js';
import type {Config} from '@/config.js'; import type {Config} from '@/config.js';
import type { MiPartialLocalUser, MiLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/User.js'; import type {MiLocalUser, MiPartialLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser} from '@/models/User.js';
import type {IMentionedRemoteUsers, MiNote} from '@/models/Note.js'; import type {IMentionedRemoteUsers, MiNote} from '@/models/Note.js';
import type {MiBlocking} from '@/models/Blocking.js'; import type {MiBlocking} from '@/models/Blocking.js';
import type {MiRelay} from '@/models/Relay.js'; import type {MiRelay} from '@/models/Relay.js';
@ -23,7 +23,14 @@ import { MfmService } from '@/core/MfmService.js';
import {UserEntityService} from '@/core/entities/UserEntityService.js'; import {UserEntityService} from '@/core/entities/UserEntityService.js';
import {DriveFileEntityService} from '@/core/entities/DriveFileEntityService.js'; import {DriveFileEntityService} from '@/core/entities/DriveFileEntityService.js';
import type {MiUserKeypair} from '@/models/UserKeypair.js'; import type {MiUserKeypair} from '@/models/UserKeypair.js';
import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository, InstancesRepository } from '@/models/_.js'; import type {
DriveFilesRepository,
InstancesRepository,
NotesRepository,
PollsRepository,
UserProfilesRepository,
UsersRepository
} from '@/models/_.js';
import {bindThis} from '@/decorators.js'; import {bindThis} from '@/decorators.js';
import {CustomEmojiService} from '@/core/CustomEmojiService.js'; import {CustomEmojiService} from '@/core/CustomEmojiService.js';
import {isNotNull} from '@/misc/is-not-null.js'; import {isNotNull} from '@/misc/is-not-null.js';
@ -32,7 +39,33 @@ import { MetaService } from '../MetaService.js';
import {JsonLdService} from './JsonLdService.js'; import {JsonLdService} from './JsonLdService.js';
import {ApMfmService} from './ApMfmService.js'; import {ApMfmService} from './ApMfmService.js';
import {CONTEXT} from './misc/contexts.js'; import {CONTEXT} from './misc/contexts.js';
import type { IAccept, IActivity, IAdd, IAnnounce, IApDocument, IApEmoji, IApHashtag, IApImage, IApMention, IBlock, ICreate, IDelete, IFlag, IFollow, IKey, ILike, IMove, IObject, IPost, IQuestion, IReject, IRemove, ITombstone, IUndo, IUpdate } from './type.js'; import type {
IAccept,
IActivity,
IAdd,
IAnnounce,
IApDocument,
IApEmoji,
IApHashtag,
IApImage,
IApMention,
IBlock,
ICreate,
IDelete,
IFlag,
IFollow,
IKey,
ILike,
IMove,
IObject,
IPost,
IQuestion,
IReject,
IRemove,
ITombstone,
IUndo,
IUpdate
} from './type.js';
@Injectable() @Injectable()
export class ApRendererService { export class ApRendererService {
@ -793,6 +826,12 @@ export class ApRendererService {
@bindThis @bindThis
public async attachLdSignature(activity: any, user: { id: MiUser['id']; host: null; }): Promise<IActivity> { public async attachLdSignature(activity: any, user: { id: MiUser['id']; host: null; }): Promise<IActivity> {
// When using authorized fetch, Linked Data signatures are often undesired (as it can allow blocked instances to bypass the check).
// We allow admins to disable LD signatures for increased privacy, at the expense of increased incoming fetch (GET) requests.
if (!this.config.attachLdSignatureForRelays) {
return activity;
}
const keypair = await this.userKeypairService.getUserKeypair(user.id); const keypair = await this.userKeypairService.getUserKeypair(user.id);
const jsonLd = this.jsonLdService.use(); const jsonLd = this.jsonLdService.use();