kubewarden/policy-sdk-go

GitHub: kubewarden/policy-sdk-go

Kubewarden 的 Go 语言策略开发 SDK,用于编写编译为 WebAssembly 的 Kubernetes 准入控制策略

Stars: 9 | Forks: 8

[![Stable](https://img.shields.io/badge/status-stable-brightgreen?style=for-the-badge)](https://github.com/kubewarden/community/blob/main/REPOSITORIES.md#stable) [![GoDoc](https://godoc.org/github.com/kubewarden/policy-sdk-go?status.svg)](https://godoc.org/github.com/kubewarden/policy-sdk-go) # Kubewarden Go Policy SDK 该模块提供了一个 SDK,可用于使用 Go 编程语言编写 [Kubewarden 策略](https://github.com/kubewarden/)。 由于当前 Go 编译器的限制,Go 策略必须使用 [TinyGo](https://github.com/tinygo-org/tinygo) 构建。 ## TinyGo 的已知限制 TinyGo 尚不完全支持 Go 标准库。但是,这不应成为策略作者的限制。 # 验证 此 SDK 提供了接受和拒绝验证请求的辅助方法。 验证策略包含以下步骤: 1. 从传入的 payload 中提取要检查的对象 2. (可选)从传入的 payload 中提取设置对象。 3. 验证代码 4. 传达验证结果:接受/拒绝 第 4 步使用此 SDK 提供的辅助函数完成。 至于第 1 步,可以使用两种方法。 ## 执行“类似 jq”的搜索 策略接收一个类型为 `[]byte` 的 `payload` 参数。这包含[此处](https://docs.kubewarden.io/writing-policies/spec/validating-policies#the-validationrequest-object)描述的 JSON 文档。 策略作者可以利用 [`github.com/tidwall/gjson`](https://github.com/tidwall/gjson) 包在此 JSON 文档中搜索数据。 例如,假设您要验证 Kubernetes 对象内的 `labels`。可以使用以下代码片段完成: ``` data := gjson.GetBytes( payload, "request.object.metadata.labels") labels := mapset.NewThreadUnsafeSet() denied_labels_violations := []string{} constrained_labels_violations := []string{} data.ForEach(func(key, value gjson.Result) bool { label := key.String() labelValue := value.String() // do something with label and labelValue return true }) ``` 这种_“类似 jq”_的方法在策略必须深入查看 Kubernetes 对象时非常方便。这在处理可选的内部对象时尤其有用。 ## 使用原生 Go 类型 大多数策略针对特定类型的 Kubernetes 资源,如 Pod、Ingress、Service 等。因此,另一种可能的方法是将传入的对象反序列化为原生 Go 类型。 TinyGo 尚不完全支持 Go 标准库,而且对 Go 反射的支持有限。 因此,无法从上游(例如:`k8s.io/api/core/v1`)导入官方的 Kubernetes Go 库。 导入这些官方 Kubernetes 类型将导致编译失败。 此外,Kubewarden 在 [`github.com/kubewarden/k8s-objects`](https://github.com/kubewarden/k8s-objects) 包中为所有 Kubernetes 类型提供了对 TinyGo 友好的 Go 类型。 使用此 SDK 需要 **TinyGo 0.28.1 或更高版本。** ### 示例 此代码片段展示了如何实现一个使用“原生 Go 类型”方法的 `validation` 函数: ``` // Create a ValidationRequest instance from the incoming payload validationRequest := kubewarden_protocol.ValidationRequest{} err := json.Unmarshal(payload, &validationRequest) if err != nil { return kubewarden.RejectRequest( kubewarden.Message(err.Error()), kubewarden.Code(400)) } // Access the **raw** JSON that describes the object ingressJSON := validationRequest.Request.Object // Try to create an Ingress instance using the RAW JSON we got from the // ValidationRequest. // This policy works only against Ingress objects, if the creation fails // we reject the request and provide a meaningful error. ingress := &networkingv1.Ingress{} if err := json.Unmarshal([]byte(ingressJSON), ingress); err != nil { return kubewarden.RejectRequest( kubewarden.Message( fmt.Sprintf("Cannot decode Ingress object: %s", err.Error())), kubewarden.Code(400)) } // the validation logic ``` **注意:** `github.com/kubewarden/k8s-objects` 包的组织方式与官方 `k8s.io` 包相同。 # 变更策略 变更策略的工作方式与验证策略完全相同。唯一的区别是,当一个请求需要被接受**并且**变更时,策略必须返回应用了所有必需更改的输入对象。 变更策略可以通过利用 `github.com/kubewarden/k8s-objects` 包中定义的 Kubernetes Go 类型以及此 SDK 提供的辅助方法来实现。 以下示例定义了一个始终更改 Ingress 对象名称的变更策略: ``` import ( "encoding/json" "fmt" networkingv1 "github.com/kubewarden/k8s-objects/api/networking/v1" kubewarden "github.com/kubewarden/policy-sdk-go" ) func validate(payload []byte) ([]byte, error) { // Create a ValidationRequest instance from the incoming payload validationRequest := kubewarden_protocol.ValidationRequest{} err := json.Unmarshal(payload, &validationRequest) if err != nil { return kubewarden.RejectRequest( kubewarden.Message(err.Error()), kubewarden.Code(400)) } // Access the **raw** JSON that describes the object ingressJSON := validationRequest.Request.Object // Try to create a Ingress instance using the RAW JSON we got from the // ValidationRequest. // This policy works only against Ingress objects, if the creation fails // we reject the request and provide a meaningful error. ingress := &networkingv1.Ingress{} if err := json.Unmarshal([]byte(ingressJSON), ingress); err != nil { return kubewarden.RejectRequest( kubewarden.Message( fmt.Sprintf("Cannot decode Ingress object: %s", err.Error())), kubewarden.Code(400)) } ingress.Metadata.Name = fmt.Sprintf("%s-changed", ingress.Metadata.Name) return kubewarden.MutateRequest(ingress) } ``` # 日志记录 策略可以生成日志消息,然后将其传播到主机环境(例如:[kwctl](https://github.com/kubewarden/kwctl)、 [policy-server](https://github.com/kubewarden/policy-server))。 此 Go 模块提供了与 [onelog](https://github.com/francoispqt/onelog) 项目集成的日志记录功能。 选择此日志解决方案的原因如下: - 它也适用于 WebAssembly 二进制文件。其他流行的日志解决方案甚至无法构建为 WebAssembly。 - 它提供了[良好的性能](https://github.com/francoispqt/onelog#benchmarks) - 它支持结构化日志记录。 ## 用法 官方 [onelog](https://github.com/francoispqt/onelog) 项目提供的说明也适用于 Kubewarden 策略。 必须将 `onelog.Logger` 实例配置为使用 `KubewardenLogWriter` 对象。 ``` kl := kubewarden.KubewardenLogWriter{} logger := onelog.New( &kl, onelog.ALL, // shortcut for onelog.DEBUG|onelog.INFO|onelog.WARN|onelog.ERROR|onelog.FATAL, ) logger.Info("info message from tinygo") logger.DebugWithFields("i'm not sure what's going on", func(e onelog.Entry) { e.String("string", "foobar") e.Int("int", 12345) e.Int64("int64", 12345) e.Float("float64", 0.15) e.Bool("bool", true) e.Err("err", errors.New("someError")) e.ObjectFunc("user", func(e onelog.Entry) { e.String("name", "somename") }) }) ``` # 主机功能 策略执行器公开了可供 guest 利用附加功能。 这些功能通过此 SDK 暴露给 Go 策略,通过 `github.com/kubewarden/policy-sdk-go/capabilities` 中定义的 `Host` 类型实现。 ## 获取 OCI manifest digest 策略可以请求 OCI manifest 的 digest。这可用于获取容器镜像的不可变引用或存储在容器注册表中的任何内容(例如 Kubewarden 策略、Helm charts 等)。 ``` host := capabilities.NewHost() digest, err := host.GetOCIManifestDigest("busybox:latest") ``` ## 主机名 DNS 查找 策略可以使用评估策略的主机的 DNS 解析器查找给定主机名的地址。 ``` host := capabilities.NewHost() ips, err := host.LookupHost("kubewarden.io") ``` ## Sigstore 验证 策略可以要求主机对存储在容器注册表中的对象(例如容器镜像、kubewarden 策略、helm chart 等)执行验证操作,利用 [Sigstore](https://sigstore.dev) 原语。 目前,此 SDK 公开了可以使用公钥和 Sigstore 无密钥机制执行验证的辅助函数。 # 测试 [![GoDoc](https://godoc.org/github.com/kubewarden/policy-sdk-go/testing?status.svg)](https://godoc.org/github.com/kubewarden/policy-sdk-go/testing) `kubewarden/policy-sdk-go/testing` 模块提供了一些测试辅助工具, 简化了编写单元测试的过程。 ## 主机功能 策略的 Go 单元测试**不**在 WebAssembly 环境中运行, 而是使用官方 Go 编译器构建为原生可执行文件。 因此,在测试时必须模拟主机功能。这对于编写可以处理来自主机的不同类型响应的特设测试也很有用。 上面描述的 `Host` 类型依赖于与主机交互的内部 `waPC` 客户端。在测试时,该客户端是 `MockWapcClient` 的一个实例。 开发人员可以使用 `capabilities` 包中的 `NewMockWapcClient` 辅助方法创建 `MockWapcClient` 实例。其用法如下: ``` mockWapcClient := &mocks.MockWapcClient{} mockWapcClient.On("HostCall", "kubewarden", "kubernetes", "get_resource", request).Return(wapcResponse, nil) ``` # 项目模板 我们提供了一个 GitHub 仓库模板,可用于快速 构建一个编写 Go 的新 Kubewarden 策略脚手架。 可以在[此处](https://github.com/kubewarden/go-policy-template)找到。
标签:AI工具, EVTX分析, GJSON, Go, Homebrew安装, Kubewarden, Ruby工具, TinyGo, UDP扫描, WebAssembly, Web截图, 子域名突变, 容器安全, 开发包, 开源库, 搜索引擎爬虫, 日志审计, 策略即代码, 策略开发, 策略引擎, 网络安全挑战, 聊天机器人安全, 验证策略