detective

package
v1.1.2 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 23 Imported by: 0

README

Detective

Parity grade: A · SDK aws-sdk-go-v2/service/detective@v1.39.1 · last audited 2026-07-13 (40f059288a40c1d9b7956624bb288861e2e0651d)

Coverage

Metric Value
Operations audited 29 (27 ok, 2 partial)
Feature families 2 (2 ok)
Known gaps 4
Deferred items 1
Resource leaks clean
Known gaps
  • StartMonitoringMember's precondition (member status ACCEPTED_BUT_DISABLED) is unreachable through normal API flow: AcceptInvitation transitions INVITED straight to ENABLED, mirroring the AWS happy path, but real Detective can also land a member in ACCEPTED_BUT_DISABLED (data-volume-too-high / volume-unknown edge cases per MemberDisabledReason) which this emulator does not model. Deferred: modeling those admission-control edge cases is a larger feature, not a wire/state bug.
  • DisableOrganizationAdminAccount does not delete the organization behavior graph (AWS docs: 'Deletes the organization behavior graph.'). Not fixed this pass: this emulator's one-graph-per-account model does not distinguish an org behavior graph from a personal one, so forcibly deleting b.graphs on Disable risks destroying state a test/flow expects to persist independently, without a clear real-world precedent to validate against in this simplified model.
  • MemberDetail response omits several AWS-optional/deprecated fields never populated: DisabledReason, VolumeUsageInBytes (deprecated), VolumeUsageUpdatedTime (deprecated), PercentOfGraphUtilization (deprecated), PercentOfGraphUtilizationUpdatedTime (deprecated), InvitationType, VolumeUsageByDatasourcePackage, DatasourcePackageIngestStates. All are optional/analytics fields real clients treat as absent-safe; not stubs since the op itself is real, just an unpopulated optional field. Low priority.
  • List pagination tokens are not uniformly opaque: ListGraphs/ListMembers/ListIndicators use base64(offset) via encodePageToken, but ListInvitations/ListInvestigations/ListOrganizationAdminAccounts/ListDatasourcePackages use the raw next item's ID/ARN as the token. Both are wire-legal (AWS never guarantees token structure to callers) but the latter leaks internal identifiers. Stylistic/hygiene, not a wire-shape bug.
Deferred
  • Detective Organizations edge cases beyond the base Enable/Disable/List/Describe/Update surface (delegated-admin-account transfer, cross-region graph semantics) — out of scope for a single-region single-account emulator.

More

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrGraphNotFound is returned when a behavior graph does not exist.
	ErrGraphNotFound = awserr.New(errResourceNotFound, awserr.ErrNotFound)
	// ErrAlreadyHasGraph is returned when account already has a graph in region.
	ErrAlreadyHasGraph = awserr.New(errConflictException, awserr.ErrAlreadyExists)
	// ErrMemberNotFound is returned when a member does not exist.
	ErrMemberNotFound = awserr.New(errResourceNotFound, awserr.ErrNotFound)
	// ErrValidation is returned on invalid input.
	ErrValidation = awserr.New(errValidation, awserr.ErrInvalidParameter)
)
View Source
var ErrNilAppContext = errors.New("detective: nil app context")

ErrNilAppContext is returned when Init is called with a nil AppContext.

Functions

This section is empty.

Types

type Account

type Account struct {
	AccountID    string
	EmailAddress string
}

Account is an AWS account for member operations.

type DatasourcePackageIngestDetail

type DatasourcePackageIngestDetail struct {
	IngestState string
}

DatasourcePackageIngestDetail holds the ingest state for a datasource package.

type Graph

type Graph struct {
	CreatedTime time.Time
	Tags        map[string]string
	Arn         string
}

Graph represents a Detective behavior graph. CreatedTime is first so its non-pointer prefix (wall, ext) reduces GC pointer bytes.

type Handler

type Handler struct {
	Backend StorageBackend
	// contains filtered or unexported fields
}

Handler handles Detective HTTP requests.

func NewHandler

func NewHandler(b StorageBackend) *Handler

NewHandler constructs a new Handler.

func (*Handler) ExtractOperation

func (h *Handler) ExtractOperation(c *echo.Context) string

ExtractOperation extracts the operation name from the request.

func (*Handler) ExtractResource

func (h *Handler) ExtractResource(c *echo.Context) string

ExtractResource extracts the resource identifier from the request.

func (*Handler) GetSupportedOperations

func (h *Handler) GetSupportedOperations() []string

GetSupportedOperations returns the list of supported operations.

func (*Handler) Handler

func (h *Handler) Handler() echo.HandlerFunc

Handler returns the Echo handler function.

func (*Handler) MatchPriority

func (h *Handler) MatchPriority() int

MatchPriority returns the routing priority.

func (*Handler) Name

func (h *Handler) Name() string

Name returns the service name.

func (*Handler) Reset

func (h *Handler) Reset()

Reset resets the backend.

func (*Handler) Restore

func (h *Handler) Restore(ctx context.Context, data []byte) error

Restore implements persistence.Persistable by delegating to the backend.

func (*Handler) RouteMatcher

func (h *Handler) RouteMatcher() service.Matcher

RouteMatcher returns a matcher that accepts Detective REST paths.

func (*Handler) Snapshot

func (h *Handler) Snapshot(ctx context.Context) []byte

Snapshot implements persistence.Persistable by delegating to the backend. Without this, cli.go's generic setupPersistence (which type-asserts the registered service.Registerable, i.e. *Handler, for Snapshot/Restore) never finds a persistable Detective service even though InMemoryBackend itself has always implemented Snapshot/Restore -- the backend methods were dead wiring until Handler delegated to them.

type InMemoryBackend

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

InMemoryBackend implements StorageBackend using in-memory maps.

graphs, members, and investigations are store.Table-backed (see store_setup.go); tags, datasources, and orgConfigs remain plain maps since their values are not *T; orgAdmins remains a plain order-sensitive slice.

func NewInMemoryBackend

func NewInMemoryBackend(accountID, region string) *InMemoryBackend

NewInMemoryBackend constructs a new InMemoryBackend.

func (*InMemoryBackend) AcceptInvitation

func (b *InMemoryBackend) AcceptInvitation(graphARN string) error

AcceptInvitation accepts a graph invitation on behalf of the member account.

func (*InMemoryBackend) AccountID

func (b *InMemoryBackend) AccountID() string

AccountID returns the account ID.

func (*InMemoryBackend) BatchGetGraphMemberDatasources

func (b *InMemoryBackend) BatchGetGraphMemberDatasources(
	graphARN string,
	accountIDs []string,
) ([]MembershipDatasources, []UnprocessedAccount, error)

BatchGetGraphMemberDatasources returns datasource package info for member accounts of a graph.

func (*InMemoryBackend) BatchGetMembershipDatasources

func (b *InMemoryBackend) BatchGetMembershipDatasources(
	graphARNs []string,
) ([]MembershipDatasources, []UnprocessedGraph, error)

BatchGetMembershipDatasources returns datasource history for the account across graphs.

func (*InMemoryBackend) CreateGraph

func (b *InMemoryBackend) CreateGraph(tags map[string]string) (*Graph, error)

CreateGraph creates a new behavior graph. Returns existing one if already created (idempotent).

func (*InMemoryBackend) CreateMembers

func (b *InMemoryBackend) CreateMembers(
	graphARN string,
	accounts []Account,
	_ string,
) ([]*MemberDetail, []UnprocessedAccount, error)

CreateMembers creates or invites member accounts to a behavior graph.

func (*InMemoryBackend) DeleteGraph

func (b *InMemoryBackend) DeleteGraph(graphARN string) error

DeleteGraph deletes a behavior graph.

func (*InMemoryBackend) DeleteMembers

func (b *InMemoryBackend) DeleteMembers(
	graphARN string,
	accountIDs []string,
) ([]string, []UnprocessedAccount, error)

DeleteMembers removes member accounts from a behavior graph.

func (*InMemoryBackend) DescribeOrganizationConfiguration

func (b *InMemoryBackend) DescribeOrganizationConfiguration(graphARN string) (bool, error)

DescribeOrganizationConfiguration returns AutoEnable setting for a graph.

func (*InMemoryBackend) DisableOrganizationAdminAccount

func (b *InMemoryBackend) DisableOrganizationAdminAccount() error

DisableOrganizationAdminAccount removes the Detective administrator account.

func (*InMemoryBackend) DisassociateMembership

func (b *InMemoryBackend) DisassociateMembership(graphARN string) error

DisassociateMembership removes the calling account from a graph it belongs to.

func (*InMemoryBackend) EnableOrganizationAdminAccount

func (b *InMemoryBackend) EnableOrganizationAdminAccount(accountID string) error

EnableOrganizationAdminAccount designates a Detective administrator account.

func (*InMemoryBackend) GetInvestigation

func (b *InMemoryBackend) GetInvestigation(graphARN, investigationID string) (*Investigation, error)

GetInvestigation returns an investigation by graph ARN and investigation ID.

func (*InMemoryBackend) GetMembers

func (b *InMemoryBackend) GetMembers(
	graphARN string,
	accountIDs []string,
) ([]*MemberDetail, []UnprocessedAccount, error)

GetMembers returns member details for the given account IDs.

func (*InMemoryBackend) ListDatasourcePackages

func (b *InMemoryBackend) ListDatasourcePackages(
	graphARN string,
	maxResults int32,
	nextToken string,
) (map[string]DatasourcePackageIngestDetail, string, error)

ListDatasourcePackages returns datasource package ingest details for a graph.

func (*InMemoryBackend) ListGraphs

func (b *InMemoryBackend) ListGraphs(maxResults int32, nextToken string) ([]*Graph, string, error)

ListGraphs returns behavior graphs for the admin account.

func (*InMemoryBackend) ListIndicators

func (b *InMemoryBackend) ListIndicators(
	graphARN, investigationID, indicatorType string,
	maxResults int32,
	nextToken string,
) ([]*Indicator, string, error)

ListIndicators returns indicators for an investigation.

func (*InMemoryBackend) ListInvestigations

func (b *InMemoryBackend) ListInvestigations(
	graphARN string,
	maxResults int32,
	nextToken string,
) ([]*InvestigationDetail, string, error)

ListInvestigations returns investigations for a graph.

func (*InMemoryBackend) ListInvitations

func (b *InMemoryBackend) ListInvitations(maxResults int32, nextToken string) ([]*MemberDetail, string, error)

ListInvitations returns graphs where this account has an open or accepted invitation.

func (*InMemoryBackend) ListMembers

func (b *InMemoryBackend) ListMembers(
	graphARN string,
	maxResults int32,
	nextToken string,
) ([]*MemberDetail, string, error)

ListMembers returns member accounts for a behavior graph.

func (*InMemoryBackend) ListOrganizationAdminAccounts

func (b *InMemoryBackend) ListOrganizationAdminAccounts(
	maxResults int32,
	nextToken string,
) ([]*OrgAdmin, string, error)

ListOrganizationAdminAccounts returns Detective organization administrator accounts.

func (*InMemoryBackend) ListTagsForResource

func (b *InMemoryBackend) ListTagsForResource(resourceARN string) (map[string]string, error)

ListTagsForResource returns tags for a resource.

func (*InMemoryBackend) Region

func (b *InMemoryBackend) Region() string

Region returns the region.

func (*InMemoryBackend) RejectInvitation

func (b *InMemoryBackend) RejectInvitation(graphARN string) error

RejectInvitation rejects a graph invitation on behalf of the member account.

func (*InMemoryBackend) Reset

func (b *InMemoryBackend) Reset()

Reset clears all state.

func (*InMemoryBackend) Restore

func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error

Restore deserializes backend state from a snapshot.

func (*InMemoryBackend) Snapshot

func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte

Snapshot serializes the backend state to JSON.

func (*InMemoryBackend) StartInvestigation

func (b *InMemoryBackend) StartInvestigation(
	graphARN, entityARN string,
	scopeStart, scopeEnd time.Time,
) (string, error)

StartInvestigation creates a new investigation for an entity within a graph.

func (*InMemoryBackend) StartMonitoringMember

func (b *InMemoryBackend) StartMonitoringMember(graphARN, accountID string) error

StartMonitoringMember enables monitoring for a member in ACCEPTED_BUT_DISABLED state.

func (*InMemoryBackend) TagResource

func (b *InMemoryBackend) TagResource(resourceARN string, tags map[string]string) error

TagResource adds or updates tags on a resource.

func (*InMemoryBackend) UntagResource

func (b *InMemoryBackend) UntagResource(resourceARN string, tagKeys []string) error

UntagResource removes tags from a resource.

func (*InMemoryBackend) UpdateDatasourcePackages

func (b *InMemoryBackend) UpdateDatasourcePackages(graphARN string, packages []string) error

UpdateDatasourcePackages enables datasource packages on a graph.

func (*InMemoryBackend) UpdateInvestigationState

func (b *InMemoryBackend) UpdateInvestigationState(graphARN, investigationID, state string) error

UpdateInvestigationState updates the state of an investigation.

func (*InMemoryBackend) UpdateOrganizationConfiguration

func (b *InMemoryBackend) UpdateOrganizationConfiguration(graphARN string, autoEnable bool) error

UpdateOrganizationConfiguration sets the AutoEnable flag for a graph.

type Indicator

type Indicator struct {
	IndicatorType string
	Title         string
}

Indicator is a compromise indicator within an investigation.

type Investigation

type Investigation struct {
	CreatedTime     time.Time
	ScopeStartTime  time.Time
	ScopeEndTime    time.Time
	GraphARN        string
	InvestigationID string
	EntityARN       string
	EntityType      string
	Severity        string
	State           string
	Status          string
}

Investigation holds investigation report data. time.Time fields are first so their non-pointer prefix reduces GC pointer bytes.

type InvestigationDetail

type InvestigationDetail struct {
	CreatedTime     time.Time
	EntityARN       string
	EntityType      string
	InvestigationID string
	Severity        string
	State           string
	Status          string
}

InvestigationDetail is a summary of an investigation used in list responses. time.Time is first so its non-pointer prefix reduces GC pointer bytes.

type MemberDetail

type MemberDetail struct {
	InvitedTime     time.Time
	UpdatedTime     time.Time
	AccountID       string
	AdministratorID string
	EmailAddress    string
	GraphARN        string
	Status          string
}

MemberDetail is the detail of a behavior graph member. time.Time fields are first so their non-pointer prefix reduces GC pointer bytes.

type MembershipDatasources

type MembershipDatasources struct {
	DatasourcePackageIngestStates map[string]string
	AccountID                     string
	GraphARN                      string
}

MembershipDatasources holds datasource package info for a member or graph.

type OrgAdmin

type OrgAdmin struct {
	DelegationTime time.Time
	AccountID      string
	GraphARN       string
}

OrgAdmin represents a Detective organization administrator account. DelegationTime is first so its non-pointer prefix reduces GC pointer bytes.

type Provider

type Provider struct{}

Provider implements service.Provider for Amazon Detective.

func (*Provider) Init

Init initializes the Detective service backend and handler.

func (*Provider) Name

func (p *Provider) Name() string

Name returns the provider name.

type StorageBackend

type StorageBackend interface {
	CreateGraph(tags map[string]string) (*Graph, error)
	DeleteGraph(graphARN string) error
	ListGraphs(maxResults int32, nextToken string) ([]*Graph, string, error)

	CreateMembers(graphARN string, accounts []Account, message string) ([]*MemberDetail, []UnprocessedAccount, error)
	DeleteMembers(graphARN string, accountIDs []string) ([]string, []UnprocessedAccount, error)
	GetMembers(graphARN string, accountIDs []string) ([]*MemberDetail, []UnprocessedAccount, error)
	ListMembers(graphARN string, maxResults int32, nextToken string) ([]*MemberDetail, string, error)

	TagResource(resourceARN string, tags map[string]string) error
	UntagResource(resourceARN string, tagKeys []string) error
	ListTagsForResource(resourceARN string) (map[string]string, error)

	AcceptInvitation(graphARN string) error
	RejectInvitation(graphARN string) error
	DisassociateMembership(graphARN string) error
	ListInvitations(maxResults int32, nextToken string) ([]*MemberDetail, string, error)

	StartInvestigation(graphARN, entityARN string, scopeStart, scopeEnd time.Time) (string, error)
	GetInvestigation(graphARN, investigationID string) (*Investigation, error)
	ListInvestigations(graphARN string, maxResults int32, nextToken string) ([]*InvestigationDetail, string, error)
	UpdateInvestigationState(graphARN, investigationID, state string) error
	ListIndicators(
		graphARN, investigationID, indicatorType string,
		maxResults int32,
		nextToken string,
	) ([]*Indicator, string, error)

	ListDatasourcePackages(
		graphARN string,
		maxResults int32,
		nextToken string,
	) (map[string]DatasourcePackageIngestDetail, string, error)
	UpdateDatasourcePackages(graphARN string, packages []string) error
	BatchGetGraphMemberDatasources(
		graphARN string,
		accountIDs []string,
	) ([]MembershipDatasources, []UnprocessedAccount, error)
	BatchGetMembershipDatasources(graphARNs []string) ([]MembershipDatasources, []UnprocessedGraph, error)

	EnableOrganizationAdminAccount(accountID string) error
	DisableOrganizationAdminAccount() error
	ListOrganizationAdminAccounts(maxResults int32, nextToken string) ([]*OrgAdmin, string, error)
	DescribeOrganizationConfiguration(graphARN string) (bool, error)
	UpdateOrganizationConfiguration(graphARN string, autoEnable bool) error

	StartMonitoringMember(graphARN, accountID string) error

	AccountID() string
	Region() string
	Reset()
	Snapshot(ctx context.Context) []byte
	Restore(ctx context.Context, data []byte) error
}

StorageBackend is the interface for Detective storage operations.

type UnprocessedAccount

type UnprocessedAccount struct {
	AccountID string
	Reason    string
}

UnprocessedAccount is an account that could not be processed.

type UnprocessedGraph

type UnprocessedGraph struct {
	GraphArn string
	Reason   string
}

UnprocessedGraph is a graph that could not be processed.

Jump to

Keyboard shortcuts

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