mirror

package
v0.9.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

Documentation

Overview

Package mirror snapshots live SecOps state to local files (pull) and pushes local rule changes back (push). It is the file-mirroring layer on top of the pure danny.vn/secops/chronicle SDK; all on-disk layout, slugging, YAML formatting, and secret redaction live here, never in the SDK.

Index

Constants

View Source
const (
	DirRules            = "rules"
	DirRefLists         = "reference_lists"
	DirDataTables       = "data_tables"
	DirDashboards       = "dashboards"
	DirCurated          = "curated"
	DirFeeds            = "feeds"
	DirParsers          = "parsers"
	DirRuleExcl         = "rule_exclusions"
	DirForwarders       = "forwarders"
	DirMetrics          = "metric_definitions"
	DirScheduledReports = "scheduled_reports"
	DirDataTaps         = "datataps"
	DirErrorNotifs      = "error_notifications"
	DirFederation       = "federation_groups"
	DirSavedQueries     = "saved_queries"
)

On-disk subdirectory names, one per artifact type.

View Source
const (
	DirSOAR              = "soar"
	DirSOARConnectors    = "connectors"
	DirSOARJobs          = "jobs"
	DirSOARGrouping      = "grouping"
	DirSOARCases         = "cases"
	DirSOARPlaybooks     = "playbooks"
	DirSOARConnAllowlist = "connector_allowlist"
	DirSOARWebhooks      = "webhooks"
	DirSOAREnvironments  = "environments"
	DirSOARNetworks      = "networks"
	DirSOARTrackingLists = "tracking_lists"
	DirSOARSocRoles      = "soc_roles"
	DirSOARIdp           = "idp"
	DirSOARVisualFams    = "visual_families"
	DirSOARSla           = "sla_definitions"
	DirSOARCaseStages    = "case_stages"
	DirSOARCaseTags      = "case_tags"
	DirSOARRootCauses    = "close_root_causes"
	DirSOARBlacklists    = "blacklists"
	DirSOARPlaybookCats  = "playbook_categories"
)

On-disk subdirectory names for SOAR snapshots (under <root>/soar).

Variables

View Source
var SurfaceFamilies = buildSurfaceFamilies()

SurfaceFamilies is the full registry. Keep it in lock-step with CATALOG.md and the §6 version table; the drift-guard test enforces the version + consistency invariants.

Functions

func BuildSIEMSurface

func BuildSIEMSurface(name string, c *chronicle.Client) (reconcile.Surface, bool)

BuildSIEMSurface constructs the named engine surface bound to c, reporting whether the name is a known engine surface.

func BuildSOARSurface

func BuildSOARSurface(name string, lc *legacy.Client) (reconcile.Surface, bool)

BuildSOARSurface constructs the named engine surface bound to lc, reporting whether the name is a known engine surface.

func DashboardsSurfaceDeref added in v0.4.4

func DashboardsSurfaceDeref(c *chronicle.Client) reconcile.Surface

DashboardsSurfaceDeref is the `pull --with-charts` variant: every chart is dereferenced into its inline query.

func DashboardsSurfaceForMirror added in v0.4.4

func DashboardsSurfaceForMirror(c *chronicle.Client, dir string) reconcile.Surface

DashboardsSurfaceForMirror is the push/drift variant: a live dashboard is dereferenced iff its on-disk mirror file is inline, so each dashboard is compared in its OWN shape (a mixed inline/reference mirror never phantom-diffs).

func DataRoot

func DataRoot(base string) string

DataRoot returns base if non-empty, else the current working directory.

func DecodeRawList added in v0.2.1

func DecodeRawList(raw json.RawMessage) ([]json.RawMessage, error)

DecodeRawList exposes decodeRawList to callers outside this package (e.g. the CLI): it tolerates either a bare JSON array or an object wrapping one, so a legacy list response decodes the same way regardless of tenant shaping.

func EnsureDir

func EnsureDir(path string) (string, error)

EnsureDir creates path (and parents) if needed and returns it.

func GroupingRulesSurface added in v0.4.0

func GroupingRulesSurface(c *soar.Client) reconcile.Surface

GroupingRulesSurface exposes alert-grouping rules as config-as-code through the reconcile engine, backed by the modern soar.Client.

func PrintSOARSettingSingleton

func PrintSOARSettingSingleton(ctx context.Context, label string, get rawGetter, w io.Writer) error

PrintSOARSettingSingleton fetches a singleton settings object and prints it as pretty JSON. Read-only.

func PromoteRule added in v0.5.0

func PromoteRule(ctx context.Context, c *chronicle.Client, file string, opts RulesCreateDeploymentOptions, dryRun, assumeYes bool, w io.Writer) (int, error)

PromoteRule validates one YARA-L file, then creates AND deploys it to the requested initial state in a single guarded step — the "ship a new rule" path that otherwise needs `push rules-create` followed by `push rules-deploy`. It refuses a file that already has a companion .yaml (that rule is tracked; use rules-update / rules-deploy). Returns the number of rules promoted (0 or 1).

func PullCurated

func PullCurated(ctx context.Context, c *chronicle.Client, outDir string) (int, error)

PullCurated snapshots curated rule-set categories, their rule sets, and the per-precision deployment state into a single sorted curated/deployments.yaml for clean diffs. Categories and rule sets are sorted by display name (falling back to id); deployments are keyed by precision. Returns the number of categories written.

func PullCuratedRules

func PullCuratedRules(ctx context.Context, c *chronicle.Client, outDir, filter string) (int, error)

PullCuratedRules snapshots featured/Content-Hub curated rules with full YARA-L source plus per-rule metadata. Layout under outDir:

<category_slug>/<rule_set_slug>/<rule_slug>.yaral
<category_slug>/<rule_set_slug>/<rule_slug>.yaml
_index.yaml

Hidden-source rules (RuleTextHidden) get a stub .yaral note rather than being skipped. Slug collisions within a rule set are disambiguated with a short id suffix. filter is passed straight to the API. Returns the number of rules.

func PullDataTables

func PullDataTables(ctx context.Context, c *chronicle.Client, outDir string) (int, error)

PullDataTables snapshots every data table in the instance into outDir.

Per table it derives tableID from the last path segment of Name (falling back to displayName), then writes <slug>.csv (a header row from the column info followed by each row's positional Values, capped at maxDataTableRows) and <slug>.yaml (display name, name, description, the raw columns, row count, and timestamps). Returns the number of tables written.

func PullFeeds

func PullFeeds(ctx context.Context, c *chronicle.Client, outDir string) (int, error)

PullFeeds snapshots every ingestion feed to outDir as <slug>.yaml, with credential-bearing scalars under settings redacted before anything touches disk. It returns the number of feeds written. Read-only against the instance.

func PullParsers

func PullParsers(ctx context.Context, c *chronicle.Client, outDir string, logTypes []string) (int, error)

PullParsers snapshots the single ACTIVE parser per log type to outDir as <logType>.conf (base64-decoded CBN source) plus <logType>.yaml (metadata). It returns the number of log types written. Read-only against the instance.

When logTypes is nil, the set is derived from configured feeds: the last segment of each feed's Details["logType"], sorted and de-duplicated. Per-type errors (list failure, no ACTIVE parser, bad base64) are warned to stderr and skipped so one bad log type never aborts the pull.

func PullReferenceLists

func PullReferenceLists(ctx context.Context, c *chronicle.Client, outDir string) (int, error)

PullReferenceLists snapshots every reference list to outDir. For each list it writes <slug>.txt — one entry Value per line, with a trailing newline only when the list is non-empty — and <slug>.yaml with the typed metadata. The slug is derived from DisplayName, falling back to the last segment of Name. Returns the number of lists written.

func PullRules

func PullRules(ctx context.Context, c *chronicle.Client, outDir string) (int, error)

PullRules snapshots every custom (user-authored) detection rule into outDir.

For each rule it writes <slug>.yaral (the YARA-L source) and a companion <slug>.yaml (metadata + deployment state) using the shared ruleCompanion / deploymentMeta structs. Deployments are listed once and indexed by ruleID so the per-rule lookup is O(1). It returns the number of rules written.

func PullSOARCases

func PullSOARCases(ctx context.Context, lc *legacy.Client, outDir string) (int, error)

PullSOARCases snapshots the current OPEN case queue (legacy external API) to <outDir>/open.json. Cases are live data, not config — this is a point-in-time view. Returns the number of case cards captured.

func PullSOARGrouping

func PullSOARGrouping(ctx context.Context, c *soar.Client, lc *legacy.Client, outDir string, prune bool) (int, error)

PullSOARGrouping snapshots alert-grouping rules (the modern v1alpha reconcile surface) into <outDir>/rules/<slug>.json and the General/Overflow grouping settings singleton into <outDir>/settings.json. Returns the rules written. Prune removes local rule files with no live counterpart (engine-gated on a complete pull and never targets the non-deletable fallback rule).

func PullSOARPlaybooks

func PullSOARPlaybooks(ctx context.Context, lc *legacy.Client, outDir string, prune bool) (int, error)

PullSOARPlaybooks snapshots every playbook's full definition (via the v1alpha bridge) to <outDir>/<playbook>.json. When prune is true, local .json files with no live counterpart are removed so the mirror is an exact 1:1 reflection of the instance. Returns playbooks written.

func PushCuratedDeployments added in v0.1.6

func PushCuratedDeployments(ctx context.Context, c *chronicle.Client, curatedDir string, dryRun, assumeYes bool, w io.Writer) (int, error)

PushCuratedDeployments reconciles curated/deployments.yaml to live curated rule-set deployment state. Curated content is Google-managed, so the file never creates or deletes rule sets; it only sets enabled/alerting on existing (category, rule set, precision) deployments through the batch update API.

func PushRulesCreate

func PushRulesCreate(ctx context.Context, c *chronicle.Client, rulesDir string, dryRun, assumeYes bool, w io.Writer) (int, error)

PushRulesCreate creates live rules from *.yaral files that have no companion *.yaml. A .yaral without a sibling .yaml is treated as a brand-new rule that has never been deployed.

For each candidate it validates the YARA-L (printing an OK/FAIL table). On a dry run it stops after validation. If !assumeYes it aborts with a message (the CLI layer owns interactive confirmation). On apply it creates the rule, then applies the default deployment (enabled=true, alerting=true, runFrequency="LIVE"). Multi-event rules cannot run LIVE, so if the default deployment comes back disabled it re-issues the deployment at HOURLY. Finally it writes the companion .yaml so the rule is tracked locally. Returns the number of rules created (0 on dry-run/no work).

func PushRulesCreateWithOptions added in v0.2.0

func PushRulesCreateWithOptions(ctx context.Context, c *chronicle.Client, rulesDir string, opts RulesCreateDeploymentOptions, dryRun, assumeYes bool, w io.Writer) (int, error)

PushRulesCreateWithOptions is PushRulesCreate with caller-controlled initial deployment state, used by the CLI flags.

func PushRulesDeploy

func PushRulesDeploy(ctx context.Context, c *chronicle.Client, rulesDir string, dryRun, assumeYes bool, w io.Writer) (int, error)

PushRulesDeploy reconciles each tracked rule's deployment state (enabled / alerting / run frequency) from its companion `<slug>.yaml` to live, applying only the rules whose desired deployment differs from live. This is the rule deployment state machine as code (it subsumes enable / disable / alerting). Returns the number of deployments changed (0 on dry-run / no work).

func PushRulesDeployFiltered added in v0.1.6

func PushRulesDeployFiltered(ctx context.Context, c *chronicle.Client, rulesDir, ruleFilter string, dryRun, assumeYes bool, w io.Writer) (int, error)

PushRulesDeployFiltered is PushRulesDeploy scoped to one tracked rule when ruleFilter is non-empty. The filter accepts a rule id, full resource name, display name, or local slug/stem, so operators can target the form they have open without listing live state first.

func PushRulesDisable

func PushRulesDisable(ctx context.Context, c *chronicle.Client, rulesDir string, dryRun, assumeYes bool, w io.Writer) (int, error)

PushRulesDisable disables locally-tracked rules whose companion deployment.enabled is currently true. For each it calls UpdateRuleDeployment(enabled=false) — alerting and run frequency are left untouched — and rewrites the companion .yaml to reflect the disabled state.

On a dry run it prints a preview table and makes no API call. If !assumeYes it aborts with a message. Returns the number of rules disabled (0 on dry-run/no work).

func PushRulesUpdate

func PushRulesUpdate(ctx context.Context, c *chronicle.Client, rulesDir string, dryRun, assumeYes bool, w io.Writer) (int, error)

PushRulesUpdate updates the live YARA-L text of every tracked rule whose local `<slug>.yaral` differs from the live revision. Identity + the optimistic- concurrency etag come from the companion `<slug>.yaml`, so an out-of-band live edit since the last pull is rejected (etag mismatch) rather than clobbered. Each candidate's new text is validated before any mutation. Returns the number of rules updated (0 on dry-run / no work).

func PushSOARBulkClose

func PushSOARBulkClose(ctx context.Context, lc *legacy.Client, ids []int, reason legacy.CloseReason, rootCause, comment string, dryRun, assumeYes bool, w io.Writer) (int, error)

PushSOARBulkClose bulk-closes the given SOAR cases (legacy external API). It is guarded: dry-run prints the preview and stops; a real close requires assumeYes. Returns the number of cases requested for closing (0 on dry-run).

func PushSOARIntegrationCreate

func PushSOARIntegrationCreate(ctx context.Context, lc *legacy.Client, integrationID, env string, dryRun, assumeYes bool, w io.Writer) error

PushSOARIntegrationCreate creates a new, UNCONFIGURED (inert) instance of an already-installed integration in one environment. A fresh instance carries no credentials and runs no actions until configured, so create is low-blast. A singleton integration that allows only its default instance returns an error; that is surfaced, not retried. Guarded: dry-run previews; a real create needs assumeYes.

func PushSOARIntegrationDelete

func PushSOARIntegrationDelete(ctx context.Context, lc *legacy.Client, integrationID, env, instanceID string, dryRun, assumeYes bool, w io.Writer) error

PushSOARIntegrationDelete deletes one integration instance. It resolves the full instance object first (DeleteIntegrationInstance takes the whole object as a body, not a bare id) by listing the integration's instances in the environment and matching the id, warns if playbooks depend on it, then deletes. Guarded; cannot be undone.

func PushSOARPlaybookSave

func PushSOARPlaybookSave(ctx context.Context, lc *legacy.Client, file string, dryRun, assumeYes bool, w io.Writer) error

PushSOARPlaybookSave saves a playbook definition (a JSON file, typically one pulled by PullSOARPlaybooks and edited) via the v1alpha bridge. SavePlaybook mints a NEW version identifier and is a whole-body REPLACE. Guarded.

func PushSOARSettingPolicy

func PushSOARSettingPolicy(ctx context.Context, label, field string, value int, set rawSetter, dryRun, assumeYes bool, w io.Writer) error

PushSOARSettingPolicy upserts a singleton case-routing policy: a single integer enum field. Guarded — dry-run previews; a real change needs assumeYes.

func SIEMSurfaceNames

func SIEMSurfaceNames() []string

SIEMSurfaceNames returns the engine-backed SIEM surface names, sorted.

func SOARSurfaceNames

func SOARSurfaceNames() []string

SOARSurfaceNames returns the engine-backed SOAR surface names, sorted.

func Slugify

func Slugify(s string) string

Slugify makes s safe as a filename component: it keeps [A-Za-z0-9._-], collapses any other run of characters to a single "_", trims leading/trailing "_", and returns "_unnamed" when the result would otherwise be empty.

Types

type Area

type Area string

Area is the top-level functional grouping in docs/design/catalog.md.

const (
	AreaSIEM  Area = "SIEM"
	AreaSOAR  Area = "SOAR"
	AreaOther Area = "Other" // cross-cutting: Threat Intel, Content Hub
)

type Auth

type Auth string

Auth is the credential a family authenticates with.

const (
	AuthADC    Auth = "ADC"    // Google OAuth / ADC token
	AuthAppKey Auth = "AppKey" // Siemplify AppKey
)

type DriftItem

type DriftItem struct {
	Name           string
	Created        int  // local-only (would be created)
	Updated        int  // changed (would be updated)
	Deleted        int  // live-only orphan on a prune-eligible surface (would be pruned)
	Untracked      int  // live-only on a NoDelete surface (not push-reconcilable; pull to adopt)
	Incomplete     bool // the live listing was incomplete (a per-item read failed)
	Err            error
	CreatedNames   []string
	UpdatedNames   []string
	DeletedNames   []string
	UntrackedNames []string
}

DriftItem is the drift outcome for one surface. The *Names slices carry the slug of each diverged object so a report can name what drifted (a bare "~1" is undiagnosable without a manual diff).

func (DriftItem) Drifted

func (d DriftItem) Drifted() bool

Drifted reports a reconcilable divergence. It is false when indeterminate (an incomplete/errored listing is "could not verify", not confirmed drift) and ignores Untracked (not push-reconcilable).

func (DriftItem) Indeterminate

func (d DriftItem) Indeterminate() bool

Indeterminate reports that drift could not be judged (error or incomplete list).

type DriftReport

type DriftReport struct{ Items []DriftItem }

DriftReport aggregates per-surface outcomes.

func Drift

func Drift(ctx context.Context, targets []DriftTarget, w io.Writer) DriftReport

Drift checks each target and writes a one-line-per-surface report to w. It is read-only (BuildPlan lists live + loads local; it never writes). A per-surface error is recorded on the item and the sweep continues.

func (DriftReport) Drifted

func (r DriftReport) Drifted() bool

Drifted reports whether any surface has a reconcilable divergence.

func (DriftReport) Indeterminate

func (r DriftReport) Indeterminate() bool

Indeterminate reports whether any surface could not be verified.

type DriftTarget

type DriftTarget struct {
	Surface reconcile.Surface
	Dir     string
}

DriftTarget is one surface to check, with its on-disk directory.

type FamilyLane

type FamilyLane string

FamilyLane is the §3 modeling lane (named FamilyLane to avoid colliding with the reconcile-engine vocabulary).

const (
	LaneReconcile   FamilyLane = "reconcile"
	LaneRaw         FamilyLane = "raw"
	LaneImperative  FamilyLane = "imperative"
	LaneOperational FamilyLane = "operational"
)

type FamilyStatus

type FamilyStatus string

FamilyStatus mirrors the docs/design/catalog.md status legend.

const (
	StatusDesigned  FamilyStatus = "designed"  // 📐
	StatusBuilt     FamilyStatus = "built"     // 🔨
	StatusValidated FamilyStatus = "validated" // ✅
	StatusReadOnly  FamilyStatus = "read-only" // 🔒
	StatusBlocked   FamilyStatus = "blocked"   // ⛔
)

type Generation

type Generation string

Generation is the API generation a family is operated on.

const (
	GenNew    Generation = "New"    // modern Google REST (projects/…/instances/… shape)
	GenLegacy Generation = "Legacy" // Siemplify external /api/external/v1
)

type Host

type Host string

Host is the domain a family's calls go to.

const (
	HostChronicle Host = "chronicle" // chronicle.googleapis.com
	HostSiemplify Host = "siemplify" // *.siemplify-soar.com
)

type Plane

type Plane string

Plane is the (product, transport) pairing from docs/design/surfaces.md.

const (
	PlaneSIEM       Plane = "SIEM"        // chronicle.googleapis.com, ADC/OAuth
	PlaneSOARLegacy Plane = "SOAR-legacy" // *.siemplify-soar.com, external /api/external/v1
	PlaneSOARModern Plane = "SOAR-modern" // *.siemplify-soar.com, v1alpha
)

type RulesCreateDeploymentOptions added in v0.2.0

type RulesCreateDeploymentOptions struct {
	Enabled      bool
	Alerting     bool
	RunFrequency string
}

RulesCreateDeploymentOptions controls the initial deployment PATCH after a new YARA-L rule is created.

func DefaultRulesCreateDeploymentOptions added in v0.2.0

func DefaultRulesCreateDeploymentOptions() RulesCreateDeploymentOptions

type SurfaceFamily

type SurfaceFamily struct {
	Name        string
	Area        Area
	Plane       Plane
	Host        Host
	Auth        Auth
	Generation  Generation
	APIVersion  string // "" = N/A (the Legacy external API has no version ladder)
	Lane        FamilyLane
	Status      FamilyStatus
	SDKLocation string
}

SurfaceFamily is one API family's home and maturity.

func SurfaceFamilyByName

func SurfaceFamilyByName(name string) []SurfaceFamily

SurfaceFamilyByName returns the registry entries with the given Name (a family can appear under more than one generation/path, e.g. cases).

Directories

Path Synopsis
Package reconcile is the product-neutral core of secopsctl's config-as-code loop: pull = List/Read live state into files, push = Create/Update/Delete that reconciles files back to live.
Package reconcile is the product-neutral core of secopsctl's config-as-code loop: pull = List/Read live state into files, push = Create/Update/Delete that reconciles files back to live.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL