Compare commits
193 Commits
v0.1.2-rc0
...
main
Author | SHA1 | Date |
---|---|---|
|
ad055641c4 | |
|
067638b6a4 | |
|
f4d8c9bc4d | |
|
fda611ed06 | |
|
1d1ea6430f | |
|
1d024c046f | |
|
d4a7c52d77 | |
|
282d7de50e | |
|
42aa4fed7b | |
|
d7b9e7c232 | |
|
c10821bc7d | |
|
547f8a010d | |
|
ba89cfc30a | |
|
5cf319a473 | |
|
5eba651678 | |
|
d823f91069 | |
|
154d41d0ac | |
|
4fa5ac43cb | |
|
ee58e604d2 | |
|
68c1655c7b | |
|
bbcfb01a4c | |
|
bc38d252f3 | |
|
a0f0069382 | |
|
f50f51e6bc | |
|
fddd483595 | |
|
edaa0ed3bc | |
|
bce66e61c4 | |
|
5536b00efc | |
|
27e47b38d0 | |
|
113e4cf164 | |
|
3ad32276c5 | |
|
f97b4aafba | |
|
7233e7f02d | |
|
b851b9e9de | |
|
51ee2ba29d | |
|
3f0060d8d0 | |
|
35e210df4a | |
|
dceca995c9 | |
|
3dce913b90 | |
|
fcd1656024 | |
|
56f036751d | |
|
c402a84bc3 | |
|
ccc5839310 | |
|
018c7ef967 | |
|
dbcecde665 | |
|
9fe399c486 | |
|
333ce38597 | |
|
341ef4d331 | |
|
1d26a256c8 | |
|
b7c8d5184e | |
|
3b56a3c4f9 | |
|
8f1b98eb3d | |
|
9bc6ea7789 | |
|
6473e9cc0a | |
|
24db81f218 | |
|
6228e17373 | |
|
1aaad2e47c | |
|
5a4b3bd6e7 | |
|
7b7d268d65 | |
|
dd3ad640fc | |
|
5ad7a25e7a | |
|
16ecf44c2a | |
|
feb8df3cc4 | |
|
557dcc54fc | |
|
f166790865 | |
|
1491652de1 | |
|
75dac1f159 | |
|
96efe0ea4b | |
|
b0662833a3 | |
|
16349938d6 | |
|
efcdb6d039 | |
|
076e487892 | |
|
6a4a3a9abf | |
|
4a7f74da41 | |
|
b2b4c8852f | |
|
33d216a7f1 | |
|
af66cc1583 | |
|
46c97e8811 | |
|
84dd6f1c08 | |
|
990a47c899 | |
|
5c75c1049f | |
|
bc56d631e5 | |
|
a65245ccf8 | |
|
cc9699e33b | |
|
440bebc72f | |
|
215ebba46e | |
|
a21dc9b9b4 | |
|
42edcca630 | |
|
6be6334478 | |
|
50e19dc3fe | |
|
521417a858 | |
|
ff7c5ea6c1 | |
|
8d42d3146c | |
|
ebe1622927 | |
|
1d77acff28 | |
|
b4516db5cb | |
|
6ea27583aa | |
|
53c4519413 | |
|
8e08a8f3e5 | |
|
a3b9595952 | |
|
d5d4fcd3ee | |
|
26e76ed267 | |
|
c7ba0b9fcd | |
|
66fee76160 | |
|
7209c2c92d | |
|
dda68fa620 | |
|
b1d6dd9ad7 | |
|
049f47f2a2 | |
|
91f1595f3d | |
|
19808e9eb6 | |
|
d008e86507 | |
|
a4c5817881 | |
|
33bd40b500 | |
|
373029277d | |
|
e34b369d54 | |
|
204e1e658c | |
|
8c5e9b4cd3 | |
|
33dd048750 | |
|
4d513d2d19 | |
|
136f1e1e22 | |
|
f09254acd7 | |
|
5b118e5fc5 | |
|
3b53c500b1 | |
|
2739a64e9b | |
|
14b6ab08c0 | |
|
6fcbaca04b | |
|
214ec99e35 | |
|
3a15247ad6 | |
|
628528ff4f | |
|
e4984bc324 | |
|
297acf3ab3 | |
|
145ef07c78 | |
|
791b858a11 | |
|
164c13e3fa | |
|
bc9cd082c9 | |
|
b1adf3e8ba | |
|
17e754adec | |
|
1903720e1b | |
|
0efb770df8 | |
|
01d8064778 | |
|
c3ad5d2227 | |
|
677549d22f | |
|
fb00fc92c7 | |
|
ee2779853f | |
|
7718b6ea88 | |
|
62fcfa822c | |
|
0f2347c18d | |
|
d6aeedfd63 | |
|
de40b8ac7f | |
|
2bcfeeb43d | |
|
04bb52780e | |
|
39a912eee7 | |
|
61d5b01303 | |
|
9eaaa791dc | |
|
3a468c41ed | |
|
98cf6d0007 | |
|
8a4dde3b7d | |
|
330d274e5b | |
|
e62db32eab | |
|
77645ce022 | |
|
1702951b7f | |
|
d44bd6b449 | |
|
0e58e84363 | |
|
e08ae0cbb4 | |
|
5da0e23cec | |
|
d9314e1e59 | |
|
4dbcbf36c8 | |
|
756fae3772 | |
|
f1377456fa | |
|
0a1ac6fb6e | |
|
5e56ccfbdb | |
|
6d59d5134a | |
|
0efc6532c9 | |
|
2058b30f08 | |
|
877f05d00f | |
|
8fc73ca9cf | |
|
d303ed5499 | |
|
a22491e22b | |
|
6a1a3447d2 | |
|
4c5f505a62 | |
|
2f1fda0af2 | |
|
be040ee54f | |
|
029a4f62f9 | |
|
29baf91044 | |
|
d7e2ead631 | |
|
9a3622fc00 | |
|
2b6a9f97bc | |
|
9bf119eedb | |
|
5c99b08a0a | |
|
4f40d33684 | |
|
2b33c38ec4 | |
|
edc235915c | |
|
4622255984 |
|
@ -10,4 +10,5 @@ DO-NOT-COMMIT-local-setup.yaml
|
|||
deployment/compose/minio/data
|
||||
deployment/compose/tempo/data
|
||||
deployment/compose/loki/data
|
||||
.env
|
||||
.env
|
||||
pod*.yaml
|
||||
|
|
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -1,5 +1,23 @@
|
|||
# Changelog
|
||||
|
||||
## 0.3.0 - 2025-02-05
|
||||
|
||||
- Add `kubernetes:sysdig` actionner
|
||||
|
||||
## 0.2.1 - 2024-12-09
|
||||
|
||||
- Fix missing metrics for the `notifications`
|
||||
|
||||
## 0.2.0 - 2024-11-26
|
||||
|
||||
- Add `gcp:function` actionner
|
||||
- Add `gcp:gcs` output
|
||||
- Add `ignore_standalone_pods` parameter for `kubernetes:terminate` actionner
|
||||
- Allow to wait until the completion of `kubernetes:drain`
|
||||
- Allow to check/print the rules without specifying a `config.yaml`
|
||||
- Migration of the Helm chart to [https://github.com/falcosecurity/charts/](https://github.com/falcosecurity/charts/)
|
||||
- Use smaller image for the `kubernetes:tcpdump` actionner
|
||||
|
||||
## 0.1.1 - 2024-10-01
|
||||
|
||||
- Fix panics with actionners `cilium:networkpolicy` and `calico:networkpolicy` because of a wrong init
|
||||
|
|
14
README.md
14
README.md
|
@ -35,7 +35,7 @@
|
|||
|
||||
## Architecture
|
||||
|
||||
`Falco Talon` can receive the `events` from [`Falco`](https://falco.org) or [`Falcosidekick`](https://github.com/falcosecurity/falco-talon):
|
||||
`Falco Talon` can receive the `events` from [`Falco`](https://falco.org) or [`Falcosidekick`](https://github.com/falcosecurity/falcosidekick):
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
|
@ -112,19 +112,21 @@ To generate the images to test locally you can run `mage buildImagesLocal`
|
|||
|
||||
### Helm
|
||||
|
||||
The helm chart is available in the folder [`deployment/helm`](https://github.com/falcosecurity/falco-talon/tree/main/deployment/helm).
|
||||
The helm chart is available in the repo [`charts`](https://github.com/falcosecurity/charts/tree/master/charts/falco-talon).
|
||||
|
||||
Two config files are provided:
|
||||
* `values.yaml` allows you to configure `Falcon Talon` and the deployment
|
||||
* `values.yaml` allows you to configure `Falcon Talon` and the deployment, the list of available values is [here](https://github.com/falcosecurity/charts/tree/master/charts/falco-talon#configuration)
|
||||
* `rules.yaml` contains rules to set
|
||||
|
||||
```shell
|
||||
cd deployment/helm/
|
||||
helm install falco-talon . -n falco --create-namespace
|
||||
helm repo add falcosecurity https://falcosecurity.github.io/charts
|
||||
helm repo update
|
||||
helm install falco-talon falcosecurity/falco -n falco --create-namespace
|
||||
```
|
||||
|
||||
#### Configure Falcosidekick
|
||||
|
||||
Once you have installed `Falco Talon` with Helm, you need to connect `Falcosidekick` by adding the flag `--set falcosidekick.config.webhook.address=http://falco-talon:2803`
|
||||
Once you have installed `Falco Talon` with Helm, you need to connect `Falcosidekick` by adding the flag `--set falcosidekick.config.talon.address=http://falco-talon:2803`
|
||||
|
||||
```shell
|
||||
helm install falco falcosecurity/falco --namespace falco \
|
||||
|
|
|
@ -20,6 +20,8 @@ import (
|
|||
lambdaInvoke "github.com/falcosecurity/falco-talon/actionners/aws/lambda"
|
||||
calicoNetworkpolicy "github.com/falcosecurity/falco-talon/actionners/calico/networkpolicy"
|
||||
ciliumNetworkpolicy "github.com/falcosecurity/falco-talon/actionners/cilium/networkpolicy"
|
||||
gcpFunctionCall "github.com/falcosecurity/falco-talon/actionners/gcp/function"
|
||||
k8sAnnotation "github.com/falcosecurity/falco-talon/actionners/kubernetes/annotation"
|
||||
k8sCordon "github.com/falcosecurity/falco-talon/actionners/kubernetes/cordon"
|
||||
k8sDelete "github.com/falcosecurity/falco-talon/actionners/kubernetes/delete"
|
||||
k8sDownload "github.com/falcosecurity/falco-talon/actionners/kubernetes/download"
|
||||
|
@ -29,6 +31,7 @@ import (
|
|||
k8sLog "github.com/falcosecurity/falco-talon/actionners/kubernetes/log"
|
||||
k8sNetworkpolicy "github.com/falcosecurity/falco-talon/actionners/kubernetes/networkpolicy"
|
||||
k8sScript "github.com/falcosecurity/falco-talon/actionners/kubernetes/script"
|
||||
k8sSysdig "github.com/falcosecurity/falco-talon/actionners/kubernetes/sysdig"
|
||||
k8sTcpdump "github.com/falcosecurity/falco-talon/actionners/kubernetes/tcpdump"
|
||||
k8sTerminate "github.com/falcosecurity/falco-talon/actionners/kubernetes/terminate"
|
||||
"github.com/falcosecurity/falco-talon/configuration"
|
||||
|
@ -71,6 +74,7 @@ func ListDefaultActionners() *Actionners {
|
|||
defaultActionners.Add(
|
||||
k8sTerminate.Register(),
|
||||
k8sLabel.Register(),
|
||||
k8sAnnotation.Register(),
|
||||
k8sNetworkpolicy.Register(),
|
||||
k8sExec.Register(),
|
||||
k8sScript.Register(),
|
||||
|
@ -80,7 +84,9 @@ func ListDefaultActionners() *Actionners {
|
|||
k8sDrain.Register(),
|
||||
k8sDownload.Register(),
|
||||
k8sTcpdump.Register(),
|
||||
k8sSysdig.Register(),
|
||||
lambdaInvoke.Register(),
|
||||
gcpFunctionCall.Register(),
|
||||
calicoNetworkpolicy.Register(),
|
||||
ciliumNetworkpolicy.Register(),
|
||||
)
|
||||
|
@ -106,7 +112,7 @@ func Init() error {
|
|||
for _, actionner := range *defaultActionners {
|
||||
if category == actionner.Information().Category {
|
||||
if err := actionner.Init(); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Message: "init", Error: err.Error(), Category: actionner.Information().Category, Status: utils.FailureStr})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Message: "init", Error: err.Error(), Category: actionner.Information().Category, Status: utils.FailureStr})
|
||||
return err
|
||||
}
|
||||
enabledCategories[category] = true
|
||||
|
@ -170,7 +176,7 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
|
||||
if rule.DryRun == trueStr {
|
||||
log.Output = "no action, dry-run is enabled"
|
||||
utils.PrintLog("info", log)
|
||||
utils.PrintLog(utils.InfoStr, log)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -178,7 +184,7 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
if actionner == nil {
|
||||
log.Status = utils.FailureStr
|
||||
log.Error = fmt.Sprintf("unknown actionner '%v'", action.GetActionner())
|
||||
utils.PrintLog("error", log)
|
||||
utils.PrintLog(utils.ErrorStr, log)
|
||||
return fmt.Errorf("unknown actionner '%v'", action.GetActionner())
|
||||
}
|
||||
|
||||
|
@ -188,7 +194,7 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
if err2 := actionner.Checks(event, action); err2 != nil {
|
||||
log.Status = utils.FailureStr
|
||||
log.Error = err2.Error()
|
||||
utils.PrintLog("error", log)
|
||||
utils.PrintLog(utils.ErrorStr, log)
|
||||
span.SetStatus(codes.Error, err2.Error())
|
||||
span.RecordError(err2)
|
||||
span.End()
|
||||
|
@ -219,6 +225,11 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
trace.WithAttributes(attribute.String("actionner.name", action.GetActionnerName())),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
logP := log
|
||||
logP.Status = utils.InProgressStr
|
||||
utils.PrintLog(utils.InfoStr, logP)
|
||||
|
||||
result, data, err := actionner.Run(event, action)
|
||||
span.SetAttributes(attribute.String("action.result", result.Status))
|
||||
span.SetAttributes(attribute.String("action.output", result.Output))
|
||||
|
@ -251,7 +262,7 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
log.Error = err.Error()
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
utils.PrintLog("error", log)
|
||||
utils.PrintLog(utils.ErrorStr, log)
|
||||
go notifiers.Notify(actx, rule, action, event, log)
|
||||
return err
|
||||
}
|
||||
|
@ -259,13 +270,13 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
span.AddEvent(result.Output)
|
||||
span.SetStatus(codes.Ok, "action successfully completed")
|
||||
|
||||
utils.PrintLog("info", log)
|
||||
utils.PrintLog(utils.InfoStr, log)
|
||||
go notifiers.Notify(actx, rule, action, event, log)
|
||||
|
||||
if actionner.Information().RequireOutput {
|
||||
octx, span := tracer.Start(actx, "output")
|
||||
|
||||
log = utils.LogLine{
|
||||
logO := utils.LogLine{
|
||||
Message: "output",
|
||||
Action: action.GetName(),
|
||||
TraceID: event.TraceID,
|
||||
|
@ -273,27 +284,27 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
|
||||
if output == nil {
|
||||
err = fmt.Errorf("an output is required")
|
||||
log.Status = utils.FailureStr
|
||||
log.Error = err.Error()
|
||||
log.OutputTarget = "n/a"
|
||||
utils.PrintLog("error", log)
|
||||
metrics.IncreaseCounter(log)
|
||||
logO.Status = utils.FailureStr
|
||||
logO.Error = err.Error()
|
||||
logO.OutputTarget = "n/a"
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
metrics.IncreaseCounter(logO)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
|
||||
if data == nil || len(data.Bytes) == 0 {
|
||||
err = fmt.Errorf("empty output")
|
||||
log.Status = utils.FailureStr
|
||||
log.Error = err.Error()
|
||||
utils.PrintLog("error", log)
|
||||
metrics.IncreaseCounter(log)
|
||||
logO.Status = utils.FailureStr
|
||||
logO.Error = err.Error()
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
metrics.IncreaseCounter(logO)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
|
@ -302,67 +313,67 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
o := outputs.ListDefaultOutputs().FindOutput(target)
|
||||
if o == nil {
|
||||
err = fmt.Errorf("unknown output target '%v'", target)
|
||||
log.Status = utils.FailureStr
|
||||
log.OutputTarget = target
|
||||
log.Error = err.Error()
|
||||
utils.PrintLog("error", log)
|
||||
metrics.IncreaseCounter(log)
|
||||
logO.Status = utils.FailureStr
|
||||
logO.OutputTarget = target
|
||||
logO.Error = err.Error()
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
metrics.IncreaseCounter(logO)
|
||||
span.SetAttributes(attribute.String("output.target", target))
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
|
||||
log.Category = o.Information().Category
|
||||
log.OutputTarget = target
|
||||
logO.Category = o.Information().Category
|
||||
logO.OutputTarget = target
|
||||
|
||||
span.SetAttributes(attribute.String("output.name", o.Information().Name))
|
||||
span.SetAttributes(attribute.String("output.category", o.Information().Category))
|
||||
span.SetAttributes(attribute.String("output.target", target))
|
||||
|
||||
if err2 := o.Checks(output); err2 != nil {
|
||||
log.Status = utils.FailureStr
|
||||
log.Error = err2.Error()
|
||||
utils.PrintLog("error", log)
|
||||
metrics.IncreaseCounter(log)
|
||||
logO.Status = utils.FailureStr
|
||||
logO.Error = err2.Error()
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
metrics.IncreaseCounter(logO)
|
||||
span.SetStatus(codes.Error, err2.Error())
|
||||
span.RecordError(err2)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
|
||||
result, err = o.Run(output, data)
|
||||
log.Status = result.Status
|
||||
log.Objects = result.Objects
|
||||
logO.Status = result.Status
|
||||
logO.Objects = result.Objects
|
||||
if result.Output != "" {
|
||||
log.Output = result.Output
|
||||
logO.Output = result.Output
|
||||
}
|
||||
if result.Error != "" {
|
||||
log.Error = result.Error
|
||||
logO.Error = result.Error
|
||||
}
|
||||
|
||||
span.SetAttributes(attribute.String("output.status", result.Status))
|
||||
span.SetAttributes(attribute.String("output.message", result.Output))
|
||||
|
||||
metrics.IncreaseCounter(log)
|
||||
metrics.IncreaseCounter(logO)
|
||||
|
||||
if err != nil {
|
||||
log.Error = err.Error()
|
||||
utils.PrintLog("error", log)
|
||||
logO.Error = err.Error()
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
span.SetStatus(codes.Ok, "output successfully completed")
|
||||
span.AddEvent(result.Output)
|
||||
|
||||
utils.PrintLog("info", log)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
utils.PrintLog(utils.InfoStr, logO)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return nil
|
||||
}
|
||||
|
@ -370,7 +381,7 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
if actionner.Information().AllowOutput && output != nil && data != nil {
|
||||
octx, span := tracer.Start(actx, "output")
|
||||
|
||||
log = utils.LogLine{
|
||||
logO := utils.LogLine{
|
||||
Message: "output",
|
||||
Rule: rule.GetName(),
|
||||
Action: action.GetName(),
|
||||
|
@ -381,20 +392,20 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
o := outputs.GetOutputs().FindOutput(target)
|
||||
if o == nil {
|
||||
err = fmt.Errorf("unknown target '%v'", target)
|
||||
log.OutputTarget = target
|
||||
log.Status = utils.FailureStr
|
||||
log.Error = err.Error()
|
||||
utils.PrintLog("error", log)
|
||||
logO.OutputTarget = target
|
||||
logO.Status = utils.FailureStr
|
||||
logO.Error = err.Error()
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
span.SetAttributes(attribute.String("output.target", target))
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
|
||||
log.OutputTarget = target
|
||||
log.Category = o.Information().Category
|
||||
logO.OutputTarget = target
|
||||
logO.Category = o.Information().Category
|
||||
|
||||
span.SetAttributes(attribute.String("output.name", o.Information().Name))
|
||||
span.SetAttributes(attribute.String("output.category", o.Information().Category))
|
||||
|
@ -402,46 +413,46 @@ func runAction(mctx context.Context, rule *rules.Rule, action *rules.Action, eve
|
|||
|
||||
if len(data.Bytes) == 0 {
|
||||
err = fmt.Errorf("empty output")
|
||||
log.Status = utils.FailureStr
|
||||
log.Error = err.Error()
|
||||
utils.PrintLog("error", log)
|
||||
metrics.IncreaseCounter(log)
|
||||
logO.Status = utils.FailureStr
|
||||
logO.Error = err.Error()
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
metrics.IncreaseCounter(logO)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
|
||||
result, err = o.Run(output, data)
|
||||
log.Status = result.Status
|
||||
log.Objects = result.Objects
|
||||
logO.Status = result.Status
|
||||
logO.Objects = result.Objects
|
||||
if result.Output != "" {
|
||||
log.Output = result.Output
|
||||
logO.Output = result.Output
|
||||
}
|
||||
if result.Error != "" {
|
||||
log.Error = result.Error
|
||||
logO.Error = result.Error
|
||||
}
|
||||
|
||||
span.SetAttributes(attribute.String("output.status", result.Status))
|
||||
span.SetAttributes(attribute.String("output.message", result.Output))
|
||||
|
||||
metrics.IncreaseCounter(log)
|
||||
metrics.IncreaseCounter(logO)
|
||||
|
||||
if err != nil {
|
||||
log.Error = err.Error()
|
||||
utils.PrintLog("error", log)
|
||||
logO.Error = err.Error()
|
||||
utils.PrintLog(utils.ErrorStr, logO)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return err
|
||||
}
|
||||
span.SetStatus(codes.Ok, "output successfully completed")
|
||||
span.AddEvent(result.Output)
|
||||
|
||||
utils.PrintLog("info", log)
|
||||
go notifiers.Notify(octx, rule, action, event, log)
|
||||
utils.PrintLog(utils.InfoStr, logO)
|
||||
go notifiers.Notify(octx, rule, action, event, logO)
|
||||
span.End()
|
||||
return nil
|
||||
}
|
||||
|
@ -486,7 +497,7 @@ func StartConsumer(eventsC <-chan nats.MessageWithContext) {
|
|||
}
|
||||
|
||||
if !config.PrintAllEvents {
|
||||
utils.PrintLog("info", log)
|
||||
utils.PrintLog(utils.InfoStr, log)
|
||||
}
|
||||
|
||||
for _, i := range triggeredRules {
|
||||
|
@ -506,7 +517,7 @@ func StartConsumer(eventsC <-chan nats.MessageWithContext) {
|
|||
span.SetStatus(codes.Ok, "match detected")
|
||||
span.End()
|
||||
|
||||
utils.PrintLog("info", log)
|
||||
utils.PrintLog(utils.InfoStr, log)
|
||||
metrics.IncreaseCounter(log)
|
||||
|
||||
for _, a := range i.GetActions() {
|
||||
|
@ -527,7 +538,7 @@ func StartConsumer(eventsC <-chan nats.MessageWithContext) {
|
|||
TraceID: e.TraceID,
|
||||
Error: err.Error(),
|
||||
}
|
||||
utils.PrintLog("error", log)
|
||||
utils.PrintLog(utils.ErrorStr, log)
|
||||
if a.IgnoreErrors != trueStr {
|
||||
break
|
||||
}
|
||||
|
|
|
@ -80,11 +80,11 @@ rules:
|
|||
actionner: cilium:networkpolicy
|
||||
parameters:
|
||||
allow_cidr:
|
||||
- "192.168.1.0/24"
|
||||
- "172.17.0.0/16"
|
||||
- "192.168.1.0/24"
|
||||
- "172.17.0.0/16"
|
||||
allow_namespaces:
|
||||
- "green-ns"
|
||||
- "blue-ns"
|
||||
- "green-ns"
|
||||
- "blue-ns"
|
||||
`
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
package functions
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/functions/apiv2/functionspb"
|
||||
"google.golang.org/api/idtoken"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/internal/events"
|
||||
"github.com/falcosecurity/falco-talon/internal/gcp/checks"
|
||||
"github.com/falcosecurity/falco-talon/internal/gcp/client"
|
||||
"github.com/falcosecurity/falco-talon/internal/models"
|
||||
"github.com/falcosecurity/falco-talon/internal/rules"
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
Name string = "function"
|
||||
Category string = "gcp"
|
||||
Description string = "Invoke a GCP function forwarding the Falco event payload"
|
||||
Source string = "any"
|
||||
Continue bool = true
|
||||
AllowOutput bool = false
|
||||
RequireOutput bool = false
|
||||
Permissions string = `{
|
||||
"cloudfunctions.functions.get",
|
||||
"cloudfunctions.functions.invoke"
|
||||
}`
|
||||
Example string = `- action: Invoke GCP Cloud Function
|
||||
actionner: gcp:function
|
||||
parameters:
|
||||
gcp_function_name: sample-function
|
||||
gcp_function_location: us-central1
|
||||
gcp_function_timeout: 10
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
RequiredOutputFields = []string{}
|
||||
)
|
||||
|
||||
type Parameters struct {
|
||||
GCPFunctionName string `mapstructure:"gcp_function_name" validate:"required"`
|
||||
GCPFunctionLocation string `mapstructure:"gcp_function_location" validate:"required"`
|
||||
GCPFunctionTimeout int `mapstructure:"gcp_function_timeout"`
|
||||
}
|
||||
|
||||
type Actionner struct{}
|
||||
|
||||
func Register() *Actionner {
|
||||
return new(Actionner)
|
||||
}
|
||||
|
||||
func (a Actionner) Init() error {
|
||||
return client.Init()
|
||||
}
|
||||
|
||||
func (a Actionner) Information() models.Information {
|
||||
return models.Information{
|
||||
Name: Name,
|
||||
FullName: Category + ":" + Name,
|
||||
Category: Category,
|
||||
Description: Description,
|
||||
Source: Source,
|
||||
RequiredOutputFields: RequiredOutputFields,
|
||||
Permissions: Permissions,
|
||||
Example: Example,
|
||||
Continue: Continue,
|
||||
AllowOutput: AllowOutput,
|
||||
RequireOutput: RequireOutput,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Actionner) Parameters() models.Parameters {
|
||||
return Parameters{
|
||||
GCPFunctionName: "",
|
||||
GCPFunctionLocation: "us-central1", // Default location
|
||||
}
|
||||
}
|
||||
|
||||
func (a Actionner) Checks(_ *events.Event, action *rules.Action) error {
|
||||
var parameters Parameters
|
||||
err := utils.DecodeParams(action.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return checks.CheckFunctionExist{}.Run(parameters.GCPFunctionName, parameters.GCPFunctionLocation)
|
||||
}
|
||||
|
||||
func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine, *models.Data, error) {
|
||||
gcpClient, err := client.GetGCPClient()
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: nil,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
return a.RunWithClient(gcpClient, event, action)
|
||||
}
|
||||
|
||||
func (a Actionner) CheckParameters(action *rules.Action) error {
|
||||
var parameters Parameters
|
||||
err := utils.DecodeParams(action.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = utils.ValidateStruct(parameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a Actionner) RunWithClient(c client.GCPClientAPI, event *events.Event, action *rules.Action) (utils.LogLine, *models.Data, error) {
|
||||
var parameters Parameters
|
||||
err := utils.DecodeParams(action.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: nil,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
objects := map[string]string{
|
||||
"name": parameters.GCPFunctionName,
|
||||
"location": parameters.GCPFunctionLocation,
|
||||
}
|
||||
|
||||
functionName := fmt.Sprintf("projects/%s/locations/%s/functions/%s", c.ProjectID(), parameters.GCPFunctionLocation, parameters.GCPFunctionName)
|
||||
|
||||
getFunctionReq := &functionspb.GetFunctionRequest{
|
||||
Name: functionName,
|
||||
}
|
||||
|
||||
gcpFunctionClient, err := c.GetGcpFunctionClient(context.Background())
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
function, err := gcpFunctionClient.GetFunction(ctx, getFunctionReq)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: fmt.Sprintf("failed to get function: %v", err),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
if function.ServiceConfig.Uri == "" {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: "function does not have a valid URL",
|
||||
Status: utils.FailureStr,
|
||||
}, nil, fmt.Errorf("function does not have a valid URL")
|
||||
}
|
||||
|
||||
functionURL := function.ServiceConfig.Uri
|
||||
|
||||
payload, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
tokenSource, err := idtoken.NewTokenSource(ctx, functionURL)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: fmt.Sprintf("failed to create ID token source: %v", err),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
token, err := tokenSource.Token()
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: fmt.Sprintf("failed to obtain ID token: %v", err),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", functionURL, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: fmt.Sprintf("failed to create HTTP request: %v", err),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
|
||||
|
||||
if parameters.GCPFunctionTimeout > 0 {
|
||||
httpClient := http.Client{
|
||||
Timeout: time.Duration(parameters.GCPFunctionTimeout),
|
||||
}
|
||||
c.SetHTTPClient(&httpClient)
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient().Do(req)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: fmt.Sprintf("failed to invoke function: %v", err),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: fmt.Sprintf("failed to read response body: %v", err),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: fmt.Sprintf("function invocation failed with status %d: %s", resp.StatusCode, string(respBody)),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, fmt.Errorf("function invocation failed with status %d: %s", resp.StatusCode, string(respBody))
|
||||
}
|
||||
|
||||
objects["function_response"] = string(respBody)
|
||||
objects["function_response_status"] = strconv.Itoa(resp.StatusCode)
|
||||
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Status: utils.SuccessStr,
|
||||
}, nil, nil
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
package annotation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/internal/events"
|
||||
k8sChecks "github.com/falcosecurity/falco-talon/internal/kubernetes/checks"
|
||||
k8s "github.com/falcosecurity/falco-talon/internal/kubernetes/client"
|
||||
"github.com/falcosecurity/falco-talon/internal/models"
|
||||
"github.com/falcosecurity/falco-talon/internal/rules"
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
Name string = "annotation"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Add, modify or delete the annotations of the pod/node"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = true
|
||||
UseContext bool = false
|
||||
AllowOutput bool = false
|
||||
RequireOutput bool = false
|
||||
Permissions string = `apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: falco-talon
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
- patch
|
||||
- list
|
||||
`
|
||||
Example string = `- action: Annotation the pod
|
||||
actionner: kubernetes:annotation
|
||||
parameters:
|
||||
level: pod
|
||||
annotations:
|
||||
suspicious: "true"
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
RequiredOutputFields = []string{"k8s.ns.name", "k8s.pod.name"}
|
||||
)
|
||||
|
||||
type patch struct {
|
||||
Op string `json:"op"`
|
||||
Path string `json:"path"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type Parameters struct {
|
||||
Annotations map[string]string `mapstructure:"annotations" validate:"required"`
|
||||
Level string `mapstructure:"level" validate:"omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
metadataAnnotations = "/metadata/annotations/"
|
||||
podStr = "pod"
|
||||
nodeStr = "node"
|
||||
)
|
||||
|
||||
type Actionner struct{}
|
||||
|
||||
func Register() *Actionner {
|
||||
return new(Actionner)
|
||||
}
|
||||
|
||||
func (a Actionner) Init() error {
|
||||
return k8s.Init()
|
||||
}
|
||||
|
||||
func (a Actionner) Information() models.Information {
|
||||
return models.Information{
|
||||
Name: Name,
|
||||
FullName: Category + ":" + Name,
|
||||
Category: Category,
|
||||
Description: Description,
|
||||
Source: Source,
|
||||
RequiredOutputFields: RequiredOutputFields,
|
||||
Permissions: Permissions,
|
||||
Example: Example,
|
||||
Continue: Continue,
|
||||
AllowOutput: AllowOutput,
|
||||
RequireOutput: RequireOutput,
|
||||
}
|
||||
}
|
||||
func (a Actionner) Parameters() models.Parameters {
|
||||
return Parameters{
|
||||
Annotations: map[string]string{},
|
||||
Level: "pod",
|
||||
}
|
||||
}
|
||||
|
||||
func (a Actionner) Checks(event *events.Event, _ *rules.Action) error {
|
||||
return k8sChecks.CheckPodExist(event)
|
||||
}
|
||||
|
||||
func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine, *models.Data, error) {
|
||||
podName := event.GetPodName()
|
||||
namespace := event.GetNamespaceName()
|
||||
|
||||
objects := map[string]string{}
|
||||
|
||||
payload := make([]patch, 0)
|
||||
|
||||
var parameters Parameters
|
||||
err := utils.DecodeParams(action.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: nil,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
client := k8s.GetClient()
|
||||
|
||||
var kind string
|
||||
var node *corev1.Node
|
||||
|
||||
pod, err2 := client.GetPod(podName, namespace)
|
||||
if err2 != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err2.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err2
|
||||
}
|
||||
if parameters.Level == nodeStr {
|
||||
kind = nodeStr
|
||||
node, err = client.GetNodeFromPod(pod)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
objects[nodeStr] = node.Name
|
||||
if node.ObjectMeta.Annotations == nil {
|
||||
node.ObjectMeta.Annotations = make(map[string]string)
|
||||
node.ObjectMeta.Annotations[podStr] = podStr
|
||||
parameters.Annotations[podStr] = ""
|
||||
_, err = client.Clientset.CoreV1().Nodes().Update(context.Background(), node, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kind = podStr
|
||||
objects[podStr] = podName
|
||||
objects["namespace"] = namespace
|
||||
if pod.ObjectMeta.Annotations == nil {
|
||||
pod.ObjectMeta.Annotations = make(map[string]string)
|
||||
pod.ObjectMeta.Annotations[podStr] = podStr
|
||||
parameters.Annotations[podStr] = ""
|
||||
_, err = client.Clientset.CoreV1().Pods(namespace).Update(context.Background(), pod, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i, j := range parameters.Annotations {
|
||||
if fmt.Sprintf("%v", j) == "" {
|
||||
continue
|
||||
}
|
||||
payload = append(payload, patch{
|
||||
Op: "replace",
|
||||
Path: metadataAnnotations + strings.ReplaceAll(i, "/", "~1"),
|
||||
Value: fmt.Sprintf("%v", j),
|
||||
})
|
||||
}
|
||||
|
||||
payloadBytes, _ := json.Marshal(payload)
|
||||
if kind == podStr {
|
||||
_, err = client.Clientset.CoreV1().Pods(namespace).Patch(context.Background(), podName, types.JSONPatchType, payloadBytes, metav1.PatchOptions{})
|
||||
}
|
||||
if kind == nodeStr {
|
||||
_, err = client.Clientset.CoreV1().Nodes().Patch(context.Background(), node.Name, types.JSONPatchType, payloadBytes, metav1.PatchOptions{})
|
||||
}
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
payload = make([]patch, 0)
|
||||
action.GetParameters()
|
||||
for i, j := range parameters.Annotations {
|
||||
if fmt.Sprintf("%v", j) != "" {
|
||||
continue
|
||||
}
|
||||
payload = append(payload, patch{
|
||||
Op: "remove",
|
||||
Path: metadataAnnotations + strings.ReplaceAll(i, "/", "~1"),
|
||||
})
|
||||
}
|
||||
|
||||
payloadBytes, _ = json.Marshal(payload)
|
||||
if kind == nodeStr {
|
||||
_, err = client.Clientset.CoreV1().Nodes().Patch(context.Background(), node.Name, types.JSONPatchType, payloadBytes, metav1.PatchOptions{})
|
||||
} else {
|
||||
_, err = client.Clientset.CoreV1().Pods(namespace).Patch(context.Background(), podName, types.JSONPatchType, payloadBytes, metav1.PatchOptions{})
|
||||
}
|
||||
if err != nil {
|
||||
if err.Error() != "the server rejected our request due to an error in our request" {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
}
|
||||
var output string
|
||||
if kind == nodeStr {
|
||||
output = fmt.Sprintf("the node '%v' has been annotationed", node.Name)
|
||||
} else {
|
||||
output = fmt.Sprintf("the pod '%v' in the namespace '%v' has been annotated", podName, namespace)
|
||||
}
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Output: output,
|
||||
Status: utils.SuccessStr,
|
||||
}, nil, nil
|
||||
}
|
||||
|
||||
func (a Actionner) CheckParameters(action *rules.Action) error {
|
||||
var parameters Parameters
|
||||
err := utils.DecodeParams(action.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = utils.ValidateStruct(parameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(parameters.Annotations) == 0 {
|
||||
return errors.New("parameter 'annotations' should have at least one annotation")
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -19,7 +19,7 @@ const (
|
|||
Name string = "cordon"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Cordon a node"
|
||||
Source string = "syscalls"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = true
|
||||
UseContext bool = false
|
||||
AllowOutput bool = false
|
||||
|
|
|
@ -19,7 +19,7 @@ const (
|
|||
Name string = "delete"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Delete a resource"
|
||||
Source string = "k8saudit"
|
||||
Source string = "k8s_audit"
|
||||
Continue bool = false
|
||||
UseContext bool = false
|
||||
AllowOutput bool = false
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package drain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
@ -24,8 +23,8 @@ import (
|
|||
const (
|
||||
Name string = "drain"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Drain a pod"
|
||||
Source string = "syscalls"
|
||||
Description string = "Drain a node"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = true
|
||||
UseContext bool = false
|
||||
AllowOutput bool = false
|
||||
|
@ -119,7 +118,7 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine
|
|||
return a.RunWithClient(*client, event, action)
|
||||
}
|
||||
|
||||
func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, action *rules.Action) (utils.LogLine, *models.Data, error) {
|
||||
func (a Actionner) RunWithClient(client k8s.Client, event *events.Event, action *rules.Action) (utils.LogLine, *models.Data, error) {
|
||||
podName := event.GetPodName()
|
||||
namespace := event.GetNamespaceName()
|
||||
objects := map[string]string{}
|
||||
|
@ -158,7 +157,7 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
nodeName := node.GetName()
|
||||
objects["node"] = nodeName
|
||||
|
||||
pods, err := client.ListPods(context.Background(), metav1.ListOptions{
|
||||
pods, err := client.ListPods(metav1.ListOptions{
|
||||
FieldSelector: fmt.Sprintf("spec.nodeName=%s", nodeName),
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -188,11 +187,11 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
case <-stopListingDone:
|
||||
return
|
||||
case <-ticker.C:
|
||||
pods2, err2 := client.ListPods(context.Background(), metav1.ListOptions{
|
||||
pods2, err2 := client.ListPods(metav1.ListOptions{
|
||||
FieldSelector: fmt.Sprintf("spec.nodeName=%s", nodeName),
|
||||
})
|
||||
if err2 != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error listing pods on node '%v': %v", nodeName, err2)})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Message: fmt.Sprintf("error listing pods on node '%v': %v", nodeName, err2)})
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -220,13 +219,7 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
go func(pod corev1.Pod) {
|
||||
defer wg.Done()
|
||||
|
||||
ownerKind, err := k8s.GetOwnerKind(p)
|
||||
if err != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error getting pod '%v' owner kind: %v", p.Name, err)})
|
||||
atomic.AddInt32(&otherErrorsCount, 1)
|
||||
return
|
||||
}
|
||||
|
||||
ownerKind := k8s.PodKind(p)
|
||||
switch ownerKind {
|
||||
case utils.DaemonSetStr:
|
||||
if parameters.IgnoreDaemonsets {
|
||||
|
@ -241,20 +234,20 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
case utils.ReplicaSetStr:
|
||||
replicaSetName, err := k8s.GetOwnerName(p)
|
||||
if err != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error getting pod owner name: %v", err)})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Message: fmt.Sprintf("error getting pod owner name: %v", err)})
|
||||
atomic.AddInt32(&otherErrorsCount, 1)
|
||||
return
|
||||
}
|
||||
if parameters.MinHealthyReplicas != "" {
|
||||
replicaSet, err := client.GetReplicaSet(replicaSetName, p.Namespace)
|
||||
if err != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error getting replica set for pod '%v': %v", p.Name, err)})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Message: fmt.Sprintf("error getting replica set for pod '%v': %v", p.Name, err)})
|
||||
atomic.AddInt32(&otherErrorsCount, 1)
|
||||
return
|
||||
}
|
||||
minHealthyReplicasValue, kind, err := helpers.ParseMinHealthyReplicas(parameters.MinHealthyReplicas)
|
||||
if err != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error parsing min_healthy_replicas: %v", err)})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Message: fmt.Sprintf("error parsing min_healthy_replicas: %v", err)})
|
||||
atomic.AddInt32(&otherErrorsCount, 1)
|
||||
return
|
||||
}
|
||||
|
@ -262,7 +255,7 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
case "absolut":
|
||||
healthyReplicasCount, err := k8s.GetHealthyReplicasCount(replicaSet)
|
||||
if err != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error getting health replicas count for pod '%v': %v", p.Name, err)})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Message: fmt.Sprintf("error getting health replicas count for pod '%v': %v", p.Name, err)})
|
||||
atomic.AddInt32(&otherErrorsCount, 1)
|
||||
return
|
||||
}
|
||||
|
@ -274,7 +267,7 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
healthyReplicasValue, err := k8s.GetHealthyReplicasCount(replicaSet)
|
||||
minHealthyReplicasAbsoluteValue := int64(float64(minHealthyReplicasValue) / 100.0 * float64(healthyReplicasValue))
|
||||
if err != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error getting health replicas count for pod '%v': %v", p.Name, err)})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Message: fmt.Sprintf("error getting health replicas count for pod '%v': %v", p.Name, err)})
|
||||
atomic.AddInt32(&otherErrorsCount, 1)
|
||||
return
|
||||
}
|
||||
|
@ -287,7 +280,7 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
}
|
||||
|
||||
if err := client.EvictPod(p); err != nil {
|
||||
utils.PrintLog("warning", utils.LogLine{Message: fmt.Sprintf("error evicting pod '%v': %v", p.Name, err)})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Message: fmt.Sprintf("error evicting pod '%v': %v", p.Name, err)})
|
||||
atomic.AddInt32(&evictionErrorsCount, 1)
|
||||
return
|
||||
}
|
||||
|
@ -300,7 +293,7 @@ func (a Actionner) RunWithClient(client k8s.DrainClient, event *events.Event, ac
|
|||
for {
|
||||
select {
|
||||
case <-timeout:
|
||||
utils.PrintLog("error", utils.LogLine{Message: fmt.Sprintf("pod '%v' did not terminate within the max_wait_period", pod.Name)})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Message: fmt.Sprintf("pod '%v' did not terminate within the max_wait_period", pod.Name)})
|
||||
atomic.AddInt32(&evictionWaitPeriodErrorsCount, 1)
|
||||
return
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ const (
|
|||
Name string = "exec"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Exec a command in a pod"
|
||||
Source string = "syscalls"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = true
|
||||
UseContext bool = true
|
||||
AllowOutput bool = false
|
||||
|
|
|
@ -22,8 +22,8 @@ import (
|
|||
const (
|
||||
Name string = "label"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Add, modify or delete the labels of the pod"
|
||||
Source string = "syscalls"
|
||||
Description string = "Add, modify or delete the labels of the pod/node"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = true
|
||||
UseContext bool = false
|
||||
AllowOutput bool = false
|
||||
|
@ -48,7 +48,7 @@ rules:
|
|||
parameters:
|
||||
level: pod
|
||||
labels:
|
||||
suspicious: true
|
||||
suspicious: "true"
|
||||
`
|
||||
)
|
||||
|
||||
|
@ -132,16 +132,16 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine
|
|||
var kind string
|
||||
var node *corev1.Node
|
||||
|
||||
pod, err2 := client.GetPod(podName, namespace)
|
||||
if err2 != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err2.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err2
|
||||
}
|
||||
if parameters.Level == nodeStr {
|
||||
kind = nodeStr
|
||||
pod, err2 := client.GetPod(podName, namespace)
|
||||
if err2 != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err2.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err2
|
||||
}
|
||||
node, err = client.GetNodeFromPod(pod)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
|
@ -151,10 +151,36 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine
|
|||
}, nil, err
|
||||
}
|
||||
objects[nodeStr] = node.Name
|
||||
if node.ObjectMeta.Labels == nil {
|
||||
node.ObjectMeta.Labels = make(map[string]string)
|
||||
node.ObjectMeta.Labels[podStr] = podStr
|
||||
parameters.Labels[podStr] = ""
|
||||
_, err = client.Clientset.CoreV1().Nodes().Update(context.Background(), node, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kind = podStr
|
||||
objects[podStr] = podName
|
||||
objects["namespace"] = namespace
|
||||
if pod.ObjectMeta.Labels == nil {
|
||||
pod.ObjectMeta.Labels = make(map[string]string)
|
||||
pod.ObjectMeta.Labels[podStr] = podStr
|
||||
parameters.Labels[podStr] = ""
|
||||
_, err = client.Clientset.CoreV1().Pods(namespace).Update(context.Background(), pod, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i, j := range parameters.Labels {
|
||||
|
|
|
@ -20,7 +20,7 @@ const (
|
|||
Name string = "log"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Get logs from a pod"
|
||||
Source string = "syscalls"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = true
|
||||
UseContext bool = false
|
||||
AllowOutput bool = true
|
||||
|
|
|
@ -18,7 +18,7 @@ const (
|
|||
Name string = "script"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Run a script in a pod"
|
||||
Source string = "syscalls"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = true
|
||||
UseContext bool = true
|
||||
AllowOutput bool = false
|
||||
|
|
|
@ -0,0 +1,295 @@
|
|||
package sysdig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/internal/events"
|
||||
k8sChecks "github.com/falcosecurity/falco-talon/internal/kubernetes/checks"
|
||||
k8s "github.com/falcosecurity/falco-talon/internal/kubernetes/client"
|
||||
"github.com/falcosecurity/falco-talon/internal/models"
|
||||
"github.com/falcosecurity/falco-talon/internal/rules"
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
Name string = "sysdig"
|
||||
Category string = "kubernetes"
|
||||
Description string = "Capture the syscalls packets in a pod"
|
||||
Source string = "syscalls, k8s_audit"
|
||||
Continue bool = false
|
||||
UseContext bool = false
|
||||
AllowOutput bool = false
|
||||
RequireOutput bool = true
|
||||
Permissions string = `apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: falco-talon
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/exec
|
||||
verbs:
|
||||
- get
|
||||
- create
|
||||
- apiGroups:
|
||||
- "batch"
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- create
|
||||
`
|
||||
Example string = `- action: Create a syscall capture from a pod
|
||||
actionner: kubernetes:sysdig
|
||||
parameters:
|
||||
duration: 10
|
||||
buffer_size: 1024
|
||||
output:
|
||||
target: aws:s3
|
||||
parameters:
|
||||
bucket: my-bucket
|
||||
prefix: /captures/
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
RequiredOutputFields = []string{"k8s.ns.name, k8s.pod.name", "ka.target.namespace, (ka.target.pod.name or ka.target.name)"}
|
||||
)
|
||||
|
||||
type Parameters struct {
|
||||
Image string `mapstructure:"image"`
|
||||
Scope string `mapstructure:"scope" validate:"oneof=pod node"`
|
||||
Duration int `mapstructure:"duration" validate:"gt=0,lte=30"`
|
||||
BufferSize int `mapstructure:"buffer_size" validate:"gte=128"`
|
||||
}
|
||||
|
||||
const (
|
||||
baseName string = "falco-talon-sysdig-"
|
||||
defaultImage string = "issif/sysdig:latest"
|
||||
defaultScope string = "pod"
|
||||
defaultTTL int = 60
|
||||
defaultDuration int = 5
|
||||
defaultMaxDuration int = 30
|
||||
defaultBufferSize int = 2048
|
||||
)
|
||||
|
||||
type Actionner struct{}
|
||||
|
||||
func Register() *Actionner {
|
||||
return new(Actionner)
|
||||
}
|
||||
|
||||
func (a Actionner) Init() error {
|
||||
return k8s.Init()
|
||||
}
|
||||
|
||||
func (a Actionner) Information() models.Information {
|
||||
return models.Information{
|
||||
Name: Name,
|
||||
FullName: Category + ":" + Name,
|
||||
Category: Category,
|
||||
Description: Description,
|
||||
Source: Source,
|
||||
RequiredOutputFields: RequiredOutputFields,
|
||||
Permissions: Permissions,
|
||||
Example: Example,
|
||||
Continue: Continue,
|
||||
AllowOutput: AllowOutput,
|
||||
RequireOutput: RequireOutput,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Actionner) Parameters() models.Parameters {
|
||||
return Parameters{
|
||||
Duration: defaultDuration,
|
||||
Scope: defaultScope,
|
||||
BufferSize: defaultBufferSize,
|
||||
Image: defaultImage,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Actionner) Checks(event *events.Event, _ *rules.Action) error {
|
||||
return k8sChecks.CheckPodExist(event)
|
||||
}
|
||||
|
||||
func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine, *models.Data, error) {
|
||||
podName := event.GetPodName()
|
||||
namespace := event.GetNamespaceName()
|
||||
|
||||
objects := map[string]string{
|
||||
"pod": podName,
|
||||
"namespace": namespace,
|
||||
}
|
||||
|
||||
var parameters Parameters
|
||||
err := utils.DecodeParams(action.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: nil,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
if parameters.Duration == 0 {
|
||||
parameters.Duration = defaultDuration
|
||||
}
|
||||
|
||||
if parameters.Image == "" {
|
||||
parameters.Image = defaultImage
|
||||
}
|
||||
|
||||
if parameters.Scope == "" {
|
||||
parameters.Scope = defaultScope
|
||||
}
|
||||
|
||||
if parameters.BufferSize == 0 {
|
||||
parameters.BufferSize = defaultBufferSize
|
||||
}
|
||||
|
||||
client := k8s.GetClient()
|
||||
|
||||
pod, _ := client.GetPod(podName, namespace)
|
||||
containers := k8s.GetContainers(pod)
|
||||
if len(containers) == 0 {
|
||||
err = fmt.Errorf("no container found")
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
job, err := client.CreateJob("falco-talon-sysdig", namespace, parameters.Image, pod.Spec.NodeName, defaultTTL)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
objects["job"] = job
|
||||
|
||||
timeout := time.NewTimer(20 * time.Second)
|
||||
ticker := time.NewTicker(300 * time.Millisecond)
|
||||
defer timeout.Stop()
|
||||
defer ticker.Stop()
|
||||
|
||||
var ready bool
|
||||
var jPod, jContainer string
|
||||
for !ready {
|
||||
select {
|
||||
case <-timeout.C:
|
||||
err = fmt.Errorf("the job '%v' in the namespace '%v' for the sysdig capture is not ready", job, namespace)
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
case <-ticker.C:
|
||||
p, err2 := client.ListPods(metav1.ListOptions{LabelSelector: "batch.kubernetes.io/job-name=" + job})
|
||||
if err2 != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err2.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err2
|
||||
}
|
||||
if len(p.Items) > 0 {
|
||||
if p.Items[0].Status.Phase == corev1.PodRunning && p.Items[0].Status.ContainerStatuses[0].Ready {
|
||||
jPod = p.Items[0].Name
|
||||
jContainer = p.Items[0].Spec.Containers[0].Name
|
||||
ready = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
command := []string{"tee", "/tmp/talon-script.sh", "/dev/null"}
|
||||
sysdigCmd := fmt.Sprintf("sysdig --modern-bpf --cri /run/containerd/containerd.sock -M %v -s %v -z -w /tmp/sysdig.scap.gz", parameters.Duration, parameters.BufferSize)
|
||||
if parameters.Scope == "pod" {
|
||||
containers := []string{}
|
||||
for _, i := range pod.Status.ContainerStatuses {
|
||||
containers = append(containers, strings.ReplaceAll(i.ContainerID, "containerd://", "")[:12])
|
||||
}
|
||||
sysdigCmd = fmt.Sprintf("%v \"container.id in (%v)\"", sysdigCmd, strings.Join(containers, ","))
|
||||
}
|
||||
script := fmt.Sprintf("%v || [ $? -eq 0 ] && echo OK || exit 1\n", sysdigCmd)
|
||||
_, err = client.Exec(namespace, jPod, jContainer, command, script)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
command = []string{"sh", "/tmp/talon-script.sh"}
|
||||
_, err = client.Exec(namespace, jPod, jContainer, command, "")
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
command = []string{"cat", "/tmp/sysdig.scap.gz"}
|
||||
output, err := client.Exec(namespace, jPod, jContainer, command, "")
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, nil, err
|
||||
}
|
||||
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Output: fmt.Sprintf("a sysdig capture '%v' has been created", "sysdig.scap.gz"),
|
||||
Status: utils.SuccessStr,
|
||||
}, &models.Data{Name: "sysdig.scap.gz", Objects: objects, Bytes: output.Bytes()}, nil
|
||||
}
|
||||
|
||||
func (a Actionner) CheckParameters(action *rules.Action) error {
|
||||
var parameters Parameters
|
||||
|
||||
err := utils.DecodeParams(action.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if parameters.Scope == "" {
|
||||
parameters.Scope = defaultScope
|
||||
}
|
||||
|
||||
if parameters.BufferSize == 0 {
|
||||
parameters.BufferSize = defaultBufferSize
|
||||
}
|
||||
|
||||
if parameters.Duration == 0 {
|
||||
parameters.Duration = defaultDuration
|
||||
}
|
||||
|
||||
err = utils.ValidateStruct(parameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -51,7 +51,7 @@ rules:
|
|||
- get
|
||||
- create
|
||||
`
|
||||
Example string = `- action: Get logs of the pod
|
||||
Example string = `- action: Create a packet capture from a pod
|
||||
actionner: kubernetes:tcpdump
|
||||
parameters:
|
||||
duration: 10
|
||||
|
@ -77,8 +77,9 @@ type Parameters struct {
|
|||
const (
|
||||
baseName string = "falco-talon-tcpdump-"
|
||||
defaultImage string = "issif/tcpdump:latest"
|
||||
defaultTTL int = 300
|
||||
defaultTTL int = 60
|
||||
defaultDuration int = 5
|
||||
defaulSnaplen int = 4096
|
||||
)
|
||||
|
||||
type Actionner struct{}
|
||||
|
@ -109,9 +110,9 @@ func (a Actionner) Information() models.Information {
|
|||
|
||||
func (a Actionner) Parameters() models.Parameters {
|
||||
return Parameters{
|
||||
Duration: 20,
|
||||
Snaplen: 4096,
|
||||
Image: "issif/tcpdump:latest",
|
||||
Duration: defaultDuration,
|
||||
Snaplen: defaulSnaplen,
|
||||
Image: defaultImage,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,8 +171,8 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine
|
|||
}, nil, err
|
||||
}
|
||||
|
||||
command := []string{"tee", "/tmp/talon-script.sh", ">", "/dev/null"}
|
||||
script := fmt.Sprintf("timeout %vs tcpdump -n -i any -s %v -w /tmp/tcpdump.pcap || [ $? -eq 124 ] && echo OK || exit 1", parameters.Duration, parameters.Snaplen)
|
||||
command := []string{"tee", "/tmp/talon-script.sh", "/dev/null"}
|
||||
script := fmt.Sprintf("timeout %vs tcpdump -n -i any -s %v -w /tmp/tcpdump.pcap || [ $? -eq 124 ] && echo OK || exit 1\n", parameters.Duration, parameters.Snaplen)
|
||||
_, err = client.Exec(namespace, podName, ephemeralContainerName, command, script)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
|
|
|
@ -50,6 +50,7 @@ rules:
|
|||
grace_period_seconds: 5
|
||||
ignore_daemonsets: true
|
||||
ignore_statefulsets: true
|
||||
ignore_standalone_pods: true
|
||||
min_healthy_replicas: 33%
|
||||
`
|
||||
)
|
||||
|
@ -59,10 +60,11 @@ var (
|
|||
)
|
||||
|
||||
type Parameters struct {
|
||||
MinHealthyReplicas string `mapstructure:"min_healthy_replicas" validate:"omitempty,is_absolut_or_percent"`
|
||||
IgnoreDaemonsets bool `mapstructure:"ignore_daemonsets" validate:"omitempty"`
|
||||
IgnoreStatefulSets bool `mapstructure:"ignore_statefulsets" validate:"omitempty"`
|
||||
GracePeriodSeconds int `mapstructure:"grace_period_seconds" validate:"omitempty"`
|
||||
MinHealthyReplicas string `mapstructure:"min_healthy_replicas" validate:"omitempty,is_absolut_or_percent"`
|
||||
IgnoreDaemonsets bool `mapstructure:"ignore_daemonsets" validate:"omitempty"`
|
||||
IgnoreStatefulSets bool `mapstructure:"ignore_statefulsets" validate:"omitempty"`
|
||||
IgnoreStandalonePods bool `mapstructure:"ignore_standalone_pods" validate:"omitempty"`
|
||||
GracePeriodSeconds int `mapstructure:"grace_period_seconds" validate:"omitempty"`
|
||||
}
|
||||
|
||||
type Actionner struct{}
|
||||
|
@ -92,10 +94,11 @@ func (a Actionner) Information() models.Information {
|
|||
}
|
||||
func (a Actionner) Parameters() models.Parameters {
|
||||
return Parameters{
|
||||
MinHealthyReplicas: "",
|
||||
IgnoreDaemonsets: false,
|
||||
IgnoreStatefulSets: false,
|
||||
GracePeriodSeconds: 0,
|
||||
MinHealthyReplicas: "",
|
||||
IgnoreDaemonsets: false,
|
||||
IgnoreStatefulSets: false,
|
||||
IgnoreStandalonePods: true,
|
||||
GracePeriodSeconds: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,16 +140,7 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine
|
|||
err
|
||||
}
|
||||
|
||||
ownerKind, err := k8s.GetOwnerKind(*pod)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
},
|
||||
nil,
|
||||
err
|
||||
}
|
||||
ownerKind := k8s.PodKind(*pod)
|
||||
|
||||
switch ownerKind {
|
||||
case utils.DaemonSetStr:
|
||||
|
@ -226,6 +220,14 @@ func (a Actionner) Run(event *events.Event, action *rules.Action) (utils.LogLine
|
|||
}
|
||||
}
|
||||
}
|
||||
case utils.StandalonePodStr:
|
||||
if parameters.IgnoreStandalonePods {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Status: "ignored",
|
||||
Result: fmt.Sprintf("the pod '%v' in the namespace '%v' is a standalone pod and will be ignored.", podName, namespace),
|
||||
}, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
err = client.Clientset.CoreV1().Pods(namespace).Delete(context.Background(), podName, metav1.DeleteOptions{GracePeriodSeconds: gracePeriodSeconds})
|
||||
|
|
10
cmd/root.go
10
cmd/root.go
|
@ -21,7 +21,7 @@ no-code solution. With easy rules, you can perform actions over compromised pods
|
|||
func Execute() {
|
||||
err := RootCmd.Execute()
|
||||
if err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error()})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,10 @@ func init() {
|
|||
actionnersCmd.AddCommand(actionnersListCmd)
|
||||
outputsCmd.AddCommand(outputsListCmd)
|
||||
notifiersCmd.AddCommand(notifiersListCmd)
|
||||
RootCmd.PersistentFlags().StringP("config", "c", "/etc/falco-talon/config.yaml", "Falco Talon Config File")
|
||||
RootCmd.PersistentFlags().StringArrayP("rules", "r", []string{"/etc/falco-talon/rules.yaml"}, "Falco Talon Rules File")
|
||||
RootCmd.PersistentFlags().StringArrayP("rules", "r", []string{}, "Falco Talon Rules File")
|
||||
serverCmd.Flags().StringP("config", "c", "/etc/falco-talon/config.yaml", "Falco Talon Config File")
|
||||
rulesCmd.PersistentFlags().StringP("config", "c", "", "Falco Talon Config File")
|
||||
actionnersCmd.PersistentFlags().StringP("config", "c", "", "Falco Talon Config File")
|
||||
outputsCmd.PersistentFlags().StringP("config", "c", "", "Falco Talon Config File")
|
||||
notifiersCmd.PersistentFlags().StringP("config", "c", "", "Falco Talon Config File")
|
||||
}
|
||||
|
|
24
cmd/rules.go
24
cmd/rules.go
|
@ -34,7 +34,7 @@ var rulesChecksCmd = &cobra.Command{
|
|||
}
|
||||
rules := ruleengine.ParseRules(config.RulesFiles)
|
||||
if rules == nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
}
|
||||
defaultActionners := actionners.ListDefaultActionners()
|
||||
defaultOutputs := outputs.ListDefaultOutputs()
|
||||
|
@ -45,36 +45,36 @@ var rulesChecksCmd = &cobra.Command{
|
|||
for _, j := range i.GetActions() {
|
||||
actionner := defaultActionners.FindActionner(j.GetActionner())
|
||||
if actionner == nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "unknown actionner", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "unknown actionner", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
continue
|
||||
}
|
||||
if err := actionner.CheckParameters(j); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
o := j.GetOutput()
|
||||
if o == nil && actionner.Information().RequireOutput {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
if actionner != nil {
|
||||
o := j.GetOutput()
|
||||
if o == nil && actionner.Information().RequireOutput {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
if o != nil {
|
||||
output := defaultOutputs.FindOutput(o.GetTarget())
|
||||
if output == nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "unknown target", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "unknown target", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
} else if len(o.Parameters) == 0 {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "missing parameters for the output", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "missing parameters for the output", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
} else {
|
||||
if err := output.CheckParameters(o); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
@ -84,9 +84,9 @@ var rulesChecksCmd = &cobra.Command{
|
|||
}
|
||||
}
|
||||
if !valid {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
}
|
||||
utils.PrintLog("info", utils.LogLine{Result: "rules file valid", Message: "rules"})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Result: "rules file valid", Message: "rules"})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ var rulesPrintCmd = &cobra.Command{
|
|||
}
|
||||
rules := ruleengine.ParseRules(config.RulesFiles)
|
||||
if rules == nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
}
|
||||
type yamlFile struct {
|
||||
Name string `yaml:"rule"`
|
||||
|
@ -136,7 +136,7 @@ var rulesPrintCmd = &cobra.Command{
|
|||
|
||||
var q []yamlFile
|
||||
if err := copier.Copy(&q, &rules); err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error()})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error()})
|
||||
}
|
||||
|
||||
b, _ := yaml.Marshal(q)
|
||||
|
|
|
@ -40,7 +40,7 @@ var serverCmd = &cobra.Command{
|
|||
}
|
||||
rules := ruleengine.ParseRules(config.RulesFiles)
|
||||
if rules == nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
}
|
||||
|
||||
defaultActionners := actionners.ListDefaultActionners()
|
||||
|
@ -52,31 +52,31 @@ var serverCmd = &cobra.Command{
|
|||
for _, j := range i.GetActions() {
|
||||
actionner := defaultActionners.FindActionner(j.GetActionner())
|
||||
if actionner == nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "unknown actionner", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "unknown actionner", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
} else {
|
||||
if err := actionner.CheckParameters(j); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
if actionner != nil {
|
||||
o := j.GetOutput()
|
||||
if o == nil && actionner.Information().RequireOutput {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
if o != nil {
|
||||
output := defaultOutputs.FindOutput(o.GetTarget())
|
||||
if output == nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "unknown target", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "unknown target", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
} else if len(o.Parameters) == 0 {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "missing parameters for the output", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "missing parameters for the output", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
} else {
|
||||
if err := output.CheckParameters(o); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
@ -86,28 +86,28 @@ var serverCmd = &cobra.Command{
|
|||
}
|
||||
}
|
||||
if !valid {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
}
|
||||
|
||||
// init actionners
|
||||
if err := actionners.Init(); err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error(), Message: "actionners"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error(), Message: "actionners"})
|
||||
}
|
||||
|
||||
// init outputs
|
||||
if err := outputs.Init(); err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error(), Message: "outputs"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error(), Message: "outputs"})
|
||||
}
|
||||
|
||||
// init notifiers
|
||||
notifiers.Init()
|
||||
|
||||
if rules != nil {
|
||||
utils.PrintLog("info", utils.LogLine{Result: fmt.Sprintf("%v rule(s) has/have been successfully loaded", len(*rules)), Message: "init"})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Result: fmt.Sprintf("%v rule(s) has/have been successfully loaded", len(*rules)), Message: "init"})
|
||||
}
|
||||
|
||||
if config.WatchRules {
|
||||
utils.PrintLog("info", utils.LogLine{Result: "watch of rules enabled", Message: "init"})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Result: "watch of rules enabled", Message: "init"})
|
||||
}
|
||||
|
||||
srv := http.Server{
|
||||
|
@ -122,13 +122,13 @@ var serverCmd = &cobra.Command{
|
|||
ignore := false
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
return
|
||||
}
|
||||
defer watcher.Close()
|
||||
for _, i := range config.RulesFiles {
|
||||
if err := watcher.Add(i); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -141,10 +141,10 @@ var serverCmd = &cobra.Command{
|
|||
time.Sleep(1 * time.Second)
|
||||
ignore = false
|
||||
}()
|
||||
utils.PrintLog("info", utils.LogLine{Result: "changes detected", Message: "rules"})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Result: "changes detected", Message: "rules"})
|
||||
newRules := ruleengine.ParseRules(config.RulesFiles)
|
||||
if newRules == nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -160,46 +160,46 @@ var serverCmd = &cobra.Command{
|
|||
break
|
||||
}
|
||||
if err := actionner.CheckParameters(j); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Rule: i.GetName(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Rule: i.GetName(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
o := j.GetOutput()
|
||||
if o == nil && actionner.Information().RequireOutput {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "an output is required", Rule: i.GetName(), Action: j.GetName(), Actionner: j.GetActionner(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
if o != nil {
|
||||
output := defaultOutputs.FindOutput(o.GetTarget())
|
||||
if output == nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "unknown target", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "unknown target", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
if len(o.Parameters) == 0 {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "missing parameters for the output", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "missing parameters for the output", Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
if err := output.CheckParameters(o); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Rule: i.GetName(), Action: j.GetName(), OutputTarget: o.GetTarget(), Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "invalid rules", Message: "rules"})
|
||||
break
|
||||
}
|
||||
utils.PrintLog("info", utils.LogLine{Result: fmt.Sprintf("%v rules have been successfully loaded", len(*rules)), Message: "rules"})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Result: fmt.Sprintf("%v rules have been successfully loaded", len(*rules)), Message: "rules"})
|
||||
rules = newRules
|
||||
if err := actionners.Init(); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Message: "actionners"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Message: "actionners"})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case err := <-watcher.Errors:
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@ -207,7 +207,7 @@ var serverCmd = &cobra.Command{
|
|||
// start the local NATS
|
||||
ns, err := nats.StartServer(config.Deduplication.TimeWindowSeconds)
|
||||
if err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error(), Message: "nats"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error(), Message: "nats"})
|
||||
}
|
||||
defer ns.Shutdown()
|
||||
|
||||
|
@ -216,21 +216,21 @@ var serverCmd = &cobra.Command{
|
|||
go func() {
|
||||
err2 := k8s.Init()
|
||||
if err2 != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err2.Error(), Message: "lease"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err2.Error(), Message: "lease"})
|
||||
}
|
||||
c, err2 := k8s.GetClient().GetLeaseHolder()
|
||||
if err2 != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err2.Error(), Message: "lease"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err2.Error(), Message: "lease"})
|
||||
}
|
||||
for {
|
||||
s := <-c
|
||||
if s == *utils.GetLocalIP() {
|
||||
s = "127.0.0.1"
|
||||
}
|
||||
utils.PrintLog("info", utils.LogLine{Result: fmt.Sprintf("new leader detected '%v'", s), Message: "nats"})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Result: fmt.Sprintf("new leader detected '%v'", s), Message: "nats"})
|
||||
err2 = nats.GetPublisher().SetJetStreamContext("nats://" + s + ":4222")
|
||||
if err2 != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err2.Error(), Message: "nats"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err2.Error(), Message: "nats"})
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@ -240,27 +240,27 @@ var serverCmd = &cobra.Command{
|
|||
c, err := nats.GetConsumer().ConsumeMsg()
|
||||
|
||||
if err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error(), Message: "nats"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error(), Message: "nats"})
|
||||
}
|
||||
go actionners.StartConsumer(c)
|
||||
|
||||
utils.PrintLog("info", utils.LogLine{Result: fmt.Sprintf("Falco Talon is up and listening on %s:%d", config.ListenAddress, config.ListenPort), Message: "http"})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Result: fmt.Sprintf("Falco Talon is up and listening on %s:%d", config.ListenAddress, config.ListenPort), Message: "http"})
|
||||
|
||||
ctx := context.Background()
|
||||
otelShutdown, err := traces.SetupOTelSDK(ctx)
|
||||
if err != nil {
|
||||
utils.PrintLog("warn", utils.LogLine{Error: err.Error(), Message: "otel-traces"})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Error: err.Error(), Message: "otel-traces"})
|
||||
}
|
||||
defer func() {
|
||||
if err := otelShutdown(ctx); err != nil {
|
||||
utils.PrintLog("warn", utils.LogLine{Error: err.Error(), Message: "otel-traces"})
|
||||
utils.PrintLog(utils.WarningStr, utils.LogLine{Error: err.Error(), Message: "otel-traces"})
|
||||
}
|
||||
}()
|
||||
|
||||
metrics.Init()
|
||||
|
||||
if err := srv.ListenAndServe(); err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error(), Message: "http"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error(), Message: "http"})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -35,19 +35,20 @@ type Otel struct {
|
|||
}
|
||||
|
||||
type Configuration struct {
|
||||
Notifiers map[string]map[string]any `mapstructure:"notifiers"`
|
||||
AwsConfig AwsConfig `mapstructure:"aws"`
|
||||
LogFormat string `mapstructure:"log_format"`
|
||||
KubeConfig string `mapstructure:"kubeconfig"`
|
||||
ListenAddress string `mapstructure:"listen_address"`
|
||||
MinioConfig MinioConfig `mapstructure:"minio"`
|
||||
RulesFiles []string `mapstructure:"rules_files"`
|
||||
DefaultNotifiers []string `mapstructure:"default_notifiers"`
|
||||
Otel Otel `mapstructure:"otel"`
|
||||
Deduplication deduplication `mapstructure:"deduplication"`
|
||||
ListenPort int `mapstructure:"listen_port"`
|
||||
WatchRules bool `mapstructure:"watch_rules"`
|
||||
PrintAllEvents bool `mapstructure:"print_all_events"`
|
||||
Notifiers map[string]map[string]interface{} `mapstructure:"notifiers"`
|
||||
AwsConfig AwsConfig `mapstructure:"aws"`
|
||||
GcpConfig GcpConfig `mapstructure:"gcp"`
|
||||
LogFormat string `mapstructure:"log_format"`
|
||||
KubeConfig string `mapstructure:"kubeconfig"`
|
||||
ListenAddress string `mapstructure:"listen_address"`
|
||||
MinioConfig MinioConfig `mapstructure:"minio"`
|
||||
RulesFiles []string `mapstructure:"rules_files"`
|
||||
DefaultNotifiers []string `mapstructure:"default_notifiers"`
|
||||
Otel Otel `mapstructure:"otel"`
|
||||
Deduplication deduplication `mapstructure:"deduplication"`
|
||||
ListenPort int `mapstructure:"listen_port"`
|
||||
WatchRules bool `mapstructure:"watch_rules"`
|
||||
PrintAllEvents bool `mapstructure:"print_all_events"`
|
||||
}
|
||||
|
||||
type deduplication struct {
|
||||
|
@ -63,6 +64,11 @@ type AwsConfig struct {
|
|||
ExternalID string `mapstructure:"external_id"`
|
||||
}
|
||||
|
||||
type GcpConfig struct {
|
||||
Region string `mapstructure:"region"`
|
||||
CredentialsPath string `mapstructure:"credentials_path"`
|
||||
}
|
||||
|
||||
type MinioConfig struct {
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
AccessKey string `mapstructure:"access_key"`
|
||||
|
@ -101,12 +107,12 @@ func CreateConfiguration(configFile string) *Configuration {
|
|||
v.SetConfigFile(configFile)
|
||||
err := v.ReadInConfig()
|
||||
if err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: fmt.Sprintf("error when reading config file: '%v'", err.Error()), Message: "config"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: fmt.Sprintf("error when reading config file: '%v'", err.Error()), Message: "config"})
|
||||
}
|
||||
}
|
||||
|
||||
if err := v.Unmarshal(config); err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: fmt.Sprintf("error unmarshalling config file: '%v'", err.Error()), Message: "config"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: fmt.Sprintf("error unmarshalling config file: '%v'", err.Error()), Message: "config"})
|
||||
}
|
||||
|
||||
return config
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
# Change Log
|
||||
|
||||
This file documents all notable changes to Falco Talon Helm Chart. The release
|
||||
numbering uses [semantic versioning](http://semver.org).
|
||||
|
||||
## 0.1.1 - 2024-10-01
|
||||
|
||||
- Use version `0.1.1`
|
||||
- Fix wrong port for the `serviceMonitor`
|
||||
|
||||
## 0.1.0 - 2024-09-05
|
||||
|
||||
- First release
|
|
@ -1,16 +0,0 @@
|
|||
apiVersion: v1
|
||||
appVersion: 0.1.1
|
||||
description: React to the events from Falco
|
||||
name: falco-talon
|
||||
version: 0.1.1
|
||||
keywords:
|
||||
- falco
|
||||
- monitoring
|
||||
- security
|
||||
- response-engine
|
||||
home: https://github.com/falcosecurity/falco-talon
|
||||
sources:
|
||||
- https://github.com/falcosecurity/falco-talon
|
||||
maintainers:
|
||||
- name: Issif
|
||||
email: issif+github@gadz.org
|
|
@ -1,61 +0,0 @@
|
|||
# Falco Talon
|
||||
|
||||
   
|
||||
|
||||
## Description
|
||||
|
||||
`Falco Talon` is a Response Engine for managing threats in your Kubernetes. It enhances the solutions proposed by the Falco community with a no-code tailor made solution. With easy rules, you can react to `events` from [`Falco`](https://falco.org) in milliseconds.
|
||||
|
||||
## Architecture
|
||||
|
||||
`Falco Talon` can receive the `events` from [`Falco`](https://falco.org) or [`Falcosidekick`](https://github.com/falco-talon/falcosidekick):
|
||||
|
||||
## Documentation
|
||||
|
||||
The full documentation is available on its own website: [https://docs.falco-talon.org/docs](https://docs.falco-talon.org/docs).
|
||||
|
||||
## Helm
|
||||
|
||||
The helm chart is available in the folder [`deployment/helm`](https://github.com/falcosecurity/falco-talon/tree/main/deployment/helm).
|
||||
|
||||
Two config files are provided:
|
||||
* `values.yaml` allows you to configure `Falcon Talon` and the deployment
|
||||
* `rules.yaml` contains rules to set
|
||||
|
||||
### Install Falco Talon
|
||||
|
||||
```shell
|
||||
git clone https://github.com/falcosecurity/falco-talon.git
|
||||
cd deployment/helm/
|
||||
helm upgrade -i falco-talon . -n falco --create-namespace -f values.yaml
|
||||
```
|
||||
|
||||
### Uninstall Falco Talon
|
||||
|
||||
```
|
||||
helm delete falco-talon -n falco
|
||||
````
|
||||
|
||||
### Configuration
|
||||
|
||||
{{ template "chart.valuesSection" . }}
|
||||
|
||||
## Configure Falcosidekick
|
||||
|
||||
Once you have installed `Falco Talon` with Helm, you need to connect `Falcosidekick` by adding the flag `--set falcosidekick.config.webhook.address=http://falco-talon:2803`
|
||||
|
||||
```shell
|
||||
helm upgrade -i falco falco-talon/falco --namespace falco \
|
||||
--create-namespace \
|
||||
--set tty=true \
|
||||
--set falcosidekick.enabled=true \
|
||||
--set falcosidekick.config.talon.address=http://falco-talon:2803
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Falco Talon is licensed to you under the [Apache 2.0](./LICENSE) open source license.
|
||||
|
||||
## Author
|
||||
|
||||
Thomas Labarussias (https://github.com/Issif)
|
|
@ -1,120 +0,0 @@
|
|||
# falco-talon
|
||||
|
||||
 
|
||||
|
||||
React to the events from Falco
|
||||
|
||||
**Homepage:** <https://github.com/falcosecurity/falco-talon>
|
||||
|
||||
## Maintainers
|
||||
|
||||
| Name | Email | Url |
|
||||
| ---- | ------ | --- |
|
||||
| Issif | <issif+github@gadz.org> | |
|
||||
|
||||
## Source Code
|
||||
|
||||
* <https://github.com/falcosecurity/falco-talon>
|
||||
|
||||
## Values
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| affinity | object | `{}` | affinity |
|
||||
| config | object | `{"aws":{"accesKey":"","externalId":"","region":"","roleArn":"","secretKey":""},"deduplication":{"leaderElection":true,"timeWindowSeconds":5},"defaultNotifiers":["k8sevents"],"listenAddress":"0.0.0.0","listenPort":2803,"minio":{"accessKey":"","endpoint":"","secretKey":"","useSsl":false},"notifiers":{"elasticsearch":{"createIndexTemplate":true,"numberOfReplicas":1,"numberOfShards":1,"url":""},"loki":{"apiKey":"","customHeaders":[],"hostPort":"","tenant":"","user":""},"slack":{"footer":"https://github.com/falcosecurity/falco-talon","format":"long","icon":"https://upload.wikimedia.org/wikipedia/commons/2/26/Circaetus_gallicus_claw.jpg","username":"Falco Talon","webhookUrl":""},"smtp":{"format":"html","from":"","hostPort":"","password":"","tls":false,"to":"","user":""},"webhook":{"url":""}},"otel":{"collectorEndpoint":"","collectorPort":4317,"collectorUseInsecureGrpc":false,"metricsEnabled":false,"tracesEnabled":false},"printAllEvents":false,"rulesFiles":["rules.yaml","rules_override.yaml"],"watchRules":true}` | config of Falco Talon (See https://docs.falco-talon.org/docs/configuration/) |
|
||||
| config.aws | object | `{"accesKey":"","externalId":"","region":"","roleArn":"","secretKey":""}` | aws |
|
||||
| config.aws.accesKey | string | `""` | access key (if not specified, default access_key from provider credential chain will be used) |
|
||||
| config.aws.externalId | string | `""` | external id |
|
||||
| config.aws.region | string | `""` | region (if not specified, default region from provider credential chain will be used) |
|
||||
| config.aws.roleArn | string | `""` | role arn |
|
||||
| config.aws.secretKey | string | `""` | secret key (if not specified, default secret_key from provider credential chain will be used) |
|
||||
| config.deduplication | object | `{"leaderElection":true,"timeWindowSeconds":5}` | deduplication of the Falco events |
|
||||
| config.deduplication.leaderElection | bool | `true` | enable the leader election for cluster mode |
|
||||
| config.deduplication.timeWindowSeconds | int | `5` | duration in seconds for the deduplication time window |
|
||||
| config.defaultNotifiers | list | `["k8sevents"]` | default notifiers for all rules |
|
||||
| config.listenAddress | string | `"0.0.0.0"` | listen address |
|
||||
| config.listenPort | int | `2803` | listen port |
|
||||
| config.minio | object | `{"accessKey":"","endpoint":"","secretKey":"","useSsl":false}` | minio |
|
||||
| config.minio.accessKey | string | `""` | access key |
|
||||
| config.minio.endpoint | string | `""` | endpoint |
|
||||
| config.minio.secretKey | string | `""` | secret key |
|
||||
| config.minio.useSsl | bool | `false` | use ssl |
|
||||
| config.notifiers | object | `{"elasticsearch":{"createIndexTemplate":true,"numberOfReplicas":1,"numberOfShards":1,"url":""},"loki":{"apiKey":"","customHeaders":[],"hostPort":"","tenant":"","user":""},"slack":{"footer":"https://github.com/falcosecurity/falco-talon","format":"long","icon":"https://upload.wikimedia.org/wikipedia/commons/2/26/Circaetus_gallicus_claw.jpg","username":"Falco Talon","webhookUrl":""},"smtp":{"format":"html","from":"","hostPort":"","password":"","tls":false,"to":"","user":""},"webhook":{"url":""}}` | notifiers (See https://docs.falco-talon.org/docs/notifiers/list/ for the settings) |
|
||||
| config.notifiers.elasticsearch | object | `{"createIndexTemplate":true,"numberOfReplicas":1,"numberOfShards":1,"url":""}` | elasticsearch |
|
||||
| config.notifiers.elasticsearch.createIndexTemplate | bool | `true` | create the index template |
|
||||
| config.notifiers.elasticsearch.numberOfReplicas | int | `1` | number of replicas |
|
||||
| config.notifiers.elasticsearch.numberOfShards | int | `1` | number of shards |
|
||||
| config.notifiers.elasticsearch.url | string | `""` | url |
|
||||
| config.notifiers.loki | object | `{"apiKey":"","customHeaders":[],"hostPort":"","tenant":"","user":""}` | loki |
|
||||
| config.notifiers.loki.apiKey | string | `""` | api key |
|
||||
| config.notifiers.loki.customHeaders | list | `[]` | custom headers |
|
||||
| config.notifiers.loki.hostPort | string | `""` | host:port |
|
||||
| config.notifiers.loki.tenant | string | `""` | tenant |
|
||||
| config.notifiers.loki.user | string | `""` | user |
|
||||
| config.notifiers.slack | object | `{"footer":"https://github.com/falcosecurity/falco-talon","format":"long","icon":"https://upload.wikimedia.org/wikipedia/commons/2/26/Circaetus_gallicus_claw.jpg","username":"Falco Talon","webhookUrl":""}` | slack |
|
||||
| config.notifiers.slack.footer | string | `"https://github.com/falcosecurity/falco-talon"` | footer |
|
||||
| config.notifiers.slack.format | string | `"long"` | format |
|
||||
| config.notifiers.slack.icon | string | `"https://upload.wikimedia.org/wikipedia/commons/2/26/Circaetus_gallicus_claw.jpg"` | icon |
|
||||
| config.notifiers.slack.username | string | `"Falco Talon"` | username |
|
||||
| config.notifiers.slack.webhookUrl | string | `""` | webhook url |
|
||||
| config.notifiers.smtp | object | `{"format":"html","from":"","hostPort":"","password":"","tls":false,"to":"","user":""}` | smtp |
|
||||
| config.notifiers.smtp.format | string | `"html"` | format |
|
||||
| config.notifiers.smtp.from | string | `""` | from |
|
||||
| config.notifiers.smtp.hostPort | string | `""` | host:port |
|
||||
| config.notifiers.smtp.password | string | `""` | password |
|
||||
| config.notifiers.smtp.tls | bool | `false` | enable tls |
|
||||
| config.notifiers.smtp.to | string | `""` | to |
|
||||
| config.notifiers.smtp.user | string | `""` | user |
|
||||
| config.notifiers.webhook | object | `{"url":""}` | webhook |
|
||||
| config.notifiers.webhook.url | string | `""` | url |
|
||||
| config.otel | object | `{"collectorEndpoint":"","collectorPort":4317,"collectorUseInsecureGrpc":false,"metricsEnabled":false,"tracesEnabled":false}` | open telemetry parameters |
|
||||
| config.otel.collectorEndpoint | string | `""` | collector endpoint |
|
||||
| config.otel.collectorPort | int | `4317` | collector port |
|
||||
| config.otel.collectorUseInsecureGrpc | bool | `false` | use insecure grpc |
|
||||
| config.otel.metricsEnabled | bool | `false` | enable otel metrics |
|
||||
| config.otel.tracesEnabled | bool | `false` | enable otel traces |
|
||||
| config.printAllEvents | bool | `false` | print in stdout all received events, not only those which match a rule |
|
||||
| config.rulesFiles | list | `["rules.yaml","rules_override.yaml"]` | list of rules to load |
|
||||
| config.watchRules | bool | `true` | auto reload the rules when the files change |
|
||||
| extraEnv | list | `[{"name":"LOG_LEVEL","value":"warning"}]` | extra env |
|
||||
| image | object | `{"pullPolicy":"Always","registry":"falco.docker.scarf.sh","repository":"issif/falco-talon","tag":""}` | image parameters |
|
||||
| image.pullPolicy | string | `"Always"` | The image pull policy |
|
||||
| image.registry | string | `"falco.docker.scarf.sh"` | The image registry to pull from |
|
||||
| image.repository | string | `"issif/falco-talon"` | The image repository to pull from |
|
||||
| image.tag | string | `""` | Override the image tag to pull |
|
||||
| imagePullSecrets | list | `[]` | one or more secrets to be used when pulling images |
|
||||
| ingress | object | `{"annotations":{},"enabled":false,"hosts":[{"host":"falco-talon.local","paths":[{"path":"/"}]}],"tls":[]}` | ingress parameters |
|
||||
| ingress.annotations | object | `{}` | annotations of the ingress |
|
||||
| ingress.enabled | bool | `false` | enable the ingress |
|
||||
| ingress.hosts | list | `[{"host":"falco-talon.local","paths":[{"path":"/"}]}]` | hosts |
|
||||
| ingress.tls | list | `[]` | tls |
|
||||
| nameOverride | string | `""` | override name |
|
||||
| nodeSelector | object | `{}` | node selector |
|
||||
| podAnnotations | object | `{}` | pod annotations |
|
||||
| podSecurityContext | object | `{"fsGroup":1234,"runAsUser":1234}` | pod security context |
|
||||
| podSecurityContext.fsGroup | int | `1234` | group |
|
||||
| podSecurityContext.runAsUser | int | `1234` | user id |
|
||||
| podSecurityPolicy | object | `{"create":false}` | pod security policy |
|
||||
| podSecurityPolicy.create | bool | `false` | enable the creation of the PSP |
|
||||
| priorityClassName | string | `""` | priority class name |
|
||||
| rbac | object | `{"caliconetworkpolicies":["get","update","patch","create"],"ciliumnetworkpolicies":["get","update","patch","create"],"clusterroles":["get","delete"],"configmaps":["get","delete"],"daemonsets":["get","delete"],"deployments":["get","delete"],"events":["get","update","patch","create"],"leases":["get","update","patch","watch","create"],"namespaces":["get","delete"],"networkpolicies":["get","update","patch","create"],"nodes":["get","update","patch","watch","create"],"pods":["get","update","patch","delete","list"],"podsEphemeralcontainers":["patch","create"],"podsEviction":["get","create"],"podsExec":["get","create"],"podsLog":["get"],"replicasets":["get","delete"],"roles":["get","delete"],"secrets":["get","delete"],"statefulsets":["get","delete"]}` | rbac |
|
||||
| replicaCount | int | `2` | number of running pods |
|
||||
| resources | object | `{}` | resources |
|
||||
| service | object | `{"annotations":{},"port":2803,"type":"ClusterIP"}` | service parameters |
|
||||
| service.annotations | object | `{}` | annotations of the service |
|
||||
| service.port | int | `2803` | port of the service |
|
||||
| service.type | string | `"ClusterIP"` | type of service |
|
||||
| serviceMonitor | object | `{"additionalLabels":{},"enabled":false,"interval":"30s","path":"/metrics","relabelings":[],"scheme":"http","scrapeTimeout":"10s","targetLabels":[],"tlsConfig":{}}` | serviceMonitor holds the configuration for the ServiceMonitor CRD. |
|
||||
| serviceMonitor.additionalLabels | object | `{}` | additionalLabels specifies labels to be added on the Service Monitor. |
|
||||
| serviceMonitor.enabled | bool | `false` | enable the deployment of a Service Monitor for the Prometheus Operator. |
|
||||
| serviceMonitor.interval | string | `"30s"` | interval specifies the time interval at which Prometheus should scrape metrics from the service. |
|
||||
| serviceMonitor.path | string | `"/metrics"` | path at which the metrics are expose |
|
||||
| serviceMonitor.relabelings | list | `[]` | relabelings configures the relabeling rules to apply the target’s metadata labels. |
|
||||
| serviceMonitor.scheme | string | `"http"` | scheme specifies network protocol used by the metrics endpoint. In this case HTTP. |
|
||||
| serviceMonitor.scrapeTimeout | string | `"10s"` | scrapeTimeout determines the maximum time Prometheus should wait for a target to respond to a scrape request. If the target does not respond within the specified timeout, Prometheus considers the scrape as failed for that target. |
|
||||
| serviceMonitor.targetLabels | list | `[]` | targetLabels defines the labels which are transferred from the associated Kubernetes service object onto the ingested metrics. |
|
||||
| serviceMonitor.tlsConfig | object | `{}` | tlsConfig specifies TLS (Transport Layer Security) configuration for secure communication when scraping metrics from a service. It allows you to define the details of the TLS connection, such as CA certificate, client certificate, and client key. Currently, the k8s-metacollector does not support TLS configuration for the metrics endpoint. |
|
||||
| tolerations | list | `[]` | tolerations |
|
||||
|
||||
----------------------------------------------
|
||||
Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
|
|
@ -1,30 +0,0 @@
|
|||
- action: Terminate Pod
|
||||
actionner: kubernetes:terminate
|
||||
|
||||
- action: Disable outbound connections with Calico
|
||||
actionner: calico:networkpolicy
|
||||
|
||||
- action: Label Pod as Suspicious
|
||||
actionner: kubernetes:label
|
||||
parameters:
|
||||
labels:
|
||||
suspicious: "true"
|
||||
|
||||
- rule: Suspicious outbound connection
|
||||
match:
|
||||
rules:
|
||||
- Outbound Connection to Suspicious IPs
|
||||
actions:
|
||||
- action: Disable outbound connections with Calico
|
||||
- action: Terminate Pod
|
||||
parameters:
|
||||
grace_period_seconds: 20
|
||||
|
||||
- rule: Terminal shell in container
|
||||
match:
|
||||
rules:
|
||||
- Terminal shell in container
|
||||
output_fields:
|
||||
- k8s.ns.name!=kube-system, k8s.ns.name!=falco
|
||||
actions:
|
||||
- action: Label Pod as Suspicious
|
|
@ -1,6 +0,0 @@
|
|||
- action: Terminate Pod
|
||||
actionner: kubernetes:terminate
|
||||
parameters:
|
||||
ignore_daemonsets: true
|
||||
ignore_statefulsets: true
|
||||
grace_period_seconds: 2
|
|
@ -1,64 +0,0 @@
|
|||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "falco-talon.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "falco-talon.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for ingress.
|
||||
*/}}
|
||||
{{- define "falco-talon.ingress.apiVersion" -}}
|
||||
{{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) -}}
|
||||
{{- print "networking.k8s.io/v1" -}}
|
||||
{{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}}
|
||||
{{- print "networking.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "extensions/v1beta1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "falco-talon.labels" -}}
|
||||
helm.sh/chart: {{ include "falco-talon.chart" . }}
|
||||
app.kubernetes.io/part-of: {{ include "falco-talon.name" . }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Name }}
|
||||
{{ include "falco-talon.selectorLabels" . }}
|
||||
{{- if .Values.image.tag }}
|
||||
app.kubernetes.io/version: {{ .Values.image.tag }}
|
||||
{{- else }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "falco-talon.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "falco-talon.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return if ingress is stable.
|
||||
*/}}
|
||||
{{- define "falco-talon.ingress.isStable" -}}
|
||||
{{- eq (include "falco-talon.ingress.apiVersion" .) "networking.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return if ingress supports pathType.
|
||||
*/}}
|
||||
{{- define "falco-talon.ingress.supportsPathType" -}}
|
||||
{{- or (eq (include "falco-talon.ingress.isStable" .) "true") (and (eq (include "falco-talon.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}}
|
||||
{{- end -}}
|
|
@ -1,18 +0,0 @@
|
|||
{{- if .Values.podSecurityPolicy.create }}
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ template "falco-talon.name" .}}
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- policy
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
- {{ template "falco-talon.name" . }}
|
||||
verbs:
|
||||
- use
|
||||
{{- end }}
|
|
@ -1,12 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "falco-talon.name" . }}-rules
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
data:
|
||||
rules.yaml: |-
|
||||
{{- range $file := .Values.config.rulesFiles -}}
|
||||
{{ $fileContent := $.Files.Get . }}
|
||||
{{- $fileContent | nindent 4 -}}
|
||||
{{- end -}}
|
|
@ -1,94 +0,0 @@
|
|||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ include "falco-talon.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 8 }}
|
||||
{{- if .Values.podAnnotations }}
|
||||
{{ toYaml .Values.podAnnotations | indent 8 }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
timestamp: {{ now }}
|
||||
spec:
|
||||
serviceAccountName: {{ include "falco-talon.name" . }}
|
||||
{{- if .Values.priorityClassName }}
|
||||
priorityClassName: "{{ .Values.priorityClassName }}"
|
||||
{{- end }}
|
||||
securityContext:
|
||||
runAsUser: {{ .Values.podSecurityContext.runAsUser }}
|
||||
fsGroup: {{ .Values.podSecurityContext.fsGroup }}
|
||||
restartPolicy: Always
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
{{- if .Values.image.registry }}
|
||||
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}"
|
||||
{{- else }}
|
||||
image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}"
|
||||
{{- end }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
args: ["server", "-c", "/etc/falco-talon/config.yaml", "-r", "/etc/falco-talon/rules.yaml"]
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 2803
|
||||
protocol: TCP
|
||||
- name: nats
|
||||
containerPort: 4222
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
{{- if .Values.extraEnv }}
|
||||
env:
|
||||
{{- toYaml .Values.extraEnv | nindent 12 }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: "config"
|
||||
mountPath: "/etc/falco-talon/config.yaml"
|
||||
subPath: config.yaml
|
||||
readOnly: true
|
||||
- name: "rules"
|
||||
mountPath: "/etc/falco-talon/rules.yaml"
|
||||
subPath: rules.yaml
|
||||
readOnly: true
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: "rules"
|
||||
configMap:
|
||||
name: "{{ include "falco-talon.name" . }}-rules"
|
||||
- name: "config"
|
||||
secret:
|
||||
secretName: "{{ include "falco-talon.name" . }}-config"
|
|
@ -1,50 +0,0 @@
|
|||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $name := include "falco-talon.name" . -}}
|
||||
{{- $ingressApiIsStable := eq (include "falco-talon.ingress.isStable" .) "true" -}}
|
||||
{{- $ingressSupportsPathType := eq (include "falco-talon.ingress.supportsPathType" .) "true" -}}
|
||||
---
|
||||
apiVersion: {{ include "falco-talon.ingress.apiVersion" . }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $name }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if $ingressSupportsPathType }}
|
||||
pathType: {{ default "ImplementationSpecific" .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if $ingressApiIsStable }}
|
||||
service:
|
||||
name: {{ $name }}
|
||||
port:
|
||||
name: http
|
||||
{{- else }}
|
||||
serviceName: {{ $name }}
|
||||
servicePort: http
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -1,32 +0,0 @@
|
|||
{{- if .Values.podSecurityPolicy.create}}
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: {{ template "falco-talon.name" . }}
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
spec:
|
||||
privileged: false
|
||||
allowPrivilegeEscalation: false
|
||||
hostNetwork: false
|
||||
readOnlyRootFilesystem: true
|
||||
requiredDropCapabilities:
|
||||
- ALL
|
||||
fsGroup:
|
||||
ranges:
|
||||
- max: 65535
|
||||
min: 1
|
||||
rule: MustRunAs
|
||||
runAsUser:
|
||||
rule: MustRunAsNonRoot
|
||||
seLinux:
|
||||
rule: RunAsAny
|
||||
supplementalGroups:
|
||||
ranges:
|
||||
- max: 65535
|
||||
min: 1
|
||||
rule: MustRunAs
|
||||
volumes:
|
||||
- configMap
|
||||
- secret
|
||||
{{- end }}
|
|
@ -1,209 +0,0 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "falco-talon.name" . }}
|
||||
helm.sh/chart: {{ include "falco-talon.chart" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
rules:
|
||||
{{- if .Values.rbac.namespaces }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- namespaces
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.namespaces | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.pods }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.pods | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.podsEphemeralcontainers }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/ephemeralcontainers
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.podsEphemeralcontainers | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.nodes }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- nodes
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.nodes | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.podsLog }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/log
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.podsLog | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.podsExec }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/exec
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.podsExec | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.podsEviction }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/eviction
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.podsEviction | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.events }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.events | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.daemonsets }}
|
||||
- apiGroups:
|
||||
- "apps"
|
||||
resources:
|
||||
- daemonsets
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.daemonsets | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.deployments }}
|
||||
- apiGroups:
|
||||
- "apps"
|
||||
resources:
|
||||
- deployments
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.deployments | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.replicasets }}
|
||||
- apiGroups:
|
||||
- "apps"
|
||||
resources:
|
||||
- replicasets
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.replicasets | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.statefulsets }}
|
||||
- apiGroups:
|
||||
- "apps"
|
||||
resources:
|
||||
- statefulsets
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.statefulsets | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.networkpolicies }}
|
||||
- apiGroups:
|
||||
- "networking.k8s.io"
|
||||
resources:
|
||||
- networkpolicies
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.networkpolicies | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.caliconetworkpolicies }}
|
||||
- apiGroups:
|
||||
- "projectcalico.org"
|
||||
resources:
|
||||
- caliconetworkpolicies
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.caliconetworkpolicies | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.ciliumnetworkpolicies }}
|
||||
- apiGroups:
|
||||
- "cilium.io"
|
||||
resources:
|
||||
- ciliumnetworkpolicies
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.ciliumnetworkpolicies | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.roles }}
|
||||
- apiGroups:
|
||||
- "rbac.authorization.k8s.io"
|
||||
resources:
|
||||
- roles
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.roles | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.clusterroles }}
|
||||
- apiGroups:
|
||||
- "rbac.authorization.k8s.io"
|
||||
resources:
|
||||
- clusterroles
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.clusterroles | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.configmaps }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.configmaps | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.secrets }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.secrets | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.leases }}
|
||||
- apiGroups:
|
||||
- "coordination.k8s.io"
|
||||
resources:
|
||||
- leases
|
||||
verbs:
|
||||
{{ toYaml .Values.rbac.leases | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.podSecurityPolicy.create }}
|
||||
- apiGroups:
|
||||
- policy
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
- {{ template "falco-talon.name" . }}
|
||||
verbs:
|
||||
- use
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "falco-talon.name" . }}
|
||||
helm.sh/chart: {{ include "falco-talon.chart" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
|
@ -1,71 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "falco-talon.name" . }}-config
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
stringData:
|
||||
config.yaml: |
|
||||
listen_address: {{ default "0.0.0.0" .Values.config.listenAddress }}
|
||||
listen_port: {{ default 2803 .Values.config.listenPort }}
|
||||
watch_rules: {{ default true .Values.config.watchRules }}
|
||||
print_all_events: {{ default false .Values.config.printAllEvents }}
|
||||
deduplication:
|
||||
leader_election: {{ default true .Values.config.deduplication.leaderElection }}
|
||||
time_window_seconds: {{ default 5 .Values.config.deduplication.timeWindowSeconds }}
|
||||
|
||||
default_notifiers:
|
||||
{{- range .Values.config.defaultNotifiers }}
|
||||
- {{ . -}}
|
||||
{{ end }}
|
||||
|
||||
otel:
|
||||
traces_enabled: {{ default false .Values.config.otel.tracesEnabled }}
|
||||
metrics_enabled: {{ default false .Values.config.otel.metricsEnabled }}
|
||||
collector_port: {{ default 4317 .Values.config.otel.collectorPort }}
|
||||
collector_endpoint: {{ .Values.config.otel.collectorEndpoint }}
|
||||
collector_use_insecure_grpc: {{ default false .Values.config.otel.collectorUseInsecureGrpc }}
|
||||
|
||||
notifiers:
|
||||
slack:
|
||||
webhook_url: {{ .Values.config.notifiers.slack.webhookUrl }}
|
||||
icon: {{ .Values.config.notifiers.slack.icon }}
|
||||
username: {{ .Values.config.notifiers.slack.username }}
|
||||
footer: {{ .Values.config.notifiers.slack.footer }}
|
||||
format: {{ .Values.config.notifiers.slack.format }}
|
||||
webhook:
|
||||
url: {{ .Values.config.notifiers.webhook.url }}
|
||||
smtp:
|
||||
host_port: {{ .Values.config.notifiers.smtp.hostPort }}
|
||||
from: {{ .Values.config.notifiers.smtp.from }}
|
||||
to: {{ .Values.config.notifiers.smtp.to }}
|
||||
user: {{ .Values.config.notifiers.smtp.user }}
|
||||
password: {{ .Values.config.notifiers.smtp.password }}
|
||||
format: {{ .Values.config.notifiers.smtp.format }}
|
||||
tls: {{ .Values.config.notifiers.smtp.tls }}
|
||||
loki:
|
||||
url: {{ .Values.config.notifiers.loki.url }}
|
||||
user: {{ .Values.config.notifiers.loki.user }}
|
||||
api_key: {{ .Values.config.notifiers.loki.apiKey }}
|
||||
tenant: {{ .Values.config.notifiers.loki.tenant }}
|
||||
custom_headers:
|
||||
{{- range .Values.config.notifiers.loki.customHeaders }}
|
||||
- {{ . -}}
|
||||
{{ end }}
|
||||
elasticsearch:
|
||||
url: {{ .Values.config.notifiers.elasticsearch.url }}
|
||||
create_index_template: {{ .Values.config.notifiers.loki.createIndexTemplate }}
|
||||
number_of_shards: {{ .Values.config.notifiers.loki.numberOfShards }}
|
||||
number_of_replicas: {{ .Values.config.notifiers.loki.numberOfReplicas }}
|
||||
|
||||
aws:
|
||||
role_arn: {{ .Values.config.aws.roleArn }}
|
||||
external_id: {{ .Values.config.aws.externalId }}
|
||||
region: {{ .Values.config.aws.region }}
|
||||
access_key: {{ .Values.config.aws.accessKey }}
|
||||
secret_key: {{ .Values.config.aws.secretKey }}
|
||||
minio:
|
||||
endpoint: {{ .Values.config.minio.endpoint }}
|
||||
access_key: {{ .Values.config.minio.accessKey }}
|
||||
secret_key: {{ .Values.config.minio.secretKey }}
|
||||
use_ssl: {{ .Values.config.minio.useSsl }}
|
|
@ -1,44 +0,0 @@
|
|||
{{- if .Values.serviceMonitor.enabled }}
|
||||
---
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceMonitor.additionalLabels }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
endpoints:
|
||||
- port: {{ .Values.serviceMonitor.port }}
|
||||
{{- with .Values.serviceMonitor.interval }}
|
||||
interval: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.scrapeTimeout }}
|
||||
scrapeTimeout: {{ . }}
|
||||
{{- end }}
|
||||
honorLabels: true
|
||||
path: {{ .Values.serviceMonitor.path }}
|
||||
scheme: {{ .Values.serviceMonitor.scheme }}
|
||||
{{- with .Values.serviceMonitor.tlsConfig }}
|
||||
tlsConfig:
|
||||
{{- toYaml . | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.relabelings }}
|
||||
relabelings:
|
||||
{{- toYaml . | nindent 6 }}
|
||||
{{- end }}
|
||||
jobLabel: "{{ .Release.Name }}"
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "falco-talon.selectorLabels" . | nindent 6 }}
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace }}
|
||||
{{- with .Values.serviceMonitor.targetLabels }}
|
||||
targetLabels:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -1,21 +0,0 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "falco-talon.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "falco-talon.labels" . | nindent 4 }}
|
||||
{{- with .Values.service.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "falco-talon.selectorLabels" . | nindent 4 }}
|
|
@ -1,283 +0,0 @@
|
|||
# Default values for falco-talon.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
# -- number of running pods
|
||||
replicaCount: 2
|
||||
|
||||
# -- image parameters
|
||||
image:
|
||||
# -- The image registry to pull from
|
||||
registry: falco.docker.scarf.sh
|
||||
# -- The image repository to pull from
|
||||
repository: issif/falco-talon
|
||||
# -- Override the image tag to pull
|
||||
tag: ""
|
||||
# -- The image pull policy
|
||||
pullPolicy: Always
|
||||
|
||||
# -- pod security policy
|
||||
podSecurityPolicy:
|
||||
# -- enable the creation of the PSP
|
||||
create: false
|
||||
|
||||
# -- pod security context
|
||||
podSecurityContext:
|
||||
# -- user id
|
||||
runAsUser: 1234
|
||||
# -- group
|
||||
fsGroup: 1234
|
||||
|
||||
# -- one or more secrets to be used when pulling images
|
||||
imagePullSecrets: []
|
||||
# - registrySecretName
|
||||
|
||||
# -- override name
|
||||
nameOverride: ""
|
||||
|
||||
# -- extra env
|
||||
extraEnv:
|
||||
- name: LOG_LEVEL
|
||||
value: warning
|
||||
# - name: AWS_REGION # Specify if running on EKS, ECS or EC2
|
||||
# value: us-east-1
|
||||
|
||||
# -- priority class name
|
||||
priorityClassName: ""
|
||||
|
||||
# -- pod annotations
|
||||
podAnnotations: {}
|
||||
|
||||
# -- service parameters
|
||||
service:
|
||||
# -- type of service
|
||||
type: ClusterIP
|
||||
# -- port of the service
|
||||
port: 2803
|
||||
# -- annotations of the service
|
||||
annotations: {}
|
||||
# networking.gke.io/load-balancer-type: Internal
|
||||
|
||||
# -- ingress parameters
|
||||
ingress:
|
||||
# -- enable the ingress
|
||||
enabled: false
|
||||
# -- annotations of the ingress
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
# -- hosts
|
||||
hosts:
|
||||
- host: falco-talon.local
|
||||
paths:
|
||||
- path: /
|
||||
# -- pathType (e.g. ImplementationSpecific, Prefix, .. etc.)
|
||||
# pathType: Prefix
|
||||
# -- tls
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
# -- resources
|
||||
resources: {}
|
||||
# -- limits
|
||||
# limits:
|
||||
# # -- cpu limit
|
||||
# cpu: 100m
|
||||
# # -- memory limit
|
||||
# memory: 128Mi
|
||||
# -- requests
|
||||
# requests:
|
||||
# # -- cpu request
|
||||
# cpu: 100m
|
||||
# # -- memory request
|
||||
# memory: 128Mi
|
||||
|
||||
# -- node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# -- tolerations
|
||||
tolerations: []
|
||||
|
||||
# -- affinity
|
||||
affinity: {}
|
||||
|
||||
# -- rbac
|
||||
rbac:
|
||||
namespaces: ["get", "delete"]
|
||||
pods: ["get", "update", "patch", "delete", "list"]
|
||||
podsEphemeralcontainers: ["patch", "create"]
|
||||
nodes: ["get", "update", "patch", "watch", "create"]
|
||||
podsLog: ["get"]
|
||||
podsExec: ["get", "create"]
|
||||
podsEviction: ["get", "create"]
|
||||
events: ["get", "update", "patch", "create"]
|
||||
daemonsets: ["get", "delete"]
|
||||
deployments: ["get", "delete"]
|
||||
replicasets: ["get", "delete"]
|
||||
statefulsets: ["get", "delete"]
|
||||
networkpolicies: ["get", "update", "patch", "create"]
|
||||
caliconetworkpolicies: ["get", "update", "patch", "create"]
|
||||
ciliumnetworkpolicies: ["get", "update", "patch", "create"]
|
||||
roles: ["get", "delete"]
|
||||
clusterroles: ["get", "delete"]
|
||||
configmaps: ["get", "delete"]
|
||||
secrets: ["get", "delete"]
|
||||
leases: ["get", "update", "patch", "watch", "create"]
|
||||
|
||||
# -- config of Falco Talon (See https://docs.falco-talon.org/docs/configuration/)
|
||||
config:
|
||||
# -- listen address
|
||||
listenAddress: 0.0.0.0
|
||||
# -- listen port
|
||||
listenPort: 2803
|
||||
|
||||
# -- default notifiers for all rules
|
||||
defaultNotifiers:
|
||||
# - slack
|
||||
- k8sevents
|
||||
|
||||
# -- auto reload the rules when the files change
|
||||
watchRules: true
|
||||
|
||||
# -- list of rules to load
|
||||
rulesFiles: # list of locale rules files to use, they will be concatenated into a single config map
|
||||
- rules.yaml
|
||||
- rules_override.yaml
|
||||
|
||||
# -- deduplication of the Falco events
|
||||
deduplication:
|
||||
# -- enable the leader election for cluster mode
|
||||
leaderElection: true
|
||||
# -- duration in seconds for the deduplication time window
|
||||
timeWindowSeconds: 5
|
||||
|
||||
# -- print in stdout all received events, not only those which match a rule
|
||||
printAllEvents: false
|
||||
|
||||
# -- open telemetry parameters
|
||||
otel:
|
||||
# -- enable otel traces
|
||||
tracesEnabled: false
|
||||
# -- enable otel metrics
|
||||
metricsEnabled: false
|
||||
# -- collector port
|
||||
collectorPort: 4317
|
||||
# -- collector endpoint
|
||||
collectorEndpoint: ""
|
||||
# -- use insecure grpc
|
||||
collectorUseInsecureGrpc: false
|
||||
|
||||
# -- notifiers (See https://docs.falco-talon.org/docs/notifiers/list/ for the settings)
|
||||
notifiers:
|
||||
# -- slack
|
||||
slack:
|
||||
# -- webhook url
|
||||
webhookUrl: ""
|
||||
# -- icon
|
||||
icon: "https://upload.wikimedia.org/wikipedia/commons/2/26/Circaetus_gallicus_claw.jpg"
|
||||
# -- username
|
||||
username: "Falco Talon"
|
||||
# -- footer
|
||||
footer: "https://github.com/falcosecurity/falco-talon"
|
||||
# -- format
|
||||
format: "long"
|
||||
# -- webhook
|
||||
webhook:
|
||||
# -- url
|
||||
url: ""
|
||||
# -- smtp
|
||||
smtp:
|
||||
# -- host:port
|
||||
hostPort: ""
|
||||
# -- from
|
||||
from: ""
|
||||
# -- to
|
||||
to: ""
|
||||
# -- user
|
||||
user: ""
|
||||
# -- password
|
||||
password: ""
|
||||
# -- format
|
||||
format: "html"
|
||||
# -- enable tls
|
||||
tls: false
|
||||
# -- loki
|
||||
loki:
|
||||
# -- host:port
|
||||
hostPort: ""
|
||||
# -- user
|
||||
user: ""
|
||||
# -- api key
|
||||
apiKey: ""
|
||||
# -- tenant
|
||||
tenant: ""
|
||||
# -- custom headers
|
||||
customHeaders: []
|
||||
# -- elasticsearch
|
||||
elasticsearch:
|
||||
# -- url
|
||||
url: ""
|
||||
# -- create the index template
|
||||
createIndexTemplate: true
|
||||
# -- number of shards
|
||||
numberOfShards: 1
|
||||
# -- number of replicas
|
||||
numberOfReplicas: 1
|
||||
|
||||
# -- aws
|
||||
aws:
|
||||
# -- role arn
|
||||
roleArn: ""
|
||||
# -- external id
|
||||
externalId: ""
|
||||
# -- region (if not specified, default region from provider credential chain will be used)
|
||||
region: ""
|
||||
# -- access key (if not specified, default access_key from provider credential chain will be used)
|
||||
accesKey: ""
|
||||
# -- secret key (if not specified, default secret_key from provider credential chain will be used)
|
||||
secretKey: ""
|
||||
|
||||
# -- minio
|
||||
minio:
|
||||
# -- endpoint
|
||||
endpoint: ""
|
||||
# -- access key
|
||||
accessKey: ""
|
||||
# -- secret key
|
||||
secretKey: ""
|
||||
# -- use ssl
|
||||
useSsl: false
|
||||
|
||||
# -- serviceMonitor holds the configuration for the ServiceMonitor CRD.
|
||||
serviceMonitor:
|
||||
# -- enable the deployment of a Service Monitor for the Prometheus Operator.
|
||||
enabled: false
|
||||
# -- portname at which the metrics are exposed
|
||||
port: http
|
||||
# -- path at which the metrics are exposed
|
||||
path: /metrics
|
||||
# -- additionalLabels specifies labels to be added on the Service Monitor.
|
||||
additionalLabels: {}
|
||||
# -- interval specifies the time interval at which Prometheus should scrape metrics from the service.
|
||||
interval: "30s"
|
||||
# -- scheme specifies network protocol used by the metrics endpoint. In this case HTTP.
|
||||
scheme: http
|
||||
# -- scrapeTimeout determines the maximum time Prometheus should wait for a target to respond to a scrape request.
|
||||
# If the target does not respond within the specified timeout, Prometheus considers the scrape as failed for
|
||||
# that target.
|
||||
scrapeTimeout: "10s"
|
||||
# -- relabelings configures the relabeling rules to apply the target’s metadata labels.
|
||||
relabelings: []
|
||||
# -- targetLabels defines the labels which are transferred from the associated Kubernetes service object onto the ingested metrics.
|
||||
targetLabels: []
|
||||
# -- tlsConfig specifies TLS (Transport Layer Security) configuration for secure communication when
|
||||
# scraping metrics from a service. It allows you to define the details of the TLS connection, such as
|
||||
# CA certificate, client certificate, and client key. Currently, the k8s-metacollector does not support
|
||||
# TLS configuration for the metrics endpoint.
|
||||
tlsConfig: {}
|
||||
# insecureSkipVerify: false
|
||||
# caFile: /path/to/ca.crt
|
||||
# certFile: /path/to/client.crt
|
||||
# keyFile: /path/to/client.key
|
224
go.mod
224
go.mod
|
@ -1,82 +1,102 @@
|
|||
module github.com/falcosecurity/falco-talon
|
||||
|
||||
go 1.22.3
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.23.1
|
||||
toolchain go1.24.1
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.2
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.43
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.41
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17
|
||||
github.com/aws/aws-sdk-go-v2/service/lambda v1.63.2
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.65.2
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.32.2
|
||||
github.com/cilium/cilium v1.16.2
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43
|
||||
github.com/emersion/go-smtp v0.21.3
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/go-playground/validator/v10 v10.22.1
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1
|
||||
cloud.google.com/go/functions v1.19.3
|
||||
cloud.google.com/go/storage v1.50.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.37.2
|
||||
github.com/aws/aws-sdk-go-v2/config v1.30.3
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.18.3
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2
|
||||
github.com/aws/aws-sdk-go-v2/service/lambda v1.75.0
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.86.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.36.0
|
||||
github.com/cilium/cilium v1.16.8
|
||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6
|
||||
github.com/emersion/go-smtp v0.24.0
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/go-playground/validator/v10 v10.27.0
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/googleapis/gax-go/v2 v2.14.1
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/magefile/mage v1.15.0
|
||||
github.com/minio/minio-go/v7 v7.0.77
|
||||
github.com/nats-io/nats-server/v2 v2.10.21
|
||||
github.com/nats-io/nats.go v1.37.0
|
||||
github.com/projectcalico/api v0.0.0-20240708202104-e3f70b269c2c
|
||||
github.com/prometheus/client_golang v1.20.4
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0
|
||||
go.opentelemetry.io/otel v1.30.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.52.0
|
||||
go.opentelemetry.io/otel/metric v1.30.0
|
||||
go.opentelemetry.io/otel/sdk v1.30.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.30.0
|
||||
go.opentelemetry.io/otel/trace v1.30.0
|
||||
golang.org/x/text v0.19.0
|
||||
github.com/minio/minio-go/v7 v7.0.95
|
||||
github.com/nats-io/nats-server/v2 v2.11.7
|
||||
github.com/nats-io/nats.go v1.44.0
|
||||
github.com/projectcalico/api v0.0.0-20241106234619-d6b63b533e68
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/viper v1.20.1
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0
|
||||
go.opentelemetry.io/otel v1.37.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.59.1
|
||||
go.opentelemetry.io/otel/metric v1.37.0
|
||||
go.opentelemetry.io/otel/sdk v1.37.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0
|
||||
go.opentelemetry.io/otel/trace v1.37.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/text v0.28.0
|
||||
google.golang.org/api v0.215.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.31.1
|
||||
k8s.io/apimachinery v0.31.1
|
||||
k8s.io/client-go v0.31.1
|
||||
k8s.io/api v0.33.3
|
||||
k8s.io/apimachinery v0.33.3
|
||||
k8s.io/client-go v0.32.3
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/kubectl v0.31.1
|
||||
k8s.io/kubectl v0.32.3
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.18.0 // indirect
|
||||
cloud.google.com/go v0.116.0 // indirect
|
||||
cloud.google.com/go/auth v0.13.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||
cloud.google.com/go/iam v1.2.2 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.3 // indirect
|
||||
cloud.google.com/go/monitoring v1.21.2 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect
|
||||
github.com/aws/smithy-go v1.22.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.27.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.32.0 // indirect
|
||||
github.com/aws/smithy-go v1.22.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cilium/ebpf v0.16.0 // indirect
|
||||
github.com/cilium/hive v0.0.0-20241009102328-2ab688845f23 // indirect
|
||||
github.com/cilium/proxy v0.0.0-20241010085001-a4572e06b46f // indirect
|
||||
github.com/cilium/hive v0.0.0-20241122120553-e90d0875ae01 // indirect
|
||||
github.com/cilium/proxy v0.0.0-20241210133824-eaae5aca0fb9 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.13.1 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
|
@ -90,32 +110,32 @@ require (
|
|||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-tpm v0.9.5 // indirect
|
||||
github.com/google/gopacket v1.1.19 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
||||
github.com/imdario/mergo v1.0.1 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.10 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mackerelio/go-osstat v0.2.5 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/minio/crc64nvme v1.0.2 // indirect
|
||||
github.com/minio/highwayhash v1.0.3 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
|
@ -124,56 +144,66 @@ require (
|
|||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/nats-io/jwt/v2 v2.7.2 // indirect
|
||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.7.4 // indirect
|
||||
github.com/nats-io/nkeys v0.4.11 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20241025130422-66cb2e6d7274 // indirect
|
||||
github.com/philhofer/fwd v1.2.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.60.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.65.0 // indirect
|
||||
github.com/prometheus/otlptranslator v0.0.0-20250717125610-8549f4ab4f8f // indirect
|
||||
github.com/prometheus/procfs v0.17.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.5 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace // indirect
|
||||
github.com/spf13/afero v1.12.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/vishvananda/netlink v1.3.0 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
github.com/tinylib/msgp v1.3.0 // indirect
|
||||
github.com/vishvananda/netlink v1.3.1-0.20241022031324-976bd8de7d81 // indirect
|
||||
github.com/vishvananda/netns v0.0.5 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.32.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
||||
go.uber.org/dig v1.18.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/term v0.25.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
|
||||
google.golang.org/grpc v1.67.1 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
|
||||
google.golang.org/grpc v1.68.1 // indirect
|
||||
google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 // indirect
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241009153224-e386a8af8d30 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
|
|
538
go.sum
538
go.sum
|
@ -1,73 +1,108 @@
|
|||
cel.dev/expr v0.16.0 h1:yloc84fytn4zmJX2GU3TkXGsaieaV7dQ057Qs4sIG2Y=
|
||||
cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
|
||||
dario.cat/mergo v0.3.16 h1:wrt7QIfeqlABnUvmf9WpFwB0mGBwtySAJKTgCpnsbOE=
|
||||
dario.cat/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
|
||||
cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
|
||||
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
|
||||
cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs=
|
||||
cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
cloud.google.com/go/functions v1.19.3 h1:V0vCHSgFTUqKn57+PUXp1UfQY0/aMkveAw7wXeM3Lq0=
|
||||
cloud.google.com/go/functions v1.19.3/go.mod h1:nOZ34tGWMmwfiSJjoH/16+Ko5106x+1Iji29wzrBeOo=
|
||||
cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA=
|
||||
cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY=
|
||||
cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk=
|
||||
cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM=
|
||||
cloud.google.com/go/longrunning v0.6.3 h1:A2q2vuyXysRcwzqDpMMLSI6mb6o39miS52UEG/Rd2ng=
|
||||
cloud.google.com/go/longrunning v0.6.3/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
|
||||
cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU=
|
||||
cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU=
|
||||
cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6QJs=
|
||||
cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY=
|
||||
cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI=
|
||||
cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 h1:o90wcURuxekmXrtxmYWTyNla0+ZEHhud6DI1ZTxd1vI=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0/go.mod h1:6fTWu4m3jocfUZLYF5KsZC1TUfRvEjs7lM4crme/irw=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0 h1:jJKWl98inONJAr/IZrdFQUWcwUO95DLY1XMD1ZIut+g=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0/go.mod h1:l2fIqmwB+FKSfvn3bAD/0i+AXAxhIZjTK2svT/mgUXs=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op h1:+OSa/t11TFhqfrX0EOSqQBDJ0YlpmK0rDSiB19dg9M0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 h1:pT3hpW0cOHRJx8Y0DfJUEQuqPild8jRGmSFmBgvydr0=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6/go.mod h1:j/I2++U0xX+cr44QjHay4Cvxj6FUbnxrgmqN3H1jTZA=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.43 h1:p33fDDihFC390dhhuv8nOmX419wjOSDQRb+USt20RrU=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.43/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17/go.mod h1:1ZRXLdTpzdJb9fwTMXiLipENRxkGMTn1sfKexGllQCw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.21 h1:7edmS3VOBDhK00b/MwGtGglCm7hhwNYnjJs/PgFdMQE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.21/go.mod h1:Q9o5h4HoIWG8XfzxqiuK/CGUbepCJ8uTlaE3bAbxytQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.2 h1:4FMHqLfk0efmTqhXVRL5xYRqlEBNBiRI7N6w4jsEdd4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.2/go.mod h1:LWoqeWlK9OZeJxsROW2RqrSPvQHKTpp69r/iDjwsSaw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.2 h1:t7iUP9+4wdc5lt3E41huP+GvQZJD38WLsgVp4iOtAjg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.2/go.mod h1:/niFCtmuQNxqx9v8WAPq5qh7EH25U4BF6tjoyq9bObM=
|
||||
github.com/aws/aws-sdk-go-v2/service/lambda v1.63.2 h1:D80A6kILpbqo0TgZyhr5FPzBGOT0nAU7aLCtk9kQT+4=
|
||||
github.com/aws/aws-sdk-go-v2/service/lambda v1.63.2/go.mod h1:qHTP1Ag4En7u0h9MFxUtNZqx/k0HYW7GjuGkzR0nUC8=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.65.2 h1:yi8m+jepdp6foK14xXLGkYBenxnlcfJ45ka4Pg7fDSQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.65.2/go.mod h1:cB6oAuus7YXRZhWCc1wIwPywwZ1XwweNp2TVAEGYeB8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo=
|
||||
github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM=
|
||||
github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aws/aws-sdk-go-v2 v1.37.2 h1:xkW1iMYawzcmYFYEV0UCMxc8gSsjCGEhBXQkdQywVbo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.37.2/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.30.3 h1:utupeVnE3bmB221W08P0Moz1lDI3OwYa2fBtUhl7TCc=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.30.3/go.mod h1:NDGwOEBdpyZwLPlQkpKIO7frf18BW8PaCmAM9iUxQmI=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.18.3 h1:ptfyXmv+ooxzFwyuBth0yqABcjVIkjDL0iTYZBSbum8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.18.3/go.mod h1:Q43Nci++Wohb0qUh4m54sNln0dbxJw8PvQWkrwOkGOI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2 h1:nRniHAvjFJGUCl04F3WaAj7qp/rcz5Gi1OVoj5ErBkc=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2/go.mod h1:eJDFKAMHHUvv4a0Zfa7bQb//wFNUXGrbFpYRCHe2kD0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.2 h1:sPiRHLVUIIQcoVZTNwqQcdtjkqkPopyYmIX0M5ElRf4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.2/go.mod h1:ik86P3sgV+Bk7c1tBFCwI3VxMoSEwl4YkRB9xn1s340=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.2 h1:ZdzDAg075H6stMZtbD2o+PyB933M/f20e9WmCBC17wA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.2/go.mod h1:eE1IIzXG9sdZCB0pNNpMpsYTLl4YdOQD3njiVN1e/E4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.2 h1:sBpc8Ph6CpfZsEdkz/8bfg8WhKlWMCms5iWj6W/AW2U=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.2/go.mod h1:Z2lDojZB+92Wo6EKiZZmJid9pPrDJW2NNIXSlaEfVlU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.2 h1:blV3dY6WbxIVOFggfYIo2E1Q2lZoy5imS7nKgu5m6Tc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.2/go.mod h1:cBWNeLBjHJRSmXAxdS7mwiMUEgx6zup4wQ9J+/PcsRQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.2 h1:oxmDEO14NBZJbK/M8y3brhMFEIGN4j8a6Aq8eY0sqlo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.2/go.mod h1:4hH+8QCrk1uRWDPsVfsNDUup3taAjO8Dnx63au7smAU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.2 h1:0hBNFAPwecERLzkhhBY+lQKUMpXSKVv4Sxovikrioms=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.2/go.mod h1:Vcnh4KyR4imrrjGN7A2kP2v9y6EPudqoPKXtnmBliPU=
|
||||
github.com/aws/aws-sdk-go-v2/service/lambda v1.75.0 h1:8hoKtn/EgZ0bA2dQ/meHFNsalY5fuA7M3QDqnrVxPLA=
|
||||
github.com/aws/aws-sdk-go-v2/service/lambda v1.75.0/go.mod h1:YDWB9+Y6hLDGdI+S1TQIs8Fq3pu5ZF+7l2ZwF7dzhjg=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.86.0 h1:utPhv4ECQzJIUbtx7vMN4A8uZxlQ5tSt1H1toPI41h8=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.86.0/go.mod h1:1/eZYtTWazDgVl96LmGdGktHFi7prAcGCrJ9JGvBITU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.27.0 h1:j7/jTOjWeJDolPwZ/J4yZ7dUsxsWZEsxNwH5O7F8eEA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.27.0/go.mod h1:M0xdEPQtgpNT7kdAX4/vOAPkFj60hSQRb7TvW9B0iug=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.32.0 h1:ywQF2N4VjqX+Psw+jLjMmUL2g1RDHlvri3NxHA08MGI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.32.0/go.mod h1:Z+qv5Q6b7sWiclvbJyPSOT1BRVU9wfSUPaqQzZ1Xg3E=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.36.0 h1:bRP/a9llXSSgDPk7Rqn5GD/DQCGo6uk95plBFKoXt2M=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.36.0/go.mod h1:tgBsFzxwl65BWkuJ/x2EUs59bD4SfYKgikvFDJi1S58=
|
||||
github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw=
|
||||
github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cilium/cilium v1.16.2 h1:c/SMeMOp6VD6OuzNQ35dyqKFemT/T3jgSDnABFimhHA=
|
||||
github.com/cilium/cilium v1.16.2/go.mod h1:w6huXlvvCbDrOdKW1P5FXjT3JIXzEREtXbvhhMZHxKM=
|
||||
github.com/cilium/cilium v1.16.8 h1:1WXUifatYSpSz1OEn4Fh7BOra6R9wuJOXBp2AVOMqCw=
|
||||
github.com/cilium/cilium v1.16.8/go.mod h1:sMtwt0KtKFetmeEAB8Z/Wj3WwaFdkRDiqxa0sqtbK3g=
|
||||
github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
|
||||
github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
|
||||
github.com/cilium/hive v0.0.0-20241009102328-2ab688845f23 h1:RQSJdQVdxE9puF18G5RGZZi2jhBb2dtA6zI+HHMyY+Y=
|
||||
github.com/cilium/hive v0.0.0-20241009102328-2ab688845f23/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI=
|
||||
github.com/cilium/proxy v0.0.0-20241010085001-a4572e06b46f h1:mMfhIzIhJeynX7f/HjMN78+wONcFS7CsZdMqLI/t8g8=
|
||||
github.com/cilium/proxy v0.0.0-20241010085001-a4572e06b46f/go.mod h1:IRkQcAu6rRYzMd7V1EXyiHP4Mvmatx4CHnpA5OR0o6U=
|
||||
github.com/cilium/hive v0.0.0-20241122120553-e90d0875ae01 h1:eNOjtUsqu2W/nTZlInLAj+zyIg/HIQ1K7norewaxsgM=
|
||||
github.com/cilium/hive v0.0.0-20241122120553-e90d0875ae01/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI=
|
||||
github.com/cilium/proxy v0.0.0-20241210133824-eaae5aca0fb9 h1:EuilS9EXYTKh2B8HXieDVMGaEf4Hleg5uA+07bt1l8c=
|
||||
github.com/cilium/proxy v0.0.0-20241210133824-eaae5aca0fb9/go.mod h1:58Ngk9Jkge6TzFPVEsdcUQvIhtsE5fim3NMRgfrstqo=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=
|
||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -75,30 +110,35 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
|||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-smtp v0.21.3 h1:7uVwagE8iPYE48WhNsng3RRpCUpFvNl39JGNSIyGVMY=
|
||||
github.com/emersion/go-smtp v0.21.3/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
|
||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-smtp v0.24.0 h1:g6AfoF140mvW0vLNPD/LuCBLEAdlxOjIXqbIkJIS6Wk=
|
||||
github.com/emersion/go-smtp v0.24.0/go.mod h1:ZtRRkbTyp2XTHCA+BmyTFTrj8xY4I+b4McvHxCU2gsQ=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE=
|
||||
github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
|
@ -127,51 +167,76 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
|||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
|
||||
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
|
||||
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
|
||||
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
|
||||
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
|
||||
github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
|
||||
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
|
||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248=
|
||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
|
@ -182,11 +247,11 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
|
||||
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
|
||||
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
|
@ -199,8 +264,6 @@ github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2
|
|||
github.com/mackerelio/go-osstat v0.2.5/go.mod h1:atxwWF+POUZcdtR1wnsUcQxTytoHG4uhl2AKKzrOajY=
|
||||
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
|
||||
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
|
@ -213,12 +276,14 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
|
|||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/minio/crc64nvme v1.0.2 h1:6uO1UxGAD+kwqWWp7mBFsi5gAse66C4NXO8cmcVculg=
|
||||
github.com/minio/crc64nvme v1.0.2/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
|
||||
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
|
||||
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.77 h1:GaGghJRg9nwDVlNbwYjSDJT1rqltQkBFDsypWX1v3Bw=
|
||||
github.com/minio/minio-go/v7 v7.0.77/go.mod h1:AVM3IUN6WwKzmwBxVdjzhH8xq+f57JSbbvzqvUzR6eg=
|
||||
github.com/minio/minio-go/v7 v7.0.95 h1:ywOUPg+PebTMTzn9VDsoFJy32ZuARN9zhB+K3IYEvYU=
|
||||
github.com/minio/minio-go/v7 v7.0.95/go.mod h1:wOOX3uxS334vImCNRVyIDdXX9OsXDm89ToynKgqUKlo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||
|
@ -232,14 +297,14 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
|
|||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/nats-io/jwt/v2 v2.7.2 h1:SCRjfDLJ2q8naXp8YlGJJS5/yj3wGSODFYVi4nnwVMw=
|
||||
github.com/nats-io/jwt/v2 v2.7.2/go.mod h1:kB6QUmqHG6Wdrzj0KP2L+OX4xiTPBeV+NHVstFaATXU=
|
||||
github.com/nats-io/nats-server/v2 v2.10.21 h1:gfG6T06wBdI25XyY2IsauarOc2srWoFxxfsOKjrzoRA=
|
||||
github.com/nats-io/nats-server/v2 v2.10.21/go.mod h1:I1YxSAEWbXCfy0bthwvNb5X43WwIWMz7gx5ZVPDr5Rc=
|
||||
github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
|
||||
github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||
github.com/nats-io/jwt/v2 v2.7.4 h1:jXFuDDxs/GQjGDZGhNgH4tXzSUK6WQi2rsj4xmsNOtI=
|
||||
github.com/nats-io/jwt/v2 v2.7.4/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
|
||||
github.com/nats-io/nats-server/v2 v2.11.7 h1:lINWQ/Hb3cnaoHmWTjj/7WppZnaSh9C/1cD//nHCbms=
|
||||
github.com/nats-io/nats-server/v2 v2.11.7/go.mod h1:DchDPVzAsAPqhqm7VLedX0L7hjnV/SYtlmsl9F8U53s=
|
||||
github.com/nats-io/nats.go v1.44.0 h1:ECKVrDLdh/kDPV1g0gAQ+2+m2KprqZK5O/eJAyAnH2M=
|
||||
github.com/nats-io/nats.go v1.44.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
|
@ -248,101 +313,123 @@ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
|||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw=
|
||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/petermattis/goid v0.0.0-20241025130422-66cb2e6d7274 h1:qli3BGQK0tYDkSEvZ/FzZTi9ZrOX86Q6CIhKLGc489A=
|
||||
github.com/petermattis/goid v0.0.0-20241025130422-66cb2e6d7274/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
|
||||
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/projectcalico/api v0.0.0-20240708202104-e3f70b269c2c h1:eFyfeRDV94LA3tgbG2EC5W02dg3QUdltHc2jxhTQMCw=
|
||||
github.com/projectcalico/api v0.0.0-20240708202104-e3f70b269c2c/go.mod h1:9EPxrA4rUH306dCpvVsFb7IcEFt4ZSvqmfSowfb6c5U=
|
||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
||||
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
|
||||
github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/projectcalico/api v0.0.0-20241106234619-d6b63b533e68 h1:n3DP8X2uRGsUZK6lsmC4soPyLfaxKBM/yLtwmlYYlBI=
|
||||
github.com/projectcalico/api v0.0.0-20241106234619-d6b63b533e68/go.mod h1:sLX5Ne6wt7d9y5sLYgvgiAtBfW6RNd4JwNhtOdBx07w=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/otlptranslator v0.0.0-20250717125610-8549f4ab4f8f h1:QQB6SuvGZjK8kdc2YaLJpYhV8fxauOsjE6jgcL6YJ8Q=
|
||||
github.com/prometheus/otlptranslator v0.0.0-20250717125610-8549f4ab4f8f/go.mod h1:P8AwMgdD7XEr6QRUJ2QWLpiAZTgTE2UYgjlu3svompI=
|
||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
||||
github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU=
|
||||
github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace h1:9PNP1jnUjRhfmGMlkXHjYPishpcw4jpSt/V/xYY3FMA=
|
||||
github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
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=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/tinylib/msgp v1.3.0 h1:ULuf7GPooDaIlbyvgAxBV/FI7ynli6LZ1/nVUNu+0ww=
|
||||
github.com/tinylib/msgp v1.3.0/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
|
||||
github.com/vishvananda/netlink v1.3.1-0.20241022031324-976bd8de7d81 h1:9fkQcQYvtTr9ayFXuMfDMVuDt4+BYG9FwsGLnrBde0M=
|
||||
github.com/vishvananda/netlink v1.3.1-0.20241022031324-976bd8de7d81/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
|
||||
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
||||
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0 h1:WypxHH02KX2poqqbaadmkMYalGyy/vil4HE4PM4nRJc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0/go.mod h1:U79SV99vtvGSEBeeHnpgGJfTsnsdkWLpPN/CcHAzBSI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.52.0 h1:kmU3H0b9ufFSi8IQCcxack+sWUblKkFbqWYs6YiACGQ=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.52.0/go.mod h1:+wsAp2+JhuGXX7YRkjlkx6hyWY3ogFPfNA4x3nyiAh0=
|
||||
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y=
|
||||
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.32.0 h1:P78qWqkLSShicHmAzfECaTgvslqHxblNE9j62Ws1NK8=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.32.0/go.mod h1:TVqo0Sda4Cv8gCIixd7LuLwW4EylumVWfhjZJjDD4DU=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0 h1:qtFISDHKolvIxzSs0gIaiPUPR0Cucb0F2coHC7ZLdps=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0/go.mod h1:Y+Pop1Q6hCOnETWTW4NROK/q1hv50hM7yDaUTjG8lp8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
|
||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0 h1:7F29RDmnlqk6B5d+sUqemt8TBfDqxryYW5gX6L74RFA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0/go.mod h1:ZiGDq7xwDMKmWDrN1XsXAj0iC7hns+2DhxBFSncNHSE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.59.1 h1:HcpSkTkJbggT8bjYP+BjyqPWlD17BH9C5CYNKeDzmcA=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.59.1/go.mod h1:0FJL+gjuUoM07xzik3KPBaN+nz/CoB15kV6WLMiXZag=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I=
|
||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
||||
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
||||
go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
|
||||
go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
|
||||
go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
|
@ -354,67 +441,108 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/W
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/api v0.215.0 h1:jdYF4qnyczlEz2ReWIsosNLDuzXyvFHJtI5gcr0J7t0=
|
||||
google.golang.org/api v0.215.0/go.mod h1:fta3CVtuJYOEdugLNWm6WodzOS8KdFckABwN4I40hzY=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk=
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
|
||||
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
|
||||
google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3 h1:hUfOButuEtpc0UvYiaYRbNwxVYr0mQQOWq6X8beJ9Gc=
|
||||
google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3/go.mod h1:jzYlkSMbKypzuu6xoAEijsNVo9ZeDF1u/zCfFgsx7jg=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
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=
|
||||
|
@ -422,33 +550,35 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP
|
|||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
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=
|
||||
k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
|
||||
k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
|
||||
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
|
||||
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0=
|
||||
k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
|
||||
k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
|
||||
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
|
||||
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
|
||||
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 h1:MErs8YA0abvOqJ8gIupA1Tz6PKXYUw34XsGlA7uSL1k=
|
||||
k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094/go.mod h1:7ioBJr1A6igWjsR2fxq2EZ0mlMwYLejazSIc2bzMp2U=
|
||||
k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24=
|
||||
k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM=
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI=
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/json v0.0.0-20241009153224-e386a8af8d30 h1:ObU1vgTtAle8WwCKgcDkPjLJYwlazQpIjzSA0asMhy4=
|
||||
sigs.k8s.io/json v0.0.0-20241009153224-e386a8af8d30/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
|
||||
k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI=
|
||||
k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
|
|
@ -79,7 +79,7 @@ func Init() error {
|
|||
}
|
||||
|
||||
if initErr == nil {
|
||||
utils.PrintLog("info", utils.LogLine{Message: "init", Category: "aws", Status: utils.SuccessStr})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Message: "init", Category: "aws", Status: utils.SuccessStr})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -58,6 +58,12 @@ func (event *Event) GetPodName() string {
|
|||
if event.OutputFields["k8s.pod.name"] != nil {
|
||||
return event.OutputFields["k8s.pod.name"].(string)
|
||||
}
|
||||
if event.OutputFields["ka.target.pod.name"] != nil {
|
||||
return event.OutputFields["ka.target.pod.name"].(string)
|
||||
}
|
||||
if event.OutputFields["ka.target.name"] != nil {
|
||||
return event.OutputFields["ka.target.name"].(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -65,6 +71,9 @@ func (event *Event) GetNamespaceName() string {
|
|||
if event.OutputFields["k8s.ns.name"] != nil {
|
||||
return event.OutputFields["k8s.ns.name"].(string)
|
||||
}
|
||||
if event.OutputFields["ka.target.namespace"] != nil {
|
||||
return event.OutputFields["ka.target.namespace"].(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package checks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cloud.google.com/go/functions/apiv2/functionspb"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/internal/gcp/client"
|
||||
)
|
||||
|
||||
type CheckFunctionExist struct{}
|
||||
|
||||
func (c CheckFunctionExist) Name() string {
|
||||
return "CheckFunctionExist"
|
||||
}
|
||||
|
||||
func (c CheckFunctionExist) Run(functionName, location string) error {
|
||||
gcpClient, err := client.GetGCPClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
functionClient, err := gcpClient.GetGcpFunctionClient(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a request to get function information
|
||||
req := &functionspb.GetFunctionRequest{
|
||||
Name: "projects/" + gcpClient.ProjectID() + "/locations/" + location + "/functions/" + functionName,
|
||||
}
|
||||
|
||||
_, err = functionClient.GetFunction(context.Background(), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
functionsv2 "cloud.google.com/go/functions/apiv2"
|
||||
"cloud.google.com/go/functions/apiv2/functionspb"
|
||||
"cloud.google.com/go/storage"
|
||||
"github.com/googleapis/gax-go/v2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/option"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/configuration"
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
)
|
||||
|
||||
const functionServiceScope = "https://www.googleapis.com/auth/cloud-platform"
|
||||
|
||||
// nolint:govet
|
||||
type GCPClient struct {
|
||||
clientOpts []option.ClientOption
|
||||
functionsClient *functionsv2.FunctionClient
|
||||
storageClient *storage.Client
|
||||
httpClient HTTPClient
|
||||
projectID string
|
||||
functionsClientOnce sync.Once
|
||||
storageClientOnce sync.Once
|
||||
}
|
||||
|
||||
type GCPClientAPI interface {
|
||||
GetGcpFunctionClient(context.Context) (*functionsv2.FunctionClient, error)
|
||||
GetStorageClient(context.Context) (*storage.Client, error)
|
||||
ProjectID() string
|
||||
HTTPClient() HTTPClient
|
||||
SetHTTPClient(httpClient HTTPClient)
|
||||
Close() []error
|
||||
}
|
||||
|
||||
type HTTPClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
type GcpFunctionAPI interface {
|
||||
GetFunction(ctx context.Context, req *functionspb.GetFunctionRequest, opts ...gax.CallOption) (*functionspb.Function, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
type GcpGcsAPI interface {
|
||||
Bucket(name string) *storage.BucketHandle
|
||||
Close() error
|
||||
}
|
||||
|
||||
var (
|
||||
gcpClient *GCPClient
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func Init() error {
|
||||
if gcpClient != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var initErr error
|
||||
once.Do(func() {
|
||||
gcpConfig := configuration.GetConfiguration().GcpConfig
|
||||
|
||||
var clientOptions []option.ClientOption
|
||||
var creds *google.Credentials
|
||||
var err error
|
||||
|
||||
if gcpConfig.CredentialsPath != "" {
|
||||
creds, err = google.CredentialsFromJSON(context.Background(), []byte(gcpConfig.CredentialsPath), functionServiceScope)
|
||||
if err != nil {
|
||||
initErr = fmt.Errorf("unable to load credentials from file: %v", err)
|
||||
return
|
||||
}
|
||||
clientOptions = append(clientOptions, option.WithCredentials(creds))
|
||||
} else {
|
||||
creds, err = google.FindDefaultCredentials(context.Background(), functionServiceScope)
|
||||
if err != nil {
|
||||
initErr = fmt.Errorf("unable to find default credentials: %v", err)
|
||||
return
|
||||
}
|
||||
clientOptions = append(clientOptions, option.WithCredentials(creds))
|
||||
}
|
||||
|
||||
projectID, err := getProjectID(creds)
|
||||
if err != nil {
|
||||
initErr = err
|
||||
return
|
||||
}
|
||||
|
||||
gcpClient = &GCPClient{
|
||||
clientOpts: clientOptions,
|
||||
projectID: projectID,
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Message: "init", Category: "gcp", Status: utils.SuccessStr})
|
||||
})
|
||||
|
||||
return initErr
|
||||
}
|
||||
|
||||
func GetGCPClient() (*GCPClient, error) {
|
||||
if gcpClient == nil {
|
||||
err := Init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return gcpClient, nil
|
||||
}
|
||||
|
||||
func (c *GCPClient) GetGcpFunctionClient(ctx context.Context) (*functionsv2.FunctionClient, error) {
|
||||
var err error
|
||||
c.functionsClientOnce.Do(func() {
|
||||
c.functionsClient, err = functionsv2.NewFunctionClient(ctx, c.clientOpts...)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.functionsClient, nil
|
||||
}
|
||||
|
||||
func (c *GCPClient) GetStorageClient(ctx context.Context) (*storage.Client, error) {
|
||||
var err error
|
||||
c.storageClientOnce.Do(func() {
|
||||
c.storageClient, err = storage.NewClient(ctx, c.clientOpts...)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.storageClient, nil
|
||||
}
|
||||
|
||||
func (c *GCPClient) ProjectID() string {
|
||||
return c.projectID
|
||||
}
|
||||
|
||||
func (c *GCPClient) HTTPClient() HTTPClient {
|
||||
return c.httpClient
|
||||
}
|
||||
|
||||
// SetHTTPClient allows the user to set a custom HTTP client
|
||||
// to be used by the GCP client
|
||||
// this allows for better testing and control over the HTTP client
|
||||
func (c *GCPClient) SetHTTPClient(httpClient HTTPClient) {
|
||||
c.httpClient = httpClient
|
||||
}
|
||||
|
||||
// Close at the main client level is responsible
|
||||
// for shutting down all the underlying service clients
|
||||
func (c *GCPClient) Close() []error {
|
||||
var errorList []error
|
||||
|
||||
if c.functionsClient != nil {
|
||||
errorList = append(errorList, c.functionsClient.Close())
|
||||
}
|
||||
if c.storageClient != nil {
|
||||
errorList = append(errorList, c.storageClient.Close())
|
||||
}
|
||||
return errorList
|
||||
}
|
||||
|
||||
func getProjectID(creds *google.Credentials) (string, error) {
|
||||
if creds.ProjectID == "" {
|
||||
return "", fmt.Errorf("project ID not available in the credentials, please specify your project ID in the GCP configuration")
|
||||
}
|
||||
return creds.ProjectID, nil
|
||||
}
|
|
@ -75,7 +75,7 @@ func MainHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
if config.PrintAllEvents {
|
||||
utils.PrintLog("info", log)
|
||||
utils.PrintLog(utils.InfoStr, log)
|
||||
}
|
||||
|
||||
metrics.IncreaseCounter(log)
|
||||
|
|
|
@ -8,11 +8,14 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
policyv1 "k8s.io/api/policy/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
|
@ -28,9 +31,8 @@ import (
|
|||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
toolsWatch "k8s.io/client-go/tools/watch"
|
||||
"k8s.io/kubectl/pkg/scheme"
|
||||
|
||||
klog "k8s.io/klog/v2"
|
||||
"k8s.io/kubectl/pkg/scheme"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/configuration"
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
|
@ -70,18 +72,10 @@ type KubernetesClient interface {
|
|||
GetLeaseHolder() (<-chan string, error)
|
||||
Exec(namespace, pod, container string, command []string, script string) (*bytes.Buffer, error)
|
||||
CreateEphemeralContainer(pod *corev1.Pod, container, name string, ttl int) error
|
||||
ListPods(ctx context.Context, opts metav1.ListOptions) (*corev1.PodList, error)
|
||||
ListPods(opts metav1.ListOptions) (*corev1.PodList, error)
|
||||
EvictPod(pod corev1.Pod) error
|
||||
}
|
||||
|
||||
type DrainClient interface {
|
||||
GetPod(name, namespace string) (*corev1.Pod, error)
|
||||
GetNodeFromPod(pod *corev1.Pod) (*corev1.Node, error)
|
||||
ListPods(ctx context.Context, options metav1.ListOptions) (*corev1.PodList, error)
|
||||
EvictPod(pod corev1.Pod) error
|
||||
GetReplicaSet(name, namespace string) (*appsv1.ReplicaSet, error)
|
||||
}
|
||||
|
||||
var (
|
||||
client *Client
|
||||
leaseHolderChan chan string
|
||||
|
@ -129,7 +123,7 @@ func Init() error {
|
|||
flag.Parse()
|
||||
|
||||
if initErr == nil {
|
||||
utils.PrintLog("info", utils.LogLine{Message: "init", Category: "kubernetes", Status: utils.SuccessStr})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Message: "init", Category: "kubernetes", Status: utils.SuccessStr})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -153,6 +147,14 @@ func (client Client) GetPod(pod, namespace string) (*corev1.Pod, error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func (client Client) GetJob(job, namespace string) (*batchv1.Job, error) {
|
||||
p, err := client.Clientset.BatchV1().Jobs(namespace).Get(context.Background(), job, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the job '%v' in the namespace '%v' doesn't exist", job, namespace)
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (client Client) GetDeployment(name, namespace string) (*appsv1.Deployment, error) {
|
||||
p, err := client.Clientset.AppsV1().Deployments(namespace).Get(context.Background(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
|
@ -365,8 +367,13 @@ func (client Client) GetLeaseHolder() (<-chan string, error) {
|
|||
leaseHolderChan = make(chan string, 20)
|
||||
namespace := os.Getenv("NAMESPACE")
|
||||
if namespace == "" {
|
||||
namespace = "falco"
|
||||
if ns, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil {
|
||||
namespace = string(ns)
|
||||
} else {
|
||||
namespace = "falco"
|
||||
}
|
||||
}
|
||||
|
||||
leaderElectionConfig := leaderelection.LeaderElectionConfig{
|
||||
Lock: &resourcelock.LeaseLock{
|
||||
LeaseMeta: metav1.ObjectMeta{
|
||||
|
@ -461,6 +468,13 @@ func (client Client) CreateEphemeralContainer(pod *corev1.Pod, container, name,
|
|||
Stdin: true,
|
||||
TTY: false,
|
||||
TerminationMessagePolicy: corev1.TerminationMessageReadFile,
|
||||
SecurityContext: &corev1.SecurityContext{
|
||||
// Capabilities: &corev1.Capabilities{
|
||||
// Add: []corev1.Capability{"SYS_ADMIN", "NET_ADMIN"},
|
||||
// },
|
||||
Privileged: utils.Pointer(true),
|
||||
RunAsUser: utils.Pointer(int64(0)),
|
||||
},
|
||||
},
|
||||
TargetContainerName: container,
|
||||
}
|
||||
|
@ -497,7 +511,7 @@ func (client Client) CreateEphemeralContainer(pod *corev1.Pod, container, name,
|
|||
return err
|
||||
}
|
||||
|
||||
timeout := time.NewTimer(10 * time.Second)
|
||||
timeout := time.NewTimer(20 * time.Second)
|
||||
ticker := time.NewTicker(300 * time.Millisecond)
|
||||
defer timeout.Stop()
|
||||
defer ticker.Stop()
|
||||
|
@ -523,8 +537,8 @@ func (client Client) CreateEphemeralContainer(pod *corev1.Pod, container, name,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (client Client) ListPods(ctx context.Context, opts metav1.ListOptions) (*corev1.PodList, error) {
|
||||
return client.CoreV1().Pods("").List(ctx, opts)
|
||||
func (client Client) ListPods(opts metav1.ListOptions) (*corev1.PodList, error) {
|
||||
return client.CoreV1().Pods("").List(context.Background(), opts)
|
||||
}
|
||||
|
||||
func (client Client) EvictPod(pod corev1.Pod) error {
|
||||
|
@ -541,11 +555,13 @@ func (client Client) EvictPod(pod corev1.Pod) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func GetOwnerKind(pod corev1.Pod) (string, error) {
|
||||
// PodKind returns the type of the pod
|
||||
// if no owner reference is found, the pod is considered as a standalone pod
|
||||
func PodKind(pod corev1.Pod) string {
|
||||
if len(pod.OwnerReferences) == 0 {
|
||||
return "", fmt.Errorf("no owner reference found")
|
||||
return utils.StandalonePodStr
|
||||
}
|
||||
return pod.OwnerReferences[0].Kind, nil
|
||||
return pod.OwnerReferences[0].Kind
|
||||
}
|
||||
|
||||
func GetOwnerName(pod corev1.Pod) (string, error) {
|
||||
|
@ -570,3 +586,111 @@ func GetContainers(pod *corev1.Pod) []string {
|
|||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (client Client) CreateJob(jobName, namespace, image, node string, ttl int) (string, error) {
|
||||
execAction := new(corev1.ExecAction)
|
||||
execAction.Command = []string{"true"}
|
||||
probe := new(corev1.Probe)
|
||||
probe.ProbeHandler.Exec = execAction
|
||||
probe.InitialDelaySeconds = int32(0)
|
||||
|
||||
endAt := time.Now().Local().Add(time.Duration(int64(ttl)) * time.Second)
|
||||
|
||||
uuid := uuid.NewString()[:5]
|
||||
|
||||
job := &batchv1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: jobName + "-" + uuid,
|
||||
Annotations: map[string]string{
|
||||
"end-at": endAt.Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/managed-by": utils.FalcoTalonStr,
|
||||
"app.kubernetes.io/name": jobName,
|
||||
"app.kubernetes.io/part-of": utils.FalcoTalonStr,
|
||||
},
|
||||
},
|
||||
Spec: batchv1.JobSpec{
|
||||
// ActiveDeadlineSeconds: utils.Pointer(int64(ttl)),
|
||||
TTLSecondsAfterFinished: utils.Pointer(int32(3600)),
|
||||
BackoffLimit: utils.Pointer(int32(1)),
|
||||
Completions: utils.Pointer(int32(1)),
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: jobName + "-" + uuid,
|
||||
Annotations: map[string]string{
|
||||
"end-at": endAt.Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/managed-by": utils.FalcoTalonStr,
|
||||
"app.kubernetes.io/name": jobName,
|
||||
"app.kubernetes.io/part-of": utils.FalcoTalonStr,
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
NodeName: node,
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: jobName,
|
||||
Command: []string{"sleep", strconv.Itoa(ttl)},
|
||||
Ports: []corev1.ContainerPort{},
|
||||
LivenessProbe: probe,
|
||||
ReadinessProbe: probe,
|
||||
Stdin: true,
|
||||
TTY: true,
|
||||
Image: image,
|
||||
SecurityContext: &corev1.SecurityContext{
|
||||
Privileged: utils.Pointer(true),
|
||||
RunAsUser: utils.Pointer(int64(0)),
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "host-fs",
|
||||
MountPath: "/host",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "host-fs",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
HostPath: utils.Pointer(corev1.HostPathVolumeSource{Path: "/"})},
|
||||
},
|
||||
},
|
||||
ActiveDeadlineSeconds: utils.Pointer(int64(ttl + 5)),
|
||||
RestartPolicy: corev1.RestartPolicyNever,
|
||||
TerminationGracePeriodSeconds: utils.Pointer(int64(1)),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := client.Clientset.BatchV1().Jobs(namespace).Create(context.Background(), job, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
timeout := time.NewTimer(time.Duration(ttl) * time.Second)
|
||||
ticker := time.NewTicker(300 * time.Millisecond)
|
||||
defer timeout.Stop()
|
||||
defer ticker.Stop()
|
||||
|
||||
var ready bool
|
||||
for !ready {
|
||||
select {
|
||||
case <-timeout.C:
|
||||
return "", fmt.Errorf("the job '%v' in the namespace '%v' is not ready", result.Name, namespace)
|
||||
case <-ticker.C:
|
||||
j, err := client.GetJob(result.Name, namespace)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if j.Status.Active > 0 {
|
||||
ready = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.Name, nil
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ func Init() error {
|
|||
}
|
||||
|
||||
if initErr == nil {
|
||||
utils.PrintLog("info", utils.LogLine{Message: "init", Category: "minio", Status: utils.SuccessStr})
|
||||
utils.PrintLog(utils.InfoStr, utils.LogLine{Message: "init", Category: "minio", Status: utils.SuccessStr})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ func Init() {
|
|||
|
||||
exporter, err := prometheus.New()
|
||||
if err != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err.Error(), Message: "init", Category: "otlp"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err.Error(), Message: "init", Category: "otlp"})
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ func Init() {
|
|||
if config.Otel.MetricsEnabled {
|
||||
otlpExporter, err2 := newOtlpMetricExporter(config)
|
||||
if err2 != nil {
|
||||
utils.PrintLog("fatal", utils.LogLine{Error: err2.Error(), Message: "init", Category: "otlp"})
|
||||
utils.PrintLog(utils.FatalStr, utils.LogLine{Error: err2.Error(), Message: "init", Category: "otlp"})
|
||||
log.Fatal(err2)
|
||||
}
|
||||
metricOpts = append(metricOpts, sdk.WithReader(sdk.NewPeriodicReader(otlpExporter)))
|
||||
|
|
|
@ -50,7 +50,7 @@ func SetupOTelSDK(ctx context.Context) (shutdown func(context.Context) error, oe
|
|||
shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown)
|
||||
otel.SetTracerProvider(tracerProvider)
|
||||
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Message: "otel"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Message: "otel"})
|
||||
}))
|
||||
tracer = tracerProvider.Tracer("falco-talon")
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package rules
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
Default = iota
|
||||
|
@ -22,7 +26,7 @@ func getPriorityNumber(priority string) int {
|
|||
return Alert
|
||||
case "critical":
|
||||
return Critical
|
||||
case "error":
|
||||
case utils.ErrorStr:
|
||||
return Error
|
||||
case "warning":
|
||||
return Warning
|
||||
|
|
|
@ -88,7 +88,7 @@ func init() {
|
|||
func ParseRules(files []string) *[]*Rule {
|
||||
a, r, err := extractActionsRules(files)
|
||||
if err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: err.Error(), Message: "rules"})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ func ParseRules(files []string) *[]*Rule {
|
|||
continue
|
||||
}
|
||||
if rule.Actions[n].Parameters[k] != nil && ru.Kind() != rt.Kind() {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "mismatch of type for a parameter", Message: "rules", Rule: rule.GetName(), Action: action.GetName()})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "mismatch of type for a parameter", Message: "rules", Rule: rule.GetName(), Action: action.GetName()})
|
||||
continue
|
||||
}
|
||||
switch rt.Kind() {
|
||||
|
@ -157,7 +157,7 @@ func ParseRules(files []string) *[]*Rule {
|
|||
continue
|
||||
}
|
||||
if rule.Actions[n].Output.Parameters[k] != nil && ru.Kind() != rt.Kind() {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "mismatch of type for a parameter", Message: "rules", Rule: rule.GetName(), Action: action.GetName(), OutputTarget: action.Output.GetTarget()})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "mismatch of type for a parameter", Message: "rules", Rule: rule.GetName(), Action: action.GetName(), OutputTarget: action.Output.GetTarget()})
|
||||
continue
|
||||
}
|
||||
switch rt.Kind() {
|
||||
|
@ -390,57 +390,57 @@ func extractActionsRules(files []string) (*[]*Action, *[]*Rule, error) {
|
|||
func (rule *Rule) isValid() bool {
|
||||
valid := true
|
||||
if rule.Name == "" {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "all rules must have a name", Message: "rules"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "all rules must have a name", Message: "rules"})
|
||||
valid = false
|
||||
}
|
||||
if rule.Continue != "" && rule.Continue != trueStr && rule.Continue != falseStr {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "'continue' setting can be 'true' or 'false' only", Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "'continue' setting can be 'true' or 'false' only", Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if rule.DryRun != "" && rule.DryRun != trueStr && rule.DryRun != falseStr {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "'dry_run' setting can be 'true' or 'false' only", Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "'dry_run' setting can be 'true' or 'false' only", Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if len(rule.Actions) == 0 {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "no action specified", Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "no action specified", Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if len(rule.Actions) != 0 {
|
||||
for _, i := range rule.Actions {
|
||||
if i.Name == "" {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "action without a name", Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "action without a name", Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if i.Actionner == "" {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "missing actionner", Message: "rules", Action: i.Name, Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "missing actionner", Message: "rules", Action: i.Name, Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if !actionCheckRegex.MatchString(i.Actionner) {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "incorrect actionner", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "incorrect actionner", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if i.Continue != "" && i.Continue != trueStr && i.Continue != falseStr {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "'continue' setting can be 'true' or 'false' only", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "'continue' setting can be 'true' or 'false' only", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if i.IgnoreErrors != "" && i.IgnoreErrors != trueStr && i.IgnoreErrors != falseStr {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "'ignore_errors' setting can be 'true' or 'false' only", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "'ignore_errors' setting can be 'true' or 'false' only", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
if i.Output.Target != "" && len(i.Output.Parameters) == 0 {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "missing 'parameters' for the output", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name, OutputTarget: i.Output.Target})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "missing 'parameters' for the output", Message: "rules", Action: i.Name, Actionner: i.Actionner, Rule: rule.Name, OutputTarget: i.Output.Target})
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !priorityCheckRegex.MatchString(rule.Match.Priority) {
|
||||
utils.PrintLog("error", utils.LogLine{Error: fmt.Sprintf("incorrect priority '%v'", rule.Match.Priority), Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: fmt.Sprintf("incorrect priority '%v'", rule.Match.Priority), Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
for _, i := range rule.Match.TagsC {
|
||||
for _, j := range i {
|
||||
if !tagCheckRegex.MatchString(j) {
|
||||
utils.PrintLog("error", utils.LogLine{Error: fmt.Sprintf("incorrect tag '%v'", j), Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: fmt.Sprintf("incorrect tag '%v'", j), Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
@ -449,13 +449,13 @@ func (rule *Rule) isValid() bool {
|
|||
t := strings.Split(strings.ReplaceAll(i, ", ", ","), ",")
|
||||
for _, j := range t {
|
||||
if !outputFieldKeyCheckRegex.MatchString(j) {
|
||||
utils.PrintLog("error", utils.LogLine{Error: fmt.Sprintf("incorrect output field key '%v'", j), Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: fmt.Sprintf("incorrect output field key '%v'", j), Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := rule.setPriorityNumberComparator(); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: fmt.Sprintf("incorrect priority comparator '%v'", rule.Match.PriorityComparator), Message: "rules", Rule: rule.Name})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: fmt.Sprintf("incorrect priority comparator '%v'", rule.Match.PriorityComparator), Message: "rules", Rule: rule.Name})
|
||||
valid = false
|
||||
}
|
||||
return valid
|
||||
|
|
|
@ -31,7 +31,7 @@ var mapping = `
|
|||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
utils.ErrorStr: {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
|
|
|
@ -113,7 +113,7 @@ func (c *Client) Request(u string, payload any) error {
|
|||
// defer + recover to catch panic if output doesn't respond
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Error: "recover"})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Error: "recover"})
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ func Init() {
|
|||
for _, j := range *defaultNotifiers {
|
||||
if strings.ToLower(i) == j.Information().Name {
|
||||
if err := j.Init(config.Notifiers[i]); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Message: "init", Error: err.Error(), Category: j.Information().Name, Status: utils.FailureStr})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Message: "init", Error: err.Error(), Category: j.Information().Name, Status: utils.FailureStr})
|
||||
continue
|
||||
}
|
||||
enabledNotifiers.Add(j)
|
||||
|
@ -157,13 +157,13 @@ func Notify(actx context.Context, rule *rules.Rule, action *rules.Action, event
|
|||
span.RecordError(err)
|
||||
logN.Status = utils.FailureStr
|
||||
logN.Error = err.Error()
|
||||
utils.PrintLog("error", logN)
|
||||
utils.PrintLog(utils.ErrorStr, logN)
|
||||
metrics.IncreaseCounter(log)
|
||||
} else {
|
||||
span.SetStatus(codes.Ok, "notification successfully sent")
|
||||
logN.Status = utils.SuccessStr
|
||||
utils.PrintLog("info", logN)
|
||||
metrics.IncreaseCounter(log)
|
||||
utils.PrintLog(utils.InfoStr, logN)
|
||||
metrics.IncreaseCounter(logN)
|
||||
}
|
||||
span.End()
|
||||
}
|
||||
|
|
|
@ -25,11 +25,11 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
Red string = "#e20b0b"
|
||||
Green string = "#23ba47"
|
||||
Grey string = "#a4a8b1"
|
||||
|
||||
ignoredStr string = "ignored"
|
||||
Red string = "#e20b0b"
|
||||
Green string = "#23ba47"
|
||||
Grey string = "#a4a8b1"
|
||||
threeBackticks = "```"
|
||||
ignoredStr string = "ignored"
|
||||
)
|
||||
|
||||
type Parameters struct {
|
||||
|
@ -190,7 +190,7 @@ func newPayload(log utils.LogLine) Payload {
|
|||
}
|
||||
if log.Event != "" {
|
||||
field.Title = "Event"
|
||||
field.Value = "```" + log.Event + "```"
|
||||
field.Value = threeBackticks + log.Event + threeBackticks
|
||||
field.Short = false
|
||||
fields = append(fields, field)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
package gcs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/internal/gcp/client"
|
||||
"github.com/falcosecurity/falco-talon/internal/models"
|
||||
"github.com/falcosecurity/falco-talon/internal/rules"
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
Name string = "gcs"
|
||||
Category string = "gcp"
|
||||
Description string = "Store on GCP Cloud Storage"
|
||||
Permissions string = `Required IAM permissions for GCS:
|
||||
- storage.objects.create
|
||||
- storage.objects.get
|
||||
- storage.objects.list
|
||||
- storage.objects.update`
|
||||
Example string = `- action: Get logs of the pod
|
||||
actionner: kubernetes:download
|
||||
parameters:
|
||||
tail_lines: 200
|
||||
output:
|
||||
target: gcp:gcs
|
||||
parameters:
|
||||
bucket: falco-talon
|
||||
prefix: files
|
||||
`
|
||||
)
|
||||
|
||||
type Parameters struct {
|
||||
Bucket string `mapstructure:"bucket" validate:"required"`
|
||||
Prefix string `mapstructure:"prefix" validate:""`
|
||||
}
|
||||
|
||||
type Output struct{}
|
||||
|
||||
func Register() *Output {
|
||||
return new(Output)
|
||||
}
|
||||
|
||||
func (o Output) Init() error {
|
||||
return client.Init()
|
||||
}
|
||||
|
||||
func (o Output) Information() models.Information {
|
||||
return models.Information{
|
||||
Name: Name,
|
||||
FullName: Category + ":" + Name,
|
||||
Category: Category,
|
||||
Description: Description,
|
||||
Permissions: Permissions,
|
||||
Example: Example,
|
||||
}
|
||||
}
|
||||
|
||||
func (o Output) Parameters() models.Parameters {
|
||||
return Parameters{
|
||||
Prefix: "",
|
||||
Bucket: "",
|
||||
}
|
||||
}
|
||||
|
||||
func (o Output) Checks(_ *rules.Output) error { return nil }
|
||||
|
||||
func (o Output) Run(output *rules.Output, data *models.Data) (utils.LogLine, error) {
|
||||
gcpClient, err := client.GetGCPClient()
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: nil,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, err
|
||||
}
|
||||
|
||||
storageClient, err := gcpClient.GetStorageClient(context.Background())
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: nil,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, err
|
||||
}
|
||||
return o.RunWithClient(storageClient, output, data)
|
||||
}
|
||||
|
||||
func (o Output) CheckParameters(output *rules.Output) error {
|
||||
var parameters Parameters
|
||||
|
||||
err := utils.DecodeParams(output.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = utils.ValidateStruct(parameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o Output) RunWithClient(client client.GcpGcsAPI, output *rules.Output, data *models.Data) (utils.LogLine, error) {
|
||||
var parameters Parameters
|
||||
err := utils.DecodeParams(output.GetParameters(), ¶meters)
|
||||
if err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: nil,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, err
|
||||
}
|
||||
|
||||
parameters.Prefix = strings.TrimSuffix(parameters.Prefix, "/")
|
||||
if parameters.Prefix != "" {
|
||||
parameters.Prefix += "/"
|
||||
}
|
||||
|
||||
var key string
|
||||
switch {
|
||||
case data.Objects["namespace"] != "" && data.Objects["pod"] != "":
|
||||
key = fmt.Sprintf("%v_%v_%v_%v", time.Now().Format("2006-01-02T15-04-05Z"), data.Objects["namespace"], data.Objects["pod"], strings.ReplaceAll(data.Name, "/", "_"))
|
||||
case data.Objects["hostname"] != "":
|
||||
key = fmt.Sprintf("%v_%v_%v", time.Now().Format("2006-01-02T15-04-05Z"), data.Objects["hostname"], strings.ReplaceAll(data.Name, "/", "_"))
|
||||
default:
|
||||
var s string
|
||||
for i, j := range data.Objects {
|
||||
if i != "file" {
|
||||
s += j + "_"
|
||||
}
|
||||
}
|
||||
key = fmt.Sprintf("%v_%v%v", time.Now().Format("2006-01-02T15-04-05Z"), s, strings.ReplaceAll(data.Name, "/", "_"))
|
||||
}
|
||||
|
||||
objects := map[string]string{
|
||||
"file": data.Name,
|
||||
"bucket": parameters.Bucket,
|
||||
"prefix": parameters.Prefix,
|
||||
"key": key,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if err := putObject(ctx, client, parameters.Bucket, parameters.Prefix, key, *data); err != nil {
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Error: err.Error(),
|
||||
Status: utils.FailureStr,
|
||||
}, err
|
||||
}
|
||||
|
||||
return utils.LogLine{
|
||||
Objects: objects,
|
||||
Output: fmt.Sprintf("The file '%v' has been uploaded as the key '%v' to the bucket '%v'", data.Name, parameters.Prefix+key, parameters.Bucket),
|
||||
Status: utils.SuccessStr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func putObject(ctx context.Context, storageClient client.GcpGcsAPI, bucketName, prefix, key string, data models.Data) error {
|
||||
bucket := storageClient.Bucket(bucketName)
|
||||
objectName := prefix + key
|
||||
wc := bucket.Object(objectName).NewWriter(ctx)
|
||||
defer wc.Close()
|
||||
|
||||
if _, err := wc.Write(data.Bytes); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -4,7 +4,8 @@ import (
|
|||
"github.com/falcosecurity/falco-talon/internal/rules"
|
||||
awss3 "github.com/falcosecurity/falco-talon/outputs/aws/s3"
|
||||
"github.com/falcosecurity/falco-talon/outputs/file"
|
||||
minio "github.com/falcosecurity/falco-talon/outputs/minio"
|
||||
"github.com/falcosecurity/falco-talon/outputs/gcs"
|
||||
"github.com/falcosecurity/falco-talon/outputs/minio"
|
||||
|
||||
"github.com/falcosecurity/falco-talon/internal/models"
|
||||
"github.com/falcosecurity/falco-talon/utils"
|
||||
|
@ -36,6 +37,7 @@ func ListDefaultOutputs() *Outputs {
|
|||
file.Register(),
|
||||
minio.Register(),
|
||||
awss3.Register(),
|
||||
gcs.Register(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -89,7 +91,7 @@ func Init() error {
|
|||
for _, output := range *defaultOutputs {
|
||||
if category == output.Information().Category {
|
||||
if err := output.Init(); err != nil {
|
||||
utils.PrintLog("error", utils.LogLine{Message: "init", Error: err.Error(), Category: category, Status: utils.FailureStr})
|
||||
utils.PrintLog(utils.ErrorStr, utils.LogLine{Message: "init", Error: err.Error(), Category: category, Status: utils.FailureStr})
|
||||
return err
|
||||
}
|
||||
enabledCategories[category] = true
|
||||
|
|
69
rules.yaml
69
rules.yaml
|
@ -1,5 +1,8 @@
|
|||
- action: Terminate Pod
|
||||
actionner: kubernetes:terminate
|
||||
parameters:
|
||||
grace_period_seconds: 5
|
||||
ignore_standalone_pods: true
|
||||
|
||||
- action: Disable outbound connections
|
||||
actionner: kubernetes:networkpolicy
|
||||
|
@ -31,6 +34,14 @@
|
|||
aws_lambda_alias_or_version: $LATEST
|
||||
aws_lambda_invocation_type: RequestResponse
|
||||
|
||||
- action: Invoke GCP function
|
||||
actionner: gcp:function
|
||||
additional_contexts:
|
||||
- aws
|
||||
parameters:
|
||||
gcp_function_name: simple-http-function
|
||||
gcp_function_location: us-central1
|
||||
|
||||
- rule: Suspicious outbound connection
|
||||
description: "Label pods with suspicious outbound connections if not in the kube-system"
|
||||
match:
|
||||
|
@ -50,14 +61,21 @@
|
|||
output_fields:
|
||||
- k8s.ns.name!=kube-system, k8s.ns.name!=falco
|
||||
actions:
|
||||
- action: Label Pod as Suspicious
|
||||
- action: Terminate Pod
|
||||
|
||||
- rule: Test invoke lambda
|
||||
match:
|
||||
rules:
|
||||
- Test invoke lambda
|
||||
actions:
|
||||
- action: Invoke Lambda function
|
||||
# - rule: Test invoke lambda
|
||||
# match:
|
||||
# rules:
|
||||
# - Test invoke lambda
|
||||
# actions:
|
||||
# - action: Invoke Lambda function
|
||||
|
||||
# - rule: Test invoke GCP function
|
||||
# match:
|
||||
# rules:
|
||||
# - Test invoke GCP function
|
||||
# actions:
|
||||
# - action: Invoke GCP function
|
||||
|
||||
- rule: Delete unknown namespace
|
||||
match:
|
||||
|
@ -142,7 +160,8 @@
|
|||
additional_contexts:
|
||||
- k8snode
|
||||
parameters:
|
||||
command: echo "${NODE_HOSTNAME}"
|
||||
shell: /bin/sh
|
||||
command: uname -a
|
||||
- action: Test log
|
||||
actionner: kubernetes:log
|
||||
output:
|
||||
|
@ -150,15 +169,15 @@
|
|||
parameters:
|
||||
bucket: falcosidekick-tests
|
||||
prefix: logs/
|
||||
# - action: Test download
|
||||
# actionner: kubernetes:download
|
||||
# parameters:
|
||||
# file: "${FD_NAME}"
|
||||
# output:
|
||||
# target: minio:s3
|
||||
# parameters:
|
||||
# bucket: falco-talon
|
||||
# prefix: /files/
|
||||
- action: Test download
|
||||
actionner: kubernetes:download
|
||||
parameters:
|
||||
file: "${FD_NAME}"
|
||||
output:
|
||||
target: minio:s3
|
||||
parameters:
|
||||
bucket: falco-talon
|
||||
prefix: /files/
|
||||
|
||||
- rule: Test tcpdump
|
||||
match:
|
||||
|
@ -177,6 +196,22 @@
|
|||
prefix: /tcpdump/
|
||||
region: us-east-1
|
||||
|
||||
- rule: Test sysdig
|
||||
match:
|
||||
rules:
|
||||
- Test sysdig
|
||||
actions:
|
||||
- action: Test sysdig
|
||||
actionner: kubernetes:sysdig
|
||||
parameters:
|
||||
duration: 5
|
||||
scope: pod
|
||||
buffer_size: 4096
|
||||
output:
|
||||
target: local:file
|
||||
parameters:
|
||||
destination: /tmp/
|
||||
|
||||
- rule: Test log
|
||||
match:
|
||||
rules:
|
||||
|
|
|
@ -30,21 +30,24 @@ const (
|
|||
MapIntStr string = "map[string]int"
|
||||
MapInterfaceStr string = "map[string]interface {}"
|
||||
|
||||
errorStr string = "error"
|
||||
warningStr string = "warning"
|
||||
fatalStr string = "fatal"
|
||||
InfoStr string = "info"
|
||||
ErrorStr string = "error"
|
||||
WarningStr string = "warning"
|
||||
FatalStr string = "fatal"
|
||||
|
||||
textStr string = "text"
|
||||
colorStr string = "color"
|
||||
|
||||
SuccessStr string = "success"
|
||||
FailureStr string = "failure"
|
||||
InProgressStr string = "in_progress"
|
||||
SuccessStr string = "success"
|
||||
FailureStr string = "failure"
|
||||
|
||||
ansiChars string = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
|
||||
|
||||
DaemonSetStr = "DaemonSet"
|
||||
StatefulSetStr = "StatefulSet"
|
||||
ReplicaSetStr = "ReplicaSet"
|
||||
DaemonSetStr = "DaemonSet"
|
||||
StatefulSetStr = "StatefulSet"
|
||||
ReplicaSetStr = "ReplicaSet"
|
||||
StandalonePodStr = "StandalonePod"
|
||||
)
|
||||
|
||||
type LogLine struct {
|
||||
|
@ -105,11 +108,11 @@ func PrintLog(level string, line LogLine) {
|
|||
|
||||
var l *zerolog.Event
|
||||
switch strings.ToLower(level) {
|
||||
case warningStr:
|
||||
case WarningStr:
|
||||
l = log.Warn()
|
||||
case errorStr:
|
||||
case ErrorStr:
|
||||
l = log.Error()
|
||||
case fatalStr:
|
||||
case FatalStr:
|
||||
l = log.Fatal()
|
||||
default:
|
||||
l = log.Info()
|
||||
|
@ -303,3 +306,7 @@ func GetLocalIP() *string {
|
|||
}
|
||||
return localIP
|
||||
}
|
||||
|
||||
func Pointer[T any](d T) *T {
|
||||
return &d
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue