Skip to content

SolAr Discovery

SolAr Discovery is a standalone tool that scans OCI registries for Open Component Model (OCM) packages and populates the SolAr catalog by creating Component and ComponentVersion resources in a Kubernetes cluster.

Discovery is fully optional — the SolAr catalog can be populated through other means (direct API calls, GitOps, catalog chaining). See ADR-008, principle 6.

Operating Modes

Discovery supports two operating modes that can be used independently or combined on the same registry.

Scan Mode

In scan mode, discovery periodically performs a full scan of the registry, walking all repositories to find OCM component descriptors. This is the simplest mode and works with any OCI registry.

registries:
  - name: my-registry
    hostname: registry.example.com
    scanInterval: 24h

Webhook Mode

In webhook mode, discovery listens for HTTP notifications from the registry. When a new image is pushed or deleted, the registry sends an event and discovery processes it immediately. This provides near-real-time catalog updates.

Webhook mode requires a registry that supports event notifications (e.g. Zot).

registries:
  - name: my-registry
    hostname: registry.example.com
    webhookPath: events
    flavor: zot

Combined Mode

Both modes can be enabled on the same registry. The scan provides a baseline and catches anything the webhook might miss; the webhook provides real-time updates between scans.

registries:
  - name: my-registry
    hostname: registry.example.com
    scanInterval: 24h
    webhookPath: events
    flavor: zot

Installation

Helm Chart

The recommended way to deploy discovery in a Kubernetes cluster:

helm upgrade --install solar-discovery oci://ghcr.io/opendefensecloud/charts/solar-discovery \
  --namespace solar-system \
  --set namespace=solar-system \
  --values my-values.yaml

Binary

Discovery can also be run as a standalone binary outside a cluster:

solar-discovery --config config.yaml --namespace default

When running outside a cluster, set the KUBECONFIG environment variable to point to a kubeconfig file with access to the target cluster's SolAr API.

Configuration

Config File Format

The config file is a YAML file listing the registries to scan:

registries:
  - name: production
    hostname: registry.example.com
    scanInterval: 24h
    credentials:
      username: ${REGISTRY_USERNAME}
      password: ${REGISTRY_PASSWORD}

  - name: staging
    hostname: staging-registry.example.com
    scanInterval: 1h
    plainHTTP: true

Environment Variable Substitution

The config file supports $VAR and ${VAR} syntax for environment variable expansion. This is the recommended way to inject credentials without storing them in plaintext:

registries:
  - name: my-registry
    hostname: registry.example.com
    credentials:
      username: ${REGISTRY_USERNAME}
      password: ${REGISTRY_PASSWORD}

Registry Fields

Field Type Required Default Description
name string yes Unique local identifier for this registry
hostname string yes Registry hostname and optional port
scanInterval duration no 24h How often to run a full scan (set to 0 to disable scan mode)
webhookPath string no Webhook endpoint path (enables webhook mode)
flavor string no Webhook implementation (e.g. zot)
plainHTTP bool no false Use HTTP instead of HTTPS
credentials.username string no Registry username
credentials.password string no Registry password

CLI Flags

Flag Short Default Description
--config -c Path to the registry config file (required)
--namespace -n default Kubernetes namespace for Component/ComponentVersion resources
--listen -l 0.0.0.0:8080 Address for the webhook HTTP listener

Helm Chart Values

See charts/solar-discovery/values.yaml for the full list of configurable values. Key settings:

Value Description
registries List of registry configurations (rendered into the ConfigMap)
namespace Target namespace for discovered resources
envFrom Secret/ConfigMap references for environment variables (credentials)
caBundle.enabled Mount a CA bundle ConfigMap for TLS connections
caBundle.configMapName Name of the CA bundle ConfigMap
service.enabled Create a Service for webhook mode
rbac.create Create ClusterRole/ClusterRoleBinding for API access

Examples

Minimal Scan-Only Setup

# values.yaml
registries:
  - name: main
    hostname: registry.example.com
    scanInterval: 1h

namespace: solar-system
service:
  enabled: false

Webhook with Zot Registry

# values.yaml
registries:
  - name: zot
    hostname: zot.internal:5000
    webhookPath: events
    flavor: zot
    credentials:
      username: ${username}
      password: ${password}

namespace: solar-system

envFrom:
  - secretRef:
      name: zot-credentials

caBundle:
  enabled: true
  configMapName: root-bundle

Multiple Registries

# values.yaml
registries:
  - name: production
    hostname: prod-registry.example.com
    scanInterval: 24h
    credentials:
      username: ${PROD_USERNAME}
      password: ${PROD_PASSWORD}

  - name: staging
    hostname: staging-registry.example.com
    scanInterval: 30m
    webhookPath: events
    flavor: zot
    credentials:
      username: ${STAGING_USERNAME}
      password: ${STAGING_PASSWORD}

namespace: solar-system

envFrom:
  - secretRef:
      name: registry-credentials

Running Outside a Cluster

# Set kubeconfig for API access
export KUBECONFIG=~/.kube/config

# Set registry credentials
export REGISTRY_USERNAME=admin
export REGISTRY_PASSWORD=secret

# Run discovery
solar-discovery --config config.yaml --namespace solar-system