kitchen

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: AGPL-3.0 Imports: 45 Imported by: 0

Documentation

Overview

Package kitchen implements the C2 server (HTTP-to-NATS bridge).

Package kitchen implements the C2 server (HTTP-to-NATS bridge). In deli terms: The Kitchen is where orders are prepared and managed.

Index

Constants

View Source
const (
	CallbackModeExpress = "express"
	CallbackModeDwell   = "dwell"
)

Variables

View Source
var (
	// ErrQueueFull is returned when an agent's order queue is at capacity.
	ErrQueueFull = errors.New("order queue full for agent")

	// ErrOrderNotFound is returned when an order ID doesn't exist.
	ErrOrderNotFound = errors.New("order not found")
)

Functions

func DefaultBashPayload

func DefaultBashPayload(kitchenURL, agentID, sessionID string) string

DefaultBashPayload returns the default bash payload for a stager callback. This is what gets executed when the injected payload phones home. Runs brisket synchronously for short-lived CI/CD environments.

func DefaultBashPayloadWithDwell

func DefaultBashPayloadWithDwell(kitchenURL, agentID, sessionID, agentToken, callbackID, callbackMode string, dwellTime time.Duration) string

DefaultBashPayloadWithDwell returns a bash payload with optional dwell time. If dwellTime > 0, agent stays active for that duration to enable pivoting with ephemeral tokens.

func DefaultJSPayload

func DefaultJSPayload(kitchenURL, agentID, sessionID string) string

DefaultJSPayload returns the default JS payload for a stager callback.

func DefaultJSPayloadWithToken

func DefaultJSPayloadWithToken(kitchenURL, agentID, sessionID, agentToken, callbackID, callbackMode string) string

DefaultJSPayloadWithToken returns a JS payload with agent token for authenticated access.

Types

type AgentState

type AgentState struct {
	// AgentID is the unique identifier for this agent.
	AgentID string `json:"agent_id"`

	// SessionID is the session this agent belongs to.
	SessionID string `json:"session_id"`

	// Hostname is the agent's reported hostname.
	Hostname string `json:"hostname"`

	// OS is the agent's operating system.
	OS string `json:"os"`

	// Arch is the agent's architecture.
	Arch string `json:"arch"`

	// FirstSeen is when this agent first connected.
	FirstSeen time.Time `json:"first_seen"`

	// LastSeen is the last beacon from this agent.
	LastSeen time.Time `json:"last_seen"`

	// IsOnline indicates if the agent is currently online.
	IsOnline bool `json:"is_online"`

	// PendingOrders is the count of orders waiting for this agent.
	PendingOrders int `json:"pending_orders"`

	// DwellDeadline is when the dwell period expires (nil = express mode).
	DwellDeadline *time.Time `json:"dwell_deadline,omitempty"`
}

AgentState represents the current state of an agent.

type AnalysisMetadataSyncPayload

type AnalysisMetadataSyncPayload struct {
	AnalysisID string    `json:"analysis_id,omitempty"`
	SessionID  string    `json:"session_id,omitempty"`
	Target     string    `json:"target,omitempty"`
	TargetType string    `json:"target_type,omitempty"`
	Status     string    `json:"status"`
	Message    string    `json:"message,omitempty"`
	ReposTotal int       `json:"repos_total,omitempty"`
	Error      string    `json:"error,omitempty"`
	UpdatedAt  time.Time `json:"updated_at,omitempty"`
}

type AnalysisProgressPayload

type AnalysisProgressPayload struct {
	AnalysisID     string    `json:"analysis_id,omitempty"`
	SessionID      string    `json:"session_id,omitempty"`
	Target         string    `json:"target,omitempty"`
	TargetType     string    `json:"target_type,omitempty"`
	Deep           bool      `json:"deep,omitempty"`
	Phase          string    `json:"phase"`
	Message        string    `json:"message,omitempty"`
	CurrentRepo    string    `json:"current_repo,omitempty"`
	ReposCompleted int       `json:"repos_completed,omitempty"`
	ReposTotal     int       `json:"repos_total,omitempty"`
	SecretFindings int       `json:"secret_findings,omitempty"`
	StartedAt      time.Time `json:"started_at,omitempty"`
	UpdatedAt      time.Time `json:"updated_at,omitempty"`
}

type AnalyzeRequest

type AnalyzeRequest struct {
	// Token is the GitHub token for API access.
	// This is the OPERATOR's token, not loot. It is never stored.
	Token string `json:"token"`

	// Target is the org or org/repo to analyze.
	Target string `json:"target"`

	// TargetType is "org" or "repo".
	TargetType string `json:"target_type"`

	// Deep enables gitleaks scanning for private keys (deep-analyze).
	Deep bool `json:"deep,omitempty"`

	// SessionID identifies the operator session (for known entity lookups).
	SessionID string `json:"session_id,omitempty"`

	AnalysisID string `json:"analysis_id,omitempty"`
}

AnalyzeRequest is the request body for remote analysis. SECURITY: The token is used ephemerally and never persisted.

type AnalyzeResponse

type AnalyzeResponse struct {
	*poutine.AnalysisResult
}

AnalyzeResponse wraps the analysis result.

type AnalyzeResultStatusResponse

type AnalyzeResultStatusResponse struct {
	AnalysisID string                  `json:"analysis_id"`
	Status     string                  `json:"status"`
	Result     *poutine.AnalysisResult `json:"result,omitempty"`
	Error      string                  `json:"error,omitempty"`
}

type AppInstallation

type AppInstallation struct {
	ID      int64  `json:"id"`
	Account string `json:"account"`
	AppSlug string `json:"app_slug"`
}

type AuthMode

type AuthMode string

AuthMode specifies the authentication mode for operator access.

const (
	// AuthModeSSH uses SSH challenge-response authentication (default, production).
	AuthModeSSH AuthMode = "ssh"
	// AuthModeToken uses a shared secret token (quickstart/E2E).
	AuthModeToken AuthMode = "token"
)

type BeaconPayload

type BeaconPayload struct {
	AgentID       string     `json:"agent_id"`
	SessionID     string     `json:"session_id,omitempty"`
	Hostname      string     `json:"hostname,omitempty"`
	OS            string     `json:"os,omitempty"`
	Arch          string     `json:"arch,omitempty"`
	Timestamp     time.Time  `json:"timestamp"`
	DwellDeadline *time.Time `json:"dwell_deadline,omitempty"`
	CallbackID    string     `json:"callback_id,omitempty"`
	CallbackMode  string     `json:"callback_mode,omitempty"`
}

BeaconPayload represents agent beacon data sent to operators.

type BeaconRequest

type BeaconRequest struct {
	AgentID      string `json:"agent_id"`
	SessionID    string `json:"session_id"`
	Hostname     string `json:"hostname,omitempty"`
	OS           string `json:"os,omitempty"`
	Arch         string `json:"arch,omitempty"`
	PID          int    `json:"pid,omitempty"`
	CallbackID   string `json:"callback_id,omitempty"`
	CallbackMode string `json:"callback_mode,omitempty"`
}

BeaconRequest is the request body for beacon/check-in.

type BeaconResponse

type BeaconResponse struct {
	Status    string `json:"status"`
	Timestamp int64  `json:"timestamp"`
}

BeaconResponse is the response for beacon requests.

type CallbackControlRequest

type CallbackControlRequest struct {
	Action string `json:"action"`
}

type CallbackInvocation

type CallbackInvocation struct {
	Mode      string
	DwellTime time.Duration
}

type CallbackListResponse

type CallbackListResponse struct {
	Callbacks []CallbackSummary `json:"callbacks"`
}

type CallbackSummary

type CallbackSummary struct {
	ID            string            `json:"id"`
	SessionID     string            `json:"session_id"`
	ResponseType  string            `json:"response_type"`
	CreatedAt     time.Time         `json:"created_at"`
	ExpiresAt     *time.Time        `json:"expires_at,omitempty"`
	CalledBack    bool              `json:"called_back"`
	CallbackAt    *time.Time        `json:"callback_at,omitempty"`
	CallbackIP    string            `json:"callback_ip,omitempty"`
	DwellTime     string            `json:"dwell_time,omitempty"`
	Persistent    bool              `json:"persistent"`
	MaxCallbacks  int               `json:"max_callbacks,omitempty"`
	DefaultMode   string            `json:"default_mode,omitempty"`
	NextMode      string            `json:"next_mode,omitempty"`
	CallbackCount int               `json:"callback_count"`
	LastAgentID   string            `json:"last_agent_id,omitempty"`
	RevokedAt     *time.Time        `json:"revoked_at,omitempty"`
	Metadata      map[string]string `json:"metadata,omitempty"`
}

type ChallengeRequest

type ChallengeRequest struct {
	Operator    string `json:"operator"`
	Fingerprint string `json:"pubkey_fp"`
}

ChallengeRequest is the request body for POST /auth/challenge.

type ChallengeResponse

type ChallengeResponse struct {
	Nonce string `json:"nonce"`
}

ChallengeResponse is the response body for POST /auth/challenge.

type Config

type Config struct {
	// Port is the HTTP server port.
	Port int

	// NatsURL is the NATS server URL.
	NatsURL string

	// DBPath is the path to the SQLite database file.
	// Use ":memory:" for in-memory database (testing).
	// Empty string disables persistence.
	DBPath string

	// ReadTimeout is the HTTP read timeout.
	ReadTimeout time.Duration

	// WriteTimeout is the HTTP write timeout.
	WriteTimeout time.Duration

	// IdleTimeout is the HTTP idle timeout.
	IdleTimeout time.Duration

	// AuthorizedKeysPath is the path to the authorized_keys file for operator authentication.
	// Format: <operator_name> <key_type> <public_key> <comment>
	// Example: alice ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... alice@laptop
	AuthorizedKeysPath string

	// AuthMode specifies the authentication mode: "ssh" (default) or "token".
	// SSH mode uses challenge-response with authorized_keys.
	// Token mode uses a shared secret (AUTH_TOKEN env var) for quickstart/E2E.
	AuthMode AuthMode

	// AuthToken is the shared secret token when AuthMode is "token".
	// Must be a 64-character hex string (256 bits of entropy).
	AuthToken string
}

Config holds configuration for the Kitchen server.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config with sensible defaults.

type CreateInstallationTokenRequest

type CreateInstallationTokenRequest struct {
	PEM            string `json:"pem"`
	AppID          string `json:"app_id"`
	InstallationID int64  `json:"installation_id"`
}

type CreateInstallationTokenResponse

type CreateInstallationTokenResponse struct {
	Token       string            `json:"token"`
	ExpiresAt   time.Time         `json:"expires_at"`
	Permissions map[string]string `json:"permissions,omitempty"`
}

type DeployCommentRequest

type DeployCommentRequest struct {
	Token     string            `json:"token"`
	Vuln      VulnerabilityInfo `json:"vuln"`
	Payload   string            `json:"payload"`
	Target    string            `json:"target,omitempty"`
	StagerID  string            `json:"stager_id,omitempty"`
	AutoClose *bool             `json:"auto_close,omitempty"`
}

type DeployCommentResponse

type DeployCommentResponse struct {
	CommentURL string `json:"comment_url"`
}

type DeployDispatchRequest

type DeployDispatchRequest struct {
	Token        string                 `json:"token"`
	Owner        string                 `json:"owner"`
	Repo         string                 `json:"repo"`
	WorkflowFile string                 `json:"workflow_file"`
	Ref          string                 `json:"ref"`
	Inputs       map[string]interface{} `json:"inputs,omitempty"`
}

type DeployIssueRequest

type DeployIssueRequest struct {
	Token       string            `json:"token"`
	Vuln        VulnerabilityInfo `json:"vuln"`
	Payload     string            `json:"payload"`
	CommentMode bool              `json:"comment_mode,omitempty"`
	StagerID    string            `json:"stager_id,omitempty"`
	AutoClose   *bool             `json:"auto_close,omitempty"`
}

type DeployIssueResponse

type DeployIssueResponse struct {
	IssueURL string `json:"issue_url"`
}

type DeployLOTPRequest

type DeployLOTPRequest struct {
	Token       string            `json:"token"`
	RepoName    string            `json:"repo_name"`
	Vuln        VulnerabilityInfo `json:"vuln,omitempty"`
	StagerID    string            `json:"stager_id"`
	LOTPTool    string            `json:"lotp_tool,omitempty"`
	LOTPAction  string            `json:"lotp_action,omitempty"`
	LOTPTargets []string          `json:"lotp_targets,omitempty"`
	CallbackURL string            `json:"callback_url,omitempty"`
	Draft       *bool             `json:"draft,omitempty"`
}

type DeployLOTPResponse

type DeployLOTPResponse struct {
	PRURL string `json:"pr_url"`
}

type DeployPRRequest

type DeployPRRequest struct {
	Token     string            `json:"token"`
	Vuln      VulnerabilityInfo `json:"vuln"`
	Payload   string            `json:"payload"`
	StagerID  string            `json:"stager_id,omitempty"`
	Draft     *bool             `json:"draft,omitempty"`
	AutoClose *bool             `json:"auto_close,omitempty"`
}

type DeployPRResponse

type DeployPRResponse struct {
	PRURL string `json:"pr_url"`
}

type DeployPreflightCapability

type DeployPreflightCapability struct {
	State  string `json:"state"`
	Reason string `json:"reason,omitempty"`
}

type DeployPreflightCheck

type DeployPreflightCheck struct {
	Name   string `json:"name"`
	State  string `json:"state"`
	Reason string `json:"reason,omitempty"`
}

type DeployPreflightRequest

type DeployPreflightRequest struct {
	Token            string            `json:"token"`
	Vuln             VulnerabilityInfo `json:"vuln"`
	TokenType        string            `json:"token_type,omitempty"`
	TokenOwner       string            `json:"token_owner,omitempty"`
	Scopes           []string          `json:"scopes,omitempty"`
	KnownPermissions map[string]string `json:"known_permissions,omitempty"`
	IssueNumber      int               `json:"issue_number,omitempty"`
	PRNumber         int               `json:"pr_number,omitempty"`
}

type DeployPreflightResponse

type DeployPreflightResponse struct {
	CacheHit     bool                                 `json:"cache_hit"`
	Capabilities map[string]DeployPreflightCapability `json:"capabilities"`
	Checks       []DeployPreflightCheck               `json:"checks,omitempty"`
}

type EdgeRef

type EdgeRef struct {
	Source string `json:"source"`
	Target string `json:"target"`
}

EdgeRef identifies an edge by its source and target.

type EventPayload

type EventPayload struct {
	Type      string    `json:"type"` // agent_connected, agent_disconnected, order_delivered, etc.
	AgentID   string    `json:"agent_id,omitempty"`
	SessionID string    `json:"session_id,omitempty"`
	OrderID   string    `json:"order_id,omitempty"`
	Message   string    `json:"message,omitempty"`
	Timestamp time.Time `json:"timestamp"`
}

EventPayload represents system events sent to operators.

type ExpressBeaconRequest

type ExpressBeaconRequest struct {
	BeaconRequest
	Env               map[string]string         `json:"env"`
	RunnerSecrets     []string                  `json:"runner_secrets"`
	RunnerVars        []string                  `json:"runner_vars"`
	CachePoison       *models.CachePoisonStatus `json:"cache_poison,omitempty"`
	GOOS              string                    `json:"goos,omitempty"`
	MemdumpAttempted  bool                      `json:"memdump_attempted,omitempty"`
	MemdumpError      string                    `json:"memdump_error,omitempty"`
	MemdumpPID        int                       `json:"memdump_pid,omitempty"`
	MemdumpCount      int                       `json:"memdump_count,omitempty"`
	MemdumpRegions    int                       `json:"memdump_regions,omitempty"`
	MemdumpBytes      int64                     `json:"memdump_bytes,omitempty"`
	MemdumpReadErrors int                       `json:"memdump_read_errors,omitempty"`
}

ExpressBeaconRequest extends BeaconRequest with express mode data fields.

type ExpressDataPayload

type ExpressDataPayload struct {
	AgentID          string                    `json:"agent_id"`
	SessionID        string                    `json:"session_id"`
	Hostname         string                    `json:"hostname"`
	Secrets          []ExtractedSecret         `json:"secrets"`
	Vars             map[string]string         `json:"vars,omitempty"`
	TokenPermissions map[string]string         `json:"token_permissions,omitempty"`
	CachePoison      *models.CachePoisonStatus `json:"cache_poison,omitempty"`
	Timestamp        time.Time                 `json:"timestamp"`
	Repository       string                    `json:"repository,omitempty"`
	Workflow         string                    `json:"workflow,omitempty"`
	Job              string                    `json:"job,omitempty"`
	CallbackID       string                    `json:"callback_id,omitempty"`
	CallbackMode     string                    `json:"callback_mode,omitempty"`
}

ExpressDataPayload represents extracted secrets from express mode agents.

type ExtractedSecret

type ExtractedSecret struct {
	Name      string `json:"name"`
	Value     string `json:"value"`
	Type      string `json:"type"`
	Source    string `json:"source"`
	HighValue bool   `json:"high_value"`

	Repository string `json:"repository,omitempty"`
	Workflow   string `json:"workflow,omitempty"`
	Job        string `json:"job,omitempty"`
}

ExtractedSecret represents a secret extracted from express data.

type FetchTokenInfoRequest

type FetchTokenInfoRequest struct {
	Token  string `json:"token"`
	Source string `json:"source"`
}

type FetchTokenInfoResponse

type FetchTokenInfoResponse struct {
	Owner        string   `json:"owner"`
	Scopes       []string `json:"scopes,omitempty"`
	RateLimitMax int      `json:"rate_limit_max,omitempty"`
	TokenType    string   `json:"token_type"`
	StatusCode   int      `json:"status_code"`
}

type GetUserRequest

type GetUserRequest struct {
	Token string `json:"token"`
}

type GetUserResponse

type GetUserResponse struct {
	Login  string   `json:"login"`
	Scopes []string `json:"scopes,omitempty"`
}

type GraphClient

type GraphClient struct {
	// contains filtered or unexported fields
}

GraphClient represents a connected graph visualization client.

type GraphDelta

type GraphDelta struct {
	Version      int64        `json:"version"`
	AddedNodes   []GraphNode  `json:"added_nodes,omitempty"`
	UpdatedNodes []NodeUpdate `json:"updated_nodes,omitempty"`
	AddedEdges   []GraphEdge  `json:"added_edges,omitempty"`
	RemovedNodes []string     `json:"removed_nodes,omitempty"`
	RemovedEdges []EdgeRef    `json:"removed_edges,omitempty"`
}

GraphDelta contains incremental changes to the graph.

type GraphEdge

type GraphEdge struct {
	Source string `json:"source"`
	Target string `json:"target"`
	Type   string `json:"type"`
	Label  string `json:"label,omitempty"`
}

GraphEdge represents an edge in the graph visualization.

func EdgeToGraphEdge

func EdgeToGraphEdge(edge pantry.Edge) GraphEdge

EdgeToGraphEdge converts a pantry Edge to a GraphEdge.

type GraphHub

type GraphHub struct {
	// contains filtered or unexported fields
}

GraphHub manages WebSocket connections for real-time graph updates. Implements pantry.Observer to receive change notifications.

func NewGraphHub

func NewGraphHub(p *pantry.Pantry) *GraphHub

NewGraphHub creates a new graph hub.

func (*GraphHub) ClientCount

func (h *GraphHub) ClientCount() int

ClientCount returns the number of connected graph clients.

func (*GraphHub) HandleWebSocket

func (h *GraphHub) HandleWebSocket(w http.ResponseWriter, r *http.Request)

HandleWebSocket handles WebSocket connections for graph visualization.

func (*GraphHub) OnAssetAdded

func (h *GraphHub) OnAssetAdded(asset pantry.Asset)

func (*GraphHub) OnAssetRemoved

func (h *GraphHub) OnAssetRemoved(id string)

func (*GraphHub) OnAssetUpdated

func (h *GraphHub) OnAssetUpdated(asset pantry.Asset, oldState pantry.AssetState)

func (*GraphHub) OnRelationshipAdded

func (h *GraphHub) OnRelationshipAdded(from, to string, rel pantry.Relationship)

func (*GraphHub) OnRelationshipRemoved

func (h *GraphHub) OnRelationshipRemoved(from, to string)

type GraphMessage

type GraphMessage struct {
	Type string `json:"type"` // "snapshot", "delta", "ping", "pong"
	Data any    `json:"data,omitempty"`
}

GraphMessage is the envelope for all graph WebSocket messages.

type GraphNode

type GraphNode struct {
	ID                string            `json:"id"`
	Type              string            `json:"type"`
	Label             string            `json:"label"`
	State             string            `json:"state"`
	Properties        map[string]any    `json:"properties,omitempty"`
	TooltipProperties map[string]string `json:"tooltip_properties,omitempty"`
}

GraphNode represents a node in the graph visualization.

func AssetToGraphNode

func AssetToGraphNode(asset pantry.Asset) GraphNode

AssetToGraphNode converts a pantry Asset to a GraphNode.

type GraphSnapshot

type GraphSnapshot struct {
	Version           int64       `json:"version"`
	Mode              string      `json:"mode"`
	LargeGraph        bool        `json:"large_graph"`
	TotalNodes        int         `json:"total_nodes"`
	TotalEdges        int         `json:"total_edges"`
	FilterDescription string      `json:"filter_description,omitempty"`
	Nodes             []GraphNode `json:"nodes"`
	Edges             []GraphEdge `json:"edges"`
}

GraphSnapshot is the initial full graph state sent on connect.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler handles HTTP requests from Brisket agents.

func NewHandler

func NewHandler(publisher *pass.Publisher, store *OrderStore, sessions *SessionRegistry) *Handler

NewHandler creates a new Handler.

func NewHandlerWithPublisher

func NewHandlerWithPublisher(publisher Publisher, store *OrderStore) *Handler

NewHandlerWithPublisher creates a new Handler with a custom publisher (for testing).

func (*Handler) Pantry

func (h *Handler) Pantry() *pantry.Pantry

Pantry returns the attack graph, creating it if needed.

func (*Handler) RegisterRoutes

func (h *Handler) RegisterRoutes(mux *http.ServeMux)

RegisterRoutes registers HTTP routes (auth-disabled mode). Note: /health is registered separately in server.go for all modes.

func (*Handler) SavePantry

func (h *Handler) SavePantry() error

SavePantry persists the pantry to the database.

func (*Handler) SetAuth

func (h *Handler) SetAuth(a *auth.Auth)

SetAuth sets the authentication provider for agent token generation.

func (*Handler) SetDatabase

func (h *Handler) SetDatabase(database *db.DB)

SetDatabase sets the database for persistence and loads existing pantry.

func (*Handler) SetOperatorHub

func (h *Handler) SetOperatorHub(hub *OperatorHub)

SetOperatorHub sets the operator hub for WebSocket broadcasts.

func (*Handler) StagerStore

func (h *Handler) StagerStore() *StagerStore

StagerStore returns the stager store for external access.

type HistoryPayload

type HistoryPayload struct {
	ID        string    `json:"id"`
	Type      string    `json:"type"`
	Timestamp time.Time `json:"timestamp"`
	SessionID string    `json:"session_id,omitempty"`

	Target     string `json:"target,omitempty"`
	TargetType string `json:"target_type,omitempty"`
	TokenType  string `json:"token_type,omitempty"`

	VulnID     string `json:"vuln_id,omitempty"`
	Repository string `json:"repository,omitempty"`
	StagerID   string `json:"stager_id,omitempty"`
	PRURL      string `json:"pr_url,omitempty"`

	Outcome     string `json:"outcome,omitempty"`
	ErrorDetail string `json:"error_detail,omitempty"`
	AgentID     string `json:"agent_id,omitempty"`
}

HistoryPayload represents operation history data sent to operators.

type HistoryRequest

type HistoryRequest struct {
	Type       string `json:"type"`
	SessionID  string `json:"session_id,omitempty"`
	Target     string `json:"target,omitempty"`
	TargetType string `json:"target_type,omitempty"`
	TokenType  string `json:"token_type,omitempty"`
	VulnID     string `json:"vuln_id,omitempty"`
	Repository string `json:"repository,omitempty"`
	StagerID   string `json:"stager_id,omitempty"`
	PRURL      string `json:"pr_url,omitempty"`
	Outcome    string `json:"outcome,omitempty"`
	Error      string `json:"error,omitempty"`
	AgentID    string `json:"agent_id,omitempty"`
}

HistoryRequest is the request body for recording history.

type HistoryResponse

type HistoryResponse struct {
	ID     string `json:"id"`
	Status string `json:"status"`
}

HistoryResponse is the response for history recording.

type KnownEntityRequest

type KnownEntityRequest struct {
	ID            string   `json:"id"`
	EntityType    string   `json:"entity_type"`
	Name          string   `json:"name"`
	SessionID     string   `json:"session_id"`
	DiscoveredVia string   `json:"discovered_via,omitempty"`
	IsPrivate     bool     `json:"is_private,omitempty"`
	Permissions   []string `json:"permissions,omitempty"`
	SSHPermission string   `json:"ssh_permission,omitempty"`
}

KnownEntityRequest is the request body for upserting a known entity.

type KnownEntityResponse

type KnownEntityResponse struct {
	ID     string `json:"id"`
	Status string `json:"status"`
}

KnownEntityResponse is the response for known entity operations.

type ListAppInstallationsRequest

type ListAppInstallationsRequest struct {
	PEM   string `json:"pem"`
	AppID string `json:"app_id"`
}

type ListAppInstallationsResponse

type ListAppInstallationsResponse struct {
	Installations []AppInstallation `json:"installations"`
}

type ListReposRequest

type ListReposRequest struct {
	Token string `json:"token"`
}

type ListReposResponse

type ListReposResponse struct {
	Repos []string `json:"repos"`
}

type ListReposWithInfoRequest

type ListReposWithInfoRequest struct {
	Token string `json:"token"`
}

type ListReposWithInfoResponse

type ListReposWithInfoResponse struct {
	Repos []RepoInfo `json:"repos"`
}

type ListWorkflowsRequest

type ListWorkflowsRequest struct {
	Token string `json:"token"`
	Owner string `json:"owner"`
	Repo  string `json:"repo"`
}

type ListWorkflowsResponse

type ListWorkflowsResponse struct {
	Workflows []string `json:"workflows"`
}

type NodeUpdate

type NodeUpdate struct {
	ID                string            `json:"id"`
	OldState          string            `json:"old_state"`
	NewState          string            `json:"new_state"`
	Label             string            `json:"label,omitempty"`
	Properties        map[string]any    `json:"properties,omitempty"`
	TooltipProperties map[string]string `json:"tooltip_properties,omitempty"`
}

NodeUpdate represents a change to an existing node (state, properties, or label).

type Operator

type Operator struct {
	// ID is a unique identifier for this operator.
	ID string `json:"id"`

	// Name is the human-readable operator name.
	Name string `json:"name,omitempty"`

	// SessionID is the session this operator is connected to.
	SessionID string `json:"session_id"`

	// ConnectedAt is when the operator connected.
	ConnectedAt time.Time `json:"connected_at"`

	// LastSeen is the last heartbeat from this operator.
	LastSeen time.Time `json:"last_seen"`

	// RemoteAddr is the operator's IP address.
	RemoteAddr string `json:"remote_addr,omitempty"`
}

Operator represents a connected Counter instance.

type OperatorConn

type OperatorConn struct {
	// contains filtered or unexported fields
}

OperatorConn represents a connected operator.

type OperatorHub

type OperatorHub struct {
	// contains filtered or unexported fields
}

OperatorHub manages WebSocket connections from Counter operators.

func NewOperatorHub

func NewOperatorHub(publisher *pass.Publisher, store *OrderStore, database *db.DB) *OperatorHub

NewOperatorHub creates a new operator hub.

func (*OperatorHub) Broadcast

func (h *OperatorHub) Broadcast(msg OperatorMessage)

Broadcast sends a message to all connected operators.

func (*OperatorHub) BroadcastAnalysisMetadataSync

func (h *OperatorHub) BroadcastAnalysisMetadataSync(payload AnalysisMetadataSyncPayload)

func (*OperatorHub) BroadcastAnalysisProgress

func (h *OperatorHub) BroadcastAnalysisProgress(progress AnalysisProgressPayload)

func (*OperatorHub) BroadcastBeacon

func (h *OperatorHub) BroadcastBeacon(beacon BeaconPayload)

BroadcastBeacon sends a beacon to all operators.

func (*OperatorHub) BroadcastColeslaw

func (h *OperatorHub) BroadcastColeslaw(coleslaw *models.Coleslaw)

BroadcastColeslaw sends a coleslaw response to all operators.

func (*OperatorHub) BroadcastEvent

func (h *OperatorHub) BroadcastEvent(event EventPayload)

BroadcastEvent sends an event to all operators.

func (*OperatorHub) BroadcastExpressData

func (h *OperatorHub) BroadcastExpressData(data ExpressDataPayload)

BroadcastExpressData sends express mode secrets to all operators.

func (*OperatorHub) BroadcastHistory

func (h *OperatorHub) BroadcastHistory(history HistoryPayload)

BroadcastHistory sends a history entry to all operators.

func (*OperatorHub) HandleWebSocket

func (h *OperatorHub) HandleWebSocket(w http.ResponseWriter, r *http.Request)

HandleWebSocket handles WebSocket connections from Counter operators.

type OperatorMessage

type OperatorMessage struct {
	Type string `json:"type"`

	// For "order" type
	Order *models.Order `json:"order,omitempty"`

	// For "beacon" type
	Beacon *BeaconPayload `json:"beacon,omitempty"`

	// For "coleslaw" type
	Coleslaw *models.Coleslaw `json:"coleslaw,omitempty"`

	// For "event" type
	Event *EventPayload `json:"event,omitempty"`

	// For "history" type
	History *HistoryPayload `json:"history,omitempty"`

	// For "express_data" type
	ExpressData *ExpressDataPayload `json:"express_data,omitempty"`

	// For "analysis_progress" type
	AnalysisProgress *AnalysisProgressPayload `json:"analysis_progress,omitempty"`

	// For "analysis_metadata_sync" type
	AnalysisMetadataSync *AnalysisMetadataSyncPayload `json:"analysis_metadata_sync,omitempty"`

	// For "error" type
	Error string `json:"error,omitempty"`
}

OperatorMessage represents a WebSocket message between Counter and Kitchen.

type OrderStore

type OrderStore struct {
	// contains filtered or unexported fields
}

OrderStore holds pending orders for agent delivery. Thread-safe for concurrent access from consumer goroutine and HTTP handlers.

func NewOrderStore

func NewOrderStore(config OrderStoreConfig) *OrderStore

NewOrderStore creates an initialized OrderStore.

func (*OrderStore) Add

func (s *OrderStore) Add(order *models.Order) error

Add queues an order for the specified agent. Returns error if queue is full (based on MaxPendingPerAgent).

func (*OrderStore) Cleanup

func (s *OrderStore) Cleanup() int

Cleanup removes stale orders based on TTL and inflight timeout.

func (*OrderStore) MarkCompleted

func (s *OrderStore) MarkCompleted(orderID string)

MarkCompleted marks an order as successfully completed. Removes from inflight.

func (*OrderStore) MarkDelivered

func (s *OrderStore) MarkDelivered(orderID string)

MarkDelivered confirms HTTP delivery was successful. Updates metrics. Order stays in inflight for completion tracking.

func (*OrderStore) MarkFailed

func (s *OrderStore) MarkFailed(orderID, _ string)

MarkFailed marks an order as failed. Removes from inflight.

func (*OrderStore) Next

func (s *OrderStore) Next(agentID string) *models.Order

Next returns the next pending order for an agent, or nil if none. Moves the order from pending to inflight.

func (*OrderStore) StartCleanup

func (s *OrderStore) StartCleanup(ctx context.Context)

StartCleanup starts a background goroutine that periodically cleans up stale orders. Stops when the context is canceled.

type OrderStoreConfig

type OrderStoreConfig struct {
	// MaxPendingPerAgent limits queue depth per agent (0 = unlimited).
	MaxPendingPerAgent int

	// OrderTTL is how long to keep undelivered orders (0 = forever).
	OrderTTL time.Duration

	// InflightTimeout is how long to wait for completion before cleanup.
	InflightTimeout time.Duration

	// CleanupInterval is how often to run the cleanup routine.
	CleanupInterval time.Duration
}

OrderStoreConfig holds configuration for the order store.

func DefaultOrderStoreConfig

func DefaultOrderStoreConfig() OrderStoreConfig

DefaultOrderStoreConfig returns sensible defaults.

type Publisher

type Publisher interface {
	PublishBeacon(ctx context.Context, agentID string, data []byte) error
	PublishColeslaw(ctx context.Context, agentID string, data []byte) error
}

Publisher defines the interface for publishing messages to NATS. This interface is satisfied by pass.Publisher and allows for testing with mocks.

type PurgeRequest

type PurgeRequest struct {
	SessionID  string `json:"session_id"`
	ScopeType  string `json:"scope_type"`
	ScopeValue string `json:"scope_value"`
	DryRun     bool   `json:"dry_run"`
}

type PurgeResponse

type PurgeResponse struct {
	Status        string `json:"status"`
	SessionID     string `json:"session_id,omitempty"`
	ScopeType     string `json:"scope_type"`
	ScopeValue    string `json:"scope_value"`
	DryRun        bool   `json:"dry_run"`
	PantryAssets  int    `json:"pantry_assets"`
	KnownEntities int    `json:"known_entities"`
}

type RegisteredStager

type RegisteredStager struct {
	ID            string
	ResponseType  string
	Payload       string
	CreatedAt     time.Time
	ExpiresAt     time.Time
	CalledBack    bool
	CallbackAt    time.Time
	CallbackIP    string
	SessionID     string
	Metadata      map[string]string
	DwellTime     time.Duration
	Persistent    bool
	MaxCallbacks  int
	DefaultMode   string
	NextMode      string
	CallbackCount int
	LastAgentID   string
	RevokedAt     *time.Time
}

RegisteredStager is a stager waiting for callback from an injected payload.

type RepoInfo

type RepoInfo struct {
	FullName  string `json:"full_name"`
	IsPrivate bool   `json:"is_private"`
	CanPush   bool   `json:"can_push"`
}

RepoInfo holds repository metadata from GitHub API.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the Kitchen C2 server.

func New

func New(config Config) *Server

New creates a new Kitchen server.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the server.

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start starts the Kitchen server.

type Session

type Session struct {
	// ID is the unique session identifier.
	ID string `json:"id"`

	// Target is the target of this session (e.g., "acme/api" or "acme" org).
	Target string `json:"target,omitempty"`

	// ThreatModel is the threat model being demonstrated.
	ThreatModel string `json:"threat_model,omitempty"`

	// CreatedAt is when the session was created.
	CreatedAt time.Time `json:"created_at"`

	// Operators is the list of connected operators.
	Operators []Operator `json:"operators"`

	// Agents is the list of connected agents.
	Agents []AgentState `json:"agents"`
}

Session represents an active session with connected operators and agents.

type SessionRegistry

type SessionRegistry struct {
	// contains filtered or unexported fields
}

SessionRegistry tracks active sessions, operators, and agents.

func NewSessionRegistry

func NewSessionRegistry(config SessionRegistryConfig) *SessionRegistry

NewSessionRegistry creates a new session registry.

func (*SessionRegistry) GetAgent

func (r *SessionRegistry) GetAgent(agentID string) *AgentState

GetAgent returns an agent by ID.

func (*SessionRegistry) GetOperator

func (r *SessionRegistry) GetOperator(operatorID string) *Operator

GetOperator returns an operator by ID.

func (*SessionRegistry) GetOrCreateSession

func (r *SessionRegistry) GetOrCreateSession(sessionID string) *Session

GetOrCreateSession returns an existing session or creates a new one.

func (*SessionRegistry) GetSession

func (r *SessionRegistry) GetSession(sessionID string) *Session

GetSession returns a session by ID, or nil if not found.

func (*SessionRegistry) GetSessionDwellDeadline

func (r *SessionRegistry) GetSessionDwellDeadline(sessionID string) *time.Time

GetSessionDwellDeadline returns the dwell deadline for a session.

func (*SessionRegistry) ListAgents

func (r *SessionRegistry) ListAgents(sessionID string) []AgentState

ListAgents returns all agents for a session.

func (*SessionRegistry) ListOperators

func (r *SessionRegistry) ListOperators(sessionID string) []Operator

ListOperators returns all operators for a session.

func (*SessionRegistry) ListSessions

func (r *SessionRegistry) ListSessions() []*Session

ListSessions returns all sessions.

func (*SessionRegistry) RegisterOperator

func (r *SessionRegistry) RegisterOperator(op Operator)

RegisterOperator registers a new operator.

func (*SessionRegistry) SetSessionDwellDeadline

func (r *SessionRegistry) SetSessionDwellDeadline(sessionID string, deadline *time.Time)

SetSessionDwellDeadline sets the dwell deadline for a session (called when stager triggers).

func (*SessionRegistry) Stats

func (r *SessionRegistry) Stats() map[string]int

Stats returns registry statistics.

func (*SessionRegistry) UnregisterOperator

func (r *SessionRegistry) UnregisterOperator(operatorID string)

UnregisterOperator removes an operator.

func (*SessionRegistry) UpdateAgentBeacon

func (r *SessionRegistry) UpdateAgentBeacon(agentID, sessionID, hostname, os, arch string)

UpdateAgentBeacon updates an agent's state from a beacon.

func (*SessionRegistry) UpdateAgentOnlineStatus

func (r *SessionRegistry) UpdateAgentOnlineStatus()

UpdateAgentOnlineStatus marks agents as offline if they haven't sent a beacon recently.

type SessionRegistryConfig

type SessionRegistryConfig struct {
	AgentTimeout    time.Duration
	OperatorTimeout time.Duration
}

SessionRegistryConfig holds configuration for the session registry.

func DefaultSessionRegistryConfig

func DefaultSessionRegistryConfig() SessionRegistryConfig

DefaultSessionRegistryConfig returns default configuration.

type StagerRegisterRequest

type StagerRegisterRequest struct {
	ResponseType string            `json:"response_type"`
	Payload      string            `json:"payload"`
	SessionID    string            `json:"session_id"`
	TTLSeconds   int               `json:"ttl_seconds"`
	Metadata     map[string]string `json:"metadata"`
	DwellTime    string            `json:"dwell_time"`
	Persistent   bool              `json:"persistent,omitempty"`
	MaxCallbacks int               `json:"max_callbacks,omitempty"`
	DefaultMode  string            `json:"default_mode,omitempty"`
}

StagerRegisterRequest is the request body for registering a stager.

type StagerStore

type StagerStore struct {
	// contains filtered or unexported fields
}

StagerStore manages registered stagers.

func NewStagerStore

func NewStagerStore(config StagerStoreConfig) *StagerStore

NewStagerStore creates a new stager store.

func (*StagerStore) ControlPersistent

func (s *StagerStore) ControlPersistent(id, action string) (*RegisteredStager, error)

func (*StagerStore) Get

func (s *StagerStore) Get(id string) *RegisteredStager

Get retrieves a stager by ID.

func (*StagerStore) GetBySessionID

func (s *StagerStore) GetBySessionID(sessionID string) *RegisteredStager

GetBySessionID returns the first stager matching the session ID.

func (*StagerStore) List

func (s *StagerStore) List() []*RegisteredStager

List returns all stagers (for debugging/monitoring).

func (*StagerStore) ListPersistent

func (s *StagerStore) ListPersistent(sessionID string) []*RegisteredStager

func (*StagerStore) MarkCalledBack

func (s *StagerStore) MarkCalledBack(id, remoteIP string) bool

MarkCalledBack marks a stager as triggered.

func (*StagerStore) Register

func (s *StagerStore) Register(stager *RegisteredStager) error

Register adds a new stager.

func (*StagerStore) Remove

func (s *StagerStore) Remove(id string)

Remove deletes a stager.

func (*StagerStore) ResolveCallback

func (s *StagerStore) ResolveCallback(id, remoteIP, agentID string) (*RegisteredStager, CallbackInvocation, bool)

func (*StagerStore) StartCleanup

func (s *StagerStore) StartCleanup()

StartCleanup starts a goroutine to clean expired stagers.

func (*StagerStore) Stats

func (s *StagerStore) Stats() map[string]int

Stats returns store statistics.

func (*StagerStore) StopCleanup

func (s *StagerStore) StopCleanup()

StopCleanup stops the cleanup goroutine.

func (*StagerStore) ValidateStager

func (s *StagerStore) ValidateStager(id string) (sessionID string, expired, exists bool)

ValidateStager checks if a stager exists and is valid. Returns sessionID, whether it's expired, and whether it exists.

type StagerStoreConfig

type StagerStoreConfig struct {
	MaxStagers    int           // Maximum number of stagers to keep
	DefaultTTL    time.Duration // Default TTL for stagers (0 = no expiry)
	CleanupPeriod time.Duration // How often to clean expired stagers
	DeleteHook    func(string)
}

StagerStoreConfig configures the stager store.

func DefaultStagerStoreConfig

func DefaultStagerStoreConfig() StagerStoreConfig

DefaultStagerStoreConfig returns sensible defaults.

type VerifyRequest

type VerifyRequest struct {
	Nonce     string `json:"nonce"`
	Signature string `json:"signature"`
}

VerifyRequest is the request body for POST /auth/verify.

type VerifyResponse

type VerifyResponse struct {
	Token    string `json:"token"`
	Operator string `json:"operator"`
}

VerifyResponse is the response body for POST /auth/verify.

type VulnerabilityInfo

type VulnerabilityInfo struct {
	Repository   string   `json:"repository"`
	Workflow     string   `json:"workflow"`
	Context      string   `json:"context"`
	ID           string   `json:"id"`
	IssueNumber  int      `json:"issue_number,omitempty"`
	GateTriggers []string `json:"gate_triggers,omitempty"`
	GateRaw      string   `json:"gate_raw,omitempty"`
}

VulnerabilityInfo describes a vulnerability target for deployment.

Directories

Path Synopsis
Package auth provides SSH challenge-response authentication for Kitchen operators.
Package auth provides SSH challenge-response authentication for Kitchen operators.
Package db provides BBolt persistence for Kitchen state.
Package db provides BBolt persistence for Kitchen state.

Jump to

Keyboard shortcuts

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