From 7d58d3327220c54f97a7c14c72c6994607da7542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Tue, 5 Nov 2024 16:17:23 +0100 Subject: [PATCH 01/11] feat: add kyverno authz server blog post MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .../dynamic-metadata.svg | 1 + .../l7-policy-with-kyverno/filters-chain.svg | 1 + .../blog/2024/l7-policy-with-kyverno/index.md | 464 ++++++++++++++++++ .../2024/l7-policy-with-kyverno/overview.svg | 1 + 4 files changed, 467 insertions(+) create mode 100644 content/en/blog/2024/l7-policy-with-kyverno/dynamic-metadata.svg create mode 100644 content/en/blog/2024/l7-policy-with-kyverno/filters-chain.svg create mode 100644 content/en/blog/2024/l7-policy-with-kyverno/index.md create mode 100644 content/en/blog/2024/l7-policy-with-kyverno/overview.svg diff --git a/content/en/blog/2024/l7-policy-with-kyverno/dynamic-metadata.svg b/content/en/blog/2024/l7-policy-with-kyverno/dynamic-metadata.svg new file mode 100644 index 0000000000000..e86d327e6181c --- /dev/null +++ b/content/en/blog/2024/l7-policy-with-kyverno/dynamic-metadata.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/content/en/blog/2024/l7-policy-with-kyverno/filters-chain.svg b/content/en/blog/2024/l7-policy-with-kyverno/filters-chain.svg new file mode 100644 index 0000000000000..b59f7756dc979 --- /dev/null +++ b/content/en/blog/2024/l7-policy-with-kyverno/filters-chain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/content/en/blog/2024/l7-policy-with-kyverno/index.md b/content/en/blog/2024/l7-policy-with-kyverno/index.md new file mode 100644 index 0000000000000..a993b44a2e9dc --- /dev/null +++ b/content/en/blog/2024/l7-policy-with-kyverno/index.md @@ -0,0 +1,464 @@ +--- +title: "Can Your Platform Do Policy? (A Kyverno revisit)" +description: Is policy your core competency? Likely not, but you need to do right. Do it once with Istio and Kyverno and get back team focus on what matters most. +publishdate: 2024-11-05 +attribution: "Charles-Edouard Brétéché (Nirmata)" +keywords: [istio,kyverno,policy,platform,authorization] +--- + +A couple of weeks ago, the [Can Your Platform Do Policy? Accelerate Teams With Platform L7 Policy Functionality](../l7-policy-with-opa) blog post was published. + +This blog post is a follow-up article, demonstrating the same capacity with the Kyverno Authz Server instead of OPA. + +Today, we're going to dive into how Istio and the Kyverno Authz Server can be used together to enforce Layer 7 policies in your platform. +We'll show you how to get started with a simple example. +You will come to see how this combination is a solid option to deliver policy quickly and transparently to application team everywhere in the business, while also providing the data the security teams need for audit and compliance. + +## Try it out + +When integrated with Istio, the Kyverno Authz Server can be used to enforce fine-grained access control policies for microservices. + +This guide shows how to enforce access control policies for a simple microservices application. + +### Prerequisites + +- A Kubernetes cluster with Istio installed. +- The `istioctl` command-line tool installed. + +Install Istio and configure your [mesh options](/docs/reference/config/istio.mesh.v1alpha1/) to enable Kyverno: + +{{< text bash >}} +$ istioctl install -y -f - <}} + +Notice that in the configuration, we define an `extensionProviders` section that points to the Kyverno Authz Server installation: + +{{< text yaml >}} +[...] + extensionProviders: + - name: kyverno-authz-server.local + envoyExtAuthzGrpc: + service: kyverno-authz-server.kyverno.svc.cluster.local + port: '9081' +[...] +{{< /text >}} + +#### Deploy the Kyverno Authz Server + +The Kyverno Authz Server is a GRPC server capable of processing Envoy External Authorization requests. + +It is configurable using Kyverno `AuthorizationPolicy` resources, either stored in-cluster or provided externally. + +{{< text bash >}} +$ kubectl create ns kyverno +{{< /text >}} +{{< text bash >}} +$ kubectl label namespace kyverno istio-injection=enabled +{{< /text >}} +{{< text bash >}} +$ helm install kyverno-authz-server --namespace kyverno --wait --repo https://kyverno.github.io/kyverno-envoy-plugin kyverno-authz-server +{{< /text >}} + +#### Deploy the sample application + +Httpbin is a well-known application that can be used to test HTTP requests and helps to show quickly how we can play with the request and response attributes. + +{{< text bash >}} +$ kubectl create ns my-app +{{< /text >}} +{{< text bash >}} +$ kubectl label namespace my-app istio-injection=enabled +{{< /text >}} +{{< text bash >}} +$ kubectl apply -f {{< github_file >}}/samples/httpbin/httpbin.yaml -n my-app +{{< /text >}} + +#### Deploy an Istio AuthorizationPolicy + +An `AuthorizationPolicy` defines the services that will be protected by the Kyverno Authz Server. + +{{< text bash >}} +$ kubectl apply -f - <}} + +Notice that in this resource, we define the Kyverno Authz Server `extensionProvider` you set in the Istio configuration: + +{{< text yaml >}} +[...] + provider: + name: kyverno-authz-server.local +[...] +{{< /text >}} + +#### Label the app to enforce the policy + +{{< text bash >}} +$ kubectl patch deploy httpbin -n my-app --type=merge -p='{ + "spec": { + "template": { + "metadata": { + "labels": { + "ext-authz": "enabled" + } + } + } + } +}' +{{< /text >}} + +#### Deploy a Kyverno AuthorizationPolicy + +A Kyverno `AuthorizationPolicy` defines the rules used by the Kyverno Authz Server to make a decision based on a given Envoy [CheckRequest](https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto#service-auth-v3-checkrequest). + +It uses the [CEL language](https://github.com/google/cel-spec) to analyse an incoming `CheckRequest` and is expected to produce a [CheckResponse](https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto#service-auth-v3-checkresponse) in return. + +The incoming request is available under the `object` field, and the policy can define `variables` that will be made available to all `authorizations`. + +{{< text bash >}} +$ kubectl apply -f - < + variables.allowed + ? envoy.Allowed().Response() + : envoy.Denied(403).Response() +EOF +{{< /text >}} + +Notice that you can build the `CheckResponse` by hand or use [CEL helper functions](https://kyverno.github.io/kyverno-envoy-plugin/latest/cel-extensions/) like `envoy.Allowed()` and `envoy.Denied(403)` to simplify creating the response message: + +{{< text yaml >}} +[...] + - expression: > + variables.allowed + ? envoy.Allowed().Response() + : envoy.Denied(403).Response() +[...] +{{< /text >}} + +## How it works + +When applying the `AuthorizationPolicy`, the Istio control plane (istiod) sends the required configurations to the sidecar proxy (Envoy) of the selected services in the policy. +Envoy will then send the request to the Kyverno Authz Server to check if the request is allowed or not. + +{{< image width="75%" link="./overview.svg" alt="Istio and Kyverno Authz Server" >}} + +The Envoy proxy works by configuring filters in a chain. One of those filters is `ext_authz`, which implements an external authorization service with a specific message. Any server implementing the correct protobuf can connect to the Envoy proxy and provide the authorization decision; The Kyverno Authz Server is one of those servers. + +{{< image link="./filters-chain.svg" alt="Filters" >}} + +Reviewing [Envoy's Authorization service documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto), you can see that the message has these attributes: + +- Ok response + + {{< text json >}} + { + "status": {...}, + "ok_response": { + "headers": [], + "headers_to_remove": [], + "response_headers_to_add": [], + "query_parameters_to_set": [], + "query_parameters_to_remove": [] + }, + "dynamic_metadata": {...} + } + {{< /text >}} + +- Denied response + + {{< text json >}} + { + "status": {...}, + "denied_response": { + "status": {...}, + "headers": [], + "body": "..." + }, + "dynamic_metadata": {...} + } + {{< /text >}} + +This means that based on the response from the authz server, Envoy can add or remove headers, query parameters, and even change the response body. + +The Kyverno Authz Server can do this as well, as documented in the [Kyverno Authz Server documentation](https://kyverno.github.io/kyverno-envoy-plugin). + +## Testing + +Let's test the simple usage (authorization) and then let's create a more advanced policy to show how we can use the Kyverno Authz Server to modify the request and response. + +Deploy an app to run curl commands to the httpbin sample application: + +{{< text bash >}} +$ kubectl -n my-app run --image=curlimages/curl curl -- /bin/sleep 100d +{{< /text >}} + +Apply the policy: + +{{< text bash >}} +$ kubectl apply -f - < + variables.allowed + ? envoy.Allowed().Response() + : envoy.Denied(403).Response() +EOF +{{< /text >}} + +The simple scenario is to allow requests if they contain the header `x-force-authorized` with the value `enabled` or `true`. +If the header is not present or has a different value, the request will be denied. + +In this case, we combined allow and denied response handling in a single expression. However it is possible to use multiple expressions, the first one returning a non null response will be used by the Kyverno Authz Server, this is useful when a rule doesn't want to make a decision and delegate to the next rule: + +{{< text yaml >}} +[...] + authorizations: + # allow the request when the header value matches + - expression: > + variables.allowed + ? envoy.Allowed().Response() + : null + # else deny the request + - expression: > + envoy.Denied(403).Response() +[...] +{{< /text >}} + +### Simple rule + +The following request will return `403`: + +{{< text bash >}} +$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get +{{< /text >}} + +The following request will return `200`: + +{{< text bash >}} +$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" +{{< /text >}} + +### Advanced manipulations + +Now the more advanced use case, apply the second policy: + +{{< text bash >}} +$ kubectl apply -f - < 401 + - expression: > + variables.force_unauthenticated + ? envoy + .Denied(401) + .WithBody("Authentication Failed") + .Response() + : null + # if force_authorized -> 200 + - expression: > + variables.force_authorized + ? envoy + .Allowed() + .WithHeader("x-validated-by", "my-security-checkpoint") + .WithoutHeader("x-force-authorized") + .WithResponseHeader("x-add-custom-response-header", "added") + .Response() + .WithMetadata(variables.metadata) + : null + # else -> 403 + - expression: > + envoy + .Denied(403) + .WithBody("Unauthorized Request") + .Response() +EOF +{{< /text >}} + +In that policy, you can see: + +- If the request has the `x-force-unauthenticated: true` header (or `x-force-unauthenticated: enabled`), we will return `401` with the "Authentication Failed" body +- Else, if the request has the `x-force-authorized: true` header (or `x-force-authorized: enabled`), we will return `200` and manipulate request headers, response headers and inject dynamic metadatas +- In all other cases, we will return `403` with the "Unauthorized Request" body + +The corresponding CheckResponse will be returned to the Envoy proxy from the Kyverno Authz Server. Envoy will use those values to modify the request and response accordingly. + +#### Change returned body + +Let's test the new capabilities: + +{{< text bash >}} +$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get +{{< /text >}} + +Now we can change the response body. + +With `403` the body will be changed to "Unauthorized Request", running the previous command, you should receive: + +{{< text plain >}} +Unauthorized Request +http_code=403 +{{< /text >}} + +#### Change returned body and status code + +Running the request with the header `x-force-unauthenticated: true`: + +{{< text bash >}} +$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-unauthenticated: true" +{{< /text >}} + +This time you should receive the body "Authentication Failed" and error `401`: + +{{< text plain >}} +Authentication Failed +http_code=401 +{{< /text >}} + +#### Adding headers to request + +Running a valid request: + +{{< text bash >}} +$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" +{{< /text >}} + +You should receive the echo body with the new header `x-validated-by: my-security-checkpoint` and the header `x-force-authorized` removed: + +{{< text plain >}} +[...] + "X-Validated-By": [ + "my-security-checkpoint" + ] +[...] +http_code=200 +{{< /text >}} + +#### Adding headers to response + +Running the same request but showing only the header: + +{{< text bash >}} +$ kubectl exec -n my-app curl -c curl -- curl -s -I -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" +{{< /text >}} + +You will find the response header added during the Authz check `x-add-custom-response-header: added`: + +{{< text plain >}} +HTTP/1.1 200 OK +[...] +x-add-custom-response-header: added +[...] +http_code=200 +{{< /text >}} + +### Sharing data between filters + +Finally, you can pass data to the following Envoy filters using `dynamic_metadata`. + +This is useful when you want to pass data to another `ext_authz` filter in the chain or you want to print it in the application logs. + +{{< image link="./dynamic-metadata.svg" alt="Metadata" >}} + +To do so, review the access log format you set earlier: + +{{< text plain >}} +[...] + accessLogFormat: | + [KYVERNO DEMO] my-new-dynamic-metadata: "%DYNAMIC_METADATA(envoy.filters.http.ext_authz)%" +[...] +{{< /text >}} + +`DYNAMIC_METADATA` is a reserved keyword to access the metadata object. The rest is the name of the filter that you want to access. + +In our case, the name `envoy.filters.http.ext_authz` is created automatically by Istio. You can verify this by dumping the Envoy configuration: + +{{< text bash >}} +$ istioctl pc all deploy/httpbin -n my-app -oyaml | grep envoy.filters.http.ext_authz +{{< /text >}} + +You will see the configurations for the filter. + +Let's test the dynamic metadata. In the advance rule, we are creating a new metadata entry: `{"my-new-metadata": "my-new-value"}`. + +Run the request and check the logs of the application: + +{{< text bash >}} +$ kubectl exec -n my-app curl -c curl -- curl -s -I httpbin:8000/get -H "x-force-authorized: true" +{{< /text >}} +{{< text bash >}} +$ kubectl logs -n my-app deploy/httpbin -c istio-proxy --tail 1 +{{< /text >}} + +You will see in the output the new attributes configured by the Kyverno policy: + +{{< text plain >}} +[...] +[KYVERNO DEMO] my-new-dynamic-metadata: '{"my-new-metadata":"my-new-value","ext_authz_duration":5}' +[...] +{{< /text >}} + +## Conclusion + +In this guide, we have shown how to integrate Istio and the Kyverno Authz Server to enforce policies for a simple microservices application. +We also showed how to use policies to modify the request and response attributes. + +This is the foundational example for building a platform-wide policy system that can be used by all application teams. diff --git a/content/en/blog/2024/l7-policy-with-kyverno/overview.svg b/content/en/blog/2024/l7-policy-with-kyverno/overview.svg new file mode 100644 index 0000000000000..dfd06e4a01a5d --- /dev/null +++ b/content/en/blog/2024/l7-policy-with-kyverno/overview.svg @@ -0,0 +1 @@ + \ No newline at end of file From 1c5cec956b6766977d1aafd7fd8714e5629f8699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 20 Nov 2024 10:19:01 +0100 Subject: [PATCH 02/11] add kyverno to spelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .spelling | 1 + 1 file changed, 1 insertion(+) diff --git a/.spelling b/.spelling index 7e58c5c9b950a..44170edccc13a 100644 --- a/.spelling +++ b/.spelling @@ -734,6 +734,7 @@ Kumar Kustomization Kustomize kustomize +Kyverno kyzy L2-L4 L3-4 From 1feff8571e8676d1ef8e58d5b1b2cea0925471e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 20 Nov 2024 10:26:41 +0100 Subject: [PATCH 03/11] fix code blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- content/en/blog/2024/l7-policy-with-kyverno/index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/en/blog/2024/l7-policy-with-kyverno/index.md b/content/en/blog/2024/l7-policy-with-kyverno/index.md index a993b44a2e9dc..2bf36c6f570ac 100644 --- a/content/en/blog/2024/l7-policy-with-kyverno/index.md +++ b/content/en/blog/2024/l7-policy-with-kyverno/index.md @@ -65,9 +65,11 @@ It is configurable using Kyverno `AuthorizationPolicy` resources, either stored {{< text bash >}} $ kubectl create ns kyverno {{< /text >}} + {{< text bash >}} $ kubectl label namespace kyverno istio-injection=enabled {{< /text >}} + {{< text bash >}} $ helm install kyverno-authz-server --namespace kyverno --wait --repo https://kyverno.github.io/kyverno-envoy-plugin kyverno-authz-server {{< /text >}} @@ -79,9 +81,11 @@ Httpbin is a well-known application that can be used to test HTTP requests and h {{< text bash >}} $ kubectl create ns my-app {{< /text >}} + {{< text bash >}} $ kubectl label namespace my-app istio-injection=enabled {{< /text >}} + {{< text bash >}} $ kubectl apply -f {{< github_file >}}/samples/httpbin/httpbin.yaml -n my-app {{< /text >}} @@ -444,6 +448,7 @@ Run the request and check the logs of the application: {{< text bash >}} $ kubectl exec -n my-app curl -c curl -- curl -s -I httpbin:8000/get -H "x-force-authorized: true" {{< /text >}} + {{< text bash >}} $ kubectl logs -n my-app deploy/httpbin -c istio-proxy --tail 1 {{< /text >}} From b2a2b3a2eaff6fa6f4fad76a6d97e35c7b895a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 20 Nov 2024 10:36:08 +0100 Subject: [PATCH 04/11] fix spelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .spelling | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.spelling b/.spelling index 44170edccc13a..de3241db58102 100644 --- a/.spelling +++ b/.spelling @@ -223,6 +223,8 @@ Cernich CFP Chaomeng Chavali +CheckRequest +CheckResponse checksum Chircop Chrony From aae9860d1e6a6b160c29bf197399b8ce6f2bacc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 20 Nov 2024 10:43:38 +0100 Subject: [PATCH 05/11] fix spelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- content/en/blog/2024/l7-policy-with-kyverno/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/en/blog/2024/l7-policy-with-kyverno/index.md b/content/en/blog/2024/l7-policy-with-kyverno/index.md index 2bf36c6f570ac..41fd316611b61 100644 --- a/content/en/blog/2024/l7-policy-with-kyverno/index.md +++ b/content/en/blog/2024/l7-policy-with-kyverno/index.md @@ -141,7 +141,7 @@ $ kubectl patch deploy httpbin -n my-app --type=merge -p='{ A Kyverno `AuthorizationPolicy` defines the rules used by the Kyverno Authz Server to make a decision based on a given Envoy [CheckRequest](https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto#service-auth-v3-checkrequest). -It uses the [CEL language](https://github.com/google/cel-spec) to analyse an incoming `CheckRequest` and is expected to produce a [CheckResponse](https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto#service-auth-v3-checkresponse) in return. +It uses the [CEL language](https://github.com/google/cel-spec) to analyze an incoming `CheckRequest` and is expected to produce a [CheckResponse](https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto#service-auth-v3-checkresponse) in return. The incoming request is available under the `object` field, and the policy can define `variables` that will be made available to all `authorizations`. @@ -340,7 +340,7 @@ EOF In that policy, you can see: - If the request has the `x-force-unauthenticated: true` header (or `x-force-unauthenticated: enabled`), we will return `401` with the "Authentication Failed" body -- Else, if the request has the `x-force-authorized: true` header (or `x-force-authorized: enabled`), we will return `200` and manipulate request headers, response headers and inject dynamic metadatas +- Else, if the request has the `x-force-authorized: true` header (or `x-force-authorized: enabled`), we will return `200` and manipulate request headers, response headers and inject dynamic metadata - In all other cases, we will return `403` with the "Unauthorized Request" body The corresponding CheckResponse will be returned to the Envoy proxy from the Kyverno Authz Server. Envoy will use those values to modify the request and response accordingly. From 81121be920e09dd28dbff508cb9bfc0f8ed72741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 20 Nov 2024 13:49:06 +0100 Subject: [PATCH 06/11] update title and description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .../dynamic-metadata.svg | 0 .../filters-chain.svg | 0 .../index.md | 6 +++--- .../overview.svg | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename content/en/blog/2024/{l7-policy-with-kyverno => authz-policy-with-kyverno}/dynamic-metadata.svg (100%) rename content/en/blog/2024/{l7-policy-with-kyverno => authz-policy-with-kyverno}/filters-chain.svg (100%) rename content/en/blog/2024/{l7-policy-with-kyverno => authz-policy-with-kyverno}/index.md (98%) rename content/en/blog/2024/{l7-policy-with-kyverno => authz-policy-with-kyverno}/overview.svg (100%) diff --git a/content/en/blog/2024/l7-policy-with-kyverno/dynamic-metadata.svg b/content/en/blog/2024/authz-policy-with-kyverno/dynamic-metadata.svg similarity index 100% rename from content/en/blog/2024/l7-policy-with-kyverno/dynamic-metadata.svg rename to content/en/blog/2024/authz-policy-with-kyverno/dynamic-metadata.svg diff --git a/content/en/blog/2024/l7-policy-with-kyverno/filters-chain.svg b/content/en/blog/2024/authz-policy-with-kyverno/filters-chain.svg similarity index 100% rename from content/en/blog/2024/l7-policy-with-kyverno/filters-chain.svg rename to content/en/blog/2024/authz-policy-with-kyverno/filters-chain.svg diff --git a/content/en/blog/2024/l7-policy-with-kyverno/index.md b/content/en/blog/2024/authz-policy-with-kyverno/index.md similarity index 98% rename from content/en/blog/2024/l7-policy-with-kyverno/index.md rename to content/en/blog/2024/authz-policy-with-kyverno/index.md index 41fd316611b61..00fec82a4884f 100644 --- a/content/en/blog/2024/l7-policy-with-kyverno/index.md +++ b/content/en/blog/2024/authz-policy-with-kyverno/index.md @@ -1,7 +1,7 @@ --- -title: "Can Your Platform Do Policy? (A Kyverno revisit)" -description: Is policy your core competency? Likely not, but you need to do right. Do it once with Istio and Kyverno and get back team focus on what matters most. -publishdate: 2024-11-05 +title: Policy based authorization - Using Kyverno Authz Server +description: Delegate authorization decisions logic to Kyverno Authz Server, leveraging Kyverno authorization policies based on CEL bringing safety, flexibility, and unprecedented performance. +publishdate: 2024-11-20 attribution: "Charles-Edouard Brétéché (Nirmata)" keywords: [istio,kyverno,policy,platform,authorization] --- diff --git a/content/en/blog/2024/l7-policy-with-kyverno/overview.svg b/content/en/blog/2024/authz-policy-with-kyverno/overview.svg similarity index 100% rename from content/en/blog/2024/l7-policy-with-kyverno/overview.svg rename to content/en/blog/2024/authz-policy-with-kyverno/overview.svg From 95001c434208a9bc8d11843cf5cd1c9495d3f886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Thu, 21 Nov 2024 09:06:43 +0100 Subject: [PATCH 07/11] address review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .../2024/authz-policy-with-kyverno/index.md | 39 +++++++------------ 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/content/en/blog/2024/authz-policy-with-kyverno/index.md b/content/en/blog/2024/authz-policy-with-kyverno/index.md index 00fec82a4884f..012b2aea9c114 100644 --- a/content/en/blog/2024/authz-policy-with-kyverno/index.md +++ b/content/en/blog/2024/authz-policy-with-kyverno/index.md @@ -1,17 +1,14 @@ --- -title: Policy based authorization - Using Kyverno Authz Server -description: Delegate authorization decisions logic to Kyverno Authz Server, leveraging Kyverno authorization policies based on CEL bringing safety, flexibility, and unprecedented performance. +title: Policy based authorization using Kyverno +description: Delegate Layer 7 authorization decision logic using Kyverno's Authz Server, leveraging policies based on CEL. publishdate: 2024-11-20 attribution: "Charles-Edouard Brétéché (Nirmata)" keywords: [istio,kyverno,policy,platform,authorization] --- -A couple of weeks ago, the [Can Your Platform Do Policy? Accelerate Teams With Platform L7 Policy Functionality](../l7-policy-with-opa) blog post was published. +Istio supports integration with many different projects. The Istio blog recently featured a post on [L7 policy functionality with OpenPolicyAgent](../l7-policy-with-opa). Kyverno is a similar project, and today we will dive how Istio and the Kyverno Authz Server can be used together to enforce Layer 7 policies in your platform. -This blog post is a follow-up article, demonstrating the same capacity with the Kyverno Authz Server instead of OPA. - -Today, we're going to dive into how Istio and the Kyverno Authz Server can be used together to enforce Layer 7 policies in your platform. -We'll show you how to get started with a simple example. +We will show you how to get started with a simple example. You will come to see how this combination is a solid option to deliver policy quickly and transparently to application team everywhere in the business, while also providing the data the security teams need for audit and compliance. ## Try it out @@ -37,7 +34,7 @@ spec: accessLogFormat: | [KYVERNO DEMO] my-new-dynamic-metadata: '%DYNAMIC_METADATA(envoy.filters.http.ext_authz)%' extensionProviders: - - name: kyverno-authz-server.local + - name: kyverno-authz-server envoyExtAuthzGrpc: service: kyverno-authz-server.kyverno.svc.cluster.local port: '9081' @@ -49,7 +46,7 @@ Notice that in the configuration, we define an `extensionProviders` section that {{< text yaml >}} [...] extensionProviders: - - name: kyverno-authz-server.local + - name: kyverno-authz-server envoyExtAuthzGrpc: service: kyverno-authz-server.kyverno.svc.cluster.local port: '9081' @@ -64,29 +61,17 @@ It is configurable using Kyverno `AuthorizationPolicy` resources, either stored {{< text bash >}} $ kubectl create ns kyverno -{{< /text >}} - -{{< text bash >}} $ kubectl label namespace kyverno istio-injection=enabled -{{< /text >}} - -{{< text bash >}} $ helm install kyverno-authz-server --namespace kyverno --wait --repo https://kyverno.github.io/kyverno-envoy-plugin kyverno-authz-server {{< /text >}} #### Deploy the sample application -Httpbin is a well-known application that can be used to test HTTP requests and helps to show quickly how we can play with the request and response attributes. +httpbin is a well-known application that can be used to test HTTP requests and helps to show quickly how we can play with the request and response attributes. {{< text bash >}} $ kubectl create ns my-app -{{< /text >}} - -{{< text bash >}} $ kubectl label namespace my-app istio-injection=enabled -{{< /text >}} - -{{< text bash >}} $ kubectl apply -f {{< github_file >}}/samples/httpbin/httpbin.yaml -n my-app {{< /text >}} @@ -100,14 +85,14 @@ apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: my-kyverno-authz - namespace: istio-system # This enforce the policy on all the mesh being istio-system the mesh config namespace + namespace: istio-system # This enforce the policy on all the mesh, istio-system being the mesh root namespace spec: selector: matchLabels: ext-authz: enabled action: CUSTOM provider: - name: kyverno-authz-server.local + name: kyverno-authz-server rules: [{}] # Empty rules, it will apply to selectors with ext-authz: enabled label EOF {{< /text >}} @@ -117,12 +102,14 @@ Notice that in this resource, we define the Kyverno Authz Server `extensionProvi {{< text yaml >}} [...] provider: - name: kyverno-authz-server.local + name: kyverno-authz-server [...] {{< /text >}} #### Label the app to enforce the policy +Let’s label the app to enforce the policy. The label is needed for the Istio `AuthorizationPolicy` to apply to the sample application pods. + {{< text bash >}} $ kubectl patch deploy httpbin -n my-app --type=merge -p='{ "spec": { @@ -222,7 +209,7 @@ Reviewing [Envoy's Authorization service documentation](https://www.envoyproxy.i This means that based on the response from the authz server, Envoy can add or remove headers, query parameters, and even change the response body. -The Kyverno Authz Server can do this as well, as documented in the [Kyverno Authz Server documentation](https://kyverno.github.io/kyverno-envoy-plugin). +We can do this as well, as documented in the [Kyverno Authz Server documentation](https://kyverno.github.io/kyverno-envoy-plugin). ## Testing From aa94c4167df8757f2b54b9ecdcd394444900dbfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Thu, 21 Nov 2024 09:14:34 +0100 Subject: [PATCH 08/11] fix testing commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- content/en/blog/2024/authz-policy-with-kyverno/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/blog/2024/authz-policy-with-kyverno/index.md b/content/en/blog/2024/authz-policy-with-kyverno/index.md index 012b2aea9c114..33313910633a3 100644 --- a/content/en/blog/2024/authz-policy-with-kyverno/index.md +++ b/content/en/blog/2024/authz-policy-with-kyverno/index.md @@ -218,7 +218,7 @@ Let's test the simple usage (authorization) and then let's create a more advance Deploy an app to run curl commands to the httpbin sample application: {{< text bash >}} -$ kubectl -n my-app run --image=curlimages/curl curl -- /bin/sleep 100d +$ kubectl apply -n my-app -f {{< github_file >}}/samples/curl/curl.yaml {{< /text >}} Apply the policy: From 4c3c9b49c628b9ef78791c301283182ac9524e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Thu, 21 Nov 2024 09:19:09 +0100 Subject: [PATCH 09/11] fix testing commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .../blog/2024/authz-policy-with-kyverno/index.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/en/blog/2024/authz-policy-with-kyverno/index.md b/content/en/blog/2024/authz-policy-with-kyverno/index.md index 33313910633a3..65efeb13c6e5d 100644 --- a/content/en/blog/2024/authz-policy-with-kyverno/index.md +++ b/content/en/blog/2024/authz-policy-with-kyverno/index.md @@ -268,13 +268,13 @@ In this case, we combined allow and denied response handling in a single express The following request will return `403`: {{< text bash >}} -$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get +$ kubectl exec -n my-app deploy/curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get {{< /text >}} The following request will return `200`: {{< text bash >}} -$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" +$ kubectl exec -n my-app deploy/curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" {{< /text >}} ### Advanced manipulations @@ -337,7 +337,7 @@ The corresponding CheckResponse will be returned to the Envoy proxy from the Kyv Let's test the new capabilities: {{< text bash >}} -$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get +$ kubectl exec -n my-app deploy/curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get {{< /text >}} Now we can change the response body. @@ -354,7 +354,7 @@ http_code=403 Running the request with the header `x-force-unauthenticated: true`: {{< text bash >}} -$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-unauthenticated: true" +$ kubectl exec -n my-app deploy/curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-unauthenticated: true" {{< /text >}} This time you should receive the body "Authentication Failed" and error `401`: @@ -369,7 +369,7 @@ http_code=401 Running a valid request: {{< text bash >}} -$ kubectl exec -n my-app curl -c curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" +$ kubectl exec -n my-app deploy/curl -- curl -s -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" {{< /text >}} You should receive the echo body with the new header `x-validated-by: my-security-checkpoint` and the header `x-force-authorized` removed: @@ -388,7 +388,7 @@ http_code=200 Running the same request but showing only the header: {{< text bash >}} -$ kubectl exec -n my-app curl -c curl -- curl -s -I -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" +$ kubectl exec -n my-app deploy/curl -- curl -s -I -w "\nhttp_code=%{http_code}" httpbin:8000/get -H "x-force-authorized: true" {{< /text >}} You will find the response header added during the Authz check `x-add-custom-response-header: added`: @@ -433,7 +433,7 @@ Let's test the dynamic metadata. In the advance rule, we are creating a new meta Run the request and check the logs of the application: {{< text bash >}} -$ kubectl exec -n my-app curl -c curl -- curl -s -I httpbin:8000/get -H "x-force-authorized: true" +$ kubectl exec -n my-app deploy/curl -- curl -s -I httpbin:8000/get -H "x-force-authorized: true" {{< /text >}} {{< text bash >}} From 20a225a1a77b687a8fae03273eb1964adf413472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Thu, 21 Nov 2024 09:29:47 +0100 Subject: [PATCH 10/11] fix spelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .spelling | 1 + 1 file changed, 1 insertion(+) diff --git a/.spelling b/.spelling index de3241db58102..48789b81fd08d 100644 --- a/.spelling +++ b/.spelling @@ -895,6 +895,7 @@ OpenCensus OpenID OpenID_Connect OpenMetrics +OpenPolicyAgent OpenShift OpenSSL openssl From 423fb93acdbadbf24a76dce867bbac024bb7edff Mon Sep 17 00:00:00 2001 From: Craig Box Date: Tue, 26 Nov 2024 12:07:22 +1300 Subject: [PATCH 11/11] change post date to today --- content/en/blog/2024/authz-policy-with-kyverno/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/blog/2024/authz-policy-with-kyverno/index.md b/content/en/blog/2024/authz-policy-with-kyverno/index.md index 65efeb13c6e5d..62155a3cc3863 100644 --- a/content/en/blog/2024/authz-policy-with-kyverno/index.md +++ b/content/en/blog/2024/authz-policy-with-kyverno/index.md @@ -1,7 +1,7 @@ --- title: Policy based authorization using Kyverno description: Delegate Layer 7 authorization decision logic using Kyverno's Authz Server, leveraging policies based on CEL. -publishdate: 2024-11-20 +publishdate: 2024-11-25 attribution: "Charles-Edouard Brétéché (Nirmata)" keywords: [istio,kyverno,policy,platform,authorization] ---