From cbd5bc2261150de88bb5c7bb3bed2d620de191e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Thu, 7 Nov 2024 17:31:13 +0100 Subject: [PATCH] docs: cleanup (#203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- {docs => .docs}/RELEASE.md | 0 .../cert-manager/cluster-issuer.yaml | 0 .../policies/demo-policy.example.com.yaml | 0 Makefile | 2 +- docs/quick_start.yaml | 212 --------------- website/docs/jp.md | 15 -- website/docs/jp/functions.md | 108 -------- website/docs/policies/asserts.md | 248 ------------------ .../{pols => policies}/authorization-rules.md | 0 website/docs/policies/authz-policy.md | 123 --------- .../docs/{pols => policies}/failure-policy.md | 0 website/docs/{pols => policies}/index.md | 0 website/docs/policies/policies.md | 100 ------- website/docs/{pols => policies}/variables.md | 0 website/docs/quick-start.md | 181 ------------- .../{install.md => authz-server.md} | 8 +- website/docs/quick-start/next-steps.md | 13 +- website/docs/quick-start/sidecar-injector.md | 3 + website/mkdocs.yaml | 20 +- 19 files changed, 29 insertions(+), 1004 deletions(-) rename {docs => .docs}/RELEASE.md (100%) rename {manifests => .manifests}/cert-manager/cluster-issuer.yaml (100%) rename {manifests => .manifests}/policies/demo-policy.example.com.yaml (100%) delete mode 100644 docs/quick_start.yaml delete mode 100644 website/docs/jp.md delete mode 100644 website/docs/jp/functions.md delete mode 100644 website/docs/policies/asserts.md rename website/docs/{pols => policies}/authorization-rules.md (100%) delete mode 100644 website/docs/policies/authz-policy.md rename website/docs/{pols => policies}/failure-policy.md (100%) rename website/docs/{pols => policies}/index.md (100%) delete mode 100644 website/docs/policies/policies.md rename website/docs/{pols => policies}/variables.md (100%) delete mode 100644 website/docs/quick-start.md rename website/docs/quick-start/{install.md => authz-server.md} (96%) create mode 100644 website/docs/quick-start/sidecar-injector.md diff --git a/docs/RELEASE.md b/.docs/RELEASE.md similarity index 100% rename from docs/RELEASE.md rename to .docs/RELEASE.md diff --git a/manifests/cert-manager/cluster-issuer.yaml b/.manifests/cert-manager/cluster-issuer.yaml similarity index 100% rename from manifests/cert-manager/cluster-issuer.yaml rename to .manifests/cert-manager/cluster-issuer.yaml diff --git a/manifests/policies/demo-policy.example.com.yaml b/.manifests/policies/demo-policy.example.com.yaml similarity index 100% rename from manifests/policies/demo-policy.example.com.yaml rename to .manifests/policies/demo-policy.example.com.yaml diff --git a/Makefile b/Makefile index cf66f5a..cedc767 100644 --- a/Makefile +++ b/Makefile @@ -318,7 +318,7 @@ install-cert-manager: $(HELM) install-cluster-issuer: ## Install cert-manager cluster issuer install-cluster-issuer: @echo Install cert-manager cluster issuer... >&2 - @kubectl apply -f manifests/cert-manager/cluster-issuer.yaml + @kubectl apply -f .manifests/cert-manager/cluster-issuer.yaml ######### # ISTIO # diff --git a/docs/quick_start.yaml b/docs/quick_start.yaml deleted file mode 100644 index 9fe3746..0000000 --- a/docs/quick_start.yaml +++ /dev/null @@ -1,212 +0,0 @@ -# Application Deployment with kyverno-envoy-plugin and Envoy sidecars. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: testapp -spec: - replicas: 1 - selector: - matchLabels: - app: testapp - template: - metadata: - labels: - app: testapp - spec: - initContainers: - - name: proxy-init - image: sanskardevops/proxyinit:latest - # Configure the iptables bootstrap script to redirect traffic to the - # Envoy proxy on port 8000, specify that Envoy will be running as user - # 1111, and that we want to exclude port 8181 from the proxy for the Kyverno health checks. - # These values must match up with the configuration - # defined below for the "envoy" and "kyverno-envoy-plugin" containers. - args: ["-p", "7000", "-u", "1111", -w, "8181"] - securityContext: - capabilities: - add: - - NET_ADMIN - runAsNonRoot: false - runAsUser: 0 - containers: - - name: test-application - image: sanskardevops/test-application:0.0.1 - ports: - - containerPort: 8080 - - name: envoy - image: envoyproxy/envoy:v1.30-latest - securityContext: - runAsUser: 1111 - imagePullPolicy: IfNotPresent - volumeMounts: - - readOnly: true - mountPath: /config - name: proxy-config - args: - - "envoy" - - "--config-path" - - "/config/envoy.yaml" - - name: kyverno-envoy-plugin - image: sanskardevops/plugin:0.0.34 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8181 - - containerPort: 9000 - volumeMounts: - - readOnly: true - mountPath: /policies - name: policy-files - args: - - "serve" - - "--policy=/policies/policy.yaml" - - "--address=:9000" - - "--healthaddress=:8181" - livenessProbe: - httpGet: - path: /health - scheme: HTTP - port: 8181 - initialDelaySeconds: 5 - periodSeconds: 5 - readinessProbe: - httpGet: - path: /health - scheme: HTTP - port: 8181 - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: proxy-config - configMap: - name: proxy-config - - name: policy-files - configMap: - name: policy-files ---- -# Envoy Config with External Authorization filter that will query kyverno-envoy-plugin. -apiVersion: v1 -kind: ConfigMap -metadata: - name: proxy-config -data: - envoy.yaml: | - static_resources: - listeners: - - address: - socket_address: - address: 0.0.0.0 - port_value: 7000 - filter_chains: - - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - codec_type: auto - stat_prefix: ingress_http - route_config: - name: local_route - virtual_hosts: - - name: backend - domains: - - "*" - routes: - - match: - prefix: "/" - route: - cluster: service - http_filters: - - name: envoy.ext_authz - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz - transport_api_version: V3 - with_request_body: - max_request_bytes: 8192 - allow_partial_message: true - failure_mode_allow: false - grpc_service: - google_grpc: - target_uri: 127.0.0.1:9000 - stat_prefix: ext_authz - timeout: 0.5s - - name: envoy.filters.http.router - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - clusters: - - name: service - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: service - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: 127.0.0.1 - port_value: 8080 - admin: - access_log_path: "/dev/null" - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 - layered_runtime: - layers: - - name: static_layer_0 - static_layer: - envoy: - resource_limits: - listener: - example_listener_name: - connection_limit: 10000 - overload: - global_downstream_max_connections: 50000 ---- -# Example policy to enforce into kyverno-envoy-plugin sidecars. -apiVersion: v1 -kind: ConfigMap -metadata: - name: policy-files -data: - policy.yaml: | - apiVersion: json.kyverno.io/v1alpha1 - kind: ValidatingPolicy - metadata: - name: checkrequest - spec: - rules: - - name: deny-guest-request-at-post - assert: - any: - - message: "POST method calls at path /book are not allowed to guests users" - check: - request: - http: - method: POST - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): admin - path: /book - - message: "GET method call is allowed to both guest and admin users" - check: - request: - http: - method: GET - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): admin - path: /book - - message: "GET method call is allowed to both guest and admin users" - check: - request: - http: - method: GET - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): guest - path: /book - \ No newline at end of file diff --git a/website/docs/jp.md b/website/docs/jp.md deleted file mode 100644 index ee0b890..0000000 --- a/website/docs/jp.md +++ /dev/null @@ -1,15 +0,0 @@ -# Overview - -`kyverno-json` uses [JMESPath community edition](https://jmespath.site/), a modern JMESPath implementation with lexical scopes support. - -The current *payload*, *policy* and *rule* are always available using the following builtin bindings: - -| Binding | Usage | -|---|---| -| `$payload` | Current payload being analysed | -| `$policy` | Current policy being executed | -| `$rule` | Current rule being evaluated | - -!!! warning - - No protection is made to prevent you from overriding those bindings. diff --git a/website/docs/jp/functions.md b/website/docs/jp/functions.md deleted file mode 100644 index 398c684..0000000 --- a/website/docs/jp/functions.md +++ /dev/null @@ -1,108 +0,0 @@ -# Functions - -## built-in functions - -| Name | Signature | -|---|---| -| abs | `abs(number)` | -| avg | `avg(array[number])` | -| ceil | `ceil(number)` | -| contains | `contains(array\|string, any)` | -| ends_with | `ends_with(string, string)` | -| find_first | `find_first(string, string, number, number)` | -| find_last | `find_last(string, string, number, number)` | -| floor | `floor(number)` | -| from_items | `from_items(array[array])` | -| group_by | `group_by(array, expref)` | -| items | `items(object)` | -| join | `join(string, array[string])` | -| keys | `keys(object)` | -| length | `length(string\|array\|object)` | -| lower | `lower(string)` | -| map | `map(expref, array)` | -| max | `max(array[number]\|array[string])` | -| max_by | `max_by(array, expref)` | -| merge | `merge(object)` | -| min | `min(array[number]\|array[string])` | -| min_by | `min_by(array, expref)` | -| not_null | `not_null(any)` | -| pad_left | `pad_left(string, number, string)` | -| pad_right | `pad_right(string, number, string)` | -| replace | `replace(string, string, string, number)` | -| reverse | `reverse(array\|string)` | -| sort | `sort(array[string]\|array[number])` | -| sort_by | `sort_by(array, expref)` | -| split | `split(string, string, number)` | -| starts_with | `starts_with(string, string)` | -| sum | `sum(array[number])` | -| to_array | `to_array(any)` | -| to_number | `to_number(any)` | -| to_string | `to_string(any)` | -| trim | `trim(string, string)` | -| trim_left | `trim_left(string, string)` | -| trim_right | `trim_right(string, string)` | -| type | `type(any)` | -| upper | `upper(string)` | -| values | `values(object)` | -| zip | `zip(array, array)` | - -## custom functions - -| Name | Signature | -|---|---| -| at | `at(array, any)` | -| concat | `concat(string, string)` | -| json_parse | `json_parse(string)` | -| wildcard | `wildcard(string, string)` | - -## kyverno functions - -| Name | Signature | -|---|---| -| compare | `compare(string, string)` | -| equal_fold | `equal_fold(string, string)` | -| replace | `replace(string, string, string, number)` | -| replace_all | `replace_all(string, string, string)` | -| to_upper | `to_upper(string)` | -| to_lower | `to_lower(string)` | -| trim | `trim(string, string)` | -| trim_prefix | `trim_prefix(string, string)` | -| split | `split(string, string)` | -| regex_replace_all | `regex_replace_all(string, string\|number, string\|number)` | -| regex_replace_all_literal | `regex_replace_all_literal(string, string\|number, string\|number)` | -| regex_match | `regex_match(string, string\|number)` | -| pattern_match | `pattern_match(string, string\|number)` | -| label_match | `label_match(object, object)` | -| to_boolean | `to_boolean(string)` | -| add | `add(any, any)` | -| sum | `sum(array)` | -| subtract | `subtract(any, any)` | -| multiply | `multiply(any, any)` | -| divide | `divide(any, any)` | -| modulo | `modulo(any, any)` | -| round | `round(number, number)` | -| base64_decode | `base64_decode(string)` | -| base64_encode | `base64_encode(string)` | -| time_since | `time_since(string, string, string)` | -| time_now | `time_now()` | -| time_now_utc | `time_now_utc()` | -| path_canonicalize | `path_canonicalize(string)` | -| truncate | `truncate(string, number)` | -| semver_compare | `semver_compare(string, string)` | -| parse_json | `parse_json(string)` | -| parse_yaml | `parse_yaml(string)` | -| lookup | `lookup(object\|array, string\|number)` | -| items | `items(object\|array, string, string)` | -| object_from_lists | `object_from_lists(array, array)` | -| random | `random(string)` | -| x509_decode | `x509_decode(string)` | -| time_to_cron | `time_to_cron(string)` | -| time_add | `time_add(string, string)` | -| time_parse | `time_parse(string, string)` | -| time_utc | `time_utc(string)` | -| time_diff | `time_diff(string, string)` | -| time_before | `time_before(string, string)` | -| time_after | `time_after(string, string)` | -| time_between | `time_between(string, string, string)` | -| time_truncate | `time_truncate(string, string)` | - diff --git a/website/docs/policies/asserts.md b/website/docs/policies/asserts.md deleted file mode 100644 index 72be0ee..0000000 --- a/website/docs/policies/asserts.md +++ /dev/null @@ -1,248 +0,0 @@ -# Assertion trees - -Assertion trees can be used to apply complex and dynamic conditional checks using [JMESPath](../jp.md) expressions. - -## Assert - -An `assert` declaration contains an `any` or `all` list in which each entry contains a: - -* `check`: the assertion check -* `message`: an optional message - -A check can contain one or more JMESPath expressions. Expressions represent projections of selected data in the JSON *payload* and the result of this projection is passed to descendants for further analysis. - -All comparisons happen in the leaves of the assertion tree. - -**A simple example**: - -This policy checks that a pod does not use the default service account: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: assert-sample -spec: - rules: - - name: foo-bar - match: - all: - - apiVersion: v1 - kind: Pod - assert: - all: - - message: "serviceAccountName 'default' is not allowed" - check: - spec: - (serviceAccountName == 'default'): false -``` - -**A detailed example**: - -Given the input payload below: - -```yaml -foo: - baz: true - bar: 4 - bat: 6 -``` - -It is possible to write a validation rule like this: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: test -spec: - rules: - - name: foo-bar-4 - validate: - assert: - all: - - message: "..." - check: - # project field `foo` onto itself, the content of `foo` becomes the current object for descendants - foo: - - # evaluate expression `(bar > `3`)`, the boolean result becomes the current object for descendants - # the `true` leaf is compared with the current value `true` - (bar > `3`): true - - # evaluate expression `(!baz)`, the boolean result becomes the current object for descendants - # the leaf `false` is compared with the current value `false` - (!baz): false - - # evaluate expression `(bar + bat)`, the numeric result becomes the current object for descendants - # the leaf `10` is compared with the current value `10` - (bar + bat): 10 -``` - -## Iterating with Projection Modifiers - -Assertion tree expressions support modifiers to influence the way projected values are processed. - -The `~` modifier applies to arrays and maps, it mean the input array or map elements will be processed individually by descendants. - -When the `~` modifier is not used, descendants receive the whole array, not each individual element. - -Consider the following input document: - -```yaml -foo: - bar: - - 1 - - 2 - - 3 -``` - -The policy below does not use the `~` modifier and `foo.bar` array is compared against the expected array: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: test -spec: - rules: - - name: foo-bar - validate: - assert: - all: - - foo: - # the content of the `bar` field will be compared against `[1, 2, 3]` - bar: - - 1 - - 2 - - 3 -``` - -With the `~` modifier, we can apply descendant assertions to all elements in the array individually. -The policy below ensures that all elements in the input array are `< 5`: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: test -spec: - rules: - - name: foo-bar - validate: - assert: - all: - - foo: - # with the `~` modifier all elements in the `[1, 2, 3]` array are processed individually and passed to descendants - ~.bar: - # the expression `(@ < `5`)` is evaluated for every element and the result is expected to be `true` - (@ < `5`): true -``` - -The `~` modifier supports binding the index of the element being processed to a named binding with the following syntax `~index_name.bar`. When this is used, we can access the element index in descendants with `$index_name`. - -When used with a map, the named binding receives the key of the element being processed. - -## Explicit bindings - -Sometimes it can be useful to refer to a parent node in the assertion tree. - -This is possible to add an explicit binding at every node in the tree by appending the `->binding_name` to the key. - -Given the input document: - -```yaml -foo: - bar: 4 - bat: 6 -``` - -The following policy will compute a sum and bind the result to the `sum` binding. A descendant can then use `$sum` and use it: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: test -spec: - rules: - - name: foo-bar - validate: - assert: - all: - - foo: - # evaluate expression `(bar + bat)` and bind it to `sum` - (bar + bat)->sum: - # get the `$sum` binding and compare it against `10` - ($sum): 10 -``` - -All binding are available to descendants, if a descendant creates a binding with a name that already exists the binding will be overridden for descendants only and it doesn't affect the bindings at upper levels in the tree. - -In other words, a node in the tree always sees bindings that are defined in the parents and if a name is reused, the first binding with the given name wins when winding up the tree. - -As a consequence, the policy below will evaluate to true: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: test -spec: - rules: - - name: foo-bar - validate: - assert: - all: - - foo: - (bar + bat)->sum: - ($sum + $sum)->sum: - ($sum): 20 - ($sum): 10 -``` - -Finally, we can always access the current payload, policy and rule being evaluated using the built-in `$payload`, `$policy` and `$rule` bindings. No protection is made to prevent you from overriding those bindings though. - - -## Escaping projection - -It can be necessary to prevent a projection under certain circumstances. - -Consider the following document: - -```yaml -foo: - (bar): 4 - (baz): - - 1 - - 2 - - 3 -``` - -Here the `(bar)` key conflict with the projection syntax. -To workaround this situation, you can escape a projection by surrounding it with `\` characters like this: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: test -spec: - rules: - - name: foo-bar - validate: - assert: - all: - - foo: - \(bar)\: 10 -``` - -In this case, the leading and trailing `\` characters will be erased and the projection won't be applied. - -Note that it's still possible to use the `~` modifier or to create a named binding with and escaped projection. - -Keys like this are perfectly valid: - -- `~index.\baz\` -- `\baz\@foo` -- `~index.\baz\@foo` diff --git a/website/docs/pols/authorization-rules.md b/website/docs/policies/authorization-rules.md similarity index 100% rename from website/docs/pols/authorization-rules.md rename to website/docs/policies/authorization-rules.md diff --git a/website/docs/policies/authz-policy.md b/website/docs/policies/authz-policy.md deleted file mode 100644 index 5013244..0000000 --- a/website/docs/policies/authz-policy.md +++ /dev/null @@ -1,123 +0,0 @@ -# Policy Reference - -This page provides guidance on writing policies for request content processed by the kyverno-json validating policy, utilizing Envoy’s [External Authorization filter](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/security/ext_authz_filter.html). - -### Writing Policies - -Let start with an example policy that restricts access to an endpoint based on user's role and permissions. - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: checkrequest -spec: - rules: - - name: deny-guest-request-at-post - assert: - any: - - message: "POST method calls at path /book are not allowed to guests users" - check: - request: - http: - method: POST - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): admin - path: /book - - message: "GET method call is allowed to both guest and admin users" - check: - request: - http: - method: GET - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): admin - path: /book - - message: "GET method call is allowed to both guest and admin users" - check: - request: - http: - method: GET - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): guest - path: /book -``` - -The above policy uses the `jwt_decode` builtin function to parse and verify the JWT containing information about the user making the request. it uses other builtins like `split`, `base64_decode`, `campare`, `contains` etc kyverno has many different [function](https://kyverno.github.io/kyverno-json/latest/jp/functions/) which can be used in policy. - -Sample input recevied by kyverno-json validating policy is shown below: - -```json -{ - "source": { - "address": { - "socketAddress": { - "address": "10.244.1.10", - "portValue": 59252 - } - } - }, - "destination": { - "address": { - "socketAddress": { - "address": "10.244.1.4", - "portValue": 8080 - } - } - }, - "request": { - "time": "2024-04-09T07:42:29.634453Z", - "http": { - "id": "14694995155993896575", - "method": "GET", - "headers": { - ":authority": "testapp.demo.svc.cluster.local:8080", - ":method": "GET", - ":path": "/book", - ":scheme": "http", - "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6Imd1ZXN0Iiwic3ViIjoiWVd4cFkyVT0ifQ.ja1bgvIt47393ba_WbSBm35NrUhdxM4mOVQN8iXz8lk", - "user-agent": "Wget", - "x-forwarded-proto": "http", - "x-request-id": "27cd2724-e0f4-4a69-a1b1-9a94edfa31bb" - }, - "path": "/book", - "host": "echo.demo.svc.cluster.local:8080", - "scheme": "http", - "protocol": "HTTP/1.1" - } - }, - "metadataContext": {}, - "routeMetadataContext": {} -} -``` - -With the help of assertion tree, we can write policies that can be used to validate the request content. - -An `assert` declaration contains an `any` or `all` list in which each entry contains a `check` and a `message`. The `check` contains a JMESPath expression that is evaluated against the request content. The `message` is a string that is returned when the check fails. -A check can contain one or more JMESPath expressions. Expressions represent projections of seleted data in the JSON payload and the result of this projection is passed to descendants for futher analysis. All comparisons happen in the leaves of the assertion tree. - -For more detail checkout [Policy Structure](https://kyverno.github.io/kyverno-json/latest/policies/policies/) and [Assertion trees](https://kyverno.github.io/kyverno-json/latest/policies/asserts/#assertion-trees). - -- HTTP method `request.http.method` -- Request path `request.http.path` -- Authorization header `request.http.headers.authorization` - -when we decode this above mentioned JWT token in the request payload we get payload.role `guest`: - -```json -{ - "exp": 2241081539, - "nbf": 1514851139, - "role": "guest", - "sub": "YWxpY2U=" -} -``` -With the input value above, the answer is: -``` -true -``` diff --git a/website/docs/pols/failure-policy.md b/website/docs/policies/failure-policy.md similarity index 100% rename from website/docs/pols/failure-policy.md rename to website/docs/policies/failure-policy.md diff --git a/website/docs/pols/index.md b/website/docs/policies/index.md similarity index 100% rename from website/docs/pols/index.md rename to website/docs/policies/index.md diff --git a/website/docs/policies/policies.md b/website/docs/policies/policies.md deleted file mode 100644 index 8eccf1e..0000000 --- a/website/docs/policies/policies.md +++ /dev/null @@ -1,100 +0,0 @@ -# Policy Structure - -Kyverno policies are [Kubernetes resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) and can be easily managed via Kubernetes APIs, GitOps workflows, and other existing tools. - -Policies that apply to JSON payload have a few differences from Kyverno policies that are applied to Kubernetes resources at admission controls. - -## Resource Scope - -Policies that apply to JSON payloads are always cluster-wide resources. - -## API Group and Kind - -`kyverno-json` policies belong to the `json.kyverno.io` group and can only be of kind `ValidatingPolicy`. - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: test -spec: - rules: - - name: foo-bar-4 - validate: - assert: - all: - - foo: - bar: 4 -``` - -## Policy Rules - -A policy can have multiple rules, and rules are processed in order. Evaluation stops at the first rule that fails. - -## Match and Exclude - -Policies that apply to JSON payloads use [assertion trees](./asserts.md) in both the `match`/`exclude` declarations as well as the `validate` rule declaration. - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: required-s3-tags -spec: - rules: - - name: require-team-tag - identifier: address - match: - any: - - type: aws_s3_bucket - exclude: - any: - - name: bypass-me - validate: - assert: - all: - - values: - tags: - Team: ?* -``` - -In the example above, every *resource* having `type: aws_s3_bucket` will match, and *payloads* having `name: bypass-me` will be excluded. - -## Identifying Payload Entries - -A policy rule can contain an optional `identifier` which declares the path to the payload element that uniquely identifies each entry. - -## Context Entries - -A policy rule can contain optional `context` entries that are made available to the rule via bindings: - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: required-s3-tags -spec: - rules: - - name: require-team-tag - match: - any: - - type: aws_s3_bucket - context: - # creates a `expectedTeam` binding automatically - - name: expectedTeam - variable: Kyverno - validate: - message: Bucket `{{ name }}` does not have the required Team tag {{ $expectedTeam }} - assert: - all: - - values: - tags: - # use the `$expectedTeam` binding coming from the context - Team: ($expectedTeam) -``` - -## No `forEach`, `pattern operators`, `anchors`, or `wildcards` - -The use of [assertion trees](./asserts.md) addresses some features of Kyverno policies that apply to Kubernetes resources. - -Specifically, [forEach](https://kyverno.io/docs/writing-policies/validate/#foreach), [pattern operators](https://kyverno.io/docs/writing-policies/validate/#operators), [anchors](https://kyverno.io/docs/writing-policies/validate/#anchors), or [wildcards](https://kyverno.io/docs/writing-policies/validate/#wildcards) are not supported for policies that apply to JSON resources. Instead, [assertion trees](./asserts.md) with [JMESPath](../jp.md) expressions are used to achieve the same powerful features. \ No newline at end of file diff --git a/website/docs/pols/variables.md b/website/docs/policies/variables.md similarity index 100% rename from website/docs/pols/variables.md rename to website/docs/policies/variables.md diff --git a/website/docs/quick-start.md b/website/docs/quick-start.md deleted file mode 100644 index 2dc7092..0000000 --- a/website/docs/quick-start.md +++ /dev/null @@ -1,181 +0,0 @@ -# Quick Start - -This section presumes testing is conducted with Envoy version 1.10.0 or newer. - -### Required tools - -1. [`minikube`](https://minikube.sigs.k8s.io/docs/) -1. [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/) - -### Create a local cluster - -Start minikube cluster with the following command: - -```console -minikube start -``` -### Install kyverno-envoy sidecar with application - -Install application with envoy and kyverno-envoy-plugin as a sidecar container. - -```console -kubectl apply -f https://raw.githubusercontent.com/kyverno/kyverno-envoy-plugin/main/quick_start.yaml -``` -The `applicaition.yaml` manifest defines the following resource: - -- The Deployment includes an example Go application that provides information of books in the library books collection and exposes APIs to `get`, `create` and `delete` books collection. Check this out for more information about the [Go test application](https://github.com/Sanskarzz/kyverno-envoy-demos/tree/main/test-application) . - -- The Deployment also includes a kyverno-envoy-plugin sidecar container in addition to the Envoy sidecar container. When Envoy recevies API request destined for the Go test applicaiton, it will check with kyverno-envoy-plugin to decide if the request should be allowed and the kyverno-envoy-plugin sidecar container is configured to query Kyverno-json engine for policy decisions on incoming requests. - -- A ConfigMap `policy-config` is used to pass the policy to kyverno-envoy-plugin sidecar in the namespace `default` where the application is deployed . - -- A ConfigMap `envoy-config` is used to pass an Envoy configuration with an External Authorization Filter to direct authorization checks to the kyverno-envoy-plugin sidecar. - -- The Deployment also includes an init container that install iptables rules to redirect all container traffic to the Envoy proxy sidecar container , more about init container can be found [here](https://github.com/kyverno/kyverno-envoy-plugin/tree/main/demo/standalone-envoy/envoy_iptables) - -### Make Test application accessible in the cluster . - -```console -kubectl expose deployment testapp --type=NodePort --name=testapp-service --port=8080 -``` - -### Set the `SERVICE_URL` environment variable to the service's IP/port. - -minikube: - -```sh -export SERVICE_PORT=$(kubectl get service testapp -o jsonpath='{.spec.ports[?(@.port==8080)].nodePort}') -export SERVICE_HOST=$(minikube ip) -export SERVICE_URL=$SERVICE_HOST:$SERVICE_PORT -echo $SERVICE_URL -``` -### Calling the sample test application and verify the authorization - -For convenience, we’ll want to store Alice’s and Bob’s tokens in environment variables. Here bob is assigned the admin role and alice is assigned the guest role. - -```bash -export ALICE_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6Imd1ZXN0Iiwic3ViIjoiWVd4cFkyVT0ifQ.ja1bgvIt47393ba_WbSBm35NrUhdxM4mOVQN8iXz8lk" -export BOB_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6ImFkbWluIiwic3ViIjoiWVd4cFkyVT0ifQ.veMeVDYlulTdieeX-jxFZ_tCmqQ_K8rwx2OktUHv5Z0" -``` - -The policy we passed to kyverno-envoy-plugin sidecar in the ConfigMap `policy-config` is configured to check the conditions of the incoming request and denies the request if the user is a guest and the request method is `POST` at the `/book` path. - -```yaml -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: checkrequest -spec: - rules: - - name: deny-guest-request-at-post - assert: - any: - - message: "POST method calls at path /book are not allowed to guests users" - check: - request: - http: - method: POST - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): admin - path: /book - - message: "GET method call is allowed to both guest and admin users" - check: - request: - http: - method: GET - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): admin - path: /book - - message: "GET method call is allowed to both guest and admin users" - check: - request: - http: - method: GET - headers: - authorization: - (split(@, ' ')[1]): - (jwt_decode(@ , 'secret').payload.role): guest - path: /book -``` - -Check for `Alice` which can get book but cannot create book. - -```bash -curl -i -H "Authorization: Bearer "$ALICE_TOKEN"" http://$SERVICE_URL/book -``` -```bash -curl -i -H "Authorization: Bearer "$ALICE_TOKEN"" -d '{"bookname":"Harry Potter", "author":"J.K. Rowling"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/book -``` -Check the `Bob` which can get book also create the book - -```bash -curl -i -H "Authorization: Bearer "$BOB_TOKEN"" http://$SERVICE_URL/book -``` - -```bash -curl -i -H "Authorization: Bearer "$BOB_TOKEN"" -d '{"bookname":"Harry Potter", "author":"J.K. Rowling"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/book -``` - -Check on logs -```bash -kubectl logs "$(kubectl get pod -l app=testapp -o jsonpath={.items..metadata.name})" -c kyverno-envoy-plugin -f -``` -First , third and last request is passed but second request is failed. - -```console -sanskar@sanskar-HP-Laptop-15s-du1xxx:~$ kubectl logs "$(kubectl get pod -l app=testapp -n demo -o jsonpath={.items..metadata.name})" -n demo -c kyverno-envoy-plugin -f -Starting HTTP server on Port 8000 -Starting GRPC server on Port 9000 -Request is initialized in kyvernojson engine . -2024/04/26 17:11:42 Request passed the deny-guest-request-at-post policy rule. -Request is initialized in kyvernojson engine . -2024/04/26 17:22:11 Request violation: -> POST method calls at path /book are not allowed to guests users - -> any[0].check.request.http.headers.authorization.(split(@, ' ')[1]).(jwt_decode(@ , 'secret').payload.role): Invalid value: "guest": Expected value: "admin" --> GET method call is allowed to both guest and admin users - -> any[1].check.request.http.headers.authorization.(split(@, ' ')[1]).(jwt_decode(@ , 'secret').payload.role): Invalid value: "guest": Expected value: "admin" - -> any[1].check.request.http.method: Invalid value: "POST": Expected value: "GET" --> GET method call is allowed to both guest and admin users - -> any[2].check.request.http.method: Invalid value: "POST": Expected value: "GET" -Request is initialized in kyvernojson engine . -2024/04/26 17:23:13 Request passed the deny-guest-request-at-post policy rule. -Request is initialized in kyvernojson engine . -2024/04/26 17:23:55 Request passed the deny-guest-request-at-post policy rule. -``` - -### Configuration - -To deploy Kyverno-Envoy include the following container in your kubernetes Deployments: - -```yaml -- name: kyverno-envoy-plugin - image: sanskardevops/plugin:0.0.34 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8181 - - containerPort: 9000 - volumeMounts: - - readOnly: true - args: - - "serve" - - "--policy=/policies/policy.yaml" - - "--address=:9000" - - "--healthaddress=:8181" - livenessProbe: - httpGet: - path: /health - scheme: HTTP - port: 8181 - initialDelaySeconds: 5 - periodSeconds: 5 - readinessProbe: - httpGet: - path: /health - scheme: HTTP - port: 8181 - initialDelaySeconds: 5 - periodSeconds: 5 -``` \ No newline at end of file diff --git a/website/docs/quick-start/install.md b/website/docs/quick-start/authz-server.md similarity index 96% rename from website/docs/quick-start/install.md rename to website/docs/quick-start/authz-server.md index 9ece33b..a839ac3 100644 --- a/website/docs/quick-start/install.md +++ b/website/docs/quick-start/authz-server.md @@ -1,4 +1,4 @@ -# Installation +# Authz server ## Setup @@ -186,3 +186,9 @@ The following request will return `200` (allowed by our policy): ```bash curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" ``` + +## Wrap Up + +Congratulations on completing the quick start guide! + +This tutorial demonstrated how to configure Istio’s EnvoyFilter to utilize the Kyverno Authz Server as an external authorization service. diff --git a/website/docs/quick-start/next-steps.md b/website/docs/quick-start/next-steps.md index be67b89..f6dbc6a 100644 --- a/website/docs/quick-start/next-steps.md +++ b/website/docs/quick-start/next-steps.md @@ -1,3 +1,14 @@ # Next steps -TODO +We covered the main components of the Kyverno Envoy Plugin. + +!!!tip + + If there's anything you would like to be improved, please [reach out](https://github.com/kyverno/kyverno-envoy-plugin), we will be happy to discuss and improve as much as we can. + +To continue exploring and learn more about the Kyverno Envoy Plugin: + +- [Start writing your own policies](../policies/index.md) +- [Browse the tutorials section](../tutorials) +- [Consult the Reference documentation](../reference/index.md) +- [Engage with our Community and start contributing](../community/index.md) \ No newline at end of file diff --git a/website/docs/quick-start/sidecar-injector.md b/website/docs/quick-start/sidecar-injector.md new file mode 100644 index 0000000..b7cd929 --- /dev/null +++ b/website/docs/quick-start/sidecar-injector.md @@ -0,0 +1,3 @@ +# Sidecar injector + +This is not ready yet, hopefully it will be available soon! \ No newline at end of file diff --git a/website/mkdocs.yaml b/website/mkdocs.yaml index 8309085..2007ab3 100644 --- a/website/mkdocs.yaml +++ b/website/mkdocs.yaml @@ -4,28 +4,20 @@ nav: - Home: index.md - Quick start: - quick-start/index.md - - quick-start/install.md + - quick-start/authz-server.md + - quick-start/sidecar-injector.md - quick-start/next-steps.md - Policies: - - pols/index.md - - pols/failure-policy.md - - pols/variables.md - - pols/authorization-rules.md + - policies/index.md + - policies/failure-policy.md + - policies/variables.md + - policies/authorization-rules.md - CEL extensions: - cel-extensions/index.md - cel-extensions/envoy.md - cel-extensions/jwt.md - Performance: - performance/index.md -- Documentation: - - quick-start.md - - Writing policies: - - policies/policies.md - - policies/asserts.md - - policies/authz-policy.md - - JMESPath: - - Overview: jp.md - - Functions: jp/functions.md - Tutorials: - tutorials/standalone-envoy.md - tutorials/istio.md