Documentation
¶
Overview ¶
Package usp_threatlocker implements a generic USP adapter for the ThreatLocker Portal API (https://portalapi.<instance>.threatlocker.com/portalapi).
The ThreatLocker Portal API is uniform: every queryable resource exposes a "<Resource>GetByParameters" endpoint that takes a POST with a JSON body describing the filter, sort order and pagination, and returns the matching records. The adapter models a "feed" as one such endpoint plus its request parameters, so supporting a new ThreatLocker event type is purely a matter of configuration -- no code change required.
Events are forwarded to LimaCharlie in their original ThreatLocker JSON form; the adapter does not reshape payloads.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type HTTPError ¶
HTTPError represents a non-2xx response from the ThreatLocker API. It carries the status code so callers can classify the error (retry vs. give up) without having to parse error strings.
type ThreatLockerAdapter ¶
type ThreatLockerAdapter struct {
// contains filtered or unexported fields
}
ThreatLockerAdapter polls one or more ThreatLocker feeds and ships their records to LimaCharlie.
func NewThreatLockerAdapter ¶
func NewThreatLockerAdapter(ctx context.Context, conf ThreatLockerConfig) (*ThreatLockerAdapter, chan struct{}, error)
NewThreatLockerAdapter creates a ThreatLocker adapter wired to LimaCharlie.
func (*ThreatLockerAdapter) Close ¶
func (a *ThreatLockerAdapter) Close() error
Close stops the adapter. It is idempotent: repeated calls are no-ops and return the result of the first call.
type ThreatLockerClient ¶
type ThreatLockerClient struct {
// contains filtered or unexported fields
}
ThreatLockerClient is a thin wrapper around the ThreatLocker Portal API.
The Portal API is uniform: every queryable resource exposes a "<Resource>GetByParameters" endpoint that accepts a POST with a JSON body describing the filter, sort and pagination. This client therefore only needs a single generic POST helper, which keeps the adapter trivial to extend to new resources.
func NewThreatLockerClient ¶
func NewThreatLockerClient(baseURL, apiKey, managedOrgID string) *ThreatLockerClient
NewThreatLockerClient builds a client. baseURL is the API root, e.g. "https://portalapi.<instance>.threatlocker.com/portalapi".
func (*ThreatLockerClient) Close ¶
func (c *ThreatLockerClient) Close()
Close releases idle connections held by the underlying transport.
type ThreatLockerConfig ¶
type ThreatLockerConfig struct {
ClientOptions uspclient.ClientOptions `json:"client_options" yaml:"client_options"`
// APIKey is a ThreatLocker API token (Portal > API Users).
APIKey string `json:"api_key" yaml:"api_key"`
// Instance is the ThreatLocker instance identifier used to build the API
// root: https://portalapi.<instance>.threatlocker.com/portalapi
Instance string `json:"instance" yaml:"instance"`
// BaseURL fully overrides the API root. When set, Instance is ignored.
BaseURL string `json:"base_url" yaml:"base_url"`
// ManagedOrganizationID, when set, scopes every request to that
// organization via the managedOrganizationId header (useful for parent
// organizations querying a specific child).
ManagedOrganizationID string `json:"managed_organization_id" yaml:"managed_organization_id"`
// IncludeChildOrganizations, when true, makes the default feeds include
// child (and grandchild) organizations in their results by flipping on the
// per-endpoint child-org flags (showChildOrganizations / viewChildOrganizations).
//
// Set this when the API token is scoped to a parent/master organization and
// you want to collect the children's data: a parent has no endpoints of its
// own, so with this off the approval-request feed is empty, the system-audit
// feed carries only the adapter's own API activity, and the unified-audit
// (ActionLog) feed can fail with HTTP 500. This only affects the default
// feeds; when you supply your own `feeds`, set the flags in each feed's
// `parameters` yourself.
IncludeChildOrganizations bool `json:"include_child_organizations" yaml:"include_child_organizations"`
// CollectApprovalRequests / CollectUnifiedAudit / CollectSystemAudit select
// which of the three default feeds run. A nil (absent) value means enabled,
// so the zero-config default collects all three. Set one to false to drop
// that feed. These are ignored when a custom `feeds` list is supplied (in
// that case the list itself is authoritative). At least one default feed
// must remain enabled.
CollectApprovalRequests *bool `json:"collect_approval_requests" yaml:"collect_approval_requests"`
CollectUnifiedAudit *bool `json:"collect_unified_audit" yaml:"collect_unified_audit"`
CollectSystemAudit *bool `json:"collect_system_audit" yaml:"collect_system_audit"`
// Feeds is the set of ThreatLocker endpoints to poll. When empty, the
// adapter defaults to a single feed of pending Application Control
// approval requests.
Feeds []ThreatLockerFeed `json:"feeds" yaml:"feeds"`
// PageSize is the number of records requested per page. Default 100.
PageSize int `json:"page_size" yaml:"page_size"`
// PollInterval is the wait between polls of a feed. Default 1 minute.
PollInterval time.Duration `json:"poll_interval" yaml:"poll_interval"`
// DedupeTTL is how long a record's identifier is remembered to suppress
// re-shipping it on subsequent polls. Default 7 days.
DedupeTTL time.Duration `json:"dedupe_ttl" yaml:"dedupe_ttl"`
// Retry tuning for transient API failures.
RetryBaseDelay time.Duration `json:"retry_base_delay" yaml:"retry_base_delay"`
MaxRetryDelay time.Duration `json:"max_retry_delay" yaml:"max_retry_delay"`
MaxRetryAttempts int `json:"max_retry_attempts" yaml:"max_retry_attempts"`
// Deduper, when set, replaces the built-in in-memory deduper. It is not
// settable through a config file; it exists as a seam for tests and for
// embedders that want to supply a shared deduper.
Deduper utils.Deduper `json:"-" yaml:"-"`
}
ThreatLockerConfig is the adapter configuration.
func (*ThreatLockerConfig) Validate ¶
func (c *ThreatLockerConfig) Validate() error
type ThreatLockerFeed ¶
type ThreatLockerFeed struct {
// Name labels the feed and becomes the EventType of every shipped event.
Name string `json:"name" yaml:"name"`
// URL is the API path (relative to the API root) of the GetByParameters
// endpoint, e.g. "ApprovalRequest/ApprovalRequestGetByParameters".
URL string `json:"url" yaml:"url"`
// Parameters are merged into the request body sent to the endpoint. Use it
// for resource-specific filters, e.g. {"statusId": 1} for pending approval
// requests. The adapter always sets pageNumber/pageSize itself, and sets
// orderBy/isAscending unless they are provided here.
Parameters utils.Dict `json:"parameters" yaml:"parameters"`
// OrderBy is the field the endpoint sorts on. The adapter relies on a
// newest-first ordering (isAscending=false) for incremental polling.
OrderBy string `json:"order_by" yaml:"order_by"`
// ItemsPath is the key under which the records array lives when the
// endpoint returns an object envelope. Empty means: response is a bare
// array, or auto-detect a common key.
ItemsPath string `json:"items_path" yaml:"items_path"`
// TimestampField is the path to the record's event time (a "/" separated
// path is supported for nested fields). Defaults to "dateTime".
TimestampField string `json:"timestamp_field" yaml:"timestamp_field"`
// IDField is the path to the record's stable identifier, used for
// deduplication. Empty means: probe a set of common id fields, and fall
// back to a content hash.
IDField string `json:"id_field" yaml:"id_field"`
// MaxPages caps how many pages are fetched per poll, bounding the work of
// a first poll against a large historical data set. Defaults to 100.
MaxPages int `json:"max_pages" yaml:"max_pages"`
// Window, when > 0, enables rolling time-range filtering on each poll. On
// each call the adapter sets StartDateField to now-Window-PollInterval and
// EndDateField to now. The +PollInterval ensures consecutive polls overlap
// (so a slipped or delayed poll cycle does not leave a gap); the deduper
// suppresses re-shipping records that fall into the overlap. Endpoints
// like ActionLog and SystemAudit reject requests that omit a date range.
Window time.Duration `json:"window" yaml:"window"`
// StartDateField / EndDateField name the request-body fields that carry
// the rolling-window endpoints. Defaults: "startDate" / "endDate". Only
// consulted when Window > 0.
StartDateField string `json:"start_date_field" yaml:"start_date_field"`
EndDateField string `json:"end_date_field" yaml:"end_date_field"`
}
ThreatLockerFeed describes a single ThreatLocker "*GetByParameters" endpoint to poll. New event types are added by appending feeds -- no code change.