Documentation
¶
Index ¶
- Constants
- Variables
- func ChallengeEventFromRequest(r *ParsedRequest, labels map[string]string, txUuid string, ...) pipeline.Event
- func DumpFingerprint(dir, label string, fp *challenge.FingerprintData, req *ParsedRequest) string
- func EventFromRequest(r *ParsedRequest, labels map[string]string, txUuid string) (pipeline.Event, error)
- func GetOnChallengeEnv(ctx context.Context, w *AppsecRuntimeConfig, state *AppsecRequestState, ...) map[string]interface{}
- func GetOnChallengeSubmitEnv(w *AppsecRuntimeConfig, state *AppsecRequestState, request *ParsedRequest) map[string]interface{}
- func GetOnLoadEnv(w *AppsecRuntimeConfig) map[string]interface{}
- func GetOnMatchEnv(w *AppsecRuntimeConfig, state *AppsecRequestState, request *ParsedRequest, ...) map[string]interface{}
- func GetPostEvalEnv(ctx context.Context, w *AppsecRuntimeConfig, state *AppsecRequestState, ...) map[string]interface{}
- func GetPreEvalEnv(ctx context.Context, w *AppsecRuntimeConfig, state *AppsecRequestState, ...) map[string]interface{}
- func GetRuleDebug(id int) bool
- func LoadAppsecRules(hub *cwhub.Hub) error
- func NewCrzLogger(logger *log.Entry) *crzLogger
- func SetRuleDebug(id int, debug bool)
- type AppsecCollection
- type AppsecCollectionConfig
- type AppsecConfig
- type AppsecDropInfo
- type AppsecPhaseConfig
- type AppsecRequestState
- type AppsecRuntimeConfig
- func (w *AppsecRuntimeConfig) CancelAlert(state *AppsecRequestState) error
- func (w *AppsecRuntimeConfig) CancelEvent(state *AppsecRequestState) error
- func (w *AppsecRuntimeConfig) ClearResponse(state *AppsecRequestState)
- func (w *AppsecRuntimeConfig) DisableBodyInspection(state *AppsecRequestState) error
- func (w *AppsecRuntimeConfig) DisableInBandRuleByID(id int) error
- func (w *AppsecRuntimeConfig) DisableInBandRuleByName(name string) error
- func (w *AppsecRuntimeConfig) DisableInBandRuleByTag(tag string) error
- func (w *AppsecRuntimeConfig) DisableOutBandRuleByID(id int) error
- func (w *AppsecRuntimeConfig) DisableOutBandRuleByName(name string) error
- func (w *AppsecRuntimeConfig) DisableOutBandRuleByTag(tag string) error
- func (w *AppsecRuntimeConfig) DropRequest(state *AppsecRequestState, request *ParsedRequest, reason string) error
- func (w *AppsecRuntimeConfig) EvaluateMismatches(state *AppsecRequestState, request *ParsedRequest) *challenge.MismatchReport
- func (*AppsecRuntimeConfig) ExemptFromChallenge(state *AppsecRequestState, request *ParsedRequest, reason string) error
- func (w *AppsecRuntimeConfig) GenerateResponse(response AppsecTempResponse, logger *log.Entry) (int, BodyResponse)
- func (w *AppsecRuntimeConfig) GrantAllowlistCookieInline(state *AppsecRequestState, request *ParsedRequest, reason string, ...) error
- func (w *AppsecRuntimeConfig) GrantChallengeCookie(state *AppsecRequestState, request *ParsedRequest, reason string, ...) error
- func (w *AppsecRuntimeConfig) LoadAPISchemaWithName(ref string, filename string) error
- func (w *AppsecRuntimeConfig) LoadAPISchemaWithOptions(ref string, filename string, opts map[string]any) error
- func (w *AppsecRuntimeConfig) NewRequestState() AppsecRequestState
- func (w *AppsecRuntimeConfig) ProcessOnChallengeRules(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
- func (w *AppsecRuntimeConfig) ProcessOnLoadRules() error
- func (w *AppsecRuntimeConfig) ProcessOnMatchRules(state *AppsecRequestState, request *ParsedRequest, evt pipeline.Event) error
- func (w *AppsecRuntimeConfig) ProcessPostEvalRules(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
- func (w *AppsecRuntimeConfig) ProcessPreEvalRules(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
- func (w *AppsecRuntimeConfig) RegisterAPISchemaBodyDecoder(contentType, decoderName string) error
- func (*AppsecRuntimeConfig) RejectSubmission(state *AppsecRequestState, reason string) error
- func (w *AppsecRuntimeConfig) RemoveInbandRuleByID(state *AppsecRequestState, id int) error
- func (w *AppsecRuntimeConfig) RemoveInbandRuleByName(state *AppsecRequestState, name string) error
- func (w *AppsecRuntimeConfig) RemoveInbandRuleByTag(state *AppsecRequestState, tag string) error
- func (w *AppsecRuntimeConfig) RemoveOutbandRuleByID(state *AppsecRequestState, id int) error
- func (w *AppsecRuntimeConfig) RemoveOutbandRuleByName(state *AppsecRequestState, name string) error
- func (w *AppsecRuntimeConfig) RemoveOutbandRuleByTag(state *AppsecRequestState, tag string) error
- func (w *AppsecRuntimeConfig) SendAlert(state *AppsecRequestState) error
- func (w *AppsecRuntimeConfig) SendChallenge(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
- func (w *AppsecRuntimeConfig) SendEvent(state *AppsecRequestState) error
- func (w *AppsecRuntimeConfig) SetAction(state *AppsecRequestState, action string) error
- func (w *AppsecRuntimeConfig) SetActionByID(id int, action string) error
- func (w *AppsecRuntimeConfig) SetActionByName(name string, action string) error
- func (w *AppsecRuntimeConfig) SetActionByTag(tag string, action string) error
- func (w *AppsecRuntimeConfig) SetBodySizeExceededAction(action string) error
- func (w *AppsecRuntimeConfig) SetChallengeBody(state *AppsecRequestState, content string) error
- func (w *AppsecRuntimeConfig) SetChallengeCookie(state *AppsecRequestState, cookie cookie.AppsecCookie) error
- func (w *AppsecRuntimeConfig) SetChallengeDifficulty(level string) error
- func (*AppsecRuntimeConfig) SetChallengeDifficultyPerRequest(state *AppsecRequestState, level string) error
- func (w *AppsecRuntimeConfig) SetChallengeHeader(state *AppsecRequestState, name string, value string) error
- func (w *AppsecRuntimeConfig) SetHTTPCode(state *AppsecRequestState, code int) error
- func (w *AppsecRuntimeConfig) SetMaxBodySize(size int64) error
- func (w *AppsecRuntimeConfig) ValidateRequestWithSchema(ctx context.Context, state *AppsecRequestState, request *ParsedRequest, ...) bool
- type AppsecSubEngineOpts
- type AppsecTempResponse
- type BodyResponse
- type BodySettings
- type ChallengeEventInfo
- type ChallengeReason
- type ExtendedTransaction
- func (t *ExtendedTransaction) AddGetRequestArgument(name string, value string)
- func (t *ExtendedTransaction) AddRequestHeader(name string, value string)
- func (t *ExtendedTransaction) Close() error
- func (t *ExtendedTransaction) ID() string
- func (t *ExtendedTransaction) Interrupt(interruption *types.Interruption)
- func (t *ExtendedTransaction) Interruption() *types.Interruption
- func (t *ExtendedTransaction) IsInterrupted() bool
- func (t *ExtendedTransaction) IsRuleEngineOff() bool
- func (t *ExtendedTransaction) MatchedRules() []types.MatchedRule
- func (t *ExtendedTransaction) ProcessConnection(client string, cPort int, server string, sPort int)
- func (t *ExtendedTransaction) ProcessLogging()
- func (t *ExtendedTransaction) ProcessRequestBody() (*types.Interruption, error)
- func (t *ExtendedTransaction) ProcessRequestHeaders() *types.Interruption
- func (t *ExtendedTransaction) ProcessURI(uri string, method string, httpVersion string)
- func (t *ExtendedTransaction) RemoveRuleByIDWithError(id int) error
- func (t *ExtendedTransaction) RemoveRuleByTagWithError(tag string) error
- func (t *ExtendedTransaction) SetServerName(name string)
- func (t *ExtendedTransaction) Variables() plugintypes.TransactionVariables
- func (t *ExtendedTransaction) WriteRequestBody(body []byte) (*types.Interruption, int, error)
- type Hook
- type ParsedRequest
- type PhaseHooks
- type ReqDumpFilter
- func (r *ReqDumpFilter) FilterArgs(out *ParsedRequest) error
- func (r *ReqDumpFilter) FilterBody(out *ParsedRequest) error
- func (r *ReqDumpFilter) FilterHeaders(out *ParsedRequest) error
- func (r *ReqDumpFilter) GetFilteredRequest() *ParsedRequest
- func (r *ReqDumpFilter) NoFilters() *ReqDumpFilter
- func (r *ReqDumpFilter) ToJSON() error
- func (r *ReqDumpFilter) WithArgsContentFilter(filter string) *ReqDumpFilter
- func (r *ReqDumpFilter) WithArgsNameFilter(filter string) *ReqDumpFilter
- func (r *ReqDumpFilter) WithBody() *ReqDumpFilter
- func (r *ReqDumpFilter) WithEmptyArgsFilters() *ReqDumpFilter
- func (r *ReqDumpFilter) WithEmptyHeadersFilters() *ReqDumpFilter
- func (r *ReqDumpFilter) WithHeaders() *ReqDumpFilter
- func (r *ReqDumpFilter) WithHeadersContentFilter(filter string) *ReqDumpFilter
- func (r *ReqDumpFilter) WithHeadersNameFilter(filter string) *ReqDumpFilter
- func (r *ReqDumpFilter) WithNoBody() *ReqDumpFilter
- func (r *ReqDumpFilter) WithNoHeaders() *ReqDumpFilter
- type RulesDetails
- type SubmissionRejectInfo
Constants ¶
const ( BanRemediation = "ban" CaptchaRemediation = "captcha" AllowRemediation = "allow" ChallengeRemediation = "challenge" )
const ( // BodySizeActionDrop drops the request when the body exceeds the maximum size. BodySizeActionDrop = "drop" // BodySizeActionPartial reads the body up to the maximum size and processes it. BodySizeActionPartial = "partial" // BodySizeActionAllow processes the request without inspecting the body. BodySizeActionAllow = "allow" // DefaultMaxBodySize is the default maximum body size (10MB). DefaultMaxBodySize = int64(10 * 1024 * 1024) )
const ( PhaseInBand phase = iota PhaseOutOfBand )
const ( // ModuleName is the acquisition module name carried on events produced by // the appsec datasource. ModuleName = "appsec" // SourceWAF is the `source` field set on events generated by a WAF rule match. SourceWAF = "crowdsec-appsec" // SourceChallenge is the `source` field set on events generated by the // challenge lifecycle. It is intentionally distinct from SourceWAF so that // challenge scenarios can filter on it without colliding with WAF scenarios. SourceChallenge = "crowdsec-appsec-challenge" )
const ( URIHeaderName = "X-Crowdsec-Appsec-Uri" VerbHeaderName = "X-Crowdsec-Appsec-Verb" HostHeaderName = "X-Crowdsec-Appsec-Host" IPHeaderName = "X-Crowdsec-Appsec-Ip" APIKeyHeaderName = "X-Crowdsec-Appsec-Api-Key" UserAgentHeaderName = "X-Crowdsec-Appsec-User-Agent" HTTPVersionHeaderName = "X-Crowdsec-Appsec-Http-Version" TransactionIDHeaderName = "X-Crowdsec-Appsec-Transaction-Id" )
const APPSEC_RULE = "appsec-rule"
Variables ¶
var AppsecRulesDetails = make(map[int]RulesDetails)
FIXME: this shouldn't be a global Is using the id is a good idea ? might be too specific to coraza and not easily reusable
var DebugRules = map[int]bool{}
Functions ¶
func ChallengeEventFromRequest ¶
func ChallengeEventFromRequest(r *ParsedRequest, labels map[string]string, txUuid string, info ChallengeEventInfo) pipeline.Event
ChallengeEventFromRequest builds a LOG event for a challenge lifecycle moment. It carries SourceChallenge so it never collides with WAF scenarios, plus the reason, difficulty and (when available) fingerprint scalars for filtering.
func DumpFingerprint ¶
func DumpFingerprint(dir, label string, fp *challenge.FingerprintData, req *ParsedRequest) string
DumpFingerprint allows to dump the fingerprint + some context (ip, host, timestamp etc.) to as JSONL file for later analysis.
func EventFromRequest ¶
func GetOnChallengeEnv ¶
func GetOnChallengeEnv(ctx context.Context, w *AppsecRuntimeConfig, state *AppsecRequestState, request *ParsedRequest) map[string]interface{}
func GetOnChallengeSubmitEnv ¶
func GetOnChallengeSubmitEnv(w *AppsecRuntimeConfig, state *AppsecRequestState, request *ParsedRequest) map[string]interface{}
GetOnChallengeSubmitEnv is the env exposed to on_challenge_submit hooks. Deliberately narrow: the hook fires once during the challenge submission JSON response, so anything that would change the response shape (SendChallenge, SetRemediation, SetReturnCode, SetChallengeDifficulty, DropRequest) is intentionally omitted to avoid breaking the client-side JS handler. Operators wanting to escalate or block at the next request should do so via pre_eval.
func GetOnLoadEnv ¶
func GetOnLoadEnv(w *AppsecRuntimeConfig) map[string]interface{}
func GetOnMatchEnv ¶
func GetOnMatchEnv(w *AppsecRuntimeConfig, state *AppsecRequestState, request *ParsedRequest, evt pipeline.Event) map[string]interface{}
func GetPostEvalEnv ¶
func GetPostEvalEnv(ctx context.Context, w *AppsecRuntimeConfig, state *AppsecRequestState, request *ParsedRequest) map[string]interface{}
func GetPreEvalEnv ¶
func GetPreEvalEnv(ctx context.Context, w *AppsecRuntimeConfig, state *AppsecRequestState, request *ParsedRequest) map[string]interface{}
func GetRuleDebug ¶
func LoadAppsecRules ¶
func NewCrzLogger ¶
func SetRuleDebug ¶
Types ¶
type AppsecCollection ¶
func LoadCollection ¶
func (AppsecCollection) String ¶
func (w AppsecCollection) String() string
type AppsecCollectionConfig ¶
type AppsecCollectionConfig struct {
Type string `yaml:"type"`
Name string `yaml:"name"`
Debug bool `yaml:"debug"`
Description string `yaml:"description"`
SecLangFilesRules []string `yaml:"seclang_files_rules"`
SecLangRules []string `yaml:"seclang_rules"`
Rules []appsec_rule.CustomRule `yaml:"rules"`
Severity string `yaml:"severity"`
Labels map[string]any `yaml:"labels"` // Labels is K:V list aiming at providing context the overflow
Data []*enrichment.DataProvider `yaml:"data"`
// contains filtered or unexported fields
}
to be filled w/ seb update
type AppsecConfig ¶
type AppsecConfig struct {
Name string `yaml:"name"`
OutOfBandRules []string `yaml:"outofband_rules"`
InBandRules []string `yaml:"inband_rules"`
DefaultRemediation string `yaml:"default_remediation"`
DefaultPassAction string `yaml:"default_pass_action"`
BouncerBlockedHTTPCode int `yaml:"blocked_http_code"` // returned to the bouncer
BouncerPassedHTTPCode int `yaml:"passed_http_code"` // returned to the bouncer
UserBlockedHTTPCode int `yaml:"user_blocked_http_code"` // returned to the user
UserPassedHTTPCode int `yaml:"user_passed_http_code"` // returned to the user
OnLoad []Hook `yaml:"on_load"`
PreEval []Hook `yaml:"pre_eval"`
PostEval []Hook `yaml:"post_eval"`
OnMatch []Hook `yaml:"on_match"`
OnChallenge []Hook `yaml:"on_challenge"`
OnChallengeSubmit []Hook `yaml:"on_challenge_submit"`
VariablesTracking []string `yaml:"variables_tracking"`
InbandOptions AppsecSubEngineOpts `yaml:"inband_options"`
OutOfBandOptions AppsecSubEngineOpts `yaml:"outofband_options"`
InBand *AppsecPhaseConfig `yaml:"inband"`
OutOfBand *AppsecPhaseConfig `yaml:"outofband"`
// Data declares datafiles (e.g. bot lists queried by MatchKnownBot) that
// cwhub downloads and Build() loads into the expr datafile registry — the
// same `data:` mechanism parsers/scenarios/appsec-rules use.
Data []*enrichment.DataProvider `yaml:"data"`
// Challenge carries the WAF challenge / bot-detection runtime tuning.
// All fields are optional; unset fields fall back to the runtime
// defaults at NewChallengeRuntime time. When multiple appsec-configs
// are loaded, each later config's non-nil fields override the earlier
// values (see LoadByPath).
Challenge *challenge.Config `yaml:"challenge"`
LogLevel *log.Level `yaml:"log_level"`
Logger *log.Entry `yaml:"-"`
}
func (*AppsecConfig) Build ¶
func (wc *AppsecConfig) Build(ctx context.Context, hub *cwhub.Hub) (*AppsecRuntimeConfig, error)
func (*AppsecConfig) LoadByPath ¶
func (wc *AppsecConfig) LoadByPath(file string) error
func (*AppsecConfig) SetUpLogger ¶ added in v1.6.5
func (wc *AppsecConfig) SetUpLogger()
type AppsecDropInfo ¶ added in v1.7.4
type AppsecDropInfo struct {
Reason string
Interruption *corazatypes.Interruption
}
type AppsecPhaseConfig ¶ added in v1.7.8
type AppsecPhaseConfig struct {
Rules []string `yaml:"rules"`
OnMatch []Hook `yaml:"on_match"`
PreEval []Hook `yaml:"pre_eval"`
PostEval []Hook `yaml:"post_eval"`
OnChallenge []Hook `yaml:"on_challenge"`
OnChallengeSubmit []Hook `yaml:"on_challenge_submit"`
Options AppsecSubEngineOpts `yaml:"options"`
VariablesTracking []string `yaml:"variables_tracking"`
}
AppsecPhaseConfig holds configuration scoped to a specific phase (inband or outofband). Hooks defined here are automatically dispatched only during the corresponding phase. on_challenge and on_challenge_submit are in-band only; setting them under `outofband:` is rejected at Build() time.
type AppsecRequestState ¶ added in v1.7.4
type AppsecRequestState struct {
Tx ExtendedTransaction
CurrentPhase phase
Response AppsecTempResponse
InBandDrop *AppsecDropInfo
OutOfBandDrop *AppsecDropInfo
PendingAction *string
PendingHTTPCode *int
RequireChallenge bool
Fingerprint *challenge.FingerprintData
CookiePowDifficulty int // PoW difficulty proven by the client for the current cookie (0 if no/invalid cookie)
ChallengeDifficulty *int // per-request PoW difficulty override (nil = use runtime default)
// SubmissionRejection is set by RejectSubmission inside an
// on_challenge_submit hook to refuse cookie issuance for the current
// challenge submission. nil for any other phase / outcome.
SubmissionRejection *SubmissionRejectInfo
// ChallengeBypassed is set by GrantChallengeCookie to suppress later
// SendChallenge calls in the same request. Per-request only; cleared
// on ResetResponse. The bypass for subsequent requests is carried by
// the allowlist cookie itself, not by this flag.
ChallengeBypassed bool
// ChallengeExempt is set by the ExemptFromChallenge expr helper to exempt
// the current request from the bot challenge: SendChallenge becomes a no-op
// once it is set. It only affects the current request and doesn't mint a
// cookie (unlike GrantChallengeCookie). Deliberately not cleared by
// ResetResponse so a pre_eval exemption survives into post_eval.
ChallengeExempt bool
// HooksHalted is flipped by terminal hook actions (currently
// RejectSubmission and the inline GrantChallengeCookie variant
// exposed in on_challenge_submit) to short-circuit later rules in
// the same phase. Without this, a `LogAccepted` rule following a
// `RejectSubmission` rule with `filter: "true"` would emit a
// contradictory accept-log line for an already-rejected submission.
// Per-request only; cleared by ResetResponse.
HooksHalted bool
// LastMismatchReport caches the result of the EvaluateMismatches expr
// closure for the current request, so repeated calls from a single
// rule expression don't redo the work (or re-emit observability).
// nil until the first call.
LastMismatchReport *challenge.MismatchReport
// HookVars is a per-request scratch space exposed to expr hooks as
// `hook_vars`. Helpers (e.g. ValidateRequestWithSchema) publish string
// values here so that later hook expressions — including the `apply`
// block of the same hook — can read them. The map is allocated once in
// NewRequestState, persists across in-band/out-of-band phases, and is
// copied into pipeline.AppsecEvent.HookVars when an event is emitted.
HookVars map[string]string
DisableBodyInspection bool
}
func (*AppsecRequestState) ApplyPendingResponse ¶ added in v1.7.4
func (s *AppsecRequestState) ApplyPendingResponse()
func (*AppsecRequestState) DropInfo ¶ added in v1.7.4
func (s *AppsecRequestState) DropInfo(request *ParsedRequest) *AppsecDropInfo
func (*AppsecRequestState) ResetResponse ¶ added in v1.7.4
func (s *AppsecRequestState) ResetResponse(cfg *AppsecConfig)
type AppsecRuntimeConfig ¶
type AppsecRuntimeConfig struct {
Name string
OutOfBandRules []AppsecCollection
InBandRules []AppsecCollection
DefaultRemediation string
RemediationByTag map[string]string // Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME
RemediationById map[int]string
CompiledOnLoad []Hook // runs once at startup, not phase-scoped
CompiledOnChallenge []Hook // in-band only; runs before pre_eval
CompiledOnChallengeSubmit []Hook // in-band only; runs at /submit POST after validation
CommonHooks PhaseHooks // apply to both phases
InBandHooks PhaseHooks // only run during in-band
OutOfBandHooks PhaseHooks // only run during out-of-band
CompiledVariablesTracking []*regexp.Regexp
Config *AppsecConfig
Logger *log.Entry
// Set by on_load to ignore some rules on loading
DisabledInBandRuleIds []int
DisabledInBandRulesTags []string // Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME
DisabledOutOfBandRuleIds []int
DisabledOutOfBandRulesTags []string // Also used for ByName, as the name (for modsec rules) is a tag crowdsec-NAME
// True if at least one of the hooks use `RequireValidChallenge`
NeedWASMVM bool
ChallengeRuntime *challenge.ChallengeRuntime
// OutChan is the pipeline output channel challenge lifecycle events are sent
// on, and Labels are the datasource labels stamped on those events. Both are
// wired by the appsec datasource at startup; nil OutChan disables emission
// (e.g. in unit tests with no datasource).
OutChan chan pipeline.Event
Labels map[string]string
// FingerprintDumpDir is the on-disk directory the DumpFingerprint
FingerprintDumpDir string
RequestValidator *apivalidation.RequestValidator
DataDir string
// BodySettings controls how oversized request bodies are handled. Settable via on_load hooks.
BodySettings BodySettings
}
runtime version of AppsecConfig
func (*AppsecRuntimeConfig) CancelAlert ¶
func (w *AppsecRuntimeConfig) CancelAlert(state *AppsecRequestState) error
func (*AppsecRuntimeConfig) CancelEvent ¶
func (w *AppsecRuntimeConfig) CancelEvent(state *AppsecRequestState) error
func (*AppsecRuntimeConfig) ClearResponse ¶
func (w *AppsecRuntimeConfig) ClearResponse(state *AppsecRequestState)
func (*AppsecRuntimeConfig) DisableBodyInspection ¶ added in v1.7.8
func (w *AppsecRuntimeConfig) DisableBodyInspection(state *AppsecRequestState) error
DisableBodyInspection prevents Coraza from processing the request body for the current request. Intended for use in pre_eval hooks.
func (*AppsecRuntimeConfig) DisableInBandRuleByID ¶
func (w *AppsecRuntimeConfig) DisableInBandRuleByID(id int) error
Disable a rule at load time, meaning it will not run for any request
func (*AppsecRuntimeConfig) DisableInBandRuleByName ¶
func (w *AppsecRuntimeConfig) DisableInBandRuleByName(name string) error
Disable a rule at load time, meaning it will not run for any request
func (*AppsecRuntimeConfig) DisableInBandRuleByTag ¶
func (w *AppsecRuntimeConfig) DisableInBandRuleByTag(tag string) error
Disable a rule at load time, meaning it will not run for any request
func (*AppsecRuntimeConfig) DisableOutBandRuleByID ¶
func (w *AppsecRuntimeConfig) DisableOutBandRuleByID(id int) error
Disable a rule at load time, meaning it will not run for any request
func (*AppsecRuntimeConfig) DisableOutBandRuleByName ¶
func (w *AppsecRuntimeConfig) DisableOutBandRuleByName(name string) error
Disable a rule at load time, meaning it will not run for any request
func (*AppsecRuntimeConfig) DisableOutBandRuleByTag ¶
func (w *AppsecRuntimeConfig) DisableOutBandRuleByTag(tag string) error
Disable a rule at load time, meaning it will not run for any request
func (*AppsecRuntimeConfig) DropRequest ¶ added in v1.7.4
func (w *AppsecRuntimeConfig) DropRequest(state *AppsecRequestState, request *ParsedRequest, reason string) error
func (*AppsecRuntimeConfig) EvaluateMismatches ¶
func (w *AppsecRuntimeConfig) EvaluateMismatches(state *AppsecRequestState, request *ParsedRequest) *challenge.MismatchReport
SendChallenge issues a challenge HTML page for the current request. Cookie and submission handling live in ProcessOnChallengeRules; by the time this runs, state.Fingerprint has already been populated if a valid cookie was presented. If the client already proved a PoW at least as hard as the target difficulty for this request, SendChallenge is a no-op. When the target difficulty is raised (e.g. on_challenge calls SetChallengeDifficulty to punish a suspect fingerprint), the stored difficulty is lower than the target and a fresh challenge is issued. EvaluateMismatches runs all library-native + custom fingerprint mismatch checks, caches the result on state, and emits one structured Debug log line + one metric bump per fired signal on the first call of a given request. Subsequent calls return the cached pointer so rules can reference the report multiple times without redoing the work.
func (*AppsecRuntimeConfig) ExemptFromChallenge ¶
func (*AppsecRuntimeConfig) ExemptFromChallenge(state *AppsecRequestState, request *ParsedRequest, reason string) error
ExemptFromChallenge flags the current request as exempt from the bot challenge and records why. The flag is set once and honored by SendChallenge, so challenge configs no longer gate the challenge on an explicit bot check. The counter is bumped only on the first exemption so multiple matching configs don't inflate the count.
func (*AppsecRuntimeConfig) GenerateResponse ¶
func (w *AppsecRuntimeConfig) GenerateResponse(response AppsecTempResponse, logger *log.Entry) (int, BodyResponse)
func (*AppsecRuntimeConfig) GrantAllowlistCookieInline ¶
func (w *AppsecRuntimeConfig) GrantAllowlistCookieInline(state *AppsecRequestState, request *ParsedRequest, reason string, ttlOverride *time.Duration) error
GrantAllowlistCookieInline mints an allowlist-bypass cookie and attaches it to the in-flight challenge-submit envelope. Used from on_challenge_submit, where the client awaits the submit JSON envelope and a redirect would break its state machine (the envelope is already a ChallengeRemediation, so UserCookies is serialized). Same precedence/ttl/error semantics as mintAllowlistCookie.
func (*AppsecRuntimeConfig) GrantChallengeCookie ¶
func (w *AppsecRuntimeConfig) GrantChallengeCookie(state *AppsecRequestState, request *ParsedRequest, reason string, ttlOverride *time.Duration) error
GrantChallengeCookie mints an allowlist-bypass cookie and issues an HTTP 307 redirect carrying it back to the visitor. Used from pre_eval/post_eval.
Why a 307 and not a silent allow: the bouncer only serializes cookies on a ChallengeRemediation response (see GenerateResponse), so a plain allow drops the Set-Cookie. The redirect to the same URL preserves method+body and bounces the visitor back through the WAF with the cookie present, so ProcessOnChallengeRules' allowlist branch lets them through on the next hop.
Precedence: see mintAllowlistCookie (operator allowlist overwrites a real fingerprint). ttlOverride overrides cookie_ttl. Returns ErrAllowlistReasonSize if reason is too long.
func (*AppsecRuntimeConfig) LoadAPISchemaWithName ¶ added in v1.7.8
func (w *AppsecRuntimeConfig) LoadAPISchemaWithName(ref string, filename string) error
func (*AppsecRuntimeConfig) LoadAPISchemaWithOptions ¶ added in v1.7.8
func (w *AppsecRuntimeConfig) LoadAPISchemaWithOptions(ref string, filename string, opts map[string]any) error
LoadAPISchemaWithOptions behaves like LoadAPISchemaWithName but accepts a map of policy overrides. Supported keys:
- "on_route_not_found": "drop" | "ignore" (default: "drop")
- "on_method_not_allowed": "drop" | "ignore" (default: "drop")
- "on_unsupported_security_scheme": "drop" | "ignore" (default: "drop")
func (*AppsecRuntimeConfig) NewRequestState ¶ added in v1.7.4
func (w *AppsecRuntimeConfig) NewRequestState() AppsecRequestState
func (*AppsecRuntimeConfig) ProcessOnChallengeRules ¶
func (w *AppsecRuntimeConfig) ProcessOnChallengeRules(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
ProcessOnChallengeRules is the in-band-only challenge entry point. It handles the PoW worker JS path and the challenge submission path internally, validates any existing challenge cookie to populate state.Fingerprint, and runs the user-defined on_challenge hook expressions ONLY when there is a fingerprint to inspect — i.e. on a valid submission or when a valid cookie was presented. Requests with no cookie / invalid cookie / invalid submission skip user hooks entirely (there's nothing to evaluate).
func (*AppsecRuntimeConfig) ProcessOnLoadRules ¶
func (w *AppsecRuntimeConfig) ProcessOnLoadRules() error
func (*AppsecRuntimeConfig) ProcessOnMatchRules ¶
func (w *AppsecRuntimeConfig) ProcessOnMatchRules(state *AppsecRequestState, request *ParsedRequest, evt pipeline.Event) error
func (*AppsecRuntimeConfig) ProcessPostEvalRules ¶
func (w *AppsecRuntimeConfig) ProcessPostEvalRules(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
func (*AppsecRuntimeConfig) ProcessPreEvalRules ¶
func (w *AppsecRuntimeConfig) ProcessPreEvalRules(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
func (*AppsecRuntimeConfig) RegisterAPISchemaBodyDecoder ¶ added in v1.7.8
func (w *AppsecRuntimeConfig) RegisterAPISchemaBodyDecoder(contentType, decoderName string) error
RegisterAPISchemaBodyDecoder allows a user's on_load hook to add a Content-Type to the set the API schema validator can decode. decoderName must be one of the stable built-in identifiers exported by the api_validation package ("json", "urlencoded", "multipart", "yaml", "csv", "plain", "file"). Note that the underlying kin-openapi decoder registry is process-global: today all appsec datasources in the same process share the same set of registered body decoders.
func (*AppsecRuntimeConfig) RejectSubmission ¶
func (*AppsecRuntimeConfig) RejectSubmission(state *AppsecRequestState, reason string) error
RejectSubmission flags the in-flight challenge submission so the ProcessOnChallengeRules submit-path branch refuses to issue a cookie and returns bodyChallengeRejected. Exposed ONLY in the on_challenge_submit hook env — calling it from any other phase is a no-op (the field is inspected only at submit time).
The reason string is logged server-side and NOT echoed to the client.
func (*AppsecRuntimeConfig) RemoveInbandRuleByID ¶
func (w *AppsecRuntimeConfig) RemoveInbandRuleByID(state *AppsecRequestState, id int) error
func (*AppsecRuntimeConfig) RemoveInbandRuleByName ¶
func (w *AppsecRuntimeConfig) RemoveInbandRuleByName(state *AppsecRequestState, name string) error
func (*AppsecRuntimeConfig) RemoveInbandRuleByTag ¶
func (w *AppsecRuntimeConfig) RemoveInbandRuleByTag(state *AppsecRequestState, tag string) error
func (*AppsecRuntimeConfig) RemoveOutbandRuleByID ¶
func (w *AppsecRuntimeConfig) RemoveOutbandRuleByID(state *AppsecRequestState, id int) error
func (*AppsecRuntimeConfig) RemoveOutbandRuleByName ¶
func (w *AppsecRuntimeConfig) RemoveOutbandRuleByName(state *AppsecRequestState, name string) error
func (*AppsecRuntimeConfig) RemoveOutbandRuleByTag ¶
func (w *AppsecRuntimeConfig) RemoveOutbandRuleByTag(state *AppsecRequestState, tag string) error
func (*AppsecRuntimeConfig) SendAlert ¶
func (w *AppsecRuntimeConfig) SendAlert(state *AppsecRequestState) error
func (*AppsecRuntimeConfig) SendChallenge ¶
func (w *AppsecRuntimeConfig) SendChallenge(ctx context.Context, state *AppsecRequestState, request *ParsedRequest) error
func (*AppsecRuntimeConfig) SendEvent ¶
func (w *AppsecRuntimeConfig) SendEvent(state *AppsecRequestState) error
func (*AppsecRuntimeConfig) SetAction ¶
func (w *AppsecRuntimeConfig) SetAction(state *AppsecRequestState, action string) error
func (*AppsecRuntimeConfig) SetActionByID ¶
func (w *AppsecRuntimeConfig) SetActionByID(id int, action string) error
func (*AppsecRuntimeConfig) SetActionByName ¶
func (w *AppsecRuntimeConfig) SetActionByName(name string, action string) error
func (*AppsecRuntimeConfig) SetActionByTag ¶
func (w *AppsecRuntimeConfig) SetActionByTag(tag string, action string) error
func (*AppsecRuntimeConfig) SetBodySizeExceededAction ¶ added in v1.7.8
func (w *AppsecRuntimeConfig) SetBodySizeExceededAction(action string) error
SetBodySizeExceededAction sets what happens when the body exceeds the maximum size. Valid values: "drop" (block request), "partial" (inspect up to max size), "allow" (skip body inspection). Intended for use in on_load hooks.
func (*AppsecRuntimeConfig) SetChallengeBody ¶
func (w *AppsecRuntimeConfig) SetChallengeBody(state *AppsecRequestState, content string) error
func (*AppsecRuntimeConfig) SetChallengeCookie ¶
func (w *AppsecRuntimeConfig) SetChallengeCookie(state *AppsecRequestState, cookie cookie.AppsecCookie) error
func (*AppsecRuntimeConfig) SetChallengeDifficulty ¶
func (w *AppsecRuntimeConfig) SetChallengeDifficulty(level string) error
SetChallengeDifficulty sets the default PoW difficulty on the runtime (used from on_load).
func (*AppsecRuntimeConfig) SetChallengeDifficultyPerRequest ¶
func (*AppsecRuntimeConfig) SetChallengeDifficultyPerRequest(state *AppsecRequestState, level string) error
SetChallengeDifficultyPerRequest sets a per-request PoW difficulty override (used from pre_eval/post_eval).
func (*AppsecRuntimeConfig) SetChallengeHeader ¶
func (w *AppsecRuntimeConfig) SetChallengeHeader(state *AppsecRequestState, name string, value string) error
func (*AppsecRuntimeConfig) SetHTTPCode ¶
func (w *AppsecRuntimeConfig) SetHTTPCode(state *AppsecRequestState, code int) error
func (*AppsecRuntimeConfig) SetMaxBodySize ¶ added in v1.7.8
func (w *AppsecRuntimeConfig) SetMaxBodySize(size int64) error
SetMaxBodySize sets the maximum allowed body size in bytes. Intended for use in on_load hooks.
func (*AppsecRuntimeConfig) ValidateRequestWithSchema ¶ added in v1.7.8
func (w *AppsecRuntimeConfig) ValidateRequestWithSchema(ctx context.Context, state *AppsecRequestState, request *ParsedRequest, ref string) bool
ValidateRequestWithSchema validates r against the OpenAPI schema registered under ref. It returns true when the request is valid, false when it is not (or when no schema is registered for ref). On failure, structured error details are published into state.HookVars under the "validation_error*" keys so that subsequent hook expressions (typically the `apply` block of the same hook) can build a drop reason or enrich an event. Each call also increments the AppsecValidationOKCounter / AppsecValidationFailedCounter metric.
type AppsecSubEngineOpts ¶
type AppsecTempResponse ¶
type AppsecTempResponse struct {
InBandInterrupt bool
OutOfBandInterrupt bool
Action string // allow, deny, captcha, challenge, log
UserHTTPResponseCode int // The response code to send to the user
UserHTTPBodyContent string // The body content to send to the user, only for challenge response
UserHTTPCookies []cookie.AppsecCookie // Raw Set-Cookie headers to send to the user.
UserHeaders map[string][]string // Headers to send to the user
BouncerHTTPResponseCode int // The response code to send to the remediation component
SendEvent bool // do we send an internal event on rule match
SendAlert bool // do we send an alert on rule match
}
func (AppsecTempResponse) Clone ¶
func (r AppsecTempResponse) Clone() AppsecTempResponse
type BodyResponse ¶
type BodySettings ¶ added in v1.7.8
type BodySettings struct {
// MaxSize is the maximum allowed body size in bytes. Defaults to DefaultMaxBodySize (10MB).
MaxSize int64 `yaml:"max_body_size"`
// Action controls what happens when a body exceeds MaxSize:
// "drop" (default) - block the request, "partial" - inspect up to MaxSize bytes, "allow" - skip body inspection.
Action string `yaml:"body_size_exceeded_action"`
}
BodySettings controls how oversized request bodies are handled.
type ChallengeEventInfo ¶
type ChallengeEventInfo struct {
Reason ChallengeReason // requested | submitted | failed | rejected | solved
FailReason string // set on failed (raw error message) or rejected (operator-supplied reason)
FailErr error // set on failed; carries the sentinel-wrapped error so metrics can classify via errors.Is.
Difficulty int // target PoW difficulty for this moment
Fingerprint *challenge.FingerprintData // nil when none available (e.g. requested w/o cookie)
}
ChallengeEventInfo describes a single challenge lifecycle moment to be turned into a pipeline.Event by ChallengeEventFromRequest.
type ChallengeReason ¶
type ChallengeReason string
ChallengeReason identifies a challenge lifecycle moment. Its string value is set as the `challenge_event` field on events produced by ChallengeEventFromRequest.
const ( ChallengeReasonRequested ChallengeReason = "requested" // challenge page served to the client ChallengeReasonSubmitted ChallengeReason = "submitted" // a challenge validation attempt was received ChallengeReasonFailed ChallengeReason = "failed" // submission failed crypto/PoW validation ChallengeReasonRejected ChallengeReason = "rejected" // submission decoded fine but an on_challenge_submit hook called RejectSubmission ChallengeReasonSolved ChallengeReason = "solved" // validation passed, cookie issued )
type ExtendedTransaction ¶
type ExtendedTransaction struct {
Tx experimental.FullTransaction
}
func NewExtendedTransaction ¶
func NewExtendedTransaction(engine coraza.WAF, uuid string) ExtendedTransaction
func NewTransaction ¶
func NewTransaction(tx experimental.FullTransaction) ExtendedTransaction
func (*ExtendedTransaction) AddGetRequestArgument ¶
func (t *ExtendedTransaction) AddGetRequestArgument(name string, value string)
func (*ExtendedTransaction) AddRequestHeader ¶
func (t *ExtendedTransaction) AddRequestHeader(name string, value string)
func (*ExtendedTransaction) Close ¶ added in v1.6.6
func (t *ExtendedTransaction) Close() error
func (*ExtendedTransaction) ID ¶
func (t *ExtendedTransaction) ID() string
func (*ExtendedTransaction) Interrupt ¶ added in v1.7.4
func (t *ExtendedTransaction) Interrupt(interruption *types.Interruption)
func (*ExtendedTransaction) Interruption ¶
func (t *ExtendedTransaction) Interruption() *types.Interruption
func (*ExtendedTransaction) IsInterrupted ¶
func (t *ExtendedTransaction) IsInterrupted() bool
func (*ExtendedTransaction) IsRuleEngineOff ¶
func (t *ExtendedTransaction) IsRuleEngineOff() bool
func (*ExtendedTransaction) MatchedRules ¶
func (t *ExtendedTransaction) MatchedRules() []types.MatchedRule
func (*ExtendedTransaction) ProcessConnection ¶
func (t *ExtendedTransaction) ProcessConnection(client string, cPort int, server string, sPort int)
func (*ExtendedTransaction) ProcessLogging ¶
func (t *ExtendedTransaction) ProcessLogging()
func (*ExtendedTransaction) ProcessRequestBody ¶
func (t *ExtendedTransaction) ProcessRequestBody() (*types.Interruption, error)
func (*ExtendedTransaction) ProcessRequestHeaders ¶
func (t *ExtendedTransaction) ProcessRequestHeaders() *types.Interruption
func (*ExtendedTransaction) ProcessURI ¶
func (t *ExtendedTransaction) ProcessURI(uri string, method string, httpVersion string)
func (*ExtendedTransaction) RemoveRuleByIDWithError ¶
func (t *ExtendedTransaction) RemoveRuleByIDWithError(id int) error
func (*ExtendedTransaction) RemoveRuleByTagWithError ¶
func (t *ExtendedTransaction) RemoveRuleByTagWithError(tag string) error
func (*ExtendedTransaction) SetServerName ¶
func (t *ExtendedTransaction) SetServerName(name string)
func (*ExtendedTransaction) Variables ¶
func (t *ExtendedTransaction) Variables() plugintypes.TransactionVariables
func (*ExtendedTransaction) WriteRequestBody ¶
func (t *ExtendedTransaction) WriteRequestBody(body []byte) (*types.Interruption, int, error)
type Hook ¶
type ParsedRequest ¶
type ParsedRequest struct {
RemoteAddr string `json:"remote_addr,omitempty"`
Host string `json:"host,omitempty"`
ClientIP string `json:"client_ip,omitempty"`
URI string `json:"uri,omitempty"`
Args url.Values `json:"args,omitempty"`
ClientHost string `json:"client_host,omitempty"`
Headers http.Header `json:"headers,omitempty"`
URL *url.URL `json:"url,omitempty"`
Method string `json:"method,omitempty"`
Proto string `json:"proto,omitempty"`
Body []byte `json:"body,omitempty"`
TransferEncoding []string `json:"transfer_encoding,omitempty"`
UUID string `json:"uuid,omitempty"`
ResponseChannel chan AppsecTempResponse `json:"-"`
IsInBand bool `json:"-"`
IsOutBand bool `json:"-"`
AppsecEngine string `json:"appsec_engine,omitempty"`
RemoteAddrNormalized string `json:"normalized_remote_addr,omitempty"`
HTTPRequest *http.Request `json:"-"`
// BodyTruncated is true when the body was larger than the configured limit and was truncated (partial mode).
BodyTruncated bool `json:"body_truncated,omitempty"`
// BodySizeExceeded is true when the body exceeded the configured limit and the action is drop.
// The body is not populated in this case; a fake interruption will be triggered in the runner.
BodySizeExceeded bool `json:"body_size_exceeded,omitempty"`
}
func NewParsedRequestFromRequest ¶
func NewParsedRequestFromRequest(r *http.Request, logger *log.Entry, bodySettings BodySettings) (ParsedRequest, error)
Generate a ParsedRequest from a http.Request. ParsedRequest can be consumed by the App security Engine. bodySettings controls the maximum body size and what to do when the limit is exceeded.
func (*ParsedRequest) DumpRequest ¶
func (r *ParsedRequest) DumpRequest(params ...any) *ReqDumpFilter
type PhaseHooks ¶ added in v1.7.8
PhaseHooks bundles the three phase-scoped hook lists (pre_eval, post_eval, on_match) that run during request evaluation. OnLoad is excluded because it runs once at startup and is not phase-scoped.
type ReqDumpFilter ¶
type ReqDumpFilter struct {
HeadersContentFilters []string
HeadersNameFilters []string
HeadersDrop bool
BodyDrop bool
ArgsContentFilters []string
ArgsNameFilters []string
ArgsDrop bool
// contains filtered or unexported fields
}
func (*ReqDumpFilter) FilterArgs ¶
func (r *ReqDumpFilter) FilterArgs(out *ParsedRequest) error
func (*ReqDumpFilter) FilterBody ¶
func (r *ReqDumpFilter) FilterBody(out *ParsedRequest) error
func (*ReqDumpFilter) FilterHeaders ¶
func (r *ReqDumpFilter) FilterHeaders(out *ParsedRequest) error
func (*ReqDumpFilter) GetFilteredRequest ¶
func (r *ReqDumpFilter) GetFilteredRequest() *ParsedRequest
func (*ReqDumpFilter) ToJSON ¶
func (r *ReqDumpFilter) ToJSON() error
func (*ReqDumpFilter) WithArgsContentFilter ¶
func (r *ReqDumpFilter) WithArgsContentFilter(filter string) *ReqDumpFilter
func (*ReqDumpFilter) WithArgsNameFilter ¶
func (r *ReqDumpFilter) WithArgsNameFilter(filter string) *ReqDumpFilter
func (*ReqDumpFilter) WithBody ¶
func (r *ReqDumpFilter) WithBody() *ReqDumpFilter
func (*ReqDumpFilter) WithEmptyArgsFilters ¶
func (r *ReqDumpFilter) WithEmptyArgsFilters() *ReqDumpFilter
func (*ReqDumpFilter) WithEmptyHeadersFilters ¶
func (r *ReqDumpFilter) WithEmptyHeadersFilters() *ReqDumpFilter
func (*ReqDumpFilter) WithHeaders ¶
func (r *ReqDumpFilter) WithHeaders() *ReqDumpFilter
func (*ReqDumpFilter) WithHeadersContentFilter ¶
func (r *ReqDumpFilter) WithHeadersContentFilter(filter string) *ReqDumpFilter
func (*ReqDumpFilter) WithHeadersNameFilter ¶
func (r *ReqDumpFilter) WithHeadersNameFilter(filter string) *ReqDumpFilter
func (*ReqDumpFilter) WithNoBody ¶
func (r *ReqDumpFilter) WithNoBody() *ReqDumpFilter
func (*ReqDumpFilter) WithNoHeaders ¶
func (r *ReqDumpFilter) WithNoHeaders() *ReqDumpFilter
type RulesDetails ¶
type SubmissionRejectInfo ¶
type SubmissionRejectInfo struct {
Reason string
}
SubmissionRejectInfo signals that an on_challenge_submit hook called RejectSubmission to refuse cookie issuance for a cryptographically valid submission. ProcessOnChallengeRules inspects this on the submit-path branch and, if set, serves bodyChallengeRejected with no Set-Cookie.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package challenge implements the AppSec WAF challenge mode: a PoW-gated landing page, a fingerprint collection bundle, and the surrounding key rotation + cookie machinery.
|
Package challenge implements the AppSec WAF challenge mode: a PoW-gated landing page, a fingerprint collection bundle, and the surrounding key rotation + cookie machinery. |
|
js/cmd/bundle
command
|
|
|
js/cmd/initialbundle
command
initialbundle is a build-time tool that produces a pre-obfuscated initial challenge bundle, embedded into the Go binary.
|
initialbundle is a build-time tool that produces a pre-obfuscated initial challenge bundle, embedded into the Go binary. |
|
js/cmd/obfuscate
command
|
|