この文書は自動機械翻訳技術を使用して翻訳されています。 正確な翻訳を提供するように努めておりますが、翻訳された内容の完全性、正確性、信頼性については一切保証いたしません。 相違がある場合は、元の英語版 英語 が優先され、正式なテキストとなります。

これは未公開の文書です Admission Controller 1.34-dev.

生のポリシーを書く

生のポリシーは、任意のJSONドキュメントを評価できるポリシーです。 生のポリシーに関する詳細情報は、raw policiesページを参照してください。

以下の例は、このチュートリアルの検証セクションを完了した場合、見覚えがあるはずです。

ポリシーを`raw`としてマークすることを忘れずに、`policyType`フィールドを`metadata.yml`設定で使用してください。 詳細情報については、メタデータ仕様を参照してください。

metadata.ymlpolicyType: raw
rules:
- apiGroups: [""]
  apiVersions: ["v1"]
  resources: ["pods"]
  operations: ["CREATE"]
mutating: false
contextAware: false
executionMode: kubewarden-wapc
policyType: raw
# Consider the policy for the background audit scans. Default is true. Note the
# intrinsic limitations of the background audit feature on docs.kubewarden.io;
# If your policy hits any limitations, set to false for the audit feature to
# skip this policy and not generate false positives.
backgroundAudit: true
annotations:
  # kubewarden specific:
  io.kubewarden.policy.title: policy-name
  io.kubewarden.policy.version: 0.1.0  # should match the OCI tag
  io.kubewarden.policy.description: Short description
  io.kubewarden.policy.author: "Author name <author-email@example.com>"
  io.kubewarden.policy.url: https://github.com/yourorg/policy-name
  io.kubewarden.policy.source: https://github.com/yourorg/policy-name
  io.kubewarden.policy.license: Apache-2.0
  # The next two annotations are used in the policy report generated by the
  # Audit scanner. Severity indicates policy check result criticality and
  # Category indicates policy category. See more here at docs.kubewarden.io
  io.kubewarden.policy.severity: medium # one of info, low, medium, high, critical. See docs.
  io.kubewarden.policy.category: Resource validation
  # artifacthub specific: (optional, to release in Artifact Hub)
  io.kubewarden.policy.ociUrl: ghcr.io/yourorg/policies/policy-name # must match release workflow oci-target
  io.artifacthub.displayName: Policy Name
  io.artifacthub.resources: Pod
  io.artifacthub.keywords: pod, cool policy, kubewarden

検証

次の形式のリクエストを受け入れるポリシーを作成したいと考えています:

{
  "request": {
    "user": "alice",
    "action": "delete",
    "resource": "products"
  }
}

そして、次のことを検証します:

  • `user`が有効なユーザーのリストに含まれていること

  • `action`が有効なアクションのリストに含まれていること

  • `resource`が有効なリソースのリストに含まれていること

まず、https://github.com/kubewarden/go-policy-template[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`タイプと`Valid`および`validateSettings`関数を`settings.go`で定義する必要があります:

`Settings`構造と`Valid`および`validateSettings`関数は`settings.go`にあります。
// 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`関数を`validate.go`で置き換えます:

`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)
}