Documentation
¶
Overview ¶
Package tool is the one contract for every workload a sensor runs: a target scanner, a connector to a vendor API, a parser of a file or an enricher of findings.
Stability: Stable (docs/STABILITY.md).
A tool is a manifest plus a run function:
- the Manifest (a tool.yaml file, apiVersion openctem.io/tool/v1) declares what the tool is: its execution class, its intrusiveness tier, the CTIS types it consumes and produces, a typed configuration schema, the permissions it needs (network, filesystem, credentials), its resources and its self-test fixtures;
- Run(ctx, task) does the work and reports through ctx: records through an Emitter that checks each one as it is emitted, progress, logs, artifacts and the outcome of each target, and returns a categorized Error when it fails.
The runtime (pkg/sensorkit) never calls Run in its own process. A Go tool compiled into a sensor runs in a separate, sandboxed process (the sensor re-executes itself), speaking the same adapter protocol a tool in any other language speaks (pkg/tool/adapter). Only pkg/testkit calls Run in-process, applying the same rules the runtime applies, so a tool that would be stopped in production fails its unit test.
The runtime owns every guarantee: it admits targets against the policy, validates the configuration against the manifest's schema, delivers only the credentials the manifest declares, checks every record again on its side of the process boundary (CTIS validity, declared output types, size and count limits, control characters) and stamps the provenance. Nothing in this package lets tool code skip any of it.
The design is docs/rfcs/sensor-sdk-v2.md.
Index ¶
- Constants
- Variables
- func AdapterProtocolJSONSchema() []byte
- func AuthFailure(err error) error
- func CapDetail(s string) string
- func DecodeConfig[C any](schema *core.SettingsSchema, raw json.RawMessage) (C, error)
- func Failed(err error) error
- func Invalid(format string, args ...any) error
- func ManifestJSONSchema() []byte
- func RateLimit(after time.Duration, err error) error
- func Refused(reason string) error
- func Retry(err error) error
- func SchemaFor[C any]() (json.RawMessage, error)
- func Unreachable(err error) error
- type Builder
- func (b *Builder) Build() (Tool, error)
- func (b *Builder) Capabilities(ids ...string) *Builder
- func (b *Builder) Class(c Class) *Builder
- func (b *Builder) Describe(s string) *Builder
- func (b *Builder) Handle(h Handler) *Builder
- func (b *Builder) Manifest(edit func(m *Manifest)) *Builder
- func (b *Builder) MustBuild() Tool
- func (b *Builder) Params(ps ...*Param) *Builder
- func (b *Builder) Produces(kinds ...string) *Builder
- func (b *Builder) Targets(types ...string) *Builder
- func (b *Builder) Tier(t Tier) *Builder
- func (b *Builder) Timeout(d time.Duration) *Builder
- type ByteSize
- type Class
- type Context
- type CredentialReq
- type Duration
- type Emit
- type Emitter
- type Error
- type ErrorClass
- type Filesystem
- type Fixture
- type Handler
- type Input
- type Issue
- type Job
- type Manifest
- func (m Manifest) Canonical() ([]byte, error)
- func (m Manifest) ConfigSchema() (*core.SettingsSchema, error)
- func (m Manifest) Contract() *core.ToolContract
- func (m Manifest) Declares(kind, typ string) bool
- func (m Manifest) Digest() string
- func (m Manifest) Normalized() Manifest
- func (m Manifest) Validate() error
- type ManifestError
- type ManifestErrors
- type Mode
- type Network
- type NoConfig
- type OutputSpec
- type Param
- func (p *Param) Default(v any) *Param
- func (p *Param) Help(s string) *Param
- func (p *Param) Label(s string) *Param
- func (p *Param) MaxItems(n int) *Param
- func (p *Param) MaxLength(n int) *Param
- func (p *Param) OneOf(vals ...any) *Param
- func (p *Param) Pattern(re string) *Param
- func (p *Param) PerScan() *Param
- func (p *Param) Range(lo, hi float64) *Param
- func (p *Param) Required() *Param
- type Permissions
- type Range
- type Repo
- type ReportInfo
- type ReportInfoMetadata
- type Resources
- type RetestContext
- type RetestItem
- type RetestVerdict
- type Retester
- type RunSpec
- type Scope
- type Secret
- func (s Secret) Format(f fmt.State, _ rune)
- func (s Secret) GoString() string
- func (s Secret) IsZero() bool
- func (s Secret) LogValue() slog.Value
- func (s Secret) MarshalJSON() ([]byte, error)
- func (s Secret) MarshalText() ([]byte, error)
- func (s Secret) Reveal() string
- func (s Secret) String() string
- type Status
- type Target
- type TargetState
- type Task
- type Tier
- type Tool
- type Validator
- type Value
- func (v Value) Bool() bool
- func (v Value) BoolOr(d bool) bool
- func (v Value) Float() float64
- func (v Value) FloatOr(d float64) float64
- func (v Value) Int() int
- func (v Value) IntOr(d int) int
- func (v Value) IsSet() bool
- func (v Value) String() string
- func (v Value) StringOr(d string) string
- func (v Value) Strings() []string
- type Verdict
Constants ¶
const ( // ProfileAdapter: the program speaks adapter protocol v1. ProfileAdapter = "adapter" // ProfileExec: a CLI that writes CTIS or SARIF, with no adapter code. ProfileExec = "exec" )
Run profiles.
const ( OutputCTIS = "ctis" OutputSARIF = "sarif" OutputJSONLCTIS = "jsonl-ctis" )
Output formats of the exec profile.
const ( DefaultTimeout = 60 * time.Minute DefaultIdleTimeout = 10 * time.Minute DefaultMaxOutputBytes = 64 << 20 DefaultMaxRecords = 200000 )
Defaults of Resources.
const ( KindAsset = "asset" KindFinding = "finding" KindDependency = "dependency" )
Produce kinds.
const ( RetestFinding = "finding" RetestAsset = "asset" )
Retest item kinds.
const APIVersion = "openctem.io/tool/v1"
APIVersion is the manifest format this package reads and writes.
const MaxErrorDetail = 256
MaxErrorDetail bounds Error.Detail on the wire.
const MaxManifestBytes = 256 << 10
MaxManifestBytes bounds a tool.yaml file.
const MaxRetestItems = 1000
MaxRetestItems bounds the items of one retest task.
const ProtocolVersion = 1
ProtocolVersion is the adapter protocol version this SDK speaks.
const Redacted = "[REDACTED]"
Redacted is what a Secret prints.
Variables ¶
var ( // ErrUndeclaredOutput: the record's kind is not in Manifest.Produces. // The record is quarantined (not delivered). ErrUndeclaredOutput = errors.New("undeclared output type") // ErrOutputLimit: the task reached Resources.MaxRecords or // MaxOutputBytes. The tool should stop; the task ends partial. ErrOutputLimit = errors.New("output limit reached") // ErrInvalidRecord: the record is not valid CTIS. ErrInvalidRecord = errors.New("invalid CTIS record") // ErrUndeclaredCredential: the tool asked for a credential its manifest // does not declare, or one the operator did not store. ErrUndeclaredCredential = errors.New("credential not declared or not granted") )
Errors the emitter returns.
var ErrRetestRecord = errors.New("tool: a retest task reports verdicts, not records")
ErrRetestRecord is the error of a record emitted in a retest task.
Functions ¶
func AdapterProtocolJSONSchema ¶
func AdapterProtocolJSONSchema() []byte
AdapterProtocolJSONSchema returns the JSON Schema of one adapter protocol v1 message, for implementations in other languages.
func DecodeConfig ¶
func DecodeConfig[C any](schema *core.SettingsSchema, raw json.RawMessage) (C, error)
DecodeConfig validates raw against schema (nil: no configuration), fills the defaults and decodes it into C, refusing unknown keys.
func ManifestJSONSchema ¶
func ManifestJSONSchema() []byte
ManifestJSONSchema returns the JSON Schema of tool.yaml (draft 2020-12), for editors and for implementations in other languages. Validate checks more than the schema can express (class against permissions, placeholders against the config schema, no secrets in config).
func SchemaFor ¶
func SchemaFor[C any]() (json.RawMessage, error)
SchemaFor derives a configuration schema (the settings schema subset) from C's struct tags; nil when C has no fields. The output is deterministic.
func Unreachable ¶
Unreachable reports that a target did not answer (retried next run).
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder declares a simple tool without writing a manifest by hand:
var Dotenv = tool.Define("dotenv", "1.0.0").
Describe("Finds .env files a web server serves").
Targets("http_service", "domain").
Produces("finding:misconfiguration").
Params(
tool.StringParam("path").Label("Path").Default("/.env").Pattern("^/").MaxLength(256),
tool.IntParam("timeout").Label("Timeout (s)").Default(10).Range(1, 60),
).
Handle(func(ctx tool.Context, job *tool.Job, emit tool.Emit) error {
for _, t := range job.Targets() {
// ... probe t.URL(job.Param("path").String()) ...
_ = emit.Misconfiguration(t, tool.Issue{RuleID: "dotenv-exposed", Title: ".env is readable", Severity: "high"})
ctx.TargetDone(t)
}
return nil
}).
MustBuild()
The result is an ordinary Tool: the same manifest checks, the same runtime guarantees (out-of-process execution, admission, output checks, provenance) and the same tests (pkg/testkit) as a tool written with New. Fields the builder has no method for are set with Manifest.
func Define ¶
Define starts a tool declaration. The defaults are the target-scan class and tier T1 (active, non-intrusive); Class and Tier change them.
func (*Builder) Capabilities ¶
Capabilities declares the platform capability ids the tool provides.
func (*Builder) Manifest ¶
Manifest edits the manifest directly, for the fields the builder has no method for (permissions, credentials, resources, self-tests, modes).
func (*Builder) MustBuild ¶
MustBuild is Build for a package-level declaration: an invalid tool compiled into a sensor must stop it at start, not run.
func (*Builder) Params ¶
Params declares the tool's parameters: they become the manifest's configuration schema, which the platform renders as a form and the runtime enforces.
func (*Builder) Produces ¶
Produces declares the output types ("finding:<type>", "asset:<type>", "dependency"). A record of any other type is refused.
type ByteSize ¶
type ByteSize int64
ByteSize is a size in bytes; in a manifest a number or a string with a binary or decimal suffix ("512Mi", "1Gi", "64MB").
func ParseByteSize ¶
ParseByteSize reads "1024", "512Ki", "512Mi", "1Gi", "64MB", "1G".
func (*ByteSize) UnmarshalJSON ¶
UnmarshalJSON reads a number or a size string.
type Class ¶
type Class string
Class is a tool's execution class: what it touches and how the runtime dispatches it.
const ( // TargetScan touches customer targets (hosts, URLs, repositories). TargetScan Class = "target-scan" // Connector reads a vendor API with credentials. Connector Class = "connector" // Parser reads a file and produces records; no network. Parser Class = "parser" // Enricher annotates findings; it never creates assets. Enricher Class = "enricher" )
Execution classes.
type Context ¶
type Context interface {
context.Context
// Log is a structured logger. Values are redacted (Secret prints
// [REDACTED]) and the runtime bounds the rate and size of what it
// keeps.
Log() *slog.Logger
// Progress reports done of total units (throttled by the runtime).
Progress(done, total int, msg string)
// Emit is the record channel. Each record is checked when it is
// emitted.
Emit() Emitter
// TargetDone reports that the tool finished a target.
TargetDone(t Target)
// TargetError reports that a target failed (its scan coverage); err
// is categorized like a Run error.
TargetError(t Target, err error)
// TargetSkipped reports that the tool did not work on a target.
TargetSkipped(t Target, reason string)
// Artifact creates a size-capped artifact (a raw log, a screenshot),
// delivered separately from the records.
Artifact(name, mediaType string) (io.WriteCloser, error)
// Workdir is the task's private directory, removed after the task.
Workdir() string
// Secret returns a credential the manifest declares and the operator
// stored; anything else is ErrUndeclaredCredential.
Secret(name string) (Secret, error)
// HTTP is a client that reaches only what the manifest's network
// permission allows: the task's targets (NetTargets), the vendor
// hosts (NetVendor) or nothing (NetNone); it never reaches cloud
// metadata endpoints. It is defense in depth: the sandbox backend's
// network class is the boundary.
HTTP() *http.Client
}
Context is what a running tool gets from the runtime. It is canceled on cancel, on the task's deadline and on the sensor's kill switch.
type CredentialReq ¶
type CredentialReq struct {
// Name is how the tool asks for it (Context.Secret).
Name string `json:"name"`
Kind string `json:"kind"`
Required bool `json:"required,omitempty"`
Description string `json:"description,omitempty"`
}
CredentialReq is a credential a tool declares.
type Duration ¶
Duration is a time.Duration; in a manifest a string such as "20m" or a number of seconds.
func (Duration) MarshalJSON ¶
MarshalJSON writes the duration as a string ("20m0s").
func (*Duration) UnmarshalJSON ¶
UnmarshalJSON reads "20m", "1h30m" or a number of seconds.
type Emit ¶
type Emit struct {
// contains filtered or unexported fields
}
Emit builds CTIS records for the common cases and sends them through the task's emitter, which checks each one (CTIS validity, declared output types, limits). CTIS returns the emitter for anything else.
func (Emit) Asset ¶
Asset emits a discovered asset of a CTIS type ("domain", "ip_address", "http_service", ...).
func (Emit) Misconfiguration ¶
Misconfiguration emits a misconfiguration finding on target t.
type Emitter ¶
type Emitter interface {
// Asset emits an asset.
Asset(a ctis.Asset) error
// Finding emits a finding of target t. A finding without an asset
// reference is filed on t's asset.
Finding(t Target, f ctis.Finding) error
// Dependency emits a dependency (SBOM component) found on t.
Dependency(t Target, d ctis.Dependency) error
// Report emits every record of a report (the output of a converter),
// plus its tool, metadata and properties (ReportInfo).
Report(r *ctis.Report) error
}
Emitter is the record channel. Every call checks the record at once, so a tool learns about a bad record at the line that produced it:
- it must be valid CTIS (required fields, enums, ranges);
- its kind must be in Manifest.Produces, else ErrUndeclaredOutput (the record is quarantined, the task ends partial);
- the task's record count and bytes must stay within the resources, else ErrOutputLimit (the tool should stop);
- control and bidirectional-override characters are removed and long strings cut;
- provenance (which tool, version, sandbox, sensor, task) is stamped by the runtime, never taken from the tool.
The runtime repeats every check on its side of the process boundary.
type Error ¶
type Error struct {
Class ErrorClass
// Retryable defaults from Class; a tool may only turn it off.
Retryable bool
RetryAfter time.Duration
// Detail is a short, human description. The runtime redacts it and
// caps it at MaxErrorDetail bytes before it leaves the sensor.
Detail string
// Err is the cause, for local logs only; it is never sent.
Err error
}
Error is a categorized tool error.
type ErrorClass ¶
type ErrorClass string
ErrorClass categorizes an error, so the platform can tell a retry from a refusal from a broken tool.
const ( // InvalidInput: the configuration or targets are wrong; not retried. InvalidInput ErrorClass = "invalid_input" // TargetUnreachable: a target did not answer; retried on the next run. TargetUnreachable ErrorClass = "target_unreachable" // RefusedByPolicy: the scope or the local policy refused it; the job // goes back to the queue for another sensor. RefusedByPolicy ErrorClass = "refused_by_policy" // Transient: retry with back-off. Transient ErrorClass = "transient" // RateLimited: retry after RetryAfter. RateLimited ErrorClass = "rate_limited" // AuthFailed: a connector's credentials were refused. AuthFailed ErrorClass = "auth_failed" // PermissionDenied: the credentials lack a permission. PermissionDenied ErrorClass = "permission_denied" // NotFound: the resource does not exist. NotFound ErrorClass = "not_found" // ToolError: the tool failed; not retried by default. A plain error // returned from Run is a ToolError. ToolError ErrorClass = "tool_error" )
Error classes a tool may return.
const ( Timeout ErrorClass = "timeout" Canceled ErrorClass = "canceled" ResourceExhausted ErrorClass = "resource_exhausted" OutputRejected ErrorClass = "output_rejected" ToolCrashed ErrorClass = "tool_crashed" )
Error classes set by the runtime only; a tool that returns one gets ToolError instead.
func (ErrorClass) Retryable ¶
func (c ErrorClass) Retryable() bool
Retryable is the class's default retry verdict.
func (ErrorClass) RuntimeOnly ¶
func (c ErrorClass) RuntimeOnly() bool
RuntimeOnly reports whether c is set by the runtime only.
func (ErrorClass) Valid ¶
func (c ErrorClass) Valid() bool
Valid reports whether c is a class a tool may return.
type Filesystem ¶
type Filesystem string
Filesystem is what a tool may read besides its private directory.
const ( // FSWorkdir: the task's private directory only (the default). FSWorkdir Filesystem = "workdir" // FSScanRootsReadOnly: also the sensor's scan roots, read-only. FSScanRootsReadOnly Filesystem = "scan-roots-read-only" )
Filesystem permissions.
type Fixture ¶
type Fixture struct {
Name string `json:"name"`
Task string `json:"task"`
Expect string `json:"expect"`
}
Fixture is one self-test: a task file and the CTIS it must produce, both relative to the manifest's directory.
type Handler ¶
Handler does the work of one task of a tool declared with Define. job holds the task and its parameters (validated, defaults filled); emit builds CTIS records.
type Input ¶
type Input struct {
Name string `json:"name"`
MediaType string `json:"media_type"`
// Path is relative to the task's directory.
Path string `json:"path"`
Size int64 `json:"size,omitempty"`
SHA256 string `json:"sha256,omitempty"`
}
Input is a file given to the task (a parser's input).
type Issue ¶
type Issue struct {
RuleID string
Title string
Severity ctis.Severity
Description string
// Evidence is the proof (a response excerpt, a banner); never a
// secret value.
Evidence string
// CVE is the vulnerability's CVE id (Vulnerability only).
CVE string
}
Issue is a finding in a few fields. Severity is critical, high, medium, low or info.
type Job ¶
type Job struct {
Task
// contains filtered or unexported fields
}
Job is one task of a tool declared with Define, with typed access to its targets and parameters.
type Manifest ¶
type Manifest struct {
// APIVersion is APIVersion ("" in Go code means APIVersion).
APIVersion string `json:"apiVersion"`
// Name is unique per sensor: ^[a-z][a-z0-9-]{1,62}$.
Name string `json:"name"`
// Version is the semantic version of the tool adapter (not of the
// engine it runs).
Version string `json:"version"`
Description string `json:"description,omitempty"`
Class Class `json:"class"`
// Modes the tool runs in; empty means both.
Modes []Mode `json:"modes,omitempty"`
Tier Tier `json:"tier"`
// Capabilities are the platform's capability ids the tool provides
// ("web.probe", "vuln.templates", ...).
Capabilities []string `json:"capabilities,omitempty"`
// Consumes are CTIS asset types, "file:<media type>" for parsers, or
// "finding:<type>" for enrichers.
Consumes []string `json:"consumes,omitempty"`
// Produces are "asset:<type>", "finding:<type>" or "dependency". A
// record of any other kind is refused (ErrUndeclaredOutput).
Produces []string `json:"produces"`
// Config is the tool's configuration schema: the closed JSON Schema
// subset of api RFC-038 (pkg/core settings schemas), with no secret
// fields (secrets are credentials, never configuration). nil: no
// configuration (New derives one from the config type when it has
// fields).
Config json.RawMessage `json:"config,omitempty"`
Permissions Permissions `json:"permissions"`
Resources Resources `json:"resources"`
// Selftest are fixtures: a task and the CTIS it must produce.
Selftest []Fixture `json:"selftest,omitempty"`
// Retest says the tool can check again what it reported (a retest
// task, see Retester). Target-scan tools only.
Retest bool `json:"retest,omitempty"`
// Protocol is the range of adapter protocol versions the tool speaks.
Protocol Range `json:"protocol"`
// Run says how to start a tool that is not compiled into the sensor.
Run *RunSpec `json:"run,omitempty"`
}
Manifest describes a tool. Its file form is tool.yaml; LoadManifest reads it, strictly (an unknown key is an error: the manifest is a security document). The runtime trusts the manifest file or the one compiled into the sensor, never a tool's description of itself.
func LoadManifest ¶
LoadManifest reads a manifest (YAML or JSON) strictly: unknown keys, duplicate keys and more than one document are errors. The result is validated (Validate) and has its defaults filled.
func LoadManifestFile ¶
LoadManifestFile reads and validates a tool.yaml file.
func (Manifest) ConfigSchema ¶
func (m Manifest) ConfigSchema() (*core.SettingsSchema, error)
ConfigSchema parses the configuration schema (nil when there is none).
func (Manifest) Contract ¶
func (m Manifest) Contract() *core.ToolContract
Contract names the manifest in the sensor manifest (core.ToolContract): its digest and the fields the platform plans with.
func (Manifest) Declares ¶
Declares reports whether the manifest produces records of kind ("asset", "finding", "dependency") and CTIS type typ ("" for dependencies).
func (Manifest) Digest ¶
Digest is "sha256:" + the hex SHA-256 of the manifest's canonical JSON (defaults filled, object members sorted, no insignificant whitespace). The runtime compares a tool's self-description with its file by digest, and the sensor registers manifests with the platform by digest.
func (Manifest) Normalized ¶
Normalized returns the manifest with its defaults filled, as the runtime sees it.
func (Manifest) Validate ¶
Validate checks the manifest: identity, class against permissions and tier, consumes/produces from the CTIS vocabulary, a configuration schema in the settings subset with no secret fields, resources within bounds, and a run specification with a closed set of placeholders and no shell. The error is ManifestErrors with every problem.
type ManifestError ¶
ManifestError is one problem in a manifest. Path is a JSON pointer.
func (ManifestError) Error ¶
func (e ManifestError) Error() string
type ManifestErrors ¶
type ManifestErrors []ManifestError
ManifestErrors are every problem found in a manifest.
func (ManifestErrors) Error ¶
func (e ManifestErrors) Error() string
type Network ¶
type Network string
Network is the network a tool needs.
const ( // NetNone: no network at all. NetNone Network = "none" // NetTargets: the task's targets only, through the zone's egress. NetTargets Network = "targets" // NetEgressProxy: through the sensor's egress proxy only. NetEgressProxy Network = "egress-proxy" // NetVendor: the declared vendor hosts only. NetVendor Network = "vendor" )
Network permissions.
type NoConfig ¶
type NoConfig struct{}
NoConfig is the configuration type of a tool without configuration.
type OutputSpec ¶
type OutputSpec struct {
// Format is OutputCTIS, OutputSARIF or OutputJSONLCTIS.
Format string `json:"format"`
// From is "stdout" or "file" (the {{task.output}} path).
From string `json:"from"`
}
OutputSpec is an exec-profile tool's output.
type Param ¶
type Param struct {
// contains filtered or unexported fields
}
Param is one parameter of a tool declared with Define. Its methods set what the platform shows (Label, Help) and what the runtime enforces (Default, Range, OneOf, Pattern, MaxLength, MaxItems, Required).
func (*Param) PerScan ¶
PerScan lets a scan set the parameter (otherwise only the tool's settings on the sensor or platform do).
type Permissions ¶
type Permissions struct {
// Network defaults by class: none for parsers and enrichers, targets
// for target scans, vendor for connectors.
Network Network `json:"network,omitempty"`
// VendorHosts are the hosts a vendor-network tool may reach
// ("api.example.com", "api.example.com:8443", or "${config.<key>}" for
// a string configuration key holding a URL or host).
VendorHosts []string `json:"vendor_hosts,omitempty"`
Filesystem Filesystem `json:"filesystem,omitempty"`
// Credentials the tool may receive. Only these are ever delivered,
// and only when the sensor's operator stored them.
Credentials []CredentialReq `json:"credentials,omitempty"`
// LinuxCaps the tool needs (NET_RAW for SYN scans); granted only when
// the local policy allows.
LinuxCaps []string `json:"linux_caps,omitempty"`
}
Permissions are what a tool needs. The effective permission is the manifest's intersected with the sensor's policy and the job.
type Repo ¶
type Repo struct {
URL string `json:"url,omitempty"`
Branch string `json:"branch,omitempty"`
Commit string `json:"commit,omitempty"`
DefaultBranch bool `json:"default_branch,omitempty"`
PullRequest int `json:"pull_request,omitempty"`
}
Repo is a CI task's repository.
type ReportInfo ¶
type ReportInfo struct {
Tool *ctis.Tool `json:"tool,omitempty"`
Metadata *ReportInfoMetadata `json:"metadata,omitempty"`
Properties ctis.Properties `json:"properties,omitempty"`
}
ReportInfo is what a report carries besides its records: the tool's vendor and capabilities, metadata such as the coverage type and branch, and properties. The runtime keeps the tool's name as the manifest's.
func InfoOf ¶
func InfoOf(r *ctis.Report) *ReportInfo
InfoOf returns the ReportInfo of r (nil when r carries none).
type ReportInfoMetadata ¶
type ReportInfoMetadata struct {
ID string `json:"id,omitempty"`
DurationMs int `json:"duration_ms,omitempty"`
SourceRef string `json:"source_ref,omitempty"`
SourceType string `json:"source_type,omitempty"`
CoverageType string `json:"coverage_type,omitempty"`
Branch *ctis.BranchInfo `json:"branch,omitempty"`
Scope *ctis.Scope `json:"scope,omitempty"`
Properties ctis.Properties `json:"properties,omitempty"`
}
ReportInfoMetadata is the part of a report's metadata a tool may set.
type Resources ¶
type Resources struct {
CPU float64 `json:"cpu,omitempty"`
Memory ByteSize `json:"memory,omitempty"`
Timeout Duration `json:"timeout,omitempty"`
IdleTimeout Duration `json:"idle_timeout,omitempty"`
MaxOutputBytes ByteSize `json:"max_output_bytes,omitempty"`
MaxRecords int `json:"max_records,omitempty"`
// Cost is the slot cost for the sensor's capacity model.
Cost int `json:"cost,omitempty"`
}
Resources bound one task of the tool. Zero fields take the runtime's defaults.
type RetestContext ¶
type RetestContext interface {
Context
// Verdict reports the verdict on item. The first verdict of an item
// counts; a verdict on an item not in the task is ignored. detail is
// cut to MaxErrorDetail and redacted.
Verdict(item RetestItem, v Verdict, detail string)
}
RetestContext is the Context of a retest task.
type RetestItem ¶
type RetestItem struct {
// Ref is the platform's opaque id of the item, echoed in its verdict.
Ref string `json:"ref"`
// Target is the ref of the task target the item is on.
Target string `json:"target"`
// Kind is RetestFinding or RetestAsset.
Kind string `json:"kind"`
// RuleID is the check that reported the finding (a template id, a rule
// id).
RuleID string `json:"rule_id,omitempty"`
// Fingerprint is the finding's fingerprint as the platform keeps it.
Fingerprint string `json:"fingerprint,omitempty"`
// Attrs are typed hints from the platform.
Attrs map[string]string `json:"attrs,omitempty"`
}
RetestItem is one thing the platform asks the tool to check again.
type RetestVerdict ¶
type RetestVerdict struct {
Ref string `json:"ref"`
Verdict Verdict `json:"verdict"`
Detail string `json:"detail,omitempty"`
}
RetestVerdict is an item's final verdict, as the runtime reports it.
type Retester ¶
type Retester interface {
Retest(ctx RetestContext, task Task) error
}
Retester is implemented by a tool that can retest (Manifest.Retest). The runtime calls Retest instead of Run for a retest task.
type RunSpec ¶
type RunSpec struct {
// Profile is ProfileAdapter (default) or ProfileExec.
Profile string `json:"profile,omitempty"`
// Argv is the program and its arguments. Never a shell. Placeholders
// are a closed set: {{config.<key>}} (a scalar key of the config
// schema), {{target.value}}, {{target.host}}, {{target.port}},
// {{target.url}}, {{task.targets_file}}, {{task.targets_json}},
// {{task.config_file}}, {{task.output}}, {{task.workdir}}.
Argv []string `json:"argv"`
// Output is where an exec-profile tool writes its results.
Output *OutputSpec `json:"output,omitempty"`
// ExitCodes maps an exec-profile tool's exit codes to outcomes
// ("ok", "partial") or error classes; default: 0 ok, else tool_error.
ExitCodes map[string]string `json:"exit_codes,omitempty"`
}
RunSpec says how the runtime starts a tool that is its own program.
type Scope ¶
type Scope struct {
Includes []string `json:"includes,omitempty"`
Excludes []string `json:"excludes,omitempty"`
}
Scope is a job's scope.
type Secret ¶
type Secret struct {
// contains filtered or unexported fields
}
Secret is a credential. It prints, formats, logs and marshals as [REDACTED]; Reveal returns the value, and the SDK never logs it.
func (Secret) MarshalJSON ¶
MarshalJSON writes "[REDACTED]".
func (Secret) MarshalText ¶
MarshalText writes [REDACTED].
type Status ¶
type Status string
Status is how a task ended.
const ( // StatusOK: every target done. StatusOK Status = "ok" // StatusPartial: some targets failed, or output was capped or // quarantined. StatusPartial Status = "partial" // StatusFailed: the task failed. StatusFailed Status = "failed" // StatusCanceled: the task was canceled. StatusCanceled Status = "canceled" )
Task outcomes.
type Target ¶
type Target struct {
// Ref is an opaque reference that links records to the platform's
// asset.
Ref string `json:"ref"`
// Type is a CTIS asset type ("http_service", "domain", "repository").
Type string `json:"type,omitempty"`
// Value is the target itself ("https://a.example:8443", "10.0.4.7",
// "/src").
Value string `json:"value"`
// Attrs are typed hints from the platform (port, scheme, tech, ...).
Attrs map[string]string `json:"attrs,omitempty"`
}
Target is one thing to work on.
type TargetState ¶
type TargetState string
TargetState is the outcome of one target.
const ( StateDone TargetState = "done" StateFailed TargetState = "failed" StateSkipped TargetState = "skipped" )
Target outcomes.
type Task ¶
type Task struct {
ID string `json:"id"`
Attempt int `json:"attempt,omitempty"`
Deadline time.Time `json:"deadline,omitzero"`
Targets []Target `json:"targets,omitempty"`
// Config is the effective configuration (defaults applied).
Config json.RawMessage `json:"config,omitempty"`
// Inputs are files placed in the task's directory (parsers).
Inputs []Input `json:"inputs,omitempty"`
// Repo is the repository of a runner-mode (CI) task.
Repo *Repo `json:"repo,omitempty"`
// Scope is the job's scope, read-only, for tools that expand targets.
// Expanded targets are emitted as assets, never scanned in the same
// task.
Scope Scope `json:"scope,omitzero"`
// Local is configuration the sensor itself supplies for a tool compiled
// into it (operator settings, managed content paths): never from the
// platform, never for an adapter shipped on its own.
Local json.RawMessage `json:"local,omitempty"`
// Retest, when not empty, makes the task a retest: the items to check
// again, each on one of Targets (see Retester).
Retest []RetestItem `json:"retest,omitempty"`
}
Task is one unit of work. Its targets were admitted by the runtime and its configuration validated against the manifest's schema before the tool sees it.
type Tool ¶
type Tool interface {
// Manifest describes the tool. It is static: the runtime reads it
// before any tool code runs.
Manifest() Manifest
// Run does the work of one task.
Run(ctx Context, task Task) error
}
Tool is the one contract for every workload a sensor runs.
func New ¶
New builds a Tool from a manifest and a typed run function. C is the tool's configuration: the runtime validates the task's configuration against the manifest's schema, then the tool decodes it into C (defaults filled, unknown keys refused).
When m.Config is nil and C has fields, the schema is derived from C's struct tags: json (the key), default, min, max, enum (comma-separated), pattern, maxLength, maxItems, title, description, scope ("scan" lets a scan set the key), required ("true"). A field tagged secret:"true" is refused: secrets are credentials, never configuration.
New panics when the manifest is invalid: a tool compiled into a sensor with a broken manifest must stop the sensor at start, not run.
func WithRetest ¶
func WithRetest(t Tool, fn func(ctx RetestContext, task Task) error) Tool
WithRetest returns t with a retest handler: the manifest declares Retest, Run is t's, Retest is fn. It panics without a tool or a handler, like New on an invalid manifest.
type Validator ¶
Validator is optional: semantic checks beyond the manifest's schemas, run before any target is touched.
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value is a parameter's value. The runtime validated it against the parameter's declaration, so the typed accessors only fall back when the parameter is unset (no default) or of another type.
type Verdict ¶
type Verdict string
Verdict is what a retest concluded about one item.
const ( // StillPresent: the issue (or asset) was observed again. StillPresent Verdict = "still_present" // Fixed: the check ran against the reached target and the issue is // gone (an asset: it no longer exists). Fixed Verdict = "fixed" // Unverifiable: the tool could not tell (unreachable, check not // available, error). Unverifiable Verdict = "unverifiable" )
Verdicts.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package adapter runs a tool (pkg/tool) as an adapter process: the tool's side of adapter protocol v1, newline-delimited JSON on stdin and stdout, one task per process (docs/rfcs/sensor-sdk-v2.md, D.4.2).
|
Package adapter runs a tool (pkg/tool) as an adapter process: the tool's side of adapter protocol v1, newline-delimited JSON on stdin and stdout, one task per process (docs/rfcs/sensor-sdk-v2.md, D.4.2). |
|
Package toolcompat runs code written against the older interfaces (core.Scanner, core.Collector) as tools of the tool contract (pkg/tool), so it gets the contract's runtime without a rewrite: out-of-process execution in the task sandbox, admission against the policy, declared credentials only, checked and stamped output.
|
Package toolcompat runs code written against the older interfaces (core.Scanner, core.Collector) as tools of the tool contract (pkg/tool), so it gets the contract's runtime without a rewrite: out-of-process execution in the task sandbox, admission against the policy, declared credentials only, checked and stamped output. |