appsec

package
v1.59.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2024 License: Apache-2.0, BSD-3-Clause, Apache-2.0 Imports: 8 Imported by: 0

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

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func MonitorParsedHTTPBody

func MonitorParsedHTTPBody(ctx context.Context, body interface{}) error

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

func SetUser(ctx context.Context, id string, opts ...tracer.UserMonitoringOption) error

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

func TrackCustomEvent(ctx context.Context, name string, md map[string]string)

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

func TrackUserLoginFailureEvent(ctx context.Context, uid string, exists bool, md map[string]string)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL