|
本文档采用自动化机器翻译技术翻译。 尽管我们力求提供准确的译文,但不对翻译内容的完整性、准确性或可靠性作出任何保证。 若出现任何内容不一致情况,请以原始 英文 版本为准,且原始英文版本为权威文本。 |
|
这是尚未发布的文档。 Admission Controller 1.34-dev. |
编写原始策略
原始策略是可以评估任意 JSON 文档的策略。 有关原始策略的更多信息,请参阅 原始策略 页面。
示例
如果您完成了本教程的 验证 部分,以下示例应该很熟悉。
|
请记得通过在
|
Validation
您想编写一个接受以下格式请求的策略:
{
"request": {
"user": "alice",
"action": "delete",
"resource": "products"
}
}
并验证:
-
user在有效用户列表中 -
action在有效操作列表中 -
resource在有效资源列表中
首先,通过使用 go 策略模板 来搭建策略。
确保一切就绪,包括 make、make test 和 make e2e-tests。
首先,定义表示请求有效负载的类型。
您需要声明一个自定义 RawValidationRequest 类型(创建一个文件 request.go),包含 RawValidationRequest 和 Settings 结构,而不是使用 SDK 提供的 ValidationRequest 类型:
// RawValidationRequest represents the request that is sent to the validate function by the Policy Server.
type RawValidationRequest struct {
Request Request `+json:"request"+`
// Raw policies can have settings.
Settings Settings `+json:"settings"+`
}
// Request represents the payload of the request.
type Request struct {
User string `+json:"user"+`
Action string `+json:"action"+`
Resource string `+json:"resource"+`
}
然后您需要在`settings.go`中定义`Settings`类型以及`Valid`和`validateSettings`函数:
`settings.go`中的`Settings`结构以及`Valid`和`validateSettings`函数。
// Settings represents the settings of the policy.
type Settings struct {
ValidUsers []string `+json:"validUsers"+`
ValidActions []string `+json:"validActions"+`
ValidResources []string `+json:"validResources"+`
}
// Valid returns true if the settings are valid.
func (s *Settings) Valid() (bool, error) {
if len(s.ValidUsers) == 0 {
return false, fmt.Errorf("validUsers cannot be empty")
}
if len(s.ValidActions) == 0 {
return false, fmt.Errorf("validActions cannot be empty")
}
if len(s.ValidResources) == 0 {
return false, fmt.Errorf("validResources cannot be empty")
}
return true, nil
}
// validateSettings validates the settings.
func validateSettings(payload []byte) ([]byte, error) {
logger.Info("validating settings")
settings := Settings{}
err := json.Unmarshal(payload, &settings)
if err != nil {
return kubewarden.RejectSettings(kubewarden.Message(fmt.Sprintf("Provided settings are not valid: %v", err)))
}
valid, err := settings.Valid()
if err != nil {
return kubewarden.RejectSettings(kubewarden.Message(fmt.Sprintf("Provided settings are not valid: %v", err)))
}
if valid {
return kubewarden.AcceptSettings()
}
logger.Warn("rejecting settings")
return kubewarden.RejectSettings(kubewarden.Message("Provided settings are not valid"))
}
最后,您在`validate.go`中替换`validate`函数:
`validate.go`中的`validate`函数。
func validate(payload []byte) ([]byte, error) {
// Unmarshal the payload into a RawValidationRequest instance
validationRequest := RawValidationRequest{}
err := json.Unmarshal(payload, &validationRequest)
if err != nil {
// If the payload is not valid, reject the request
return kubewarden.RejectRequest(
kubewarden.Message(err.Error()),
kubewarden.Code(400))
}
request := validationRequest.Request
settings := validationRequest.Settings
// Validate the payload
if slices.Contains(settings.ValidUsers, request.User) &&
slices.Contains(settings.ValidActions, request.Action) &&
slices.Contains(settings.ValidResources, request.Resource) {
return kubewarden.AcceptRequest()
}
return kubewarden.RejectRequest(
kubewarden.Message("The request cannot be accepted."),
kubewarden.Code(400))
}
您可以在`e2e.bats`中设置一个测试:
e2e.bats
#!/usr/bin/env bats
@test "accept" {
run kwctl run annotated-policy.wasm -r test_data/request.json -s test_data/settings.json
# this prints the output when one the checks below fails
echo "output = ${output}"
# request allowed
[ "$status" -eq 0 ]
[ $(expr "$output" : '.*allowed.*true') -ne 0 ]
}
然后`make`、`make test`和`make e2e`的输出为:
输出
make && make test && make e2e-tests
docker run \
--rm \
-e GOFLAGS="-buildvcs=false" \
-v /home/jhk/projects/suse/tmp/fab-goraw:/src \
-w /src tinygo/tinygo:0.30.0 \
tinygo build -o policy.wasm -target=wasi -no-debug .
go test -v
=== RUN TestAcceptValidSettings
--- PASS: TestAcceptValidSettings (0.00s)
=== RUN TestRejectSettingsWithEmptyValidUsers
--- PASS: TestRejectSettingsWithEmptyValidUsers (0.00s)
=== RUN TestRejectSettingsWithEmptyValidActions
--- PASS: TestRejectSettingsWithEmptyValidActions (0.00s)
=== RUN TestRejectSettingsWithEmptyValidResources
--- PASS: TestRejectSettingsWithEmptyValidResources (0.00s)
=== RUN TestValidateRequestAccept
--- PASS: TestValidateRequestAccept (0.00s)
=== RUN TestValidateRequestReject
--- PASS: TestValidateRequestReject (0.00s)
PASS
ok github.com/kubewarden/go-policy-template 0.002s
kwctl annotate -m metadata.yml -u README.md -o annotated-policy.wasm policy.wasm
bats e2e.bats
e2e.bats
✓ accept
1 test, 0 failures
变更
您需要更改之前的示例,以便变更请求而不是拒绝它。
设置应包含`defaultUser`、defaultAction`和`defaultRequest,以便在用户、操作或资源无效时变更请求。
您需要用新字段更新`Settings`类型:
// Settings defines the settings of the policy.
type Settings struct {
ValidUsers []string `+json:"validUsers"+`
ValidActions []string `+json:"validActions"+`
ValidResources []string `+json:"validResources"+`
DefaultUser string `+json:"defaultUser"+`
DefaultAction string `+json:"defaultAction"+`
DefaultResource string `+json:"defaultResource"+`
}
// Valid returns true if the settings are valid.
func (s *Settings) Valid() (bool, error) {
if len(s.ValidUsers) == 0 {
return false, fmt.Errorf("validUsers cannot be empty")
}
if len(s.ValidActions) == 0 {
return false, fmt.Errorf("validActions cannot be empty")
}
if len(s.ValidResources) == 0 {
return false, fmt.Errorf("validResources cannot be empty")
}
if s.DefaultUser == "" {
return false, fmt.Errorf("defaultUser cannot be empty")
}
if s.DefaultAction == "" {
return false, fmt.Errorf("defaultUser cannot be empty")
}
if s.DefaultResource == "" {
return false, fmt.Errorf("defaultResource cannot be empty")
}
return true, nil
}
此外,`validate`函数用于引入变更:
func validate(payload []byte) ([]byte, error) {
// Unmarshal the payload into a RawValidationRequest instance
validationRequest := RawValidationRequest{}
err := json.Unmarshal(payload, &validationRequest)
if err != nil {
// If the payload is not valid, reject the request
return kubewarden.RejectRequest(
kubewarden.Message(err.Error()),
kubewarden.Code(400))
}
request := validationRequest.Request
settings := validationRequest.Settings
logger.Info("validating request")
// Accept the request without mutating it if it is valid
if slices.Contains(settings.ValidUsers, request.User) &&
slices.Contains(settings.ValidActions, request.Action) &&
slices.Contains(settings.ValidResources, request.Resource) {
return kubewarden.AcceptRequest()
}
logger.Info("mutating request")
// Mutate the request if it is not valid
if !slices.Contains(settings.ValidUsers, request.User) {
request.User = settings.DefaultUser
}
if !slices.Contains(settings.ValidActions, request.Action) {
request.Action = settings.DefaultAction
}
if !slices.Contains(settings.ValidResources, request.Resource) {
request.Resource = settings.DefaultResource
}
return kubewarden.MutateRequest(request)
}