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
- Variables
- func DefaultBashPayload(kitchenURL, agentID, sessionID string) string
- func DefaultBashPayloadWithDwell(kitchenURL, agentID, sessionID, agentToken, callbackID, callbackMode string, ...) string
- func DefaultJSPayload(kitchenURL, agentID, sessionID string) string
- func DefaultJSPayloadWithToken(kitchenURL, agentID, sessionID, agentToken, callbackID, callbackMode string) string
- type AgentState
- type AnalysisMetadataSyncPayload
- type AnalysisProgressPayload
- type AnalyzeRequest
- type AnalyzeResponse
- type AnalyzeResultStatusResponse
- type AppInstallation
- type AuthMode
- type BeaconPayload
- type BeaconRequest
- type BeaconResponse
- type CallbackControlRequest
- type CallbackInvocation
- type CallbackListResponse
- type CallbackSummary
- type ChallengeRequest
- type ChallengeResponse
- type Config
- type CreateInstallationTokenRequest
- type CreateInstallationTokenResponse
- type DeployCommentRequest
- type DeployCommentResponse
- type DeployDispatchRequest
- type DeployIssueRequest
- type DeployIssueResponse
- type DeployLOTPRequest
- type DeployLOTPResponse
- type DeployPRRequest
- type DeployPRResponse
- type DeployPreflightCapability
- type DeployPreflightCheck
- type DeployPreflightRequest
- type DeployPreflightResponse
- type EdgeRef
- type EventPayload
- type ExpressBeaconRequest
- type ExpressDataPayload
- type ExtractedSecret
- type FetchTokenInfoRequest
- type FetchTokenInfoResponse
- type GetUserRequest
- type GetUserResponse
- type GraphClient
- type GraphDelta
- type GraphEdge
- type GraphHub
- func (h *GraphHub) ClientCount() int
- func (h *GraphHub) HandleWebSocket(w http.ResponseWriter, r *http.Request)
- func (h *GraphHub) OnAssetAdded(asset pantry.Asset)
- func (h *GraphHub) OnAssetRemoved(id string)
- func (h *GraphHub) OnAssetUpdated(asset pantry.Asset, oldState pantry.AssetState)
- func (h *GraphHub) OnRelationshipAdded(from, to string, rel pantry.Relationship)
- func (h *GraphHub) OnRelationshipRemoved(from, to string)
- type GraphMessage
- type GraphNode
- type GraphSnapshot
- type Handler
- func (h *Handler) Pantry() *pantry.Pantry
- func (h *Handler) RegisterRoutes(mux *http.ServeMux)
- func (h *Handler) SavePantry() error
- func (h *Handler) SetAuth(a *auth.Auth)
- func (h *Handler) SetDatabase(database *db.DB)
- func (h *Handler) SetOperatorHub(hub *OperatorHub)
- func (h *Handler) StagerStore() *StagerStore
- type HistoryPayload
- type HistoryRequest
- type HistoryResponse
- type KnownEntityRequest
- type KnownEntityResponse
- type ListAppInstallationsRequest
- type ListAppInstallationsResponse
- type ListReposRequest
- type ListReposResponse
- type ListReposWithInfoRequest
- type ListReposWithInfoResponse
- type ListWorkflowsRequest
- type ListWorkflowsResponse
- type NodeUpdate
- type Operator
- type OperatorConn
- type OperatorHub
- func (h *OperatorHub) Broadcast(msg OperatorMessage)
- func (h *OperatorHub) BroadcastAnalysisMetadataSync(payload AnalysisMetadataSyncPayload)
- func (h *OperatorHub) BroadcastAnalysisProgress(progress AnalysisProgressPayload)
- func (h *OperatorHub) BroadcastBeacon(beacon BeaconPayload)
- func (h *OperatorHub) BroadcastColeslaw(coleslaw *models.Coleslaw)
- func (h *OperatorHub) BroadcastEvent(event EventPayload)
- func (h *OperatorHub) BroadcastExpressData(data ExpressDataPayload)
- func (h *OperatorHub) BroadcastHistory(history HistoryPayload)
- func (h *OperatorHub) HandleWebSocket(w http.ResponseWriter, r *http.Request)
- type OperatorMessage
- type OrderStore
- func (s *OrderStore) Add(order *models.Order) error
- func (s *OrderStore) Cleanup() int
- func (s *OrderStore) MarkCompleted(orderID string)
- func (s *OrderStore) MarkDelivered(orderID string)
- func (s *OrderStore) MarkFailed(orderID, _ string)
- func (s *OrderStore) Next(agentID string) *models.Order
- func (s *OrderStore) StartCleanup(ctx context.Context)
- type OrderStoreConfig
- type Publisher
- type PurgeRequest
- type PurgeResponse
- type RegisteredStager
- type RepoInfo
- type Server
- type Session
- type SessionRegistry
- func (r *SessionRegistry) GetAgent(agentID string) *AgentState
- func (r *SessionRegistry) GetOperator(operatorID string) *Operator
- func (r *SessionRegistry) GetOrCreateSession(sessionID string) *Session
- func (r *SessionRegistry) GetSession(sessionID string) *Session
- func (r *SessionRegistry) GetSessionDwellDeadline(sessionID string) *time.Time
- func (r *SessionRegistry) ListAgents(sessionID string) []AgentState
- func (r *SessionRegistry) ListOperators(sessionID string) []Operator
- func (r *SessionRegistry) ListSessions() []*Session
- func (r *SessionRegistry) RegisterOperator(op Operator)
- func (r *SessionRegistry) SetSessionDwellDeadline(sessionID string, deadline *time.Time)
- func (r *SessionRegistry) Stats() map[string]int
- func (r *SessionRegistry) UnregisterOperator(operatorID string)
- func (r *SessionRegistry) UpdateAgentBeacon(agentID, sessionID, hostname, os, arch string)
- func (r *SessionRegistry) UpdateAgentOnlineStatus()
- type SessionRegistryConfig
- type StagerRegisterRequest
- type StagerStore
- func (s *StagerStore) ControlPersistent(id, action string) (*RegisteredStager, error)
- func (s *StagerStore) Get(id string) *RegisteredStager
- func (s *StagerStore) GetBySessionID(sessionID string) *RegisteredStager
- func (s *StagerStore) List() []*RegisteredStager
- func (s *StagerStore) ListPersistent(sessionID string) []*RegisteredStager
- func (s *StagerStore) MarkCalledBack(id, remoteIP string) bool
- func (s *StagerStore) Register(stager *RegisteredStager) error
- func (s *StagerStore) Remove(id string)
- func (s *StagerStore) ResolveCallback(id, remoteIP, agentID string) (*RegisteredStager, CallbackInvocation, bool)
- func (s *StagerStore) StartCleanup()
- func (s *StagerStore) Stats() map[string]int
- func (s *StagerStore) StopCleanup()
- func (s *StagerStore) ValidateStager(id string) (sessionID string, expired, exists bool)
- type StagerStoreConfig
- type VerifyRequest
- type VerifyResponse
- type VulnerabilityInfo
Constants ¶
const ( CallbackModeExpress = "express" CallbackModeDwell = "dwell" )
Variables ¶
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 ¶
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 ¶
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 AuthMode ¶
type AuthMode string
AuthMode specifies the authentication mode for operator access.
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 ¶
BeaconResponse is the response for beacon requests.
type CallbackControlRequest ¶
type CallbackControlRequest struct {
Action string `json:"action"`
}
type CallbackInvocation ¶
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 DeployCommentRequest ¶
type DeployCommentResponse ¶
type DeployCommentResponse struct {
CommentURL string `json:"comment_url"`
}
type DeployDispatchRequest ¶
type DeployIssueRequest ¶
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 DeployPRResponse ¶
type DeployPRResponse struct {
PRURL string `json:"pr_url"`
}
type DeployPreflightCheck ¶
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 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 FetchTokenInfoResponse ¶
type GetUserRequest ¶
type GetUserRequest struct {
Token string `json:"token"`
}
type GetUserResponse ¶
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 ¶
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 ¶
NewGraphHub creates a new graph hub.
func (*GraphHub) ClientCount ¶
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 (*GraphHub) OnAssetRemoved ¶
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 ¶
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 ¶
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) RegisterRoutes ¶
RegisterRoutes registers HTTP routes (auth-disabled mode). Note: /health is registered separately in server.go for all modes.
func (*Handler) SavePantry ¶
SavePantry persists the pantry to the database.
func (*Handler) SetDatabase ¶
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 ¶
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 ¶
KnownEntityResponse is the response for known entity operations.
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 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 PurgeResponse ¶
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.
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 ¶
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) 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 ¶
VerifyRequest is the request body for POST /auth/verify.
type VerifyResponse ¶
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.
Source Files
¶
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. |