Documentation
¶
Overview ¶
Package mapping turns the JSON or JSON Lines output of any command-line tool into a CTIS report through a declarative mapping file, so a tool that writes JSON needs no parser code.
A mapping is a JSON document (apiVersion "openctem.io/mapping/v1"). Each rule selects input records with closed predicates and sets CTIS members from source paths with a closed set of transforms. The language has no expressions, loops, code or I/O: it cannot read files, reach the network or run for longer than the input it walks. A tool that keeps its mapping in YAML converts it to JSON before calling Load; the strict decoding here is the authority.
The full language is in docs/mapping.md.
Index ¶
Constants ¶
const ( DefaultMaxInputBytes = 64 << 20 DefaultMaxRecordBytes = 1 << 20 DefaultMaxRecords = 200_000 DefaultMaxOutputs = 200_000 DefaultMaxIssues = 200 MaxInputDepth = 64 )
Default bounds of Apply.
const ( MaxMappingBytes = 256 << 10 MaxRules = 200 MaxSetsPerRule = 100 MaxPredicates = 16 MaxRegexLen = 256 MaxMapEntries = 256 MaxInValues = 256 MaxTemplateBytes = 1024 )
Bounds on a mapping file.
const ( SourceJSON = "json" SourceJSONL = "jsonl" )
Source formats.
const ( KindAsset = "asset" KindFinding = "finding" KindDependency = "dependency" )
Record kinds.
const APIVersion = "openctem.io/mapping/v1"
APIVersion is the only mapping format version this package reads.
Variables ¶
var ( ErrInputTooLarge = errors.New("mapping: input is larger than the limit") ErrNotAList = errors.New("mapping: the each path does not name a list") )
Errors of Apply.
Functions ¶
This section is empty.
Types ¶
type Issue ¶
type Issue struct {
// Record is the 1-based input record (the line for JSON Lines).
Record int `json:"record"`
// Rule is the index of the rule, or -1 for the record itself.
Rule int `json:"rule"`
Message string `json:"message"`
}
Issue is a record that was skipped or a rule output that was dropped.
type Mapping ¶
type Mapping struct {
// contains filtered or unexported fields
}
Mapping is a loaded, validated mapping file.
func Load ¶
Load parses and validates a mapping file. Every error names the rule and member it is about.
func (*Mapping) Apply ¶
func (m *Mapping) Apply(ctx context.Context, r io.Reader, opts Options) (*ctis.Report, Stats, error)
Apply reads the tool output from r and returns the CTIS report the mapping makes of it. Every rule whose predicates hold emits one record; a record that does not decode into its CTIS type or does not validate is skipped and counted. The output is deterministic for the same input, mapping and Options.Now.
A record limit or output limit ends the read early with Stats.Truncated set; an input larger than MaxInputBytes, a malformed json document or a canceled ctx returns an error and no report.
func (*Mapping) Digest ¶
Digest is the SHA-256 of the mapping's canonical JSON form ("sha256:<hex>"): object members sorted, insignificant whitespace removed. Reformatting or reordering a file keeps it; any change of content does not. A tool descriptor records it, so the mapping is covered by the descriptor's own digest.
type Options ¶
type Options struct {
// Now is the report clock; nil means time.Now. Inject it for
// reproducible output.
Now func() time.Time
// Tool is copied into report.tool. A mapping never sets it from the
// input, so a tool's output cannot claim to be another tool.
Tool *ctis.Tool
MaxInputBytes int64 // whole input; default 64 MiB
MaxRecordBytes int // one JSON Lines line; default 1 MiB
MaxRecords int // input records read; default 200 000
MaxOutputs int // assets + findings + dependencies; default 200 000
MaxIssues int // Stats.Issues kept; default 200
}
Options bound and stamp one Apply.
type Predicate ¶
type Predicate struct {
Path string `json:"path"`
Exists *bool `json:"exists,omitempty"`
Equals any `json:"equals,omitempty"`
In []any `json:"in,omitempty"`
Matches string `json:"matches,omitempty"`
}
Predicate is one closed condition on an input record. Exactly one of Exists, Equals, In and Matches is set.
type Predicates ¶
type Predicates []Predicate
Predicates is "when": one predicate object or a list that must all hold.
func (*Predicates) UnmarshalJSON ¶
func (p *Predicates) UnmarshalJSON(b []byte) error
UnmarshalJSON accepts an object or an array of objects.
type RuleSpec ¶
type RuleSpec struct {
When Predicates `json:"when,omitempty"`
Kind string `json:"kind"`
Set map[string]ValueSpec `json:"set"`
}
RuleSpec is one rule as written in the file.
type Stats ¶
type Stats struct {
Records int `json:"records"`
Assets int `json:"assets"`
Findings int `json:"findings"`
Dependencies int `json:"dependencies"`
Skipped int `json:"skipped"`
Truncated bool `json:"truncated"`
Issues []Issue `json:"issues,omitempty"`
}
Stats count what Apply did.
type ValueSpec ¶
type ValueSpec struct {
Path string `json:"path,omitempty"`
Const any `json:"const,omitempty"`
Template string `json:"template,omitempty"`
Vars map[string]string `json:"vars,omitempty"`
Default any `json:"default,omitempty"`
First bool `json:"first,omitempty"`
Trim bool `json:"trim,omitempty"`
Lower bool `json:"lower,omitempty"`
Upper bool `json:"upper,omitempty"`
Split string `json:"split,omitempty"`
Map map[string]string `json:"map,omitempty"`
Join *string `json:"join,omitempty"`
As string `json:"as,omitempty"`
MaxBytes int `json:"max_bytes,omitempty"`
// contains filtered or unexported fields
}
ValueSpec is how one CTIS member gets its value: a bare string is a source path; an object takes exactly one of Path, Const and Template, then the transforms in this order: First, Trim, Lower, Upper, Split, Map, Join, As, MaxBytes. Default applies when the result is missing or empty.
func (ValueSpec) MarshalJSON ¶
MarshalJSON writes a bare path back as a string, so the digest of a mapping does not depend on which spelling its author used.
func (*ValueSpec) UnmarshalJSON ¶
UnmarshalJSON accepts a bare path string or an object.