duo

package
v1.86.1 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: BSD-3-Clause Imports: 22 Imported by: 0

README

Duo Adapter

Entity External IDs

The Entity External ID maps to a Duo Admin API path segment. The adapter constructs URLs as:

{baseURL}/admin/v1/{path}?limit={pageSize}&offset={offset}
Entity External ID API Path Unique ID Attribute Description
User users user_id Duo users
Group groups group_id Duo groups
Phone phones phone_id Registered phones
Endpoint endpoints epkey Registered endpoints/devices

Notes

  • The only supported API version is v1.
  • Pagination uses offset-based pagination (limit + offset query params).

Adding New Entity External IDs

Requires code changes. The adapter validates against a fixed ValidEntityExternalIDs map that defines the path segment and unique ID attribute for each entity.

To add a new entity:

  1. Add a constant in datasource.go (e.g., Token = "Token").
  2. Add an entry to ValidEntityExternalIDs with the Duo Admin API path (e.g., tokens) and unique ID attribute.
  3. Validation will automatically accept the new entity since it checks against this map.
  4. Add tests in endpoint_test.go and adapter_test.go.

Documentation

Index

Constants

View Source
const (
	User     = "User"
	Group    = "Group"
	Phone    = "Phone"
	Endpoint = "Endpoint"
	RFC2822  = "Mon, 02 Jan 2006 15:04:05 -0700"
)

Variables

View Source
var (
	// ValidEntityExternalIDs is a set of valid external IDs of entities that can be queried.
	// The map value is the Entity struct which contains the unique ID attribute.
	ValidEntityExternalIDs = map[string]Entity{
		User: {
			// contains filtered or unexported fields
		},
		Endpoint: {
			// contains filtered or unexported fields
		},
		Group: {
			// contains filtered or unexported fields
		},
		Phone: {
			// contains filtered or unexported fields
		},
	}
)

Functions

func ConfigureAuth

func ConfigureAuth(request *Request, path, params string) (string, string)

func NewAdapter

func NewAdapter(client Client) framework.Adapter[Config]

NewAdapter instantiates a new Adapter.

func ParseResponse

func ParseResponse(body []byte) (
	objects []map[string]any,
	nextCursor *pagination.CompositeCursor[int64],
	err *framework.Error,
)

Types

type Adapter

type Adapter struct {
	DuoClient Client
}

Adapter implements the framework.Adapter interface to query pages of objects from datasources.

func (*Adapter) GetPage

func (a *Adapter) GetPage(ctx context.Context, request *framework.Request[Config]) framework.Response

GetPage is called by SGNL's ingestion service to query a page of objects from a datasource.

func (*Adapter) RequestPageFromDatasource

func (a *Adapter) RequestPageFromDatasource(
	ctx context.Context, request *framework.Request[Config],
) framework.Response

RequestPageFromDatasource requests a page of objects from a datasource.

func (*Adapter) ValidateGetPageRequest

func (a *Adapter) ValidateGetPageRequest(ctx context.Context, request *framework.Request[Config]) *framework.Error

ValidateGetPageRequest validates the fields of the GetPage Request.

type Client

type Client interface {
	GetPage(ctx context.Context, request *Request) (*Response, *framework.Error)
}

Client is a client that allows querying the datasource which contains JSON objects.

func NewClient

func NewClient(client *http.Client) Client

NewClient returns a Client to query the datasource.

type Config

type Config struct {
	// Common configuration
	*config.CommonConfig

	// APIVersion is the version of the Duo API to use.
	APIVersion string `json:"apiVersion,omitempty"`
}

Config is the configuration passed in each GetPage calls to the adapter. Duo Adapter configuration example: nolint: godot

{
    "requestTimeoutSeconds": 10,
    "localTimeZoneOffset": 43200,
    "apiVersion": "v1"
}

func (*Config) Validate

func (c *Config) Validate(_ context.Context) error

ValidateConfig validates that a Config received in a GetPage call is valid.

type Datasource

type Datasource struct {
	Client *http.Client
}

Datasource directly implements a Client interface to allow querying an external datasource.

func (*Datasource) GetPage

func (d *Datasource) GetPage(ctx context.Context, request *Request) (*Response, *framework.Error)

type DatasourceResponse

type DatasourceResponse struct {
	Stat     *string                  `json:"stat"`
	Metadata *ResponseMetadata        `json:"metadata,omitempty"`
	Objects  []map[string]interface{} `json:"response"`
}

Duo API response format.

type EndpointInfo

type EndpointInfo struct {
	URL  string
	Auth string
	Date string
}

func ConstructEndpoint

func ConstructEndpoint(request *Request) (*EndpointInfo, *framework.Error)

ConstructEndpoint constructs and returns the endpoint to query the datasource.

type Entity

type Entity struct {
	// contains filtered or unexported fields
}

Entity contains entity specific information, such as the entity's unique ID attribute and the endpoint path to query that entity.

type Request

type Request struct {
	// BaseURL is the Base URL of the datasource to query.
	BaseURL string

	// Duo application's integration key
	IntegrationKey string

	// Duo Admin API application's secret key.
	Secret string

	// PageSize is the maximum number of objects to return from the entity.
	PageSize int64

	// EntityExternalID is the external ID of the entity.
	// The external ID should match the API's resource name.
	EntityExternalID string

	// Cursor identifies the first object of the page to return, as returned by
	// the last request for the entity.
	// nil in the request for the first page.
	Cursor *pagination.CompositeCursor[int64]

	// APIVersion the API version to use.
	APIVersion string

	// RequestTimeoutSeconds is the timeout duration for requests made to datasources.
	// This should be set to the number of seconds to wait before timing out.
	RequestTimeoutSeconds int
}

Request is a request to the datasource.

type Response

type Response struct {
	// StatusCode is an HTTP status code.
	StatusCode int

	// RetryAfterHeader is the Retry-After response HTTP header, if set.
	RetryAfterHeader string

	// Objects is the list of items returned by the datasource.
	// May be empty.
	Objects []map[string]any

	// NextCursor is the cursor that identifies the first object of the next page.
	// nil if this is the last page in this full sync.
	NextCursor *pagination.CompositeCursor[int64]
}

Response is a response returned by the datasource.

type ResponseMetadata

type ResponseMetadata struct {
	NextOffset *int64 `json:"next_offset,omitempty"`
}

Duo API Metadata format used for pagination.

Jump to

Keyboard shortcuts

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