secmock

package module
v0.0.1-alpha Latest Latest
Warning

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

Go to latest
Published: May 28, 2026 License: MIT Imports: 13 Imported by: 0

README

secmock

Generates realistic mock security alerts for GCP, Azure, and AWS cloud providers.

v1 supports GCP Security Command Center v2 — full NotificationMessage envelopes byte-compatible with what a real Pub/Sub subscriber receives. Azure and AWS are planned.

Go Reference

Use cases: SIEM ingestion testing · load generation · developer tooling · golden-file fixtures


Install

go get github.com/coderite/secmock

Requires Go 1.26.3+.


Quick Start

import (
    "context"
    "github.com/coderite/secmock"
    "github.com/coderite/secmock/providers/gcp"
    _ "github.com/coderite/secmock/providers/gcp/categories" // register built-in templates
)

// Write 1 000 random alerts to ./alerts/
err := secmock.WriteN(context.Background(), gcp.New(), "./alerts", 1000,
    secmock.Options{Seed: 42})

Each alert is written as an individual JSON file (alert-0000.json, alert-0001.json, …).


Usage

Random alert (in-memory)
import "math/rand/v2"

p := gcp.New()
msg, err := p.Random(rand.New(rand.NewPCG(42, 42)))
By finding class
msg, err := p.ByClass(gcp.ClassThreat, rand.New(rand.NewPCG(1, 1)))
By finding class + category
msg, err := p.ByCategory(gcp.ClassThreat, "Malware: Bad IP", rand.New(rand.NewPCG(1, 1)))
Bulk write to disk
err := secmock.WriteN(ctx, gcp.New(), "./alerts", 100_000, secmock.Options{
    Seed:    42,        // omit for time-based seed
    Workers: 8,         // defaults to runtime.GOMAXPROCS(0)
    Mode:    secmock.ModeByClass,
    Class:   gcp.ClassThreat,
    OnProgress: func(written int) {
        if written%10_000 == 0 {
            log.Printf("wrote %d alerts", written)
        }
    },
})
Output format

Each file contains a NotificationMessage envelope — the same JSON a Pub/Sub subscriber receives from a real SCC notification config:

{
  "notificationConfigName": "organizations/482910573821/notificationConfigs/scc-mock-notifier",
  "finding": {
    "name": "organizations/482910573821/sources/9182736450/locations/global/findings/a3f2c1d...",
    "parent": "organizations/482910573821/sources/9182736450",
    "resourceName": "//compute.googleapis.com/projects/mock-project-4a2b1c/zones/us-central1-a/instances/inst-7e3f2a",
    "state": "ACTIVE",
    "category": "Malware: Bad IP",
    "findingClass": "THREAT",
    "severity": "HIGH",
    "eventTime": "2024-08-14T03:22:11Z",
    "mitreAttack": { "primaryTactic": "EXECUTION", "version": "14" },
    "indicator": { "ipAddresses": ["10.0.42.17"] }
  },
  "resource": {
    "name": "//compute.googleapis.com/projects/mock-project-4a2b1c/zones/us-central1-a/instances/inst-7e3f2a",
    "type": "google.compute.Instance",
    "cloudProvider": "GOOGLE_CLOUD_PLATFORM"
  }
}

GCP Catalog

22 built-in categories across all 7 SCC v2 finding classes:

Class Categories
THREAT Persistence: IAM Anomalous Grant · Malware: Bad IP · Brute Force: SSH · Defense Evasion: Modify VPC Service Control · Discovery: Service Account Self-Investigation
VULNERABILITY OS Vulnerability · Outdated Library · Public Bucket ACL · Stale CMEK Rotation
MISCONFIGURATION Public IP Address · MFA Not Enforced · Open SSH Port · Web UI Enabled · Default Service Account Used
OBSERVATION Sensitive Action: Disable Org Policy · Unusual Activity From Country
POSTURE_VIOLATION CIS GKE Hardening Drift · Org Policy Drift
TOXIC_COMBINATION Public Compute Instance with Excessive IAM · Public Bucket with PII
SCC_ERROR SCC Source API Disabled · KTD Image Pull Failure
Adding custom categories
import (
    "math/rand/v2"
    "cloud.google.com/go/securitycenter/apiv2/securitycenterpb"
    "github.com/coderite/secmock/providers/gcp"
)

func init() {
    gcp.Register(gcp.ClassThreat, "My Custom Finding", func(r *rand.Rand) *securitycenterpb.NotificationMessage {
        return gcp.NewEnvelope(r, gcp.EnvelopeInput{
            Class:        gcp.ClassThreat,
            Category:     "My Custom Finding",
            Severity:     securitycenterpb.Finding_CRITICAL,
            ResourceType: "google.compute.Instance",
        })
    })
}

Call Register from init() or program startup — not concurrently with generation.


Determinism

Same Seed + same n → byte-identical output files regardless of Workers:

// These two runs produce identical files:
secmock.WriteN(ctx, gcp.New(), dir, 500, secmock.Options{Seed: 42, Workers: 1})
secmock.WriteN(ctx, gcp.New(), dir, 500, secmock.Options{Seed: 42, Workers: 8})

Omit Seed (or set to 0) for a time-based seed that differs each run.


Error Handling

WriteN validates inputs before any files are written (preflight). If it fails mid-run, already-written files are retained on disk — useful for debugging the template that failed. Callers wanting all-or-nothing can os.RemoveAll(dir) on error.

var (
    secmock.ErrUnknownClass    // unknown finding class string
    secmock.ErrUnknownCategory // unknown category for the given class
    secmock.ErrEmptyCatalog    // provider has no registered templates
)

Roadmap

  • Azure Defender (providers/azure)
  • AWS Security Hub (providers/aws)
  • CLI tool (cmd/secmock)

License

MIT

Documentation

Overview

Package mockalerts generates mock cloud-provider security alerts. v1 supports GCP Security Command Center; Azure and AWS are planned.

Package secmock generates realistic mock security alerts for GCP, Azure, and AWS cloud providers.

v1 supports GCP Security Command Center v2 (full NotificationMessage envelopes matching what a Pub/Sub subscriber receives). Azure and AWS are planned as sibling Provider implementations under providers/.

Useful for SIEM ingestion testing, load generation, and developer tooling.

Quickstart:

import (
    "context"
    "github.com/coderite/secmock"
    "github.com/coderite/secmock/providers/gcp"
    _ "github.com/coderite/secmock/providers/gcp/categories" // register built-in templates
)

func generate(ctx context.Context) error {
    return secmock.WriteN(ctx, gcp.New(), "./alerts", 1000,
        secmock.Options{Seed: 42})
}

Determinism: same Seed and n produce byte-identical files regardless of Workers, because per-alert PCG seeds are derived sequentially from a master RNG before workers start.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrUnknownClass    = errors.New("mockalerts: unknown finding class")
	ErrUnknownCategory = errors.New("mockalerts: unknown finding category")
	ErrEmptyCatalog    = errors.New("mockalerts: provider catalog is empty")
)

Sentinel errors returned by Provider methods and WriteN.

Functions

func WriteN

func WriteN(ctx context.Context, p Provider, dir string, n int, opts Options) error

WriteN generates n envelopes from p and writes each to dir as an individual JSON file named "<FilePrefix><zero-padded-index>.json".

Determinism: same Seed and n produce byte-identical files regardless of Workers, because per-alert PCG seeds are pre-allocated sequentially from a master RNG before workers start.

On error mid-run, already-written files are retained on disk. The directory is not cleared beforehand; pre-existing files at the same indices are overwritten.

Example
package main

import (
	"context"
	"fmt"
	"os"

	secmock "github.com/coderite/secmock"
	"github.com/coderite/secmock/providers/gcp"

	_ "github.com/coderite/secmock/providers/gcp/categories"
)

func main() {
	dir, _ := os.MkdirTemp("", "alerts-example-")
	defer os.RemoveAll(dir)

	err := secmock.WriteN(context.Background(), gcp.New(), dir, 5,
		secmock.Options{
			Seed:    42,
			Workers: 2,
			Mode:    secmock.ModeByClass,
			Class:   gcp.ClassThreat,
		})
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	entries, _ := os.ReadDir(dir)
	fmt.Println("files written:", len(entries))
}
Output:
files written: 5

Types

type Catalog

type Catalog map[string][]string

Catalog maps a finding class name to its supported categories.

type Mode

type Mode int

Mode selects how WriteN draws alerts.

const (
	ModeRandom Mode = iota
	ModeByClass
	ModeByCategory
)

type Options

type Options struct {
	// Seed for the master PCG RNG; 0 means time-based.
	Seed uint64

	// Workers is the number of goroutines doing template + marshal + write.
	// 0 uses runtime.GOMAXPROCS(0).
	Workers int

	// Indent toggles pretty-printed JSON output.
	Indent bool

	// FilePrefix overrides the default "alert-" prefix.
	FilePrefix string

	// Mode selects generation strategy.
	Mode Mode

	// Class is required when Mode != ModeRandom.
	Class string

	// Category is required when Mode == ModeByCategory.
	Category string

	// OnProgress, if non-nil, is invoked after each successful file write
	// with the running total. Called from worker goroutines; the callback
	// MUST be safe to invoke concurrently.
	OnProgress func(written int)
}

Options configures a WriteN run.

type Provider

type Provider interface {
	// Name returns the provider identifier ("gcp", "azure", "aws").
	Name() string

	// Random returns a random envelope drawn uniformly across classes.
	Random(r *rand.Rand) (proto.Message, error)

	// ByClass returns an envelope for a random category within the given class.
	ByClass(class string, r *rand.Rand) (proto.Message, error)

	// ByCategory returns an envelope for the specific class+category.
	ByCategory(class, category string, r *rand.Rand) (proto.Message, error)

	// Catalog returns the supported classes and their categories.
	Catalog() Catalog
}

Provider generates mock security alerts for a single cloud provider.

Directories

Path Synopsis
internal
jsonwrite
Package jsonwrite provides pooled buffers and atomic file writes for the bulk-alert pipeline.
Package jsonwrite provides pooled buffers and atomic file writes for the bulk-alert pipeline.
providers
gcp
gcp/categories
Package categories registers the built-in GCP SCC category templates.
Package categories registers the built-in GCP SCC category templates.
gcp/faker
Package faker produces deterministic GCP-shaped fake data for SCC findings.
Package faker produces deterministic GCP-shaped fake data for SCC findings.

Jump to

Keyboard shortcuts

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