Documentation
¶
Overview ¶
Package pack is the SDK for building simrun simulation packs — standalone binaries that simrun invokes over a JSON stdin/stdout protocol to detonate attacks and report results.
Package pack provides the SDK for building simulation packs.
Index ¶
- Constants
- func CleanupLogger(input CleanupInput) *logrus.Entry
- func ExecutionIDFromContext(ctx context.Context) string
- func GetInt(m map[string]any, key string) (int, bool)
- func GetString(m map[string]any, key string) (string, bool)
- func ListSimulations() []string
- func Logger(input DetonateInput) *logrus.Entry
- func Register(s Simulation)
- func RegisterPackParams(params ...PackParam)
- func RegisterTemplate(t Template)
- func Run()
- func SetPackInfo(name, version, minSimrun string)
- func UserAgent(executionID string) string
- func Wait(ctx context.Context, duration time.Duration) error
- func WaitFor(ctx context.Context, interval, timeout time.Duration, condition func() bool) error
- func WithExecutionID(ctx context.Context, executionID string) context.Context
- type CleanupFunc
- type CleanupInput
- type DetonateFunc
- type DetonateInput
- type Error
- type LogLine
- type MITREMapping
- type ManifestInput
- type ManifestResponse
- type PackInfo
- type PackParam
- type Result
- type SSHClient
- type SSHConfig
- type Simulation
- type SimulationManifest
- type Template
- type TemplateManifest
Constants ¶
const ( LogLevelDebug = "debug" LogLevelInfo = "info" LogLevelWarn = "warn" LogLevelError = "error" )
Log levels.
const ( // SSHLoggingEnabledEnvVar enables SSH command output logging when set to "true". SSHLoggingEnabledEnvVar = "SR_SSH_LOGGING_ENABLED" // SSHLogDirEnvVar specifies the directory for SSH log files. SSHLogDirEnvVar = "SR_SSH_LOG_DIR" )
const ( PackParamTypeString = "string" PackParamTypeBoolean = "boolean" PackParamTypeObjectStringMap = "object_string_map" )
PackParam Type constants.
const ( StatusSuccess = "success" StatusError = "error" )
Status values for results.
const ( ErrCodePermissionDenied = "PERMISSION_DENIED" ErrCodeResourceNotFound = "RESOURCE_NOT_FOUND" ErrCodeTimeout = "TIMEOUT" ErrCodeInvalidParams = "INVALID_PARAMS" ErrCodeInternalError = "INTERNAL_ERROR" )
Standard error codes.
Variables ¶
This section is empty.
Functions ¶
func CleanupLogger ¶
func CleanupLogger(input CleanupInput) *logrus.Entry
CleanupLogger returns a structured logger for cleanup operations.
func ExecutionIDFromContext ¶
ExecutionIDFromContext retrieves the execution ID from context. Returns empty string if not found.
func GetInt ¶
GetInt safely extracts an integer value from a map[string]any. Handles both int and float64 (common when unmarshaling JSON).
func ListSimulations ¶
func ListSimulations() []string
ListSimulations returns the IDs of all registered simulations.
func Logger ¶
func Logger(input DetonateInput) *logrus.Entry
Logger returns a structured logger for detonate operations.
func Register ¶
func Register(s Simulation)
Register registers a simulation with the SDK. Call this from your simulation's init() function. The ID should be a lean slug (e.g., "ec2-bitcoin-mining"). The SDK combines it with Scope to form the simulation ID (scope.slug, e.g., "aws.ec2-bitcoin-mining") used in the manifest and wire protocol.
func RegisterPackParams ¶
func RegisterPackParams(params ...PackParam)
RegisterPackParams declares one or more custom pack-level parameters. Pack authors call this from main() near pack.SetPackInfo. The function validates each PackParam synchronously and panics on author bugs (reserved-name collision, duplicate name, default-vs-type mismatch, enum-on-non-string).
func RegisterTemplate ¶
func RegisterTemplate(t Template)
RegisterTemplate registers an injection template with the SDK. Call this from your template package's init() function. The ID should be a lean slug (e.g., "add-group-member"). The SDK combines it with Scope to form the template ID (scope.slug, e.g., "okta.add-group-member") used in the manifest.
func Run ¶
func Run()
Run is the main entrypoint for a pack. Call this from main(). It parses CLI arguments and dispatches to the appropriate handler.
func SetPackInfo ¶
func SetPackInfo(name, version, minSimrun string)
SetPackInfo sets the pack metadata. Call this before Run().
func UserAgent ¶
UserAgent returns the formatted User-Agent string for the given execution ID. Format: "simrun/<version> (<execution_id>)" Returns empty string if executionID is empty.
Types ¶
type CleanupFunc ¶
type CleanupFunc func(ctx context.Context, input CleanupInput) error
CleanupFunc is the signature for a simulation's Cleanup function.
type CleanupInput ¶
type CleanupInput struct {
Simulation string `json:"simulation"`
ExecutionID string `json:"execution_id"`
Params map[string]any `json:"params"`
DetonationResult *Result `json:"detonation_result,omitempty"`
}
CleanupInput is the wire format for the cleanup command input. The Simulation field is used by the SDK for routing and can be ignored by simulation handlers.
type DetonateFunc ¶
type DetonateFunc func(ctx context.Context, input DetonateInput) (*Result, error)
DetonateFunc is the signature for a simulation's Detonate function.
type DetonateInput ¶
type DetonateInput struct {
Simulation string `json:"simulation"`
ExecutionID string `json:"execution_id"`
Params map[string]any `json:"params"`
TerraformOutputs map[string]string `json:"terraform_outputs"`
}
DetonateInput is the wire format for the detonate command input. The Simulation field is used by the SDK for routing and can be ignored by simulation handlers.
type LogLine ¶
type LogLine struct {
Level string `json:"level"`
Msg string `json:"msg"`
Simulation string `json:"simulation,omitempty"`
ExecutionID string `json:"execution_id,omitempty"`
Pack string `json:"pack,omitempty"`
PackVersion string `json:"pack_version,omitempty"`
Timestamp string `json:"ts"`
Extra map[string]any `json:"-"` // Additional fields not in the struct
}
LogLine represents a JSON log line written to stderr by a pack.
func (*LogLine) UnmarshalJSON ¶
UnmarshalJSON implements custom unmarshaling to capture extra fields.
type MITREMapping ¶
type MITREMapping struct {
Tactics []string `json:"tactics"` // MITRE tactic IDs (e.g., ["TA0040"])
Techniques []string `json:"techniques"` // MITRE technique IDs (e.g., ["T1496"])
}
MITREMapping represents MITRE ATT&CK framework mappings for a simulation.
type ManifestInput ¶
ManifestInput is the input to the manifest command, read from stdin. Parameters are optional key-value configuration provided by simrun. The "default_tags" key is treated specially: its value (a string map) is injected as default tags/labels into all simulations' Terraform.
type ManifestResponse ¶
type ManifestResponse struct {
Pack PackInfo `json:"pack"`
Simulations []SimulationManifest `json:"simulations"`
Templates []TemplateManifest `json:"templates,omitempty"`
ParamsSchema json.RawMessage `json:"params_schema,omitempty"`
}
ManifestResponse is the response from the manifest command.
type PackInfo ¶
type PackInfo struct {
Name string `json:"name"`
Version string `json:"version"`
MinSimrunVersion string `json:"min_simrun_version"`
}
PackInfo contains pack metadata.
type PackParam ¶
type PackParam struct {
// Name is the parameter key. Must be unique across custom params and must
// not collide with a reserved built-in name.
Name string
// Type is one of "string", "boolean", "object_string_map".
Type string
// Description is human-readable help text shown in the UI.
Description string
// Default is the default value used when the operator does not set the
// param. Must match Type: string for "string", bool for "boolean",
// map[string]string for "object_string_map".
Default any
// Required marks the param as mandatory. Backend validation rejects a
// PUT /api/packs/{name}/parameters that omits a required param.
Required bool
// Enum, when non-empty, restricts a "string"-typed param's allowed values.
// Invalid on any non-string type.
Enum []string
}
PackParam declares a pack-level parameter that the pack exposes to operators. Authors register custom params via RegisterPackParams; the SDK ships a fixed set of built-in params (default_tags, aws_region, etc.) in addition.
type Result ¶
type Result struct {
Status string `json:"status"`
Indicators map[string]any `json:"indicators,omitempty"`
Error *Error `json:"error,omitempty"`
}
Result is the output from a Detonate or Cleanup operation.
func ErrorResult ¶
ErrorResult creates an error result with the given code and message.
func RequireString ¶
RequireString extracts a required string from a map[string]any and returns an error Result if missing or empty. Useful for extracting values from input.Params.
Example:
region, errResult := pack.RequireString(input.Params, "region")
if errResult != nil {
return errResult, nil
}
func SuccessResult ¶
SuccessResult creates a successful result with the given indicators.
type SSHClient ¶
type SSHClient struct {
// contains filtered or unexported fields
}
SSHClient represents an SSH connection for executing remote commands.
func NewSSHClient ¶
NewSSHClient creates an SSH client from config.
func SSHClientFromTerraform ¶
SSHClientFromTerraform creates an SSH client from terraform outputs in one call. This combines SSHFromTerraform and NewSSHClient into a single convenience function.
type SSHConfig ¶
type SSHConfig struct {
Host string // Required: IP or hostname
Username string // Required: SSH username
PrivateKeyPath string // Path to private key file
ConnectTimeout time.Duration // Default: 30s
}
SSHConfig configures SSH connection parameters.
func SSHFromTerraform ¶
SSHFromTerraform extracts SSH config from terraform outputs. It looks for the following standard output names:
- attacker_vm_public_ip: Host IP address
- attacker_vm_user: SSH username
- attacker_vm_private_key_path: Path to private key file
type Simulation ¶
type Simulation struct {
// ID is the simulation slug (e.g., "ec2-bitcoin-mining").
// The SDK generates the full qualified ID (scope.slug) at manifest time.
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
MITRE MITREMapping `json:"mitre"`
Scope string `json:"scope"` // Required: aws, gcp, azure, generic
IsSlow bool `json:"is_slow,omitempty"`
RequiresExternalResources bool `json:"requires_external_resources,omitempty"`
ParamsSchema any `json:"params_schema,omitempty"`
Terraform string `json:"-"` // raw HCL content, typically from //go:embed
// RequiredOutputs lists the Terraform output names that Detonate reads
// from DetonateInput.TerraformOutputs. The SDK validates these against
// the embedded Terraform body at Register time and panics if any are
// missing, so authors find sim/TF contract drift at boot rather than
// after a real `terraform apply`. Leave nil to skip validation.
RequiredOutputs []string `json:"-"`
Detonate DetonateFunc `json:"-"`
Cleanup CleanupFunc `json:"-"`
}
Simulation represents a fully registered simulation with metadata, Terraform, and handlers. Use Register() in your simulation's init() function to register simulations.
func GetSimulation ¶
func GetSimulation(id string) (*Simulation, bool)
GetSimulation returns a registered simulation by ID (scope.slug).
type SimulationManifest ¶
type SimulationManifest struct {
ID string `json:"id"` // Simulation ID: scope.slug (e.g., "aws.ec2-bitcoin-mining")
Name string `json:"name"`
Description string `json:"description"`
MITRE MITREMapping `json:"mitre"`
Scope string `json:"scope"`
IsSlow bool `json:"is_slow,omitempty"`
RequiresExternalResources bool `json:"requires_external_resources,omitempty"`
ParamsSchema json.RawMessage `json:"params_schema,omitempty"`
Terraform string `json:"terraform,omitempty"` // base64-encoded
HasCustomCleanup bool `json:"has_custom_cleanup"`
}
SimulationManifest is the manifest entry for a single simulation.
type Template ¶
type Template struct {
// ID is the template slug (e.g., "add-group-member").
// The SDK generates the full qualified ID (scope.slug) at manifest time.
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Scope string `json:"scope"` // Required: okta, aws, gcp, azure, generic
Content string `json:"-"` // Raw template content, typically from //go:embed
}
Template represents an injection template with metadata.
type TemplateManifest ¶
type TemplateManifest struct {
ID string `json:"id"` // Template ID: scope.slug (e.g., "okta.add-group-member")
Name string `json:"name"`
Description string `json:"description"`
Scope string `json:"scope"`
Content string `json:"content"` // Base64-encoded template content
Vars map[string]string `json:"vars,omitempty"` // Variable names to default values, extracted from template
}
TemplateManifest is the manifest entry for an injection template.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package aws provides AWS SDK helpers for simulation packs.
|
Package aws provides AWS SDK helpers for simulation packs. |
|
Package azure provides Azure SDK helpers for simulation packs.
|
Package azure provides Azure SDK helpers for simulation packs. |
|
Package gcp provides GCP SDK helpers for simulation packs.
|
Package gcp provides GCP SDK helpers for simulation packs. |