feat: implement attachLdSignatureForRelays
to control signing of Relayed activities
This commit is contained in:
parent
c344705d67
commit
32872181dd
6 changed files with 89 additions and 39 deletions
|
@ -106,7 +106,7 @@ redis:
|
|||
# ┌───────────────────────────┐
|
||||
#───┘ MeiliSearch configuration └─────────────────────────────
|
||||
|
||||
# You can set scope to local (default value) or global
|
||||
# You can set scope to local (default value) or global
|
||||
# (include notes from remote).
|
||||
|
||||
#meilisearch:
|
||||
|
@ -198,13 +198,15 @@ proxyRemoteFiles: true
|
|||
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
|
||||
#videoThumbnailGenerator: https://example.com
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
# Sign outgoing ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
# Sign outgoing ActivityPub Activities (default: true)
|
||||
attachLdSignatureForRelays: true
|
||||
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
|
||||
checkActivityPubGetSignature: false
|
||||
|
||||
# For security reasons, uploading attachments from the intranet is prohibited,
|
||||
# but exceptions can be made from the following settings. Default value is "undefined".
|
||||
# but exceptions can be made from the following settings. Default value is "undefined".
|
||||
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
|
||||
#allowedPrivateNetworks: [
|
||||
# '127.0.0.1/32'
|
||||
|
|
|
@ -270,8 +270,10 @@ proxyRemoteFiles: true
|
|||
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
|
||||
#videoThumbnailGenerator: https://example.com
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
# Sign outgoing ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
# Sign outgoing ActivityPub Activities (default: true)
|
||||
attachLdSignatureForRelays: true
|
||||
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
|
||||
checkActivityPubGetSignature: false
|
||||
|
||||
|
|
|
@ -285,8 +285,10 @@ proxyRemoteFiles: true
|
|||
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
|
||||
#videoThumbnailGenerator: https://example.com
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
# Sign outgoing ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
# Sign outgoing ActivityPub Activities (default: true)
|
||||
attachLdSignatureForRelays: true
|
||||
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
|
||||
checkActivityPubGetSignature: false
|
||||
|
||||
|
|
|
@ -208,8 +208,10 @@ id: "aidx"
|
|||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
# Sign outgoing ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
# Sign outgoing ActivityPub Activities (default: true)
|
||||
attachLdSignatureForRelays: true
|
||||
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
|
||||
checkActivityPubGetSignature: false
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
*/
|
||||
|
||||
import * as fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {dirname, resolve} from 'node:path';
|
||||
import * as yaml from 'js-yaml';
|
||||
import { globSync } from 'glob';
|
||||
import {globSync} from 'glob';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import type { RedisOptions } from 'ioredis';
|
||||
import type {RedisOptions} from 'ioredis';
|
||||
|
||||
type RedisOptionsSource = Partial<RedisOptions> & {
|
||||
host: string;
|
||||
|
@ -95,6 +95,7 @@ type Source = {
|
|||
customMOTD?: string[];
|
||||
|
||||
signToActivityPubGet?: boolean;
|
||||
attachLdSignatureForRelays?: boolean;
|
||||
checkActivityPubGetSignature?: boolean;
|
||||
|
||||
perChannelMaxNoteCacheCount?: number;
|
||||
|
@ -161,6 +162,7 @@ export type Config = {
|
|||
proxyRemoteFiles: boolean | undefined;
|
||||
customMOTD: string[] | undefined;
|
||||
signToActivityPubGet: boolean;
|
||||
attachLdSignatureForRelays: boolean;
|
||||
checkActivityPubGetSignature: boolean | undefined;
|
||||
|
||||
version: string;
|
||||
|
@ -291,6 +293,7 @@ export function loadConfig(): Config {
|
|||
proxyRemoteFiles: config.proxyRemoteFiles,
|
||||
customMOTD: config.customMOTD,
|
||||
signToActivityPubGet: config.signToActivityPubGet ?? true,
|
||||
attachLdSignatureForRelays: config.attachLdSignatureForRelays ?? true,
|
||||
checkActivityPubGetSignature: config.checkActivityPubGetSignature,
|
||||
mediaProxy: externalMediaProxy ?? internalMediaProxy,
|
||||
externalMediaProxyEnabled: externalMediaProxy !== null && externalMediaProxy !== internalMediaProxy,
|
||||
|
|
|
@ -3,36 +3,69 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { createPublicKey, randomUUID } from 'node:crypto';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { In } from 'typeorm';
|
||||
import {createPublicKey, randomUUID} from 'node:crypto';
|
||||
import {Inject, Injectable} from '@nestjs/common';
|
||||
import {In} from 'typeorm';
|
||||
import * as mfm from '@transfem-org/sfm-js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { MiPartialLocalUser, MiLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/User.js';
|
||||
import type { IMentionedRemoteUsers, MiNote } from '@/models/Note.js';
|
||||
import type { MiBlocking } from '@/models/Blocking.js';
|
||||
import type { MiRelay } from '@/models/Relay.js';
|
||||
import type { MiDriveFile } from '@/models/DriveFile.js';
|
||||
import type { MiNoteReaction } from '@/models/NoteReaction.js';
|
||||
import type { MiEmoji } from '@/models/Emoji.js';
|
||||
import type { MiPoll } from '@/models/Poll.js';
|
||||
import type { MiPollVote } from '@/models/PollVote.js';
|
||||
import { UserKeypairService } from '@/core/UserKeypairService.js';
|
||||
import { MfmService } from '@/core/MfmService.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
||||
import type { MiUserKeypair } from '@/models/UserKeypair.js';
|
||||
import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository, InstancesRepository } from '@/models/_.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||
import { isNotNull } from '@/misc/is-not-null.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { MetaService } from '../MetaService.js';
|
||||
import { JsonLdService } from './JsonLdService.js';
|
||||
import { ApMfmService } from './ApMfmService.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 {DI} from '@/di-symbols.js';
|
||||
import type {Config} from '@/config.js';
|
||||
import type {MiLocalUser, MiPartialLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser} from '@/models/User.js';
|
||||
import type {IMentionedRemoteUsers, MiNote} from '@/models/Note.js';
|
||||
import type {MiBlocking} from '@/models/Blocking.js';
|
||||
import type {MiRelay} from '@/models/Relay.js';
|
||||
import type {MiDriveFile} from '@/models/DriveFile.js';
|
||||
import type {MiNoteReaction} from '@/models/NoteReaction.js';
|
||||
import type {MiEmoji} from '@/models/Emoji.js';
|
||||
import type {MiPoll} from '@/models/Poll.js';
|
||||
import type {MiPollVote} from '@/models/PollVote.js';
|
||||
import {UserKeypairService} from '@/core/UserKeypairService.js';
|
||||
import {MfmService} from '@/core/MfmService.js';
|
||||
import {UserEntityService} from '@/core/entities/UserEntityService.js';
|
||||
import {DriveFileEntityService} from '@/core/entities/DriveFileEntityService.js';
|
||||
import type {MiUserKeypair} from '@/models/UserKeypair.js';
|
||||
import type {
|
||||
DriveFilesRepository,
|
||||
InstancesRepository,
|
||||
NotesRepository,
|
||||
PollsRepository,
|
||||
UserProfilesRepository,
|
||||
UsersRepository
|
||||
} from '@/models/_.js';
|
||||
import {bindThis} from '@/decorators.js';
|
||||
import {CustomEmojiService} from '@/core/CustomEmojiService.js';
|
||||
import {isNotNull} from '@/misc/is-not-null.js';
|
||||
import {IdService} from '@/core/IdService.js';
|
||||
import {MetaService} from '../MetaService.js';
|
||||
import {JsonLdService} from './JsonLdService.js';
|
||||
import {ApMfmService} from './ApMfmService.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';
|
||||
|
||||
@Injectable()
|
||||
export class ApRendererService {
|
||||
|
@ -793,6 +826,12 @@ export class ApRendererService {
|
|||
|
||||
@bindThis
|
||||
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 jsonLd = this.jsonLdService.use();
|
||||
|
|
Loading…
Reference in a new issue