| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // Unless explicitly stated otherwise all files in this repository are licensed
- // under the Apache License Version 2.0.
- // This product includes software developed at Datadog (https://www.datadoghq.com/).
- // Copyright 2016 Datadog, Inc.
- //go:build appsec
- // +build appsec
- package appsec
- import (
- "sync"
- "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo"
- "gopkg.in/DataDog/dd-trace-go.v1/internal/log"
- "gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig"
- )
- // Enabled returns true when AppSec is up and running. Meaning that the appsec build tag is enabled, the env var
- // DD_APPSEC_ENABLED is set to true, and the tracer is started.
- func Enabled() bool {
- mu.RLock()
- defer mu.RUnlock()
- return activeAppSec != nil && activeAppSec.started
- }
- // Start AppSec when enabled is enabled by both using the appsec build tag and
- // setting the environment variable DD_APPSEC_ENABLED to true.
- func Start(opts ...StartOption) {
- enabled, set, err := isEnabled()
- if err != nil {
- logUnexpectedStartError(err)
- return
- }
- // Check if AppSec is explicitly disabled
- if set && !enabled {
- log.Debug("appsec: disabled by the configuration: set the environment variable DD_APPSEC_ENABLED to true to enable it")
- return
- }
- // From this point we know that AppSec is either enabled or can be enabled through remote config
- cfg, err := newConfig()
- if err != nil {
- logUnexpectedStartError(err)
- return
- }
- for _, opt := range opts {
- opt(cfg)
- }
- appsec := newAppSec(cfg)
- appsec.startRC()
- // If the env var is not set ASM is disabled, but can be enabled through remote config
- if !set {
- log.Debug("appsec: %s is not set. AppSec won't start until activated through remote configuration", enabledEnvVar)
- if err := appsec.enableRemoteActivation(); err != nil {
- // ASM is not enabled and can't be enabled through remote configuration. Nothing more can be done.
- logUnexpectedStartError(err)
- appsec.stopRC()
- return
- }
- } else if err := appsec.start(); err != nil { // AppSec is specifically enabled
- logUnexpectedStartError(err)
- appsec.stopRC()
- return
- }
- setActiveAppSec(appsec)
- }
- // Implement the AppSec log message C1
- func logUnexpectedStartError(err error) {
- log.Error("appsec: could not start because of an unexpected error: %v\nNo security activities will be collected. Please contact support at https://docs.datadoghq.com/help/ for help.", err)
- }
- // Stop AppSec.
- func Stop() {
- setActiveAppSec(nil)
- }
- var (
- activeAppSec *appsec
- mu sync.RWMutex
- )
- func setActiveAppSec(a *appsec) {
- mu.Lock()
- defer mu.Unlock()
- if activeAppSec != nil {
- activeAppSec.stopRC()
- activeAppSec.stop()
- }
- activeAppSec = a
- }
- type appsec struct {
- cfg *Config
- unregisterWAF dyngo.UnregisterFunc
- limiter *TokenTicker
- rc *remoteconfig.Client
- started bool
- }
- func newAppSec(cfg *Config) *appsec {
- var client *remoteconfig.Client
- var err error
- if cfg.rc != nil {
- client, err = remoteconfig.NewClient(*cfg.rc)
- }
- if err != nil {
- log.Error("appsec: Remote config: disabled due to a client creation error: %v", err)
- }
- return &appsec{
- cfg: cfg,
- rc: client,
- }
- }
- // Start AppSec by registering its security protections according to the configured the security rules.
- func (a *appsec) start() error {
- a.limiter = NewTokenTicker(int64(a.cfg.traceRateLimit), int64(a.cfg.traceRateLimit))
- a.limiter.Start()
- // Register the WAF operation event listener
- unregisterWAF, err := a.registerWAF()
- if err != nil {
- return err
- }
- a.unregisterWAF = unregisterWAF
- a.started = true
- return nil
- }
- // Stop AppSec by unregistering the security protections.
- func (a *appsec) stop() {
- if a.started {
- a.started = false
- a.unregisterWAF()
- a.limiter.Stop()
- }
- }
|