Skip to content

Commit

Permalink
Add command execution flows for all three RTR roles to high-level cli…
Browse files Browse the repository at this point in the history
…ent.
  • Loading branch information
Forrest Aldridge committed Dec 12, 2022
1 parent 7c350db commit 6379571
Showing 1 changed file with 134 additions and 26 deletions.
160 changes: 134 additions & 26 deletions falcon/rtr.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,27 @@ import (
"time"

"github.com/crowdstrike/gofalcon/falcon/client/real_time_response"
"github.com/crowdstrike/gofalcon/falcon/client/real_time_response_admin"
"github.com/crowdstrike/gofalcon/falcon/models"
)

type RTR struct {
cli real_time_response.ClientService
client real_time_response.ClientService
adminClient real_time_response_admin.ClientService
}

func NewRTR(apiCfg *ApiConfig) (*RTR, error) {
client, err := NewClient(apiCfg)
if err != nil {
return nil, err
}
return &RTR{cli: client.RealTimeResponse}, nil
return &RTR{client: client.RealTimeResponse, adminClient: client.RealTimeResponseAdmin}, nil
}

type RTRSession struct {
cli real_time_response.ClientService
sessionId string
client real_time_response.ClientService
adminClient real_time_response_admin.ClientService
sessionId string
}

func (r *RTR) ActiveSessions(ctx context.Context) ([]RTRSession, error) {
Expand All @@ -36,8 +39,9 @@ func (r *RTR) ActiveSessions(ctx context.Context) ([]RTRSession, error) {
result := []RTRSession{}
for _, s := range sessions {
result = append(result, RTRSession{
cli: r.cli,
sessionId: *s.ID,
client: r.client,
adminClient: r.adminClient,
sessionId: *s.ID,
})
}
return result, nil
Expand All @@ -48,7 +52,7 @@ func (r *RTR) getActiveSessions(ctx context.Context) ([]*models.DomainSession, e
if err != nil {
return nil, err
}
response, err := r.cli.RTRListSessions(&real_time_response.RTRListSessionsParams{
response, err := r.client.RTRListSessions(&real_time_response.RTRListSessionsParams{
Context: ctx,
Body: &models.MsaIdsRequest{
Ids: sessionIds,
Expand All @@ -65,7 +69,7 @@ func (r *RTR) getActiveSessions(ctx context.Context) ([]*models.DomainSession, e

func (r *RTR) getActiveSessionIds(ctx context.Context) ([]string, error) {
activeQuery := "deleted_at:NULL"
response, err := r.cli.RTRListAllSessions(&real_time_response.RTRListAllSessionsParams{
response, err := r.client.RTRListAllSessions(&real_time_response.RTRListAllSessionsParams{
Context: ctx,
Filter: &activeQuery,
})
Expand All @@ -79,7 +83,7 @@ func (r *RTR) getActiveSessionIds(ctx context.Context) ([]string, error) {
}

func (r *RTR) NewSession(ctx context.Context, deviceID string) (*RTRSession, error) {
response, err := r.cli.RTRInitSession(&real_time_response.RTRInitSessionParams{
response, err := r.client.RTRInitSession(&real_time_response.RTRInitSessionParams{
Body: &models.DomainInitRequest{
DeviceID: &deviceID,
},
Expand All @@ -95,28 +99,66 @@ func (r *RTR) NewSession(ctx context.Context, deviceID string) (*RTRSession, err
return nil, fmt.Errorf("Unexpected return from RTRInitSession: %v", response)
}
return &RTRSession{
cli: r.cli,
sessionId: *response.GetPayload().Resources[0].SessionID,
client: r.client,
adminClient: r.adminClient,
sessionId: *response.GetPayload().Resources[0].SessionID,
}, nil
}

func (s RTRSession) ExecuteAndWait(ctx context.Context, baseCommand, commandString string) (*models.DomainStatusResponse, error) {
execution, err := s.Execute(ctx, baseCommand, commandString)
func (s RTRSession) ExecuteAndWait(ctx context.Context, baseCommand, commandString string, opts ...real_time_response.ClientOption) (*models.DomainStatusResponse, error) {
execution, err := s.Execute(ctx, baseCommand, commandString, opts...)
if err != nil {
return nil, err
}
return s.WaitForExecution(ctx, *execution.CloudRequestID)
return s.WaitForExecution(ctx, *execution.CloudRequestID, opts...)
}

func (s RTRSession) Execute(ctx context.Context, baseCommand, commandString string) (*models.DomainCommandExecuteResponse, error) {
response, err := s.cli.RTRExecuteActiveResponderCommand(&real_time_response.RTRExecuteActiveResponderCommandParams{
func (s RTRSession) ActiveResponderExecuteAndWait(ctx context.Context, baseCommand, commandString string, opts ...real_time_response.ClientOption) (*models.DomainStatusResponse, error) {
execution, err := s.ActiveResponderExecute(ctx, baseCommand, commandString, opts...)
if err != nil {
return nil, err
}
return s.ActiveResponderWaitForExecution(ctx, *execution.CloudRequestID, opts...)
}

func (s RTRSession) AdminExecuteAndWait(ctx context.Context, baseCommand, commandString string, opts ...real_time_response_admin.ClientOption) (*models.DomainStatusResponse, error) {
execution, err := s.AdminExecute(ctx, baseCommand, commandString, opts...)
if err != nil {
return nil, err
}
return s.AdminWaitForExecution(ctx, *execution.CloudRequestID, opts...)
}

func (s RTRSession) Execute(ctx context.Context, baseCommand, commandString string, opts ...real_time_response.ClientOption) (*models.DomainCommandExecuteResponse, error) {
response, err := s.client.RTRExecuteCommand(&real_time_response.RTRExecuteCommandParams{
Context: ctx,
Body: &models.DomainCommandExecuteRequest{
BaseCommand: &baseCommand,
CommandString: &commandString,
SessionID: &s.sessionId,
},
})
}, opts...)
if err != nil {
return nil, err
}
if err = AssertNoError(response.Payload.Errors); err != nil {
return nil, err
}
if len(response.Payload.Resources) != 1 {
return nil, fmt.Errorf("Expected one RTRExecuteResponse object got %d: %v", len(response.Payload.Resources), response.Payload.Resources)
}
return response.Payload.Resources[0], nil
}

func (s RTRSession) ActiveResponderExecute(ctx context.Context, baseCommand, commandString string, opts ...real_time_response.ClientOption) (*models.DomainCommandExecuteResponse, error) {
response, err := s.client.RTRExecuteActiveResponderCommand(&real_time_response.RTRExecuteActiveResponderCommandParams{
Context: ctx,
Body: &models.DomainCommandExecuteRequest{
BaseCommand: &baseCommand,
CommandString: &commandString,
SessionID: &s.sessionId,
},
}, opts...)
if err != nil {
return nil, err
}
Expand All @@ -129,12 +171,77 @@ func (s RTRSession) Execute(ctx context.Context, baseCommand, commandString stri
return response.Payload.Resources[0], nil
}

func (s *RTRSession) WaitForExecution(ctx context.Context, cloudRequestId string) (*models.DomainStatusResponse, error) {
func (s RTRSession) AdminExecute(ctx context.Context, baseCommand, commandString string, opts ...real_time_response_admin.ClientOption) (*models.DomainCommandExecuteResponse, error) {
response, err := s.adminClient.RTRExecuteAdminCommand(&real_time_response_admin.RTRExecuteAdminCommandParams{
Context: ctx,
Body: &models.DomainCommandExecuteRequest{
BaseCommand: &baseCommand,
CommandString: &commandString,
SessionID: &s.sessionId,
},
}, opts...)
if err != nil {
return nil, err
}
if err = AssertNoError(response.Payload.Errors); err != nil {
return nil, err
}
if len(response.Payload.Resources) != 1 {
return nil, fmt.Errorf("Expected one RTRExecuteActiveResponderResponse object got %d: %v", len(response.Payload.Resources), response.Payload.Resources)
}
return response.Payload.Resources[0], nil
}

func (s *RTRSession) WaitForExecution(ctx context.Context, cloudRequestId string, opts ...real_time_response.ClientOption) (*models.DomainStatusResponse, error) {
for {
response, err := s.cli.RTRCheckActiveResponderCommandStatus(&real_time_response.RTRCheckActiveResponderCommandStatusParams{
response, err := s.client.RTRCheckCommandStatus(&real_time_response.RTRCheckCommandStatusParams{
Context: ctx,
CloudRequestID: cloudRequestId,
})
}, opts...)
if err != nil {
return nil, err
}
if err = AssertNoError(response.Payload.Errors); err != nil {
return nil, err
}
if len(response.Payload.Resources) != 1 {
return nil, fmt.Errorf("Unexpected return from RTRCheckActiverResponderCommandStatus: %v", response)
}
if *response.Payload.Resources[0].Complete {
return response.Payload.Resources[0], nil
}
time.Sleep(120 * time.Millisecond)
}
}

func (s *RTRSession) ActiveResponderWaitForExecution(ctx context.Context, cloudRequestId string, opts ...real_time_response.ClientOption) (*models.DomainStatusResponse, error) {
for {
response, err := s.client.RTRCheckActiveResponderCommandStatus(&real_time_response.RTRCheckActiveResponderCommandStatusParams{
Context: ctx,
CloudRequestID: cloudRequestId,
}, opts...)
if err != nil {
return nil, err
}
if err = AssertNoError(response.Payload.Errors); err != nil {
return nil, err
}
if len(response.Payload.Resources) != 1 {
return nil, fmt.Errorf("Unexpected return from RTRCheckActiverResponderCommandStatus: %v", response)
}
if *response.Payload.Resources[0].Complete {
return response.Payload.Resources[0], nil
}
time.Sleep(120 * time.Millisecond)
}
}

func (s *RTRSession) AdminWaitForExecution(ctx context.Context, cloudRequestId string, opts ...real_time_response_admin.ClientOption) (*models.DomainStatusResponse, error) {
for {
response, err := s.adminClient.RTRCheckAdminCommandStatus(&real_time_response_admin.RTRCheckAdminCommandStatusParams{
Context: ctx,
CloudRequestID: cloudRequestId,
}, opts...)
if err != nil {
return nil, err
}
Expand All @@ -152,7 +259,7 @@ func (s *RTRSession) WaitForExecution(ctx context.Context, cloudRequestId string
}

func (s *RTRSession) ListFiles(ctx context.Context) ([]*models.DomainFileV2, error) {
response, err := s.cli.RTRListFilesV2(&real_time_response.RTRListFilesV2Params{
response, err := s.client.RTRListFilesV2(&real_time_response.RTRListFilesV2Params{
Context: ctx,
SessionID: s.sessionId,
})
Expand All @@ -166,7 +273,7 @@ func (s *RTRSession) ListFiles(ctx context.Context) ([]*models.DomainFileV2, err
}

func (s *RTRSession) GetFile(ctx context.Context, sha256, filePath string, output io.Writer) error {
_, err := s.cli.RTRGetExtractedFileContents(&real_time_response.RTRGetExtractedFileContentsParams{
_, err := s.client.RTRGetExtractedFileContents(&real_time_response.RTRGetExtractedFileContentsParams{
Context: ctx,
SessionID: s.sessionId,
Sha256: sha256,
Expand All @@ -176,7 +283,7 @@ func (s *RTRSession) GetFile(ctx context.Context, sha256, filePath string, outpu
}

func (s *RTRSession) Close(ctx context.Context) error {
response, err := s.cli.RTRDeleteSession(&real_time_response.RTRDeleteSessionParams{
response, err := s.client.RTRDeleteSession(&real_time_response.RTRDeleteSessionParams{
Context: ctx,
SessionID: s.sessionId,
})
Expand All @@ -187,7 +294,7 @@ func (s *RTRSession) Close(ctx context.Context) error {
}

func (r *RTR) PulseSession(ctx context.Context, request *models.DomainInitRequest) (*RTRSession, error) {
response, err := r.cli.RTRPulseSession(&real_time_response.RTRPulseSessionParams{
response, err := r.client.RTRPulseSession(&real_time_response.RTRPulseSessionParams{
Context: ctx,
Body: request,
})
Expand All @@ -201,7 +308,8 @@ func (r *RTR) PulseSession(ctx context.Context, request *models.DomainInitReques
return nil, fmt.Errorf("Unexpected return from RTRPulseSession: %v", response)
}
return &RTRSession{
cli: r.cli,
sessionId: *response.GetPayload().Resources[0].SessionID,
client: r.client,
adminClient: r.adminClient,
sessionId: *response.GetPayload().Resources[0].SessionID,
}, nil
}

0 comments on commit 6379571

Please sign in to comment.