Documentation
¶
Overview ¶
Package saga defines the Draugr descriptor ("Saga") — the declarative account of an application's security surface (repositories, images, hosts, infrastructure) plus the controller configuration that drives a scan. It also handles parsing, validation, env-var substitution, and assembly of distributed meta-sources.
See docs/ARCHITECTURE.md and docs/naming.md.
Index ¶
- Constants
- Variables
- func SchemaURLFor(version string) string
- func WriteClassifications(data []byte, class map[string]Classification) ([]byte, error)
- type Classification
- type Component
- type Config
- type ControllerSettings
- type Criticality
- type Exposure
- type Fragment
- type Host
- type Image
- type Infrastructure
- type MetaSource
- type Model
- type PublisherConfig
- type Reference
- type Release
- type ReportConfig
- type Repository
- type SBOMConfig
- type SBOMFormat
Constants ¶
const SchemaURL = schemaBaseURL + "/draugr.saga.schema.json"
SchemaURL is the schema that tracks the latest release. Use it to follow along with new Draugr versions; use SchemaURLFor to stay matched to a specific one.
Variables ¶
var Criticalities = []Criticality{CriticalityCritical, CriticalityImportant, CriticalitySupporting}
Criticalities lists the valid criticality levels, most to least critical.
var Exposures = []Exposure{ExposurePublic, ExposureAuthenticated, ExposureInternal, ExposureRestricted}
Exposures lists the valid exposure levels, most to least exposed.
var SBOMFormats = []SBOMFormat{SBOMSPDXJSON, SBOMSPDXTagValue, SBOMCycloneDXJSON, SBOMCycloneDXXML}
SBOMFormats lists the valid SBOM document formats.
var SchemaJSON []byte
SchemaJSON is the Saga's JSON Schema, embedded so the binary always carries the schema it actually enforces. That makes `draugr schema` exact — no network, no version guessing — and is what lets an air-gapped or pinned setup validate against precisely this build.
Functions ¶
func SchemaURLFor ¶ added in v0.33.0
SchemaURLFor returns the published schema for a specific Draugr version, so an editor validates a Saga against the same rules the installed binary applies. Unreleased builds ("dev", or an empty version) have no published copy, so they fall back to the latest.
func WriteClassifications ¶ added in v0.6.0
func WriteClassifications(data []byte, class map[string]Classification) ([]byte, error)
WriteClassifications sets each named component's exposure and criticality in the raw Saga bytes and returns the updated document. It operates on the parsed YAML nodes, so comments and ${{ VAR }} tokens are preserved (values are not substituted); indentation is normalized to two spaces. Components not present in class are left untouched. New keys are inserted right after the component's name for readability; existing values are updated in place.
Types ¶
type Classification ¶ added in v0.6.0
type Classification struct {
Exposure Exposure
Criticality Criticality
}
Classification is a component's risk tags.
type Component ¶
type Component struct {
Name string `yaml:"name"`
Labels map[string]string `yaml:"labels,omitempty"`
Exposure Exposure `yaml:"exposure,omitempty"`
Criticality Criticality `yaml:"criticality,omitempty"`
Repositories []Repository `yaml:"repositories,omitempty"`
Images []Image `yaml:"images,omitempty"`
Hosts []Host `yaml:"hosts,omitempty"`
Infrastructure []Infrastructure `yaml:"infrastructure,omitempty"`
Controllers map[string]ControllerSettings `yaml:"controllers,omitempty"`
}
Component is one logical part of an application: its repositories, images, hosts, and infrastructure, plus optional per-component controller overrides and risk classification.
type Config ¶
type Config struct {
Controllers map[string]ControllerSettings `yaml:"controllers,omitempty"`
// Reports are the report formats to render on a scan (e.g. json, sarif, markdown, html).
// Publishers deliver every rendered report to a destination.
Reports []ReportConfig `yaml:"reports,omitempty"`
// Publishers are the destinations that rendered reports are delivered to.
Publishers []PublisherConfig `yaml:"publishers,omitempty"`
// SBOM turns on Software Bill of Materials generation for this project's repositories and
// images. It is evidence rather than a control: an SBOM is an inventory, it finds nothing,
// and it never affects the verdict.
SBOM *SBOMConfig `yaml:"sbom,omitempty"`
}
Config holds global, per-controller configuration. Each controller's config tree is free-form (scanner-specific keys live under it); use ControllerEnabled to read the common "enabled" flag.
func (Config) ControllerEnabled ¶
ControllerEnabled reports whether the named controller is enabled at the project level. A controller is enabled when its config entry exists and its "enabled" key is not explicitly false. Absent entries are considered disabled.
type ControllerSettings ¶
ControllerSettings is a free-form configuration tree for one controller.
type Criticality ¶ added in v0.5.0
type Criticality string
Criticality is a component's business-criticality level — the operational impact if it fails or is compromised. It is the other axis of risk prioritization and is always human-declared, as it cannot be inferred from code. The levels are a fixed ladder with org-defined meaning. See docs/concepts.md (prioritization).
const ( CriticalityCritical Criticality = "critical" // failure causes outage or data loss CriticalityImportant Criticality = "important" // degraded functionality, no immediate outage CriticalitySupporting Criticality = "supporting" // limited operational impact )
Criticality levels, from most to least critical.
func (Criticality) Valid ¶ added in v0.5.0
func (c Criticality) Valid() bool
Valid reports whether c is a known criticality level. The empty value (unclassified) is not valid here; callers decide how to treat unset criticality.
type Exposure ¶ added in v0.5.0
type Exposure string
Exposure is a component's risk-exposure level — how reachable it is to an attacker, and so how likely a weakness in it is to be hit. It is one axis of risk prioritization; higher exposure ranks a component's findings higher. The levels are a fixed ladder: an organization may redefine what each means, but not the count. Exposure may be proposed by a surveyor from topology and confirmed by a human. See docs/concepts.md (prioritization).
const ( ExposurePublic Exposure = "public" // internet-facing, no authentication ExposureAuthenticated Exposure = "authenticated" // internet-facing, behind authentication ExposureInternal Exposure = "internal" // reachable within the environment ExposureRestricted Exposure = "restricted" // namespace- / network-policy-scoped )
Exposure levels, from most to least exposed.
type Fragment ¶
type Fragment struct {
Components []Component `yaml:"components,omitempty"`
}
Fragment is a partial Saga contributed by a Surveyor (one of "the Ravens"). The engine merges fragments into the Model.
type Host ¶
type Host struct {
Name string `yaml:"name"`
URL string `yaml:"url"`
Type string `yaml:"type,omitempty"`
}
Host is a running endpoint. Type is "browser" (browser-facing UI) or "api" (programmatic); it tunes which security-header checks apply. Optional; defaults to "browser".
type Image ¶
Image is a container image reference. Digest is the immutable content digest ("sha256:…") of the image the tag pointed to; when present it makes result caching content-addressed (a rebuilt image under the same tag re-scans). A surveyor can capture the running digest, or you can pin it by hand for reproducible caches.
type Infrastructure ¶
Infrastructure is an infrastructure surface. Kind is e.g. "kubernetes"; Ref names the concrete instance.
type MetaSource ¶
type MetaSource struct {
RepoURL string `yaml:"repoUrl"`
Path string `yaml:"path"`
Revision string `yaml:"revision,omitempty"`
}
MetaSource points at a Saga fragment kept close to a component's source.
type Model ¶
type Model struct {
Release Release `yaml:"release"`
Config Config `yaml:"config,omitempty"`
Components []Component `yaml:"components,omitempty"`
ComponentsMetaSources []MetaSource `yaml:"componentsMetaSources,omitempty"`
References []Reference `yaml:"references,omitempty"`
}
Model is a parsed Saga descriptor — the declarative account of an application's security surface plus the controller configuration that drives a scan.
func Load ¶
Load parses a Saga descriptor from YAML bytes, substituting ${{ VAR }} references from the environment and validating the result.
type PublisherConfig ¶ added in v0.21.0
type PublisherConfig struct {
Kind string `yaml:"kind"`
Dir string `yaml:"dir,omitempty"` // file: output directory
// github / github-pr-comment: Repo defaults to $GITHUB_REPOSITORY; the token to $GITHUB_TOKEN
// (or TokenEnv). github: Commit/Ref default to $GITHUB_SHA / $GITHUB_REF.
Repo string `yaml:"repo,omitempty"`
Commit string `yaml:"commit,omitempty"`
Ref string `yaml:"ref,omitempty"`
TokenEnv string `yaml:"tokenEnv,omitempty"` // env var holding the token; default GITHUB_TOKEN
// github-pr-comment: posts the markdown report as a sticky pull-request comment. PR defaults
// to the number parsed from $GITHUB_REF (refs/pull/<n>/merge); Marker identifies the sticky
// comment to update (default a Draugr marker).
PR int `yaml:"pr,omitempty"`
Marker string `yaml:"marker,omitempty"`
}
PublisherConfig configures one destination for rendered reports. Kind selects the publisher (e.g. "file", "github"); the remaining fields are read by that publisher. Known kinds and their required fields are validated by the publishing layer (pkg/publish) when the scan runs.
Secrets are never stored here: the github publisher reads its token from an environment variable (TokenEnv, default GITHUB_TOKEN), not from the Saga.
type Reference ¶
Reference links a manual/human security control (e.g. threat model, architecture diagram).
type Release ¶
type Release struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Stage string `yaml:"stage,omitempty"`
}
Release identifies what is being assessed.
type ReportConfig ¶ added in v0.21.0
type ReportConfig struct {
Format string `yaml:"format"`
// Template and TemplateFile supply the Go text/template for the "template" format (set
// exactly one). Ignored by other formats.
Template string `yaml:"template,omitempty"`
TemplateFile string `yaml:"templateFile,omitempty"`
// Filename overrides the artifact's default output filename (used by file-based publishers).
Filename string `yaml:"filename,omitempty"`
}
ReportConfig selects one report format to render on a scan. Known formats are validated by the reporting layer (pkg/report) when the scan runs, not here — the Saga stays a leaf.
type Repository ¶
type Repository struct {
URL string `yaml:"url"`
Revision string `yaml:"revision,omitempty"`
Paths []string `yaml:"paths,omitempty"`
}
Repository is a source repository at a revision, optionally scoped to paths.
type SBOMConfig ¶ added in v0.41.0
type SBOMConfig struct {
// Enabled generates one SBOM per distinct repository and image in the project.
Enabled bool `yaml:"enabled"`
// Format is the document format. Empty means SBOMSPDXJSON.
Format SBOMFormat `yaml:"format,omitempty"`
}
SBOMConfig turns on SBOM generation and chooses the document format.
type SBOMFormat ¶ added in v0.41.0
type SBOMFormat string
SBOMFormat is the document format for a generated SBOM. Both supported formats are open specifications that downstream tooling already reads.
const ( // SBOMSPDXJSON is the default: SPDX in JSON, the ISO standard (ISO/IEC 5962), and what // Draugr's own releases publish. SBOMSPDXJSON SBOMFormat = "spdx-json" // SBOMSPDXTagValue is SPDX in its original tag-value encoding, still required by some // compliance tooling. SBOMSPDXTagValue SBOMFormat = "spdx-tag-value" // SBOMCycloneDXJSON is the OWASP format in JSON, common in security tooling. SBOMCycloneDXJSON SBOMFormat = "cyclonedx-json" // SBOMCycloneDXXML is CycloneDX in XML, which some enterprise tooling still expects. SBOMCycloneDXXML SBOMFormat = "cyclonedx-xml" )
The SBOM document formats Draugr can emit: the two open specifications, each in both of its standard encodings. Which one you want is decided by whatever consumes the document, so the choice is yours rather than ours.
Syft can emit more (its own syft-json, GitHub's dependency-snapshot format, a bare PURL list), but those are either vendor-specific or not an SBOM. Keeping this list to the interchange formats means every document Draugr produces is one a third party can read.
func (SBOMFormat) Valid ¶ added in v0.41.0
func (f SBOMFormat) Valid() bool
Valid reports whether f is a known SBOM format. The empty value is not valid here; it means "the default" to callers, which resolve it before use.