pcap

package module
v0.0.0-...-03525d1 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2024 License: Apache-2.0 Imports: 39 Imported by: 0

README

PCAP

Generating the gRPC stubs

Set up the protoc compiler with output to gRPC: https://grpc.io/docs/languages/go/quickstart/

brew install protobuf

go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

Running on MacOS (including Tests)

You might end up with errors complaining about not having access to capture from local network interfaces.

Change the group for the BPF devices to staff:

sudo chgrp staff /dev/bpf*; sudo chmod g+rw /dev/bpf*; ls -la /dev/bpf*

Alternatively:

Wireshark guide on installing and running on MacOS.

Install ChmodBPF, available as part of Wireshark.

The path to the installer can be found in Wireshark > About Wireshark > Folders, MacOS Extras.

The installer is called Install ChmodBPF.pkg.

Running the tests on MacOS

All unit tests can be run locally via go test. The integration tests are included in go test ./... however and require some special handling.

The integration tests open mock servers on different IPs on the loopback device in the CIDR 127.0.0.0/8. MacOS does not by default support addresses other than 127.0.0.1. It can be configured via aliases, but attempts to do so have not led to successful test execution.

Instead, a Dockerfile and docker-compose file are provided, which will automatically execute all tests (go test and ginkgo tests via test suite).

cd src/pcap
# the dockerfile is relative to src/pcap and mounts the current code as volume into the container.
docker compose up

This will build the image from Dockerfile and run go test -v ./.... This should give you confidence in the tests completing successfully.

Running in IntelliJ

Using the Dockerfile or Docker Compose file, you can also run the tests using the Go integration in IntelliJ.

When selecting the run configuration, set up a Docker run target, either with Docker or Docker Compose. Documentation on setting up run targets os available from JetBrains.

Running Ginkgo Tests in IntelliJ and Docker

There is a Ginkgo plugin for IntelliJ, which helps develop ginkgo tests. It can be used to visualize the structure of the test file (via the Structure view) and execute specific tests in Focus mode.

Some of the integration tests require the aforementioned multiple IP addresses and will not run directly. The Ginkgo plugin does unfortunately not integrate with run targets.

A run configuration with go test can be created, which will call the Ginkgo tests via Test Suite integration. Furthermore, Ginkgo command line flags can be passed on to this command as well.

When developing Ginkgo tests, you often want to execute a subset of tests in Focus mode. By adding the -ginkgo.focus "Your ginkgo focus test expression" flag to the go test command, you can still use focus mode.

Example:

go test github.com/cloudfoundry/pcap-release/src/pcap/test/integration -test.v -ginkgo.focus="Some Test Names"

You can configure an appropriate run configuration with a Docker based run target, as shown in the screenshot below.

Important: Select the "Build on remote Target" checkbox as cross-compiling pcap-release with libpcap is not easily possible.

Build configuration in IntelliJ

Running linters

Using golangci-lint, the linters can be run locally or files can be fixed automatically:

# Execute linter locally
golangci-lint run

# Apply fixes locally
golangci-lint run --fix

Documentation

Overview

Package pcap provides types and interfaces to build a remote packet capturing tool. For details about the different applications see the different packages in `cmd/`.

Index

Constants

View Source
const (
	// CompatibilityLevel indicates whether two parties are compatible. Once there is a change
	// that requires both parties to be updated this value MUST be incremented by one. The calling
	// party has to ensure that the compatibility level of the called party is equal or larger and
	// refuse operation if it isn't.
	CompatibilityLevel int64 = 1

	// LogKeyVcapID sets on which field the vcap request id will be logged.
	LogKeyVcapID = "vcap-id"
	// LogKeyHandler sets the logged handler. Useful for distinguishing, which part of the code logged the message or error.
	LogKeyHandler  = "handler"
	LogKeyTarget   = "target"
	LogKeyResolver = "resolver"
	HeaderVcapID   = contextKeyVcapID("x-vcap-request-id")

	DefaultStatusTimeout = time.Minute
)

Variables

View Source
var (
	ErrValidationFailed = fmt.Errorf("validation failed")

	ErrNoEndpoints       = fmt.Errorf("no matching endpoints found")
	ErrNotConnected      = fmt.Errorf("client not connected to api")
	ErrResolverUnhealthy = fmt.Errorf("resolver unhealthy")
	ErrNotAuthorized     = fmt.Errorf("not authorized")
	ErrTokenUnsupported  = fmt.Errorf("token unsupported: %w", ErrNotAuthorized)

	ErrBoshNotConnected = fmt.Errorf("not connected to bosh director")
)
View Source
var (
	MessageType_name = map[int32]string{
		0: "UNKNOWN",
		1: "INSTANCE_UNAVAILABLE",
		2: "START_CAPTURE_FAILED",
		3: "INVALID_REQUEST",
		4: "CONGESTED",
		5: "LIMIT_REACHED",
		6: "CAPTURE_STOPPED",
		7: "CONNECTION_ERROR",
	}
	MessageType_value = map[string]int32{
		"UNKNOWN":              0,
		"INSTANCE_UNAVAILABLE": 1,
		"START_CAPTURE_FAILED": 2,
		"INVALID_REQUEST":      3,
		"CONGESTED":            4,
		"LIMIT_REACHED":        5,
		"CAPTURE_STOPPED":      6,
		"CONNECTION_ERROR":     7,
	}
)

Enum value maps for MessageType.

View Source
var API_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "pcap.API",
	HandlerType: (*APIServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Status",
			Handler:    _API_Status_Handler,
		},
	},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "Capture",
			Handler:       _API_Capture_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
	},
	Metadata: "pcap.proto",
}

API_ServiceDesc is the grpc.ServiceDesc for API service. It's only intended for direct use with grpc.RegisterService, and not to be introspected or modified (even as a copy)

View Source
var Agent_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "pcap.Agent",
	HandlerType: (*AgentServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Status",
			Handler:    _Agent_Status_Handler,
		},
	},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "Capture",
			Handler:       _Agent_Capture_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
	},
	Metadata: "pcap.proto",
}

Agent_ServiceDesc is the grpc.ServiceDesc for Agent service. It's only intended for direct use with grpc.RegisterService, and not to be introspected or modified (even as a copy)

View Source
var BoshResolverName = "bosh"

Functions

func MessageLogLevel

func MessageLogLevel(message *Message) zapcore.Level

MessageLogLevel translates the message types to appropropriate default log levels.

func RegisterAPIServer

func RegisterAPIServer(s grpc.ServiceRegistrar, srv APIServer)

func RegisterAgentServer

func RegisterAgentServer(s grpc.ServiceRegistrar, srv AgentServer)

func SetLogLevel

func SetLogLevel(log *zap.Logger, logLevel string)

func StopOnSignal

func StopOnSignal(log *zap.Logger, stoppable Stoppable, server *grpc.Server, stopSignals ...os.Signal)

StopOnSignal is a reusable function to handle stop signals.

The Stoppable interface defines what to do when stopping a particular process, and stopSignals defines a list of signals, for which Stop() is called.

When a server is given, it is shut down gracefully.

The provided Stoppable can also be a WaitingStoppable. Then the Wait() function is also called.

Types

type API

type API struct {
	UnimplementedAPIServer
	// contains filtered or unexported fields
}

func NewAPI

func NewAPI(bufConf BufferConf, clientTLS *ClientTLS, id string, maxConcurrentCaptures int32) (*API, error)

func (*API) Capture

func (api *API) Capture(stream API_CaptureServer) (err error)

Capture receives messages (start or stop capture) from the client and streams payload (messages or pcap data) back.

func (*API) HasResolver

func (api *API) HasResolver(handler string) bool

HasResolver checks if handler is registered.

Returns false, if the handler is not registered.

func (*API) HealthyResolverNames

func (api *API) HealthyResolverNames() []string

HealthyResolverNames provides a list of resolver names that are configured and marked healthy.

func (*API) RegisterResolver

func (api *API) RegisterResolver(resolver AgentResolver)

func (*API) Status

func (api *API) Status(context.Context, *StatusRequest) (*StatusResponse, error)

Status provides the current status information for the pcap-api service.

The service is marked unhealthy when there are no healthy resolvers available, or the API is draining (shutting down).

func (*API) Stop

func (api *API) Stop()

Stop the server. This will gracefully stop any captures that are currently running by closing API.done. Further calls to Stop have no effect.

func (*API) Wait

func (api *API) Wait()

Wait for all open capture requests to terminate.

type APIClient

type APIClient interface {
	Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
	// Capture starts capturing packets on either BOSH or CF VMs. The capture can be
	// stopped by closing the client-side send channel, or explicitly sending a Stop command.
	// The Api MUST listen for that close and the stop command and MUST stop sending packets
	// as soon as possible but SHOULD send packets that it still receives from the agents.
	Capture(ctx context.Context, opts ...grpc.CallOption) (API_CaptureClient, error)
}

APIClient is the client API for API service.

For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.

func NewAPIClient

func NewAPIClient(cc grpc.ClientConnInterface) APIClient

type APIServer

type APIServer interface {
	Status(context.Context, *StatusRequest) (*StatusResponse, error)
	// Capture starts capturing packets on either BOSH or CF VMs. The capture can be
	// stopped by closing the client-side send channel, or explicitly sending a Stop command.
	// The Api MUST listen for that close and the stop command and MUST stop sending packets
	// as soon as possible but SHOULD send packets that it still receives from the agents.
	Capture(API_CaptureServer) error
	// contains filtered or unexported methods
}

APIServer is the server API for API service. All implementations must embed UnimplementedAPIServer for forward compatibility

type API_CaptureClient

type API_CaptureClient interface {
	Send(*CaptureRequest) error
	Recv() (*CaptureResponse, error)
	grpc.ClientStream
}

type API_CaptureServer

type API_CaptureServer interface {
	Send(*CaptureResponse) error
	Recv() (*CaptureRequest, error)
	grpc.ServerStream
}

type Agent

type Agent struct {
	UnimplementedAgentServer
	// contains filtered or unexported fields
}

Agent is the central struct to which the handlers are attached.

func NewAgent

func NewAgent(bufConf BufferConf, id string) *Agent

NewAgent creates a new ready-to-use agent.

func (*Agent) Capture

func (a *Agent) Capture(stream Agent_CaptureServer) (err error)

Capture handler for the pcap-agent. See AgentServer.Capture documentation for details.

func (*Agent) Status

func (a *Agent) Status(_ context.Context, _ *StatusRequest) (*StatusResponse, error)

Status handler for the pcap-agent. See AgentServer.Status documentation for details.

func (*Agent) Stop

func (a *Agent) Stop()

Stop the server. This will gracefully stop any captures that are currently running by closing Agent.done. Further calls to Stop have no effect.

func (*Agent) Wait

func (a *Agent) Wait()

Wait for all open streams to terminate.

type AgentClient

type AgentClient interface {
	// Status returns the current status of the agent. It indicates whether the agent is ready to
	// accept new capture requests or is currently unavailable.
	Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
	// Capture is the main handler for the pcap agent. It contains the logic to open an interface
	// and start a packet capture. The resulting packets will be streamed back to the caller together
	// with messages informing the caller of any abnormal conditions that occur. The first message
	// sent must contain a payload of type StartAgentCapture, this will trigger the start of the capture.
	// The only messages that can be sent next is a StopAgentCapture which stops the capture gracefully
	// still sending any packets that are remaining and closing the stream afterwards.
	Capture(ctx context.Context, opts ...grpc.CallOption) (Agent_CaptureClient, error)
}

AgentClient is the client API for Agent service.

For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.

func NewAgentClient

func NewAgentClient(cc grpc.ClientConnInterface) AgentClient

type AgentEndpoint

type AgentEndpoint struct {
	IP         string
	Port       int
	Identifier string
}

AgentEndpoint defines the endpoint for a pcap-agent.

func (AgentEndpoint) String

func (a AgentEndpoint) String() string

type AgentRequest

type AgentRequest struct {

	// payload wraps the start and stop requests.
	//
	// Types that are assignable to Payload:
	//
	//	*AgentRequest_Start
	//	*AgentRequest_Stop
	Payload isAgentRequest_Payload `protobuf_oneof:"payload"`
	// contains filtered or unexported fields
}

AgentRequest contains either the start or stop request.

func (*AgentRequest) Descriptor deprecated

func (*AgentRequest) Descriptor() ([]byte, []int)

Deprecated: Use AgentRequest.ProtoReflect.Descriptor instead.

func (*AgentRequest) GetPayload

func (m *AgentRequest) GetPayload() isAgentRequest_Payload

func (*AgentRequest) GetStart

func (x *AgentRequest) GetStart() *StartAgentCapture

func (*AgentRequest) GetStop

func (x *AgentRequest) GetStop() *StopAgentCapture

func (*AgentRequest) ProtoMessage

func (*AgentRequest) ProtoMessage()

func (*AgentRequest) ProtoReflect

func (x *AgentRequest) ProtoReflect() protoreflect.Message

func (*AgentRequest) Reset

func (x *AgentRequest) Reset()

func (*AgentRequest) String

func (x *AgentRequest) String() string

type AgentRequest_Start

type AgentRequest_Start struct {
	Start *StartAgentCapture `protobuf:"bytes,1,opt,name=start,proto3,oneof"`
}

type AgentRequest_Stop

type AgentRequest_Stop struct {
	Stop *StopAgentCapture `protobuf:"bytes,2,opt,name=stop,proto3,oneof"`
}

type AgentResolver

type AgentResolver interface {
	// Name provides the name of the handler for outputs and internal mapping.
	Name() string
	// CanResolve determines if this handler is responsible for handling the Capture
	CanResolve(*EndpointRequest) bool
	// Resolve either resolves and returns the agents targeted by Capture or provides an error
	Resolve(*EndpointRequest, *zap.Logger) ([]AgentEndpoint, error)
	// Healthy determines, whether this handler is healthy or not
	Healthy() bool
}

AgentResolver defines resolver for different request types that ultimately lead to a selection of AgentEndpoints.

type AgentServer

type AgentServer interface {
	// Status returns the current status of the agent. It indicates whether the agent is ready to
	// accept new capture requests or is currently unavailable.
	Status(context.Context, *StatusRequest) (*StatusResponse, error)
	// Capture is the main handler for the pcap agent. It contains the logic to open an interface
	// and start a packet capture. The resulting packets will be streamed back to the caller together
	// with messages informing the caller of any abnormal conditions that occur. The first message
	// sent must contain a payload of type StartAgentCapture, this will trigger the start of the capture.
	// The only messages that can be sent next is a StopAgentCapture which stops the capture gracefully
	// still sending any packets that are remaining and closing the stream afterwards.
	Capture(Agent_CaptureServer) error
	// contains filtered or unexported methods
}

AgentServer is the server API for Agent service. All implementations must embed UnimplementedAgentServer for forward compatibility

type Agent_CaptureClient

type Agent_CaptureClient interface {
	Send(*AgentRequest) error
	Recv() (*CaptureResponse, error)
	grpc.ClientStream
}

type Agent_CaptureServer

type Agent_CaptureServer interface {
	Send(*CaptureResponse) error
	Recv() (*AgentRequest, error)
	grpc.ServerStream
}

type BoshInfo

type BoshInfo struct {
	Name            string `json:"name"`
	UUID            string `json:"uuid"`
	Version         string `json:"version"`
	Cpi             string `json:"cpi"`
	StemcellOS      string `json:"stemcell_os"`
	StemcellVersion string `json:"stemcell_version"`

	UserAuthentication struct {
		Type    string `json:"type"`
		Options struct {
			URL  string   `json:"url"`
			URLs []string `json:"urls"`
		} `json:"options"`
	} `json:"user_authentication"`
}

BoshInfo corresponds to the relevant data that is provided as JSON from the BOSH Director endpoint /info. This struct is limited to the fields needed for the supported operation types (i.e. using UAA).

type BoshInstance

type BoshInstance struct {
	AgentID     string    `json:"agent_id"`
	Cid         string    `json:"cid"`
	Job         string    `json:"job"`
	Index       int       `json:"index"`
	ID          string    `json:"id"`
	Az          string    `json:"az"`
	Ips         []string  `json:"ips"`
	VMCreatedAt time.Time `json:"vm_created_at"`
	ExpectsVM   bool      `json:"expects_vm"`
}

BoshInstance contains the metadata about a particular BOSH VM instance in a BOSH deployment.

type BoshRequest

type BoshRequest struct {
	Token      string   `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
	Deployment string   `protobuf:"bytes,2,opt,name=deployment,proto3" json:"deployment,omitempty"`
	Groups     []string `protobuf:"bytes,3,rep,name=groups,proto3" json:"groups,omitempty"`
	Instances  []string `protobuf:"bytes,4,rep,name=instances,proto3" json:"instances,omitempty"`
	// contains filtered or unexported fields
}

func (*BoshRequest) Descriptor deprecated

func (*BoshRequest) Descriptor() ([]byte, []int)

Deprecated: Use BoshRequest.ProtoReflect.Descriptor instead.

func (*BoshRequest) GetDeployment

func (x *BoshRequest) GetDeployment() string

func (*BoshRequest) GetGroups

func (x *BoshRequest) GetGroups() []string

func (*BoshRequest) GetInstances

func (x *BoshRequest) GetInstances() []string

func (*BoshRequest) GetToken

func (x *BoshRequest) GetToken() string

func (*BoshRequest) ProtoMessage

func (*BoshRequest) ProtoMessage()

func (*BoshRequest) ProtoReflect

func (x *BoshRequest) ProtoReflect() protoreflect.Message

func (*BoshRequest) Reset

func (x *BoshRequest) Reset()

func (*BoshRequest) String

func (x *BoshRequest) String() string

type BoshResolver

type BoshResolver struct {
	UaaURLs     []string
	Config      BoshResolverConfig
	DirectorURL *url.URL
	// contains filtered or unexported fields
}

BoshResolver uses a BOSH director to resolve AgentEndpoint s.

Must call setup() to initialize. This is done by NewBoshResolver(), which is the preferred way of initialization.

func NewBoshResolver

func NewBoshResolver(config BoshResolverConfig) (*BoshResolver, error)

NewBoshResolver creates and initializes a BoshResolver based on the provided config. NewBoshResolver calls setup() to establish the connection to the configured BOSH Director.

Returns an error if the configuration is incorrect (unparseable URL, incorrect or inconsistent TLS configuration) or the connection to the BOSH director fails.

func (*BoshResolver) Authenticate

func (br *BoshResolver) Authenticate(authToken string) error

func (*BoshResolver) CanResolve

func (br *BoshResolver) CanResolve(request *EndpointRequest) bool

func (*BoshResolver) Healthy

func (br *BoshResolver) Healthy() bool

Healthy returns true if the resolver can retrieve /info to the BOSH director.

func (*BoshResolver) Name

func (br *BoshResolver) Name() string

func (*BoshResolver) Resolve

func (br *BoshResolver) Resolve(request *EndpointRequest, logger *zap.Logger) ([]AgentEndpoint, error)

Resolve returns applicable AgentEndpoint s for request

Fails if:

  • the token could not be verified
  • no endpoints match the query.

No endpoints are found if:

  • none of the instance groups in the request have instances or the instance groups are not found
  • the provided instance IDs don't match any of the existing ID in selected instance groups

func (*BoshResolver) Validate

func (br *BoshResolver) Validate(endpointRequest *EndpointRequest) error

type BoshResolverConfig

type BoshResolverConfig struct {
	RawDirectorURL string     `yaml:"director_url" validate:"required,url"`
	AgentPort      int        `yaml:"agent_port" validate:"required,gt=0,lte=65535"`
	TokenScope     string     `yaml:"token_scope" validate:"required"`
	TLS            *ClientTLS `yaml:"tls" validate:"omitempty"`
}

BoshResolverConfig defines the configuration for a specific BOSH environment used for a BoshResolver.

type BufferConf

type BufferConf struct {
	// Size is the number of responses that can be buffered per stream.
	Size int `yaml:"size" validate:"gte=0"`
	// UpperLimit tells the manager of the buffer to start discarding messages
	// once the limit is exceeded. The condition looks like this:
	//   len(buf) >= UpperLimit
	UpperLimit int `yaml:"upper_limit" validate:"gte=0,ltefield=Size"`
	// LowerLimit tells the manager of the buffer to stop discarding messages
	// once the limit is reached/undercut. The condition looks like this:
	//   len(buf) <= LowerLimit
	LowerLimit int `yaml:"lower_limit" validate:"gte=0,ltefield=UpperLimit"`
}

BufferConf allows to specify the behaviour of buffers.

The recommendation is to set the upper limit slightly below the size to account for data put into the buffer while checking the fill condition or performing work. The lower limit should be low enough to make some room for new data but not too low (which would cause a lot of data to be discarded). After all the buffer should mainly soften short spikes in data transfer and these limits only protect against uncontrolled back pressure.

type CaptureOptions

type CaptureOptions struct {
	Device  string `protobuf:"bytes,1,opt,name=device,proto3" json:"device,omitempty"`
	Filter  string `protobuf:"bytes,2,opt,name=filter,proto3" json:"filter,omitempty"`
	SnapLen uint32 `protobuf:"varint,3,opt,name=snapLen,proto3" json:"snapLen,omitempty"`
	// contains filtered or unexported fields
}

func (*CaptureOptions) Descriptor deprecated

func (*CaptureOptions) Descriptor() ([]byte, []int)

Deprecated: Use CaptureOptions.ProtoReflect.Descriptor instead.

func (*CaptureOptions) GetDevice

func (x *CaptureOptions) GetDevice() string

func (*CaptureOptions) GetFilter

func (x *CaptureOptions) GetFilter() string

func (*CaptureOptions) GetSnapLen

func (x *CaptureOptions) GetSnapLen() uint32

func (*CaptureOptions) ProtoMessage

func (*CaptureOptions) ProtoMessage()

func (*CaptureOptions) ProtoReflect

func (x *CaptureOptions) ProtoReflect() protoreflect.Message

func (*CaptureOptions) Reset

func (x *CaptureOptions) Reset()

func (*CaptureOptions) String

func (x *CaptureOptions) String() string

type CaptureRequest

type CaptureRequest struct {

	// Types that are assignable to Operation:
	//
	//	*CaptureRequest_Start
	//	*CaptureRequest_Stop
	Operation isCaptureRequest_Operation `protobuf_oneof:"operation"`
	// contains filtered or unexported fields
}

func MakeStopRequest

func MakeStopRequest() *CaptureRequest

MakeStopRequest creates the generic stop CaptureRequest that can be sent to api and agent.

func (*CaptureRequest) Descriptor deprecated

func (*CaptureRequest) Descriptor() ([]byte, []int)

Deprecated: Use CaptureRequest.ProtoReflect.Descriptor instead.

func (*CaptureRequest) GetOperation

func (m *CaptureRequest) GetOperation() isCaptureRequest_Operation

func (*CaptureRequest) GetStart

func (x *CaptureRequest) GetStart() *StartCapture

func (*CaptureRequest) GetStop

func (x *CaptureRequest) GetStop() *StopCapture

func (*CaptureRequest) ProtoMessage

func (*CaptureRequest) ProtoMessage()

func (*CaptureRequest) ProtoReflect

func (x *CaptureRequest) ProtoReflect() protoreflect.Message

func (*CaptureRequest) Reset

func (x *CaptureRequest) Reset()

func (*CaptureRequest) String

func (x *CaptureRequest) String() string

type CaptureRequest_Start

type CaptureRequest_Start struct {
	Start *StartCapture `protobuf:"bytes,1,opt,name=start,proto3,oneof"`
}

type CaptureRequest_Stop

type CaptureRequest_Stop struct {
	Stop *StopCapture `protobuf:"bytes,2,opt,name=stop,proto3,oneof"`
}

type CaptureResponse

type CaptureResponse struct {

	// Types that are assignable to Payload:
	//
	//	*CaptureResponse_Packet
	//	*CaptureResponse_Message
	Payload isCaptureResponse_Payload `protobuf_oneof:"payload"`
	// contains filtered or unexported fields
}

CaptureResponse contains either a pcap packet or a message to inform the client of some condition that appeared.

func (*CaptureResponse) Descriptor deprecated

func (*CaptureResponse) Descriptor() ([]byte, []int)

Deprecated: Use CaptureResponse.ProtoReflect.Descriptor instead.

func (*CaptureResponse) GetMessage

func (x *CaptureResponse) GetMessage() *Message

func (*CaptureResponse) GetPacket

func (x *CaptureResponse) GetPacket() *Packet

func (*CaptureResponse) GetPayload

func (m *CaptureResponse) GetPayload() isCaptureResponse_Payload

func (*CaptureResponse) ProtoMessage

func (*CaptureResponse) ProtoMessage()

func (*CaptureResponse) ProtoReflect

func (x *CaptureResponse) ProtoReflect() protoreflect.Message

func (*CaptureResponse) Reset

func (x *CaptureResponse) Reset()

func (*CaptureResponse) String

func (x *CaptureResponse) String() string

type CaptureResponse_Message

type CaptureResponse_Message struct {
	Message *Message `protobuf:"bytes,2,opt,name=message,proto3,oneof"`
}

type CaptureResponse_Packet

type CaptureResponse_Packet struct {
	Packet *Packet `protobuf:"bytes,1,opt,name=packet,proto3,oneof"`
}

type Client

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

Client provides a reusable client for issuing capture requests against the pcap-api.

func NewClient

func NewClient(outputFile string, logger *zap.Logger, writer MessageWriter) (*Client, error)

NewClient sets up logging for the client and creates the outputFile. It assumes that the outputFile does not pre-exist and that the path is writeable (should be checked by CLI).

NewClient returns a new Client if there are no issues with outputFile creation.

func (*Client) Capture

func (c *Client) Capture(ctx context.Context, opts ...grpc.CallOption) (API_CaptureClient, error)

func (*Client) CaptureRequest

func (c *Client) CaptureRequest(ctx context.Context, cancel context.CancelCauseFunc, endpointRequest *EndpointRequest, options *CaptureOptions) error

func (*Client) CheckAPIHandler

func (c *Client) CheckAPIHandler(handler string) error

CheckAPIHandler checks if API is healthy and the given handler is available, if that's the case, the returned error will be nil.

func (*Client) ConnectToAPI

func (c *Client) ConnectToAPI(apiURL *url.URL, skipVerify bool) error

ConnectToAPI sets up the grpc-connection between client and pcap-api.

Depending on the http scheme in apiURL, it uses plain HTTP or TLS.

func (*Client) ProcessCapture

func (c *Client) ProcessCapture(ctx context.Context, endpointRequest *EndpointRequest, options *CaptureOptions, cancel context.CancelCauseFunc) error

ProcessCapture takes care of the complete lifecycle for a capture request. It writes the pcap-header to the outputFile, sends the CaptureRequest to the pcap-api and handles the cleanup after the capture is done.

It then delegates writing individual packets and logging messages from the api to ReadCaptureResponse. logProgress is called in another goroutine to asynchronously announce on stderr how many bytes were already written to the outputFile.

func (*Client) ReadCaptureResponse

func (c *Client) ReadCaptureResponse(stream API_CaptureClient, packetWriter *pcapgo.Writer, cancel context.CancelCauseFunc) chan struct{}

ReadCaptureResponse reads CaptureResponse's from the api in a loop and delegates writing/logging messages & packets to WriteMessage / writePacket.

It terminates if an error or clean stop-message is received.

func (*Client) Status

func (c *Client) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)

func (*Client) Stop

func (c *Client) Stop()

func (*Client) StopRequest

func (c *Client) StopRequest()

type ClientTLS

type ClientTLS struct {
	// Certificate holds the path to the PEM encoded certificate (chain) that
	// is presented by the client / server to its peer.
	Certificate string `yaml:"certificate" validate:"omitempty,file"`
	// PrivateKey is the private key matching the certificate.
	PrivateKey string `yaml:"private_key" validate:"omitempty,file"`
	// RootCas holds the path to the PEM encoded CA bundle which
	// is used to validate the certificate presented by the server if acting as
	// the client.
	RootCas string `yaml:"ca" validate:"omitempty,file"`
	// SkipVerify can be set to disable verification of the peer certificate if
	// acting as the client.
	SkipVerify bool `yaml:"skip_verify"`
	// ServerName that the certificate presented by the server must be signed
	// for.
	ServerName string `yaml:"server_name"`
}

func (*ClientTLS) Config

func (c *ClientTLS) Config() (*tls.Config, error)

type CloudfoundryRequest

type CloudfoundryRequest struct {
	Token   string  `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
	AppId   string  `protobuf:"bytes,2,opt,name=appId,proto3" json:"appId,omitempty"`
	AppType *string `protobuf:"bytes,3,opt,name=appType,proto3,oneof" json:"appType,omitempty"`
	Indices []int32 `protobuf:"varint,4,rep,packed,name=indices,proto3" json:"indices,omitempty"`
	// contains filtered or unexported fields
}

func (*CloudfoundryRequest) Descriptor deprecated

func (*CloudfoundryRequest) Descriptor() ([]byte, []int)

Deprecated: Use CloudfoundryRequest.ProtoReflect.Descriptor instead.

func (*CloudfoundryRequest) GetAppId

func (x *CloudfoundryRequest) GetAppId() string

func (*CloudfoundryRequest) GetAppType

func (x *CloudfoundryRequest) GetAppType() string

func (*CloudfoundryRequest) GetIndices

func (x *CloudfoundryRequest) GetIndices() []int32

func (*CloudfoundryRequest) GetToken

func (x *CloudfoundryRequest) GetToken() string

func (*CloudfoundryRequest) ProtoMessage

func (*CloudfoundryRequest) ProtoMessage()

func (*CloudfoundryRequest) ProtoReflect

func (x *CloudfoundryRequest) ProtoReflect() protoreflect.Message

func (*CloudfoundryRequest) Reset

func (x *CloudfoundryRequest) Reset()

func (*CloudfoundryRequest) String

func (x *CloudfoundryRequest) String() string

type CloudfoundryResolver

type CloudfoundryResolver struct {
}

func (*CloudfoundryResolver) CanResolve

func (cf *CloudfoundryResolver) CanResolve(request *EndpointRequest) bool

func (*CloudfoundryResolver) Healthy

func (cf *CloudfoundryResolver) Healthy() bool

func (*CloudfoundryResolver) Name

func (cf *CloudfoundryResolver) Name() string

func (*CloudfoundryResolver) Resolve

func (cf *CloudfoundryResolver) Resolve(request *EndpointRequest, log *zap.Logger) ([]AgentEndpoint, error)

type EndpointRequest

type EndpointRequest struct {

	// Types that are assignable to Request:
	//
	//	*EndpointRequest_Bosh
	//	*EndpointRequest_Cf
	Request isEndpointRequest_Request `protobuf_oneof:"request"`
	// contains filtered or unexported fields
}

func (*EndpointRequest) Descriptor deprecated

func (*EndpointRequest) Descriptor() ([]byte, []int)

Deprecated: Use EndpointRequest.ProtoReflect.Descriptor instead.

func (*EndpointRequest) GetBosh

func (x *EndpointRequest) GetBosh() *BoshRequest

func (*EndpointRequest) GetCf

func (*EndpointRequest) GetRequest

func (m *EndpointRequest) GetRequest() isEndpointRequest_Request

func (*EndpointRequest) ProtoMessage

func (*EndpointRequest) ProtoMessage()

func (*EndpointRequest) ProtoReflect

func (x *EndpointRequest) ProtoReflect() protoreflect.Message

func (*EndpointRequest) Reset

func (x *EndpointRequest) Reset()

func (*EndpointRequest) String

func (x *EndpointRequest) String() string

type EndpointRequest_Bosh

type EndpointRequest_Bosh struct {
	Bosh *BoshRequest `protobuf:"bytes,1,opt,name=bosh,proto3,oneof"`
}

type EndpointRequest_Cf

type EndpointRequest_Cf struct {
	Cf *CloudfoundryRequest `protobuf:"bytes,2,opt,name=cf,proto3,oneof"`
}

type Listen

type Listen struct {
	Port int        `yaml:"port" validate:"gt=0,lte=65535"`
	TLS  *ServerTLS `yaml:"tls,omitempty"`
}

Listen defines the port and optional TLS configuration for the listening socket.

type LogMessageWriter

type LogMessageWriter struct {
	Log *zap.Logger
}

func (LogMessageWriter) WriteMessage

func (c LogMessageWriter) WriteMessage(message *Message)

WriteMessage accepts a Message and writes a log-line using a log-level corresponding to the severity of the message.

type Message

type Message struct {
	Type    MessageType `protobuf:"varint,1,opt,name=type,proto3,enum=pcap.MessageType" json:"type,omitempty"`
	Message string      `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
	Origin  string      `protobuf:"bytes,3,opt,name=origin,proto3" json:"origin,omitempty"`
	// contains filtered or unexported fields
}

Message represents a control message used by the server to inform the client of something it encountered. The type specifies kind of message it is and the message contains a human readable version with more details that should be shown to the end-user. These messages MUST NOT represent error conditions in which the connection can not be continued, those must be represented using the proper error/status messages.

func (*Message) Descriptor deprecated

func (*Message) Descriptor() ([]byte, []int)

Deprecated: Use Message.ProtoReflect.Descriptor instead.

func (*Message) GetMessage

func (x *Message) GetMessage() string

func (*Message) GetOrigin

func (x *Message) GetOrigin() string

func (*Message) GetType

func (x *Message) GetType() MessageType

func (*Message) ProtoMessage

func (*Message) ProtoMessage()

func (*Message) ProtoReflect

func (x *Message) ProtoReflect() protoreflect.Message

func (*Message) Reset

func (x *Message) Reset()

func (*Message) String

func (x *Message) String() string

type MessageType

type MessageType int32

MessageType represents the underlying issue for easy assertion of the situation. It should be used by the client to provide a nice message to the end user. Future values will be added to extend functionalities of the API.

const (
	// One of the requested instances does not exist but there is at least one
	// instance to capture from. MUST be sent as soon as possible.
	MessageType_UNKNOWN MessageType = 0
	// One instance failed during capturing but there are still instances left to
	// capture from. The detailed message should contain information about the
	// stopped party.
	MessageType_INSTANCE_UNAVAILABLE MessageType = 1
	// Starting the capture request has failed because the request could not be
	// fulfilled (e.g. no matching instances, pcap feature not enabled).
	MessageType_START_CAPTURE_FAILED MessageType = 2
	// The request could not be fulfilled, e.g. because the app or BOSH deployment
	// with the requested name do not exist.
	MessageType_INVALID_REQUEST MessageType = 3
	// Some participant on the path is congested to the point of discarding data.
	// The detailed message should contain the congested party.
	MessageType_CONGESTED MessageType = 4
	// Some limit has been reached, e.g. number of concurrent requests, time,
	// bytes, etc.; Message details identifies, which limit has been reached.
	MessageType_LIMIT_REACHED MessageType = 5
	// A single agent or the overall capture has stopped gracefully.
	// The detailed message should contain information about the stopped party.
	MessageType_CAPTURE_STOPPED MessageType = 6
	// An error happened while attempting communication with PCAP components,
	// independent of the client.
	MessageType_CONNECTION_ERROR MessageType = 7
)

func (MessageType) Descriptor

func (MessageType) Enum

func (x MessageType) Enum() *MessageType

func (MessageType) EnumDescriptor deprecated

func (MessageType) EnumDescriptor() ([]byte, []int)

Deprecated: Use MessageType.Descriptor instead.

func (MessageType) Number

func (x MessageType) Number() protoreflect.EnumNumber

func (MessageType) String

func (x MessageType) String() string

func (MessageType) Type

type MessageWriter

type MessageWriter interface {
	WriteMessage(message *Message)
}

type NodeConfig

type NodeConfig struct {
	Listen   Listen     `yaml:"listen"`
	Buffer   BufferConf `yaml:"buffer"`
	LogLevel string     `yaml:"log_level"`
	ID       string     `yaml:"id" validate:"required"`
}

type Packet

type Packet struct {
	Data      []byte                 `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
	Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
	Length    int32                  `protobuf:"varint,3,opt,name=length,proto3" json:"length,omitempty"`
	// contains filtered or unexported fields
}

Packet wraps the raw pcap data stream and some metadata (CaptureInfo: timestamp & length) of one packet. More fields might be added as needed.

func (*Packet) Descriptor deprecated

func (*Packet) Descriptor() ([]byte, []int)

Deprecated: Use Packet.ProtoReflect.Descriptor instead.

func (*Packet) GetData

func (x *Packet) GetData() []byte

func (*Packet) GetLength

func (x *Packet) GetLength() int32

func (*Packet) GetTimestamp

func (x *Packet) GetTimestamp() *timestamppb.Timestamp

func (*Packet) ProtoMessage

func (*Packet) ProtoMessage()

func (*Packet) ProtoReflect

func (x *Packet) ProtoReflect() protoreflect.Message

func (*Packet) Reset

func (x *Packet) Reset()

func (*Packet) String

func (x *Packet) String() string

type ServerTLS

type ServerTLS struct {
	// Certificate holds the path to the PEM encoded certificate (chain) that
	// is presented by the client / server to its peer.
	Certificate string `yaml:"certificate" validate:"omitempty,file"`
	// PrivateKey is the private key matching the certificate.
	PrivateKey string `yaml:"private_key" validate:"omitempty,file"`
	ClientCas  string `yaml:"client_cas"`
	// Verify controls how the peer certificate is verified:
	//
	// 0: tls.NoClientCert
	//
	// 1: tls.RequestClientCert
	//
	// 2: tls.RequireAnyClientCert
	//
	// 3: tls.VerifyClientCertIfGiven
	//
	// 4: tls.RequireAndVerifyClientCert
	Verify tls.ClientAuthType `yaml:"verify"`
}

func (*ServerTLS) Config

func (c *ServerTLS) Config() (*tls.Config, error)

type StartAgentCapture

type StartAgentCapture struct {
	Capture *CaptureOptions `protobuf:"bytes,1,opt,name=capture,proto3" json:"capture,omitempty"`
	// contains filtered or unexported fields
}

StartAgentCapture holds all parameters needed to start a capture.

func (*StartAgentCapture) Descriptor deprecated

func (*StartAgentCapture) Descriptor() ([]byte, []int)

Deprecated: Use StartAgentCapture.ProtoReflect.Descriptor instead.

func (*StartAgentCapture) GetCapture

func (x *StartAgentCapture) GetCapture() *CaptureOptions

func (*StartAgentCapture) ProtoMessage

func (*StartAgentCapture) ProtoMessage()

func (*StartAgentCapture) ProtoReflect

func (x *StartAgentCapture) ProtoReflect() protoreflect.Message

func (*StartAgentCapture) Reset

func (x *StartAgentCapture) Reset()

func (*StartAgentCapture) String

func (x *StartAgentCapture) String() string

type StartCapture

type StartCapture struct {
	Request *EndpointRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"`
	Options *CaptureOptions  `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"`
	// contains filtered or unexported fields
}

func (*StartCapture) Descriptor deprecated

func (*StartCapture) Descriptor() ([]byte, []int)

Deprecated: Use StartCapture.ProtoReflect.Descriptor instead.

func (*StartCapture) GetOptions

func (x *StartCapture) GetOptions() *CaptureOptions

func (*StartCapture) GetRequest

func (x *StartCapture) GetRequest() *EndpointRequest

func (*StartCapture) ProtoMessage

func (*StartCapture) ProtoMessage()

func (*StartCapture) ProtoReflect

func (x *StartCapture) ProtoReflect() protoreflect.Message

func (*StartCapture) Reset

func (x *StartCapture) Reset()

func (*StartCapture) String

func (x *StartCapture) String() string

type StatusRequest

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

func (*StatusRequest) Descriptor deprecated

func (*StatusRequest) Descriptor() ([]byte, []int)

Deprecated: Use StatusRequest.ProtoReflect.Descriptor instead.

func (*StatusRequest) ProtoMessage

func (*StatusRequest) ProtoMessage()

func (*StatusRequest) ProtoReflect

func (x *StatusRequest) ProtoReflect() protoreflect.Message

func (*StatusRequest) Reset

func (x *StatusRequest) Reset()

func (*StatusRequest) String

func (x *StatusRequest) String() string

type StatusResponse

type StatusResponse struct {
	Healthy            bool     `protobuf:"varint,1,opt,name=healthy,proto3" json:"healthy,omitempty"`
	CompatibilityLevel int64    `protobuf:"varint,2,opt,name=compatibilityLevel,proto3" json:"compatibilityLevel,omitempty"`
	Message            string   `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
	Resolvers          []string `protobuf:"bytes,4,rep,name=resolvers,proto3" json:"resolvers,omitempty"`
	// contains filtered or unexported fields
}

func (*StatusResponse) Descriptor deprecated

func (*StatusResponse) Descriptor() ([]byte, []int)

Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead.

func (*StatusResponse) GetCompatibilityLevel

func (x *StatusResponse) GetCompatibilityLevel() int64

func (*StatusResponse) GetHealthy

func (x *StatusResponse) GetHealthy() bool

func (*StatusResponse) GetMessage

func (x *StatusResponse) GetMessage() string

func (*StatusResponse) GetResolvers

func (x *StatusResponse) GetResolvers() []string

func (*StatusResponse) ProtoMessage

func (*StatusResponse) ProtoMessage()

func (*StatusResponse) ProtoReflect

func (x *StatusResponse) ProtoReflect() protoreflect.Message

func (*StatusResponse) Reset

func (x *StatusResponse) Reset()

func (*StatusResponse) String

func (x *StatusResponse) String() string

type StopAgentCapture

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

StopAgentCapture signals the agent to stop the current capture.

func (*StopAgentCapture) Descriptor deprecated

func (*StopAgentCapture) Descriptor() ([]byte, []int)

Deprecated: Use StopAgentCapture.ProtoReflect.Descriptor instead.

func (*StopAgentCapture) ProtoMessage

func (*StopAgentCapture) ProtoMessage()

func (*StopAgentCapture) ProtoReflect

func (x *StopAgentCapture) ProtoReflect() protoreflect.Message

func (*StopAgentCapture) Reset

func (x *StopAgentCapture) Reset()

func (*StopAgentCapture) String

func (x *StopAgentCapture) String() string

type StopCapture

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

func (*StopCapture) Descriptor deprecated

func (*StopCapture) Descriptor() ([]byte, []int)

Deprecated: Use StopCapture.ProtoReflect.Descriptor instead.

func (*StopCapture) ProtoMessage

func (*StopCapture) ProtoMessage()

func (*StopCapture) ProtoReflect

func (x *StopCapture) ProtoReflect() protoreflect.Message

func (*StopCapture) Reset

func (x *StopCapture) Reset()

func (*StopCapture) String

func (x *StopCapture) String() string

type Stoppable

type Stoppable interface {
	Stop()
}

Stoppable provides an interface for services that can be stopped.

Primarily used with StopOnSignal.

type UaaKeyInfo

type UaaKeyInfo struct {
	Kty   string `json:"kty"`
	E     string `json:"e"`
	Use   string `json:"use"`
	Kid   string `json:"kid"`
	Alg   string `json:"alg"`
	Value string `json:"value"`
	N     string `json:"n"`
}

UaaKeyInfo holds the response of the UAA /token_keys endpoint.

type UnimplementedAPIServer

type UnimplementedAPIServer struct {
}

UnimplementedAPIServer must be embedded to have forward compatible implementations.

func (UnimplementedAPIServer) Capture

func (UnimplementedAPIServer) Status

type UnimplementedAgentServer

type UnimplementedAgentServer struct {
}

UnimplementedAgentServer must be embedded to have forward compatible implementations.

func (UnimplementedAgentServer) Capture

func (UnimplementedAgentServer) Status

type UnsafeAPIServer

type UnsafeAPIServer interface {
	// contains filtered or unexported methods
}

UnsafeAPIServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to APIServer will result in compilation errors.

type UnsafeAgentServer

type UnsafeAgentServer interface {
	// contains filtered or unexported methods
}

UnsafeAgentServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to AgentServer will result in compilation errors.

type WaitingStoppable

type WaitingStoppable interface {
	Stoppable

	Wait()
}

WaitingStoppable adds a Wait() function to Stoppable, which allows implementing an appropriate wait.

Directories

Path Synopsis
cmd
pcap-agent-cli
pcap-agent-cli is a simple client to manually test the pcap-agent and confirm it's operating as expected.
pcap-agent-cli is a simple client to manually test the pcap-agent and confirm it's operating as expected.
pcap-api-cli
pcap-api-cli is a simple client to manually test the pcap-api and confirm it's operating as expected.
pcap-api-cli is a simple client to manually test the pcap-api and confirm it's operating as expected.
test

Jump to

Keyboard shortcuts

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