Files
git.stella-ops.org/docs/dev/30_VEXER_CONNECTOR_GUIDE.md
master 7b5bdcf4d3 feat(docs): Add comprehensive documentation for Vexer, Vulnerability Explorer, and Zastava modules
- Introduced AGENTS.md, README.md, TASKS.md, and implementation_plan.md for Vexer, detailing mission, responsibilities, key components, and operational notes.
- Established similar documentation structure for Vulnerability Explorer and Zastava modules, including their respective workflows, integrations, and observability notes.
- Created risk scoring profiles documentation outlining the core workflow, factor model, governance, and deliverables.
- Ensured all modules adhere to the Aggregation-Only Contract and maintain determinism and provenance in outputs.
2025-10-30 00:09:39 +02:00

7.0 KiB
Raw Blame History

Vexer Connector Packaging Guide

Audience: teams implementing new Vexer provider plugins (CSAF feeds, OpenVEX attestations, etc.)
Prerequisites: read docs/modules/vexer/architecture.md and the module AGENTS.md in src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/.

The Vexer connector SDK gives you:

  • VexConnectorBase deterministic logging, SHA256 helpers, time provider.
  • VexConnectorOptionsBinder strongly typed YAML/JSON configuration binding.
  • IVexConnectorOptionsValidator<T> custom validation hooks (offline defaults, auth invariants).
  • VexConnectorDescriptor & metadata helpers for consistent telemetry.

This guide explains how to package a connector so the Vexer Worker/WebService can load it via the plugin host.


1. Project layout

Start from the template under docs/dev/templates/vexer-connector/. It contains:

Vexer.MyConnector/
├── src/
│   ├── Vexer.MyConnector.csproj
│   ├── MyConnectorOptions.cs
│   ├── MyConnector.cs
│   └── MyConnectorPlugin.cs
└── manifest/
    └── connector.manifest.yaml

Key points:

  • Target net10.0, enable TreatWarningsAsErrors, reference the StellaOps.Vexer.Connectors.Abstractions project (or NuGet once published).
  • Keep project ID prefix StellaOps.Vexer.Connectors.<Provider> so the plugin loader can discover it with the default search pattern.

1.1 csproj snippet

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\..\..\src\StellaOps.Vexer.Connectors.Abstractions\StellaOps.Vexer.Connectors.Abstractions.csproj" />
  </ItemGroup>
</Project>

Adjust the ProjectReference for your checkout (or switch to a NuGet package once published).


2. Implement the connector

  1. Options model create an options POCO with data-annotation attributes. Bind it via VexConnectorOptionsBinder.Bind<TOptions> in your connector constructor or ValidateAsync.
  2. Validator implement IVexConnectorOptionsValidator<TOptions> to add complex checks (e.g., ensure both clientId and clientSecret are present).
  3. Connector inherit from VexConnectorBase. Implement:
    • ValidateAsync run binder/validators, log configuration summary.
    • FetchAsync stream raw documents to context.RawSink.
    • NormalizeAsync convert raw documents into VexClaimBatch via format-specific normalizers (context.Normalizers).
  4. Plugin adapter expose the connector via a plugin entry point so the host can instantiate it.

2.1 Options binding example

public sealed class MyConnectorOptions
{
    [Required]
    [Url]
    public string CatalogUri { get; set; } = default!;

    [Required]
    public string ApiKey { get; set; } = default!;

    [Range(1, 64)]
    public int MaxParallelRequests { get; set; } = 4;
}

public sealed class MyConnectorOptionsValidator : IVexConnectorOptionsValidator<MyConnectorOptions>
{
    public void Validate(VexConnectorDescriptor descriptor, MyConnectorOptions options, IList<string> errors)
    {
        if (!options.CatalogUri.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
        {
            errors.Add("CatalogUri must use HTTPS.");
        }
    }
}

Bind inside the connector:

private readonly MyConnectorOptions _options;

public MyConnector(VexConnectorDescriptor descriptor, ILogger<MyConnector> logger, TimeProvider timeProvider)
    : base(descriptor, logger, timeProvider)
{
    // `settings` comes from the orchestrator; validators registered via DI.
    _options = VexConnectorOptionsBinder.Bind<MyConnectorOptions>(
        descriptor,
        VexConnectorSettings.Empty,
        validators: new[] { new MyConnectorOptionsValidator() });
}

Replace VexConnectorSettings.Empty with the actual settings from context inside ValidateAsync.


3. Plugin adapter & manifest

Create a simple plugin class that implements StellaOps.Plugin.IConnectorPlugin. The Worker/WebService plugin host uses this contract today.

public sealed class MyConnectorPlugin : IConnectorPlugin
{
    private static readonly VexConnectorDescriptor Descriptor =
        new("vexer:my-provider", VexProviderKind.Vendor, "My Provider VEX");

    public string Name => Descriptor.DisplayName;

    public bool IsAvailable(IServiceProvider services) => true; // inject feature flags if needed

    public IFeedConnector Create(IServiceProvider services)
    {
        var logger = services.GetRequiredService<ILogger<MyConnector>>();
        var timeProvider = services.GetRequiredService<TimeProvider>();
        return new MyConnector(Descriptor, logger, timeProvider);
    }
}

Note: the Vexer Worker currently instantiates connectors through the shared IConnectorPlugin contract. Once a dedicated Vexer plugin interface lands you simply swap the base interface; the descriptor/connector code remains unchanged.

Provide a manifest describing the assembly for operational tooling:

# manifest/connector.manifest.yaml
id: vexer-my-provider
assembly: StellaOps.Vexer.Connectors.MyProvider.dll
entryPoint: StellaOps.Vexer.Connectors.MyProvider.MyConnectorPlugin
description: >
  Official VEX feed for ExampleCorp products (CSAF JSON, daily updates).
tags:
  - vexer
  - csaf
  - vendor

Store manifests under /opt/stella/vexer/plugins/<connector>/manifest/ in production so the deployment tooling can inventory and verify plugins.


4. Packaging workflow

  1. dotnet publish -c Release → copy the published DLLs to /opt/stella/vexer/plugins/<Provider>/.
  2. Place connector.manifest.yaml next to the binaries.
  3. Restart the Vexer Worker or WebService (hot reload not supported yet).
  4. Verify logs: VEX-ConnectorLoader should list the connector descriptor.

4.1 Offline kits

  • Add the connector folder (binaries + manifest) to the Offline Kit bundle.
  • Include a settings.sample.yaml demonstrating offline-friendly defaults.
  • Document any external dependencies (e.g., SHA mirrors) in the manifest notes field.

5. Testing checklist

  • Unit tests around options binding & validators.
  • Integration tests (future StellaOps.Vexer.Connectors.Abstractions.Tests) verifying deterministic logging scopes: logger.BeginScope should produce vex.connector.id, vex.connector.kind, and vex.connector.operation.
  • Deterministic SHA tests: repeated CreateRawDocument calls with identical content must return the same digest.

6. Reference template

See docs/dev/templates/vexer-connector/ for the full quickstart including:

  • Sample options class + validator.
  • Connector implementation inheriting from VexConnectorBase.
  • Plugin adapter + manifest.

Copy the directory, rename namespaces/IDs, then iterate on provider-specific logic.


Last updated: 2025-10-17