Documentation ¶
Overview ¶
Package appsec provides application security features in the form of SDK functions that can be manually called to monitor specific code paths and data. Application Security is currently transparently integrated into the APM tracer and cannot be used nor started alone at the moment. You can read more on how to enable and start Application Security for Go at https://docs.datadoghq.com/security_platform/application_security/getting_started/go
Index ¶
- func MonitorParsedHTTPBody(ctx context.Context, body interface{}) error
- func SetUser(ctx context.Context, id string, opts ...tracer.UserMonitoringOption) error
- func TrackCustomEvent(ctx context.Context, name string, md map[string]string)
- func TrackUserLoginFailureEvent(ctx context.Context, uid string, exists bool, md map[string]string)
- func TrackUserLoginSuccessEvent(ctx context.Context, uid string, md map[string]string, ...) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MonitorParsedHTTPBody ¶
MonitorParsedHTTPBody runs the security monitoring rules on the given *parsed* HTTP request body and returns if the HTTP request is suspicious and configured to be blocked. The given context must be the HTTP request context as returned by the Context() method of an HTTP request. Calls to this function are ignored if AppSec is disabled or the given context is incorrect. Note that passing the raw bytes of the HTTP request body is not expected and would result in inaccurate attack detection. This function always returns nil when appsec is disabled.
Example ¶
Monitor HTTP request parsed body
package main import ( "encoding/json" "io" "net/http" "github.com/nowfred/dd-trace-go/appsec" httptrace "github.com/nowfred/dd-trace-go/contrib/net/http" ) type parsedBodyType struct { Value string `json:"value"` } func customBodyParser(body io.ReadCloser) (*parsedBodyType, error) { var parsedBody parsedBodyType err := json.NewDecoder(body).Decode(&parsedBody) return &parsedBody, err } func main() { mux := httptrace.NewServeMux() mux.HandleFunc("/body", func(w http.ResponseWriter, r *http.Request) { // Use the SDK to monitor the request's parsed body body, err := customBodyParser(r.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } appsec.MonitorParsedHTTPBody(r.Context(), body) w.Write([]byte("Body monitored using AppSec SDK\n")) }) http.ListenAndServe(":8080", mux) }
Output:
Example (CustomContext) ¶
Monitor HTTP request parsed body with a framework customized context type
r := echo.New() r.Use(echotrace.Middleware()) r.POST("/body", func(c echo.Context) (e error) { req := c.Request() body, err := customBodyParser(req.Body) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } // Use the SDK to monitor the request's parsed body appsec.MonitorParsedHTTPBody(c.Request().Context(), body) return c.String(http.StatusOK, "Body monitored using AppSec SDK") }) r.Start(":8080")
Output:
func SetUser ¶
SetUser wraps tracer.SetUser() and extends it with user blocking. On top of associating the authenticated user information to the service entry span, it checks whether the given user ID is blocked or not by returning an error when it is. A user ID is blocked when it is present in your denylist of users to block at https://app.datadoghq.com/security/appsec/denylist When an error is returned, the caller must immediately abort its execution and the request handler's. The blocking response will be automatically sent by the APM tracer middleware on use according to your blocking configuration. This function always returns nil when appsec is disabled and doesn't block users.
Example ¶
Monitor and block requests depending on user ID
package main import ( "net/http" "github.com/nowfred/dd-trace-go/appsec" httptrace "github.com/nowfred/dd-trace-go/contrib/net/http" ) func userIDFromRequest(r *http.Request) string { return r.Header.Get("user-id") } func main() { mux := httptrace.NewServeMux() mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { // We use SetUser() here to associate the user ID to the request's span. The return value // can then be checked to decide whether to block the request or not. // If it should be blocked, early exit from the handler. if err := appsec.SetUser(r.Context(), userIDFromRequest(r)); err != nil { return } w.Write([]byte("User monitored using AppSec SetUser SDK\n")) }) }
Output:
func TrackCustomEvent ¶
TrackCustomEvent sets a custom event as service entry span tags. This span is obtained through the given Go context which should contain the currently running span. This function does nothing when no span is found in the given Go context, along with an error message. Such events trigger the backend-side events monitoring ultimately blocking the IP address and/or user id associated to them.
Example ¶
package main import ( "context" "github.com/nowfred/dd-trace-go/appsec" "github.com/nowfred/dd-trace-go/ddtrace/tracer" ) func main() { // Create an example span and set a custom appsec event example to it. span, ctx := tracer.StartSpanFromContext(context.Background(), "example") defer span.Finish() appsec.TrackCustomEvent(ctx, "my-custom-event", map[string]string{"region": "us-east-1"}) // To go further in this example, you can add extra security-related context with the authenticated user id when the // request is being served for an authenticated user. tracer.SetUser(span, "user id") }
Output:
func TrackUserLoginFailureEvent ¶
TrackUserLoginFailureEvent sets a failed user login event, with the given user id and the optional metadata, as service entry span tags. The exists argument allows to distinguish whether the given user id actually exists or not. The service entry span is obtained through the given Go context which should contain the currently running span. This function does nothing when no span is found in the given Go context and logs an error message instead. Such events trigger the backend-side events monitoring, such as the Account Take-Over (ATO) monitoring, ultimately blocking the IP address and/or user id associated to them.
Example ¶
package main import ( "context" "github.com/nowfred/dd-trace-go/appsec" "github.com/nowfred/dd-trace-go/ddtrace/tracer" ) func main() { // Create an example span and set a user login failure appsec event example to it. span, ctx := tracer.StartSpanFromContext(context.Background(), "example") defer span.Finish() appsec.TrackUserLoginFailureEvent(ctx, "user id", false, nil) }
Output:
func TrackUserLoginSuccessEvent ¶
func TrackUserLoginSuccessEvent(ctx context.Context, uid string, md map[string]string, opts ...tracer.UserMonitoringOption) error
TrackUserLoginSuccessEvent sets a successful user login event, with the given user id and optional metadata, as service entry span tags. It also calls SetUser() to set the currently authenticated user, along with the given tracer.UserMonitoringOption options. As documented in SetUser(), an error is returned when the given user ID is blocked by your denylist. Cf. SetUser()'s documentation for more details. The service entry span is obtained through the given Go context which should contain the currently running span. This function does nothing when no span is found in the given Go context and logs an error message instead. Such events trigger the backend-side events monitoring, such as the Account Take-Over (ATO) monitoring, ultimately blocking the IP address and/or user id associated to them.
Example ¶
package main import ( "context" "github.com/nowfred/dd-trace-go/appsec" "github.com/nowfred/dd-trace-go/ddtrace/tracer" ) func main() { // Create an example span and set a user login success appsec event example to it. span, ctx := tracer.StartSpanFromContext(context.Background(), "example") defer span.Finish() appsec.TrackUserLoginSuccessEvent(ctx, "user id", map[string]string{"region": "us-east-1"}, tracer.WithUserName("username")) }
Output:
Types ¶
This section is empty.