Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(events): export parse functions as a go module #4096

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/Masterminds/sprig/v3 v3.2.3
github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4
github.com/aquasecurity/tracee/api v0.0.0-20240607205742-90c301111aee
github.com/aquasecurity/tracee/pkg/events/parsers v0.0.0-00010101000000-000000000000
github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20240607205742-90c301111aee
github.com/aquasecurity/tracee/types v0.0.0-20240607205742-90c301111aee
github.com/containerd/containerd v1.7.17
Expand Down Expand Up @@ -76,6 +77,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/moby v26.1.3+incompatible // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
Expand Down Expand Up @@ -105,7 +107,6 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gotest.tools/v3 v3.4.0 // indirect
k8s.io/apiextensions-apiserver v0.30.1 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect
Expand Down Expand Up @@ -177,3 +178,5 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.69 // indirect
)

replace github.com/aquasecurity/tracee/pkg/events/parsers => ./pkg/events/parsers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only temporary, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, will need follow-up PR to remove it

6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/moby v26.1.3+incompatible h1:gIzra6kadTUzPUZWpyUfkaLKymz9I8gANMB1NKk2pF0=
github.com/moby/moby v26.1.3+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
Expand Down Expand Up @@ -1430,8 +1432,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
25 changes: 23 additions & 2 deletions pkg/ebpf/events_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import (
"bytes"
"context"
"encoding/binary"
"fmt"
"strconv"
"sync"
"unsafe"

bpf "github.com/aquasecurity/libbpfgo"

"github.com/aquasecurity/tracee/pkg/bufferdecoder"
"github.com/aquasecurity/tracee/pkg/errfmt"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/events/parsers"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/pkg/policy"
"github.com/aquasecurity/tracee/pkg/utils"
Expand Down Expand Up @@ -724,13 +728,30 @@ func (t *Tracee) handleError(err error) {
// printers).
func (t *Tracee) parseArguments(e *trace.Event) error {
if t.config.Output.ParseArguments {
err := events.ParseArgs(e)
err := parsers.ParseArgs(e)
if err != nil {
return errfmt.WrapError(err)
}

if t.config.Output.ParseArgumentsFDs {
return events.ParseArgsFDs(e, uint64(t.getOrigEvtTimestamp(e)), t.FDArgPathMap)
return parseArgsFDs(e, uint64(t.getOrigEvtTimestamp(e)), t.FDArgPathMap)
}
}

return nil
}

func parseArgsFDs(event *trace.Event, origTimestamp uint64, fdArgPathMap *bpf.BPFMap) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be part of the parsers package?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No.
This function name is misleading.
It is not a parsing function, but a resolving function. It uses the real-time info from a BPF map.
Hence, it is part of the eBPF logic in user mode. Not a parsing function of known values.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please rename it to getPathFromFD then?

if fdArg := parsers.GetArg(event, "fd"); fdArg != nil {
if fd, isInt32 := fdArg.Value.(int32); isInt32 {
ts := origTimestamp
bs, err := fdArgPathMap.GetValue(unsafe.Pointer(&ts))
if err != nil {
return errfmt.WrapError(err)
}

fpath := string(bytes.Trim(bs, "\x00"))
fdArg.Value = fmt.Sprintf("%d=%s", fd, fpath)
}
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/ebpf/net_capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/google/gopacket/layers"

"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/events/parsers"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/types/trace"
)
Expand Down Expand Up @@ -103,7 +104,7 @@ func (t *Tracee) processNetCapEvent(event *trace.Event) {

// sanity checks

payloadArg := events.GetArg(event, "payload")
payloadArg := parsers.GetArg(event, "payload")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is more intuitive for the GetArg function to be in the events or pipeline package (once we will extract it from the ebpf package) and not under parsers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this concerns the ArgVal function as well (which resides both in the signatures/helpers package and in the events/params package).
I only move the code as it is, without trying to restructure the whole package.
I think all the arguments extraction functions places should be determined in its own PR and discussion. This PR won't be affected by the change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add that for now both GetArg and SetArgValue are only used by the parsers package.

if payloadArg == nil {
logger.Debugw("Network capture: no payload packet")
return
Expand Down
13 changes: 7 additions & 6 deletions pkg/ebpf/processor_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/aquasecurity/tracee/pkg/errfmt"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/events/parse"
"github.com/aquasecurity/tracee/pkg/events/parsers"
"github.com/aquasecurity/tracee/pkg/filehash"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/pkg/utils"
Expand Down Expand Up @@ -102,7 +103,7 @@ func (t *Tracee) processReadEvent(event *trace.Event) error {

// processKernelReadFile processes a security read event and changes the read type value.
func processKernelReadFile(event *trace.Event) error {
readTypeArg := events.GetArg(event, "type")
readTypeArg := parsers.GetArg(event, "type")
readTypeInt, ok := readTypeArg.Value.(int32)
if !ok {
return errfmt.Errorf("missing argument %s in event %s", "type", event.EventName)
Expand Down Expand Up @@ -287,7 +288,7 @@ func (t *Tracee) processHookedProcFops(event *trace.Event) error {
}
hookedFops = append(hookedFops, trace.HookedSymbolData{SymbolName: functionName, ModuleOwner: hookingFunction.Owner})
}
err = events.SetArgValue(event, hookedFopsPointersArgName, hookedFops)
err = parsers.SetArgValue(event, hookedFopsPointersArgName, hookedFops)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

if err != nil {
return err
}
Expand Down Expand Up @@ -326,15 +327,15 @@ func (t *Tracee) processPrintMemDump(event *trace.Event) error {
return errfmt.WrapError(err)
}
arch = string(bytes.TrimRight(utsName.Machine[:], "\x00"))
err = events.SetArgValue(event, "arch", arch)
err = parsers.SetArgValue(event, "arch", arch)
if err != nil {
return err
}
err = events.SetArgValue(event, "symbol_name", symbol.Name)
err = parsers.SetArgValue(event, "symbol_name", symbol.Name)
if err != nil {
return err
}
err = events.SetArgValue(event, "symbol_owner", symbol.Owner)
err = parsers.SetArgValue(event, "symbol_owner", symbol.Owner)
if err != nil {
return err
}
Expand Down Expand Up @@ -394,7 +395,7 @@ func (t *Tracee) processSchedProcessFork(event *trace.Event) error {
// normalizeEventArgTime normalizes the event arg time to be relative to tracee start time or
// current time.
func (t *Tracee) normalizeEventArgTime(event *trace.Event, argName string) error {
arg := events.GetArg(event, argName)
arg := parsers.GetArg(event, argName)
if arg == nil {
return errfmt.Errorf("couldn't find argument %s of event %s", argName, event.EventName)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/events/derive/net_packet_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/google/gopacket/layers"

"github.com/aquasecurity/tracee/pkg/dnscache"
"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/pkg/events/parsers"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/types/trace"
)
Expand Down Expand Up @@ -82,7 +82,7 @@ func strToLower(given string) string {

// parsePayloadArg returns the packet payload from the event.
func parsePayloadArg(event *trace.Event) ([]byte, error) {
payloadArg := events.GetArg(event, "payload")
payloadArg := parsers.GetArg(event, "payload")
if payloadArg == nil {
return nil, noPayloadError()
}
Expand Down
89 changes: 63 additions & 26 deletions pkg/events/parsers/data_parsers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (
"strings"
"sync/atomic"

"github.com/moby/moby/pkg/parsers/kernel"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this external package and not use our own environment package?
If it's because it is not exposed as a module - then maybe we should

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is mainly because of the external module issue.
However, we coupled that environment into Tracee by using the logger and errfmt packages there.
As the function only use the kernel version and not other OS information, I determined that it will be easier to use the version as a string. As I needed to parse it I thought that using such a known third-party package might be easier than trying to export many parts of the code as modules.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlonZivony do you want me to move environment as its own module? I think we should since it's required by different projects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we do.
I think we might also want to put the logger in another module, but this way we divide the project to too many pieces.
For now I think using this external library is good enough.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's the case let's take the logger and err handling out of the environment package (it should be only a few lines to change).
It doesn't make sense to use an external package for logic we already have (actually, we need to do the opposite - make as less dependencies on external packages as possible)

"golang.org/x/sys/unix"

"github.com/aquasecurity/tracee/pkg/utils/environment"
)

type SystemFunctionArgument interface {
Expand Down Expand Up @@ -264,7 +263,10 @@ func ParseOpenFlagArgument(rawValue uint64) (OpenFlagArgument, error) {
}

if len(f) == 0 {
return OpenFlagArgument{}, fmt.Errorf("no valid open flag values present in raw value: 0x%x", rawValue)
return OpenFlagArgument{}, fmt.Errorf(
"no valid open flag values present in raw value: 0x%x",
rawValue,
)
}

return OpenFlagArgument{rawValue: rawValue, stringValue: strings.Join(f, "|")}, nil
Expand Down Expand Up @@ -3262,7 +3264,7 @@ func ParseLegacyGUPFlags(rawValue uint64) LegacyGUPFlag {
var currentOSGUPFlagsParse uint32
var skipDetermineGUPFlagsFunc uint32

const gupFlagsChangeVersion = "6.3.0"
var gupFlagsChangeVersion, _ = kernel.ParseRelease("6.3.0")

// ParseGUPFlagsCurrentOS parse the GUP flags received according to current machine OS version.
// It uses optimizations to perform better than ParseGUPFlagsForOS
Expand All @@ -3272,21 +3274,14 @@ func ParseGUPFlagsCurrentOS(rawValue uint64) (SystemFunctionArgument, error) {
legacyParsing
)
if atomic.LoadUint32(&skipDetermineGUPFlagsFunc) == 0 {
osInfo, err := environment.GetOSInfo()
if err != nil {
return nil, fmt.Errorf("error getting current OS info - %s", err)
}
compare, err := osInfo.CompareOSBaseKernelRelease(gupFlagsChangeVersion)
currentVersion, err := kernel.GetKernelVersion()
if err != nil {
return nil, fmt.Errorf(
"error comparing OS versions to determine how to parse GUP flags - %s",
err,
)
return nil, fmt.Errorf("error getting current kernel version - %s", err)
}
if compare == environment.KernelVersionOlder {
atomic.StoreUint32(&currentOSGUPFlagsParse, legacyParsing)
} else {
if kernel.CompareKernelVersion(*currentVersion, *gupFlagsChangeVersion) >= 0 {
atomic.StoreUint32(&currentOSGUPFlagsParse, newVersionsParsing)
} else {
atomic.StoreUint32(&currentOSGUPFlagsParse, legacyParsing)
}
// Avoid doing this check in the future
atomic.StoreUint32(&skipDetermineGUPFlagsFunc, 1)
Expand All @@ -3305,19 +3300,17 @@ func ParseGUPFlagsCurrentOS(rawValue uint64) (SystemFunctionArgument, error) {
}

// ParseGUPFlagsForOS parse the GUP flags received according to given OS version.
func ParseGUPFlagsForOS(osInfo *environment.OSInfo, rawValue uint64) (SystemFunctionArgument, error) {
compare, err := osInfo.CompareOSBaseKernelRelease(gupFlagsChangeVersion)
func ParseGUPFlagsForOS(kernelVersion string, rawValue uint64) (
SystemFunctionArgument, error,
) {
parsedVersion, err := kernel.ParseRelease(kernelVersion)
if err != nil {
return nil, fmt.Errorf(
"error comparing OS versions to determine how to parse GUP flags - %s",
err,
)
return nil, fmt.Errorf("error parsing given kernel version - %s", err)
}

if compare == environment.KernelVersionOlder {
return ParseLegacyGUPFlags(rawValue), nil
if kernel.CompareKernelVersion(*parsedVersion, *gupFlagsChangeVersion) >= 0 {
return ParseGUPFlags(rawValue), nil
}
return ParseGUPFlags(rawValue), nil
return ParseLegacyGUPFlags(rawValue), nil
}

// =====================================================
Expand Down Expand Up @@ -3589,3 +3582,47 @@ func ParseFsNotifyObjType(rawValue uint64) (FsNotifyObjType, error) {
}
return v, nil
}

// =====================================================

// BpfAttachType is the type of probe the BPF program was attach to.
// This type is not of the kernel, but unique to Tracee. It must match the
// `bpf_attach_type_e` enum in the bpf code.
type BpfAttachType struct {
rawValue int32
stringValue string
}

var (
BPF_RAW_TRACEPOINT = BpfAttachType{rawValue: 0, stringValue: "raw_tracepoint"}
PERF_TRACEPOINT = BpfAttachType{rawValue: 1, stringValue: "tracepoint"}
PERF_KPROBE = BpfAttachType{rawValue: 2, stringValue: "kprobe"}
PERF_KRETPROBE = BpfAttachType{rawValue: 3, stringValue: "kretprobe"}
PERF_UPROBE = BpfAttachType{rawValue: 4, stringValue: "uprobe"}
PERF_URETPROBE = BpfAttachType{rawValue: 5, stringValue: "uretprobe"}
)

var attachTypeMap = map[int32]BpfAttachType{
int32(BPF_RAW_TRACEPOINT.Value()): BPF_RAW_TRACEPOINT,
int32(PERF_TRACEPOINT.Value()): PERF_TRACEPOINT,
int32(PERF_KPROBE.Value()): PERF_KPROBE,
int32(PERF_KRETPROBE.Value()): PERF_KRETPROBE,
int32(PERF_UPROBE.Value()): PERF_UPROBE,
int32(PERF_URETPROBE.Value()): PERF_URETPROBE,
}

func (attachType BpfAttachType) Value() uint64 {
return uint64(attachType.rawValue)
}

func (attachType BpfAttachType) String() string {
return attachType.stringValue
}

func ParseBpfAttachType(attachType int32) (BpfAttachType, error) {
v, ok := attachTypeMap[attachType]
if !ok {
return BpfAttachType{}, fmt.Errorf("not a valid argument: %d", attachType)
}
return v, nil
}
22 changes: 22 additions & 0 deletions pkg/events/parsers/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module tracee/pkg/events/parsers

go 1.21

require (
github.com/aquasecurity/tracee/types v0.0.0-20240531175500-73839cfd71e6
github.com/moby/moby v26.1.3+incompatible
github.com/stretchr/testify v1.9.0
golang.org/x/sys v0.20.0
)

require (
github.com/containerd/log v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.1 // indirect
)
42 changes: 42 additions & 0 deletions pkg/events/parsers/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
github.com/aquasecurity/tracee/types v0.0.0-20240531175500-73839cfd71e6 h1:2rCXNs7elaI1EWSyVNMsOmOMulnhcxSUQVY2ykgym+4=
github.com/aquasecurity/tracee/types v0.0.0-20240531175500-73839cfd71e6/go.mod h1:J0f9nzJWrFmFgMoK0s4Yirfh82vfKMatXytd1YdfU2I=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/moby/moby v26.1.3+incompatible h1:gIzra6kadTUzPUZWpyUfkaLKymz9I8gANMB1NKk2pF0=
github.com/moby/moby v26.1.3+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
Loading
Loading