Unverified Commit d4dc3044 authored by Hong Minhee's avatar Hong Minhee
Browse files

Instrument `signObject()`

parent 41fbe8b5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ To be released.
     -  Added the optional fourth parameter to `signRequest()` function.
     -  Added `VerifyProofOptions.tracerProvider` option.
     -  Added `VerifyObjectOptions.tracerProvider` option.
     -  Added `SignObjectOptions.tracerProvider` option.

 -  Added `@fedify/fedify/x/sveltekit` module for integrating with [SvelteKit]
    hook.  [[#171], [#183] by Jiyu Park]
+1 −0
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ spans:
| `activitypub.lookup_object`      | Client      | Looks up the Activity Streams object. |
| `http_signatures.sign`           | Internal    | Signs the HTTP request.               |
| `http_signatures.verify`         | Internal    | Verifies the HTTP request signature.  |
| `object_integrity_proofs.sign`   | Internal    | Makes the object integrity proof.     |
| `object_integrity_proofs.verify` | Internal    | Verifies the object integrity proof.  |
| `webfinger.handle`               | Server      | Handles the WebFinger request.        |
| `webfinger.lookup`               | Client      | Looks up the WebFinger resource.      |
+1 −0
Original line number Diff line number Diff line
@@ -1776,6 +1776,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> {
      if (privateKey.algorithm.name === "Ed25519") {
        activity = await signObject(activity, privateKey, keyId, {
          contextLoader: this.contextLoader,
          tracerProvider: this.tracerProvider,
        });
        proofCreated = true;
      }
+1 −1
Original line number Diff line number Diff line
import { getLogger } from "@logtape/logtape";
import { TracerProvider } from "@opentelemetry/api";
import type { TracerProvider } from "@opentelemetry/api";
import { signRequest } from "../sig/http.ts";
import type { Recipient } from "../vocab/actor.ts";

+55 −12
Original line number Diff line number Diff line
import { getLogger } from "@logtape/logtape";
import {
  type Span,
  SpanStatusCode,
  trace,
  type TracerProvider,
} from "@opentelemetry/api";
import { SpanStatusCode, trace, type TracerProvider } from "@opentelemetry/api";
import { encodeHex } from "@std/encoding/hex";
// @ts-ignore: json-canon is not typed
import serialize from "json-canon";
import metadata from "../deno.json" with { type: "json" };
import type { DocumentLoader } from "../runtime/docloader.ts";
import { getTypeId } from "../vocab/type.ts";
import {
  Activity,
  DataIntegrityProof,
@@ -115,6 +111,13 @@ export interface SignObjectOptions extends CreateProofOptions {
   * The document loader for loading remote JSON-LD documents.
   */
  documentLoader?: DocumentLoader;

  /**
   * The OpenTelemetry tracer provider.  If omitted, the global tracer provider
   * is used.
   * @since 1.3.0
   */
  tracerProvider?: TracerProvider;
}

/**
@@ -133,12 +136,52 @@ export async function signObject<T extends Object>(
  keyId: URL,
  options: SignObjectOptions = {},
): Promise<T> {
  const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
  const tracer = tracerProvider.getTracer(metadata.name, metadata.version);
  return await tracer.startActiveSpan(
    "object_integrity_proofs.sign",
    {
      attributes: { "activitypub.object.type": getTypeId(object).href },
    },
    async (span) => {
      try {
        if (object.id != null) {
          span.setAttribute("activitypub.object.id", object.id.href);
        }
        const existingProofs: DataIntegrityProof[] = [];
        for await (const proof of object.getProofs(options)) {
          existingProofs.push(proof);
        }
        const proof = await createProof(object, privateKey, keyId, options);
        if (span.isRecording()) {
          if (proof.cryptosuite != null) {
            span.setAttribute(
              "object_integrity_proofs.cryptosuite",
              proof.cryptosuite,
            );
          }
          if (proof.verificationMethodId != null) {
            span.setAttribute(
              "object_integrity_proofs.key_id",
              proof.verificationMethodId.href,
            );
          }
          if (proof.proofValue != null) {
            span.setAttribute(
              "object_integrity_proofs.signature",
              encodeHex(proof.proofValue),
            );
          }
        }
        return object.clone({ proofs: [...existingProofs, proof] }) as T;
      } catch (error) {
        span.setStatus({ code: SpanStatusCode.ERROR, message: String(error) });
        throw error;
      } finally {
        span.end();
      }
    },
  );
}

/**