detective

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 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-23 (40f059288a40c1d9b7956624bb288861e2e0651d)

Coverage

Metric Value
Operations audited 29 (28 ok, 1 partial)
Feature families 2 (2 ok)
Known gaps 2
Deferred items 2
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. Not fixed this pass: real AWS determines this state via internal GuardDuty volume telemetry with no documented client-controllable trigger, so modeling a way to reach it would mean inventing a control surface that does not exist in the real API rather than emulating one -- a larger, speculative feature, not a wire/state bug fix.
  • MemberDetail still omits DisabledReason, VolumeUsageInBytes (deprecated), VolumeUsageUpdatedTime (deprecated), PercentOfGraphUtilization (deprecated), PercentOfGraphUtilizationUpdatedTime (deprecated), and VolumeUsageByDatasourcePackage. InvitationType and DatasourcePackageIngestStates were fixed this pass (see CreateMembers/GetMembers/ListMembers/ListInvitations notes). The remaining fields are volume/analytics telemetry this emulator does not model (no real data-ingest pipeline), and DisabledReason has no valid state to populate since ACCEPTED_BUT_DISABLED is unreachable (see the StartMonitoringMember gap above) -- all are optional fields real clients already treat as absent-safe, so omitting them is wire-legal, just incomplete. Low priority.
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.
  • UpdateOrganizationConfiguration's AutoEnable flag has no side effect: real AWS auto-enables Detective for new Organizations member accounts as they join the org. This emulator has no Organizations-service integration to source account-join events from, so AutoEnable is stored and returned correctly (DescribeOrganizationConfiguration) but never drives member auto-creation. Out of scope for a single-account emulator with no cross-service org simulation.

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 FlaggedIPAddressDetail added in v1.2.0

type FlaggedIPAddressDetail struct {
	IPAddress string
	Reason    string
}

FlaggedIPAddressDetail describes a threat-intelligence-flagged IP address.

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 ImpossibleTravelDetail added in v1.2.0

type ImpossibleTravelDetail struct {
	StartingIPAddress string
	StartingLocation  string
	EndingIPAddress   string
	EndingLocation    string
	HourlyTimeDelta   int32
}

ImpossibleTravelDetail describes geographically impossible activity.

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. AWS docs: "Removes the Detective administrator account in the current Region. Deletes the organization behavior graph." -- so every graph referenced by the current org admin(s) is deleted along with its dependent state (members, investigations, tags, datasources), not just the orgAdmins record.

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 {
	Detail        IndicatorDetail
	IndicatorType string
}

Indicator is a compromise indicator within an investigation. The real IndicatorDetail shape has no "Title" member; it is a union-like struct with one type-specific sub-detail populated per IndicatorType.

type IndicatorDetail added in v1.2.0

type IndicatorDetail struct {
	FlaggedIPAddress    *FlaggedIPAddressDetail
	ImpossibleTravel    *ImpossibleTravelDetail
	NewASO              *NewASODetail
	NewGeolocation      *NewGeolocationDetail
	NewUserAgent        *NewUserAgentDetail
	RelatedFinding      *RelatedFindingDetail
	RelatedFindingGroup *RelatedFindingGroupDetail
	TTPsObserved        *TTPsObservedDetail
}

IndicatorDetail holds type-specific detail for a compromise indicator. Exactly one field is populated, selected by the sibling IndicatorType, mirroring the real (union-like) aws-sdk-go-v2 IndicatorDetail shape.

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
	DatasourcePackageIngestStates map[string]string
	AccountID                     string
	AdministratorID               string
	EmailAddress                  string
	GraphARN                      string
	InvitationType                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 NewASODetail added in v1.2.0

type NewASODetail struct {
	ASO                   string
	IsNewForEntireAccount bool
}

NewASODetail describes a newly observed Autonomous System Organization.

type NewGeolocationDetail added in v1.2.0

type NewGeolocationDetail struct {
	IPAddress             string
	Location              string
	IsNewForEntireAccount bool
}

NewGeolocationDetail describes a newly observed access geolocation.

type NewUserAgentDetail added in v1.2.0

type NewUserAgentDetail struct {
	UserAgent             string
	IsNewForEntireAccount bool
}

NewUserAgentDetail describes a newly observed client user agent.

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 RelatedFindingDetail added in v1.2.0

type RelatedFindingDetail struct {
	Arn       string
	Type      string
	IPAddress string
}

RelatedFindingDetail describes a GuardDuty finding related to the entity.

type RelatedFindingGroupDetail added in v1.2.0

type RelatedFindingGroupDetail struct {
	ID string
}

RelatedFindingGroupDetail describes a cluster of related findings.

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 TTPsObservedDetail added in v1.2.0

type TTPsObservedDetail struct {
	Tactic          string
	Procedure       string
	APIName         string
	IPAddress       string
	APISuccessCount int64
	APIFailureCount int64
}

TTPsObservedDetail describes an observed tactic/technique/procedure.

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