diff --git a/web/assets/examples/cel.json b/web/assets/examples/cel.json index 2bb0bfe..dcff520 100644 --- a/web/assets/examples/cel.json +++ b/web/assets/examples/cel.json @@ -2,148 +2,90 @@ "examples": [ { "name": "default", - "data": "// Welcome to the CEL Playground!\n// CEL Playground is an interactive WebAssembly powered environment to explore and experiment with the Common Expression Language (CEL).\n//\n// - Write your CEL expression here\n// - Use the area on the side for input data, in YAML or JSON format\n// - Press 'Run' to evaluate your CEL expression against the input data\n// - Explore our collection of examples for inspiration\n\naccount.balance >= transaction.withdrawal\n || (account.overdraftProtection\n && account.overdraftLimit >= transaction.withdrawal - account.balance)\n", - "inputs": [ - { - "name": "Input", - "data": "# Here is the input data in YAML or JSON format.\n\naccount:\n balance: 500\n overdraftProtection: true\n overdraftLimit: 1000\ntransaction:\n withdrawal: 700\n" - } - ], + "cel": "// Welcome to the CEL Playground!\n// CEL Playground is an interactive WebAssembly powered environment to explore and experiment with the Common Expression Language (CEL).\n//\n// - Write your CEL expression here\n// - Use the area on the side for input data, in YAML or JSON format\n// - Press 'Run' to evaluate your CEL expression against the input data\n// - Explore our collection of examples for inspiration\n\naccount.balance >= transaction.withdrawal\n || (account.overdraftProtection\n && account.overdraftLimit >= transaction.withdrawal - account.balance)\n", + "data": "# Here is the input data in YAML or JSON format.\n\naccount:\n balance: 500\n overdraftProtection: true\n overdraftLimit: 1000\ntransaction:\n withdrawal: 700\n", "category": "default" }, { "name": "Check image registry", - "data": "object.spec.template.spec.containers.all(container,\n params.allowedRegistries.exists(registry,\n ((registry in ['docker.io', 'docker.io/library']) && !container.image.contains('/')) ||\n container.image.startsWith(registry)\n )\n)\n", - "inputs": [ - { - "name": "Input", - "data": "params:\n allowedRegistries: \n - myregistry.com\n - docker.io # use 'docker.io' for Docker Hub\nobject:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: nginx\n image: nginx # the expression looks for this field\n selector:\n matchLabels:\n app: nginx\n" - } - ], + "cel": "object.spec.template.spec.containers.all(container,\n params.allowedRegistries.exists(registry,\n ((registry in ['docker.io', 'docker.io/library']) && !container.image.contains('/')) ||\n container.image.startsWith(registry)\n )\n)\n", + "data": "params:\n allowedRegistries: \n - myregistry.com\n - docker.io # use 'docker.io' for Docker Hub\nobject:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: nginx\n image: nginx # the expression looks for this field\n selector:\n matchLabels:\n app: nginx\n", "category": "Kubernetes" }, { "name": "Disallow HostPorts", - "data": "// According the Pod Security Standards, HostPorts should be disallowed entirely.\n// https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline\n\nobject.spec.template.spec.containers.all(container,\n !has(container.ports) ||\n container.ports.all(port,\n !has(port.hostPort) ||\n port.hostPort == 0\n )\n)\n", - "inputs": [ - { - "name": "Input", - "data": "object:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: nginx\n image: nginx\n ports:\n - containerPort: 80\n hostPort: 80 # the expression looks for this field\n selector:\n matchLabels:\n app: nginx\n" - } - ], + "cel": "// According the Pod Security Standards, HostPorts should be disallowed entirely.\n// https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline\n\nobject.spec.template.spec.containers.all(container,\n !has(container.ports) ||\n container.ports.all(port,\n !has(port.hostPort) ||\n port.hostPort == 0\n )\n)\n", + "data": "object:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: nginx\n image: nginx\n ports:\n - containerPort: 80\n hostPort: 80 # the expression looks for this field\n selector:\n matchLabels:\n app: nginx\n", "category": "Kubernetes" }, { "name": "Require non-root containers", - "data": "// According the Pod Security Standards, Containers must be required to run as non-root users.\n// https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n\n// Pod or Containers must set `securityContext.runAsNonRoot`\n(\n (has(object.spec.template.spec.securityContext) && has(object.spec.template.spec.securityContext.runAsNonRoot)) ||\n object.spec.template.spec.containers.all(container,\n has(container.securityContext) && has(container.securityContext.runAsNonRoot)\n )\n)\n&&\n\n// Neither Pod nor Containers should set `securityContext.runAsNonRoot` to false\n(\n (!has(object.spec.template.spec.securityContext) || !has(object.spec.template.spec.securityContext.runAsNonRoot) || object.spec.template.spec.securityContext.runAsNonRoot != false)\n &&\n object.spec.template.spec.containers.all(container,\n !has(container.securityContext) || !has(container.securityContext.runAsNonRoot) || container.securityContext.runAsNonRoot != false\n )\n)\n", - "inputs": [ - { - "name": "Input", - "data": "object:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n securityContext:\n runAsNonRoot: true # the expression looks for this field\n containers:\n - name: nginx\n image: nginx\n securityContext:\n runAsNonRoot: false # and this one\n selector:\n matchLabels:\n app: nginx\n" - } - ], + "cel": "// According the Pod Security Standards, Containers must be required to run as non-root users.\n// https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n\n// Pod or Containers must set `securityContext.runAsNonRoot`\n(\n (has(object.spec.template.spec.securityContext) && has(object.spec.template.spec.securityContext.runAsNonRoot)) ||\n object.spec.template.spec.containers.all(container,\n has(container.securityContext) && has(container.securityContext.runAsNonRoot)\n )\n)\n&&\n\n// Neither Pod nor Containers should set `securityContext.runAsNonRoot` to false\n(\n (!has(object.spec.template.spec.securityContext) || !has(object.spec.template.spec.securityContext.runAsNonRoot) || object.spec.template.spec.securityContext.runAsNonRoot != false)\n &&\n object.spec.template.spec.containers.all(container,\n !has(container.securityContext) || !has(container.securityContext.runAsNonRoot) || container.securityContext.runAsNonRoot != false\n )\n)\n", + "data": "object:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n securityContext:\n runAsNonRoot: true # the expression looks for this field\n containers:\n - name: nginx\n image: nginx\n securityContext:\n runAsNonRoot: false # and this one\n selector:\n matchLabels:\n app: nginx\n", "category": "Kubernetes" }, { "name": "Drop ALL capabilities", - "data": "// According the Pod Security Standards, Containers must drop `ALL` capabilities, and are only permitted to add back the `NET_BIND_SERVICE` capability.\n// https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n\n// Containers must drop `ALL` capabilities,\nobject.spec.template.spec.containers.all(container,\n has(container.securityContext) &&\n has(container.securityContext.capabilities) &&\n has(container.securityContext.capabilities.drop) &&\n size(container.securityContext.capabilities.drop) >= 1 &&\n container.securityContext.capabilities.drop.exists(c, c == 'ALL')\n)\n&&\n// and are only permitted to add back the `NET_BIND_SERVICE` capability\nobject.spec.template.spec.containers.all(container,\n !has(container.securityContext) ||\n !has(container.securityContext.capabilities) ||\n !has(container.securityContext.capabilities.add) ||\n container.securityContext.capabilities.add.all(cap, cap in params.allowedCapabilities)\n)\n", - "inputs": [ - { - "name": "Input", - "data": "params:\n allowedCapabilities: [NET_BIND_SERVICE]\nobject:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: nginx\n image: nginx\n securityContext:\n capabilities: # the expression looks for this object\n drop: [ALL]\n add: [NET_BIND_SERVICE]\n selector:\n matchLabels:\n app: nginx\n" - } - ], + "cel": "// According the Pod Security Standards, Containers must drop `ALL` capabilities, and are only permitted to add back the `NET_BIND_SERVICE` capability.\n// https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n\n// Containers must drop `ALL` capabilities,\nobject.spec.template.spec.containers.all(container,\n has(container.securityContext) &&\n has(container.securityContext.capabilities) &&\n has(container.securityContext.capabilities.drop) &&\n size(container.securityContext.capabilities.drop) >= 1 &&\n container.securityContext.capabilities.drop.exists(c, c == 'ALL')\n)\n&&\n// and are only permitted to add back the `NET_BIND_SERVICE` capability\nobject.spec.template.spec.containers.all(container,\n !has(container.securityContext) ||\n !has(container.securityContext.capabilities) ||\n !has(container.securityContext.capabilities.add) ||\n container.securityContext.capabilities.add.all(cap, cap in params.allowedCapabilities)\n)\n", + "data": "params:\n allowedCapabilities: [NET_BIND_SERVICE]\nobject:\n apiVersion: apps/v1\n kind: Deployment\n metadata:\n name: nginx\n spec:\n template:\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: nginx\n image: nginx\n securityContext:\n capabilities: # the expression looks for this object\n drop: [ALL]\n add: [NET_BIND_SERVICE]\n selector:\n matchLabels:\n app: nginx\n", "category": "Kubernetes" }, { "name": "Semantic version check for image tags (Regex)", - "data": "// Checks if the container images are tagged following the semantic version.\n\nobject.spec.containers.all(container,\n container.image.contains(\"@sha256\") || // allow digest\n container.image.lastIndexOf(\":\") > -1 &&\n container.image.substring(container.image.lastIndexOf(\":\") + 1)\n .matches('^v?(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$')\n // the regex above is suggested by semver.org: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string\n // allowing the \"v\" prefix\n)\n", - "inputs": [ - { - "name": "Input", - "data": "object:\n apiVersion: v1\n kind: Pod\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: ok1\n image: registry.com:80/nginx:v1.2.3-rc.1\n - name: ok2\n image: registry.com:80/nginx@sha256:asdf\n - name: wrong\n image: registry.com:80/nginx:latest # comment the wrong container to test a success scenario\n" - } - ], + "cel": "// Checks if the container images are tagged following the semantic version.\n\nobject.spec.containers.all(container,\n container.image.contains(\"@sha256\") || // allow digest\n container.image.lastIndexOf(\":\") > -1 &&\n container.image.substring(container.image.lastIndexOf(\":\") + 1)\n .matches('^v?(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$')\n // the regex above is suggested by semver.org: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string\n // allowing the \"v\" prefix\n)\n", + "data": "object:\n apiVersion: v1\n kind: Pod\n metadata:\n name: nginx\n labels:\n app: nginx\n spec:\n containers:\n - name: ok1\n image: registry.com:80/nginx:v1.2.3-rc.1\n - name: ok2\n image: registry.com:80/nginx@sha256:asdf\n - name: wrong\n image: registry.com:80/nginx:latest # comment the wrong container to test a success scenario\n", "category": "Kubernetes" }, { "name": "URLs", - "data": "// Examples of Kubernetes URL CEL library that is available in the playground.\n// https://kubernetes.io/docs/reference/using-api/cel/#kubernetes-url-library\n\nisURL(object.href) \n&& url(object.href).getScheme() == 'https' \n&& url(object.href).getHost() == 'example.com:80'\n&& url(object.href).getHostname() == 'example.com'\n&& url(object.href).getPort() == '80'\n&& url(object.href).getEscapedPath() == '/path'\n&& url(object.href).getQuery().size() == 1\n", - "inputs": [ - { - "name": "Input", - "data": "{\n \"object\": {\n \"href\": \"https://user:pass@example.com:80/path?query=val#fragment\"\n }\n}\n" - } - ], + "cel": "// Examples of Kubernetes URL CEL library that is available in the playground.\n// https://kubernetes.io/docs/reference/using-api/cel/#kubernetes-url-library\n\nisURL(object.href) \n&& url(object.href).getScheme() == 'https' \n&& url(object.href).getHost() == 'example.com:80'\n&& url(object.href).getHostname() == 'example.com'\n&& url(object.href).getPort() == '80'\n&& url(object.href).getEscapedPath() == '/path'\n&& url(object.href).getQuery().size() == 1\n", + "data": "{\n \"object\": {\n \"href\": \"https://user:pass@example.com:80/path?query=val#fragment\"\n }\n}\n", "category": "General" }, { "name": "Check JWT custom claims", - "data": "// Exercise provided in CEL-Go Google Codelab.\n// https://codelabs.developers.google.com/codelabs/cel-go/index.html#10\n// \n// Determine whether the jwt.extra_claims has at least one key that starts\n// with the group prefix, and ensure that all group-like keys have list\n// values containing only strings that end with '@acme.co'.\n\njwt.extra_claims.exists(c, c.startsWith('group'))\n&& jwt.extra_claims\n .filter(c, c.startsWith('group'))\n .all(c, jwt.extra_claims[c]\n .all(g, g.endsWith('@acme.co')))\n", - "inputs": [ - { - "name": "Input", - "data": "jwt: {\n \"iss\": \"auth.acme.com:12350\",\n \"sub\": \"serviceAccount:delegate@acme.co\",\n \"aud\": \"my-project\",\n \"extra_claims\": {\n \"group1\": [\n \"admin@acme.co\",\n \"analyst@acme.co\"\n ],\n \"groupN\": [\n \"forever@acme.co\"\n ],\n \"labels\": [ \"metadata\", \"prod\", \"pii\" ]\n }\n}\n" - } - ], + "cel": "// Exercise provided in CEL-Go Google Codelab.\n// https://codelabs.developers.google.com/codelabs/cel-go/index.html#10\n// \n// Determine whether the jwt.extra_claims has at least one key that starts\n// with the group prefix, and ensure that all group-like keys have list\n// values containing only strings that end with '@acme.co'.\n\njwt.extra_claims.exists(c, c.startsWith('group'))\n&& jwt.extra_claims\n .filter(c, c.startsWith('group'))\n .all(c, jwt.extra_claims[c]\n .all(g, g.endsWith('@acme.co')))\n", + "data": "jwt: {\n \"iss\": \"auth.acme.com:12350\",\n \"sub\": \"serviceAccount:delegate@acme.co\",\n \"aud\": \"my-project\",\n \"extra_claims\": {\n \"group1\": [\n \"admin@acme.co\",\n \"analyst@acme.co\"\n ],\n \"groupN\": [\n \"forever@acme.co\"\n ],\n \"labels\": [ \"metadata\", \"prod\", \"pii\" ]\n }\n}\n", "category": "General" }, - { "name": "Optional", - "data": "object.?foo.orValue(\"fallback\")", - "inputs": [{ "name": "Input", "data": "object: {}" }], + "cel": "object.?foo.orValue(\"fallback\")", + "data": "object: {}", "category": "General" }, { "name": "Duration and timestamp", - "data": "// Validate that 'expired' date is after a 'created' date plus a 'ttl' duration\nhas(object.expired) && \ntimestamp(object.created) + duration(object.ttl) < timestamp(object.expired)\n", - "inputs": [ - { - "name": "Input", - "data": "object:\n created: \"2023-06-14T02:00:14+00:00\"\n ttl: \"5m\"\n expired: \"2023-06-14T02:06:14+00:00\"\n" - } - ], + "cel": "// Validate that 'expired' date is after a 'created' date plus a 'ttl' duration\nhas(object.expired) && \ntimestamp(object.created) + duration(object.ttl) < timestamp(object.expired)\n", + "data": "object:\n created: \"2023-06-14T02:00:14+00:00\"\n ttl: \"5m\"\n expired: \"2023-06-14T02:06:14+00:00\"\n", "category": "General" }, { "name": "Quantity", - "data": "// Quantity library introduced in Kubernetes 1.28\n\nisQuantity(object.memory) && \nquantity(object.memory)\n .add(quantity(\"700M\"))\n .sub(1) // test without this subtraction\n .isLessThan(quantity(object.limit))\n", - "inputs": [ - { "name": "Input", "data": "object:\n memory: 1.3G\n limit: 2G\n" } - ], + "cel": "// Quantity library introduced in Kubernetes 1.28\n\nisQuantity(object.memory) && \nquantity(object.memory)\n .add(quantity(\"700M\"))\n .sub(1) // test without this subtraction\n .isLessThan(quantity(object.limit))\n", + "data": "object:\n memory: 1.3G\n limit: 2G\n", "category": "General" }, { "name": "Access Log Filtering", - "data": "// Use CEL to filter access logs in Istio by response code or target cluster.\n// https://istio.io/latest/docs/tasks/observability/logs/telemetry-api/#get-started-with-telemetry-api\n//\n// apiVersion: telemetry.istio.io/v1alpha1\n// kind: Telemetry\n// metadata:\n// name: default-exception-logging\n// namespace: istio-system\n// spec:\n// accessLogging:\n// - providers:\n// - name: otel\n// filter:\n// expression: \"response.code >= 400 || xds.cluster_name == 'BlackHoleCluster' || xds.cluster_name == 'PassthroughCluster' \"\n\nresponse.code >= 400 || (xds.cluster_name == 'BlackHoleCluster' || xds.cluster_name == 'PassthroughCluster')\n", - "inputs": [ - { - "name": "Input", - "data": "# The following configuration is true access logs only when the response code is greater or equal to 400\n# or the request went to the BlackHoleCluster or the PassthroughCluster\nrequest:\n duration: \"173.403244ms\"\n headers:\n x-request-id: \"e8e687ab-fbbd-4662-8416-11761a29de36\"\n host: \"httpbin.org\"\n id: \"e8e687ab-fbbd-4662-8416-11761a29de36\"\n method: \"GET\"\n path: \"/get\"\n protocol: \"HTTP/1.1\"\n query: \"\"\n referer: null\n scheme: \"http\"\n size: 0\n time: \"2023-10-13T20:32:04.7006+00:00\"\n total_size: 1000\n url_path: \"/get\"\n useragent: \"curl/8.2.1\"\nresponse:\n code: 200\n code_details: \"via_upstream\"\n flags: 0\n grpc_status: 2\n headers:\n content-type: \"application/json\"\n size: 1181\n total_size: 1377\nconnection:\n id: 269\n mtls: false\n requested_server_name: \"\"\nupstream:\n address: \"54.80.46.162:80\"\n local_address: \"10.244.0.37:51128\"\n port: 80\n transport_failure_reason: \"\"\nxds:\n cluster_metadata: \"\"\n cluster_name: \"PassthroughCluster\"\n filter_chain_name: \"\"\n route_metadata: \"\"\n route_name: \"allow_any\"\n upstream_host_metadata: \"NULL\"\n" - } - ], + "cel": "// Use CEL to filter access logs in Istio by response code or target cluster.\n// https://istio.io/latest/docs/tasks/observability/logs/telemetry-api/#get-started-with-telemetry-api\n//\n// apiVersion: telemetry.istio.io/v1alpha1\n// kind: Telemetry\n// metadata:\n// name: default-exception-logging\n// namespace: istio-system\n// spec:\n// accessLogging:\n// - providers:\n// - name: otel\n// filter:\n// expression: \"response.code >= 400 || xds.cluster_name == 'BlackHoleCluster' || xds.cluster_name == 'PassthroughCluster' \"\n\nresponse.code >= 400 || (xds.cluster_name == 'BlackHoleCluster' || xds.cluster_name == 'PassthroughCluster')\n", + "data": "# The following configuration is true access logs only when the response code is greater or equal to 400\n# or the request went to the BlackHoleCluster or the PassthroughCluster\nrequest:\n duration: \"173.403244ms\"\n headers:\n x-request-id: \"e8e687ab-fbbd-4662-8416-11761a29de36\"\n host: \"httpbin.org\"\n id: \"e8e687ab-fbbd-4662-8416-11761a29de36\"\n method: \"GET\"\n path: \"/get\"\n protocol: \"HTTP/1.1\"\n query: \"\"\n referer: null\n scheme: \"http\"\n size: 0\n time: \"2023-10-13T20:32:04.7006+00:00\"\n total_size: 1000\n url_path: \"/get\"\n useragent: \"curl/8.2.1\"\nresponse:\n code: 200\n code_details: \"via_upstream\"\n flags: 0\n grpc_status: 2\n headers:\n content-type: \"application/json\"\n size: 1181\n total_size: 1377\nconnection:\n id: 269\n mtls: false\n requested_server_name: \"\"\nupstream:\n address: \"54.80.46.162:80\"\n local_address: \"10.244.0.37:51128\"\n port: 80\n transport_failure_reason: \"\"\nxds:\n cluster_metadata: \"\"\n cluster_name: \"PassthroughCluster\"\n filter_chain_name: \"\"\n route_metadata: \"\"\n route_name: \"allow_any\"\n upstream_host_metadata: \"NULL\"\n", "category": "Istio" }, { "name": "Custom Metrics", - "data": "// Use CEL to customize the metrics that Istio generates\n// https://istio.io/latest/docs/tasks/observability/metrics/customize-metrics/#use-expressions-for-values\n// \n// apiVersion: telemetry.istio.io/v1alpha1\n// kind: Telemetry\n// metadata:\n// name: namespace-metrics\n// spec:\n// metrics:\n// - providers:\n// - name: prometheus\n// overrides:\n// - match:\n// metric: REQUEST_COUNT\n// tagOverrides:\n// destination_port:\n// value: \"string(destination.port)\" # <--- CEL\n// request_host:\n// value: \"request.host\" # <--- CEL\n\nhas(request.host) ? request.host : \"unknown\"\n", - "inputs": [ - { - "name": "Input", - "data": "request:\n duration: \"4.144461ms\"\n headers:\n x-request-id: \"7a61a297-e508-43b7-94e8-b3919367e2d2\"\n host: \"echo\"\n id: \"7a61a297-e508-43b7-94e8-b3919367e2d2\"\n method: \"GET\"\n path: \"/\"\n protocol: \"HTTP/1.1\"\n query: \"\"\n referer: null\n scheme: \"http\"\n size: 0\n time: \"2023-10-13T20:30:38.106932+00:00\"\n total_size: 478\n url_path: \"/\"\n useragent: \"curl/8.2.1\"\nresponse:\n code: \"200\"\n code_details: \"via_upstream\"\n flags: \"0\"\n grpc_status: \"2\"\n headers:\n content-type: \"application/json\"\n size: 714\n total_size: 1594\nconnection:\n id: 36\n mtls: true\n dns_san_local_certificate: null\n dns_san_peer_certificate: null\n requested_server_name: \"outbound_.80_._.echo.default.svc.cluster.local\"\n sha256_peer_certificate_digest: \"1386a353d125910412d0ecfa7abb2f3fbee9ff3c77dd4d5c19312a8d51e27557\"\n subject_local_certificate: \"\"\n subject_peer_certificate: \"\"\n termination_details: null\n tls_version: \"TLSv1.3\"\n uri_san_local_certificate: \"spiffe://cluster.local/ns/default/sa/default\"\n uri_san_peer_certificate: \"spiffe://cluster.local/ns/default/sa/default\"\nupstream:\n address: \"10.244.0.38:80\"\n dns_san_local_certificate: null\n dns_san_peer_certificate: null\n local_address: \"127.0.0.6:58023\"\n port: 80\n sha256_peer_certificate_digest: null\n subject_local_certificate: null\n subject_peer_certificate: null\n tls_version: null\n transport_failure_reason: \"\"\n uri_san_local_certificate: null\n uri_san_peer_certificate: null\nxds:\n cluster_metadata:\n filter_metadata:\n istio:\n services:\n - host: \"echo.default.svc.cluster.local\"\n name: \"echo\"\n namespace: \"default\"\n cluster_name: \"inbound|80||\"\n filter_chain_name: \"0.0.0.0_80\"\n route_metadata: \"\"\n route_name: \"default\"\n upstream_host_metadata: \"NULL\"\n" - } - ], + "cel": "// Use CEL to customize the metrics that Istio generates\n// https://istio.io/latest/docs/tasks/observability/metrics/customize-metrics/#use-expressions-for-values\n// \n// apiVersion: telemetry.istio.io/v1alpha1\n// kind: Telemetry\n// metadata:\n// name: namespace-metrics\n// spec:\n// metrics:\n// - providers:\n// - name: prometheus\n// overrides:\n// - match:\n// metric: REQUEST_COUNT\n// tagOverrides:\n// destination_port:\n// value: \"string(destination.port)\" # <--- CEL\n// request_host:\n// value: \"request.host\" # <--- CEL\n\nhas(request.host) ? request.host : \"unknown\"\n", + "data": "request:\n duration: \"4.144461ms\"\n headers:\n x-request-id: \"7a61a297-e508-43b7-94e8-b3919367e2d2\"\n host: \"echo\"\n id: \"7a61a297-e508-43b7-94e8-b3919367e2d2\"\n method: \"GET\"\n path: \"/\"\n protocol: \"HTTP/1.1\"\n query: \"\"\n referer: null\n scheme: \"http\"\n size: 0\n time: \"2023-10-13T20:30:38.106932+00:00\"\n total_size: 478\n url_path: \"/\"\n useragent: \"curl/8.2.1\"\nresponse:\n code: \"200\"\n code_details: \"via_upstream\"\n flags: \"0\"\n grpc_status: \"2\"\n headers:\n content-type: \"application/json\"\n size: 714\n total_size: 1594\nconnection:\n id: 36\n mtls: true\n dns_san_local_certificate: null\n dns_san_peer_certificate: null\n requested_server_name: \"outbound_.80_._.echo.default.svc.cluster.local\"\n sha256_peer_certificate_digest: \"1386a353d125910412d0ecfa7abb2f3fbee9ff3c77dd4d5c19312a8d51e27557\"\n subject_local_certificate: \"\"\n subject_peer_certificate: \"\"\n termination_details: null\n tls_version: \"TLSv1.3\"\n uri_san_local_certificate: \"spiffe://cluster.local/ns/default/sa/default\"\n uri_san_peer_certificate: \"spiffe://cluster.local/ns/default/sa/default\"\nupstream:\n address: \"10.244.0.38:80\"\n dns_san_local_certificate: null\n dns_san_peer_certificate: null\n local_address: \"127.0.0.6:58023\"\n port: 80\n sha256_peer_certificate_digest: null\n subject_local_certificate: null\n subject_peer_certificate: null\n tls_version: null\n transport_failure_reason: \"\"\n uri_san_local_certificate: null\n uri_san_peer_certificate: null\nxds:\n cluster_metadata:\n filter_metadata:\n istio:\n services:\n - host: \"echo.default.svc.cluster.local\"\n name: \"echo\"\n namespace: \"default\"\n cluster_name: \"inbound|80||\"\n filter_chain_name: \"0.0.0.0_80\"\n route_metadata: \"\"\n route_name: \"default\"\n upstream_host_metadata: \"NULL\"\n", "category": "Istio" }, { "name": "Blank", + "cel": "", "data": "", - "inputs": [{ "name": "Input", "data": "" }], "category": "Blank" } ], "versions": { - "cel-go": "v0.17.7" + "cel-go": "v0.17.8" } } diff --git a/web/assets/examples/vap.json b/web/assets/examples/vap.json index eaa49c7..ffce93c 100644 --- a/web/assets/examples/vap.json +++ b/web/assets/examples/vap.json @@ -2,72 +2,39 @@ "examples": [ { "name": "Simple Validation", - "data": "apiVersion: admissionregistration.k8s.io/v1alpha1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"force-ha-in-prod\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"apps\"]\n apiVersions: [\"v1\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"deployments\"]\n validations:\n - expression: \"object.spec.replicas >= 3\"\n message: \"All production deployments should be HA with at least three replicas\"\n", - "category": "Validation", - "inputs": [ - { - "name": "Original", - "data": "" - }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { "name": "Namespace", "data": "" }, - { "name": "Request", "data": "" }, - { "name": "Authorizer", "data": "" } - ] + "vap": "apiVersion: admissionregistration.k8s.io/v1alpha1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"force-ha-in-prod\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"apps\"]\n apiVersions: [\"v1\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"deployments\"]\n validations:\n - expression: \"object.spec.replicas >= 3\"\n message: \"All production deployments should be HA with at least three replicas\"\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataNamespace": "", + "dataRequest": "", + "dataAuthorizer": "" }, { "name": "Variables in Validation", - "data": "apiVersion: admissionregistration.k8s.io/v1beta1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"image-matches-namespace-environment.policy.example.com\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"apps\"]\n apiVersions: [\"v1\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"deployments\"]\n variables:\n - name: environment\n expression: \"'environment' in namespaceObject.metadata.labels ? namespaceObject.metadata.labels['environment'] : 'prod'\"\n - name: exempt\n expression: \"'exempt' in object.metadata.labels && object.metadata.labels['exempt'] == true\"\n - name: containers\n expression: \"object.spec.template.spec.containers\"\n - name: containersToCheck\n expression: \"variables.containers.filter(c, c.image.contains('example.com/'))\"\n validations:\n - expression: \"variables.exempt || variables.containersToCheck.all(c, c.image.startsWith(variables.environment + '.'))\"\n messageExpression: \"'only ' + variables.environment + ' images are allowed in namespace ' + namespaceObject.metadata.name\"\n", - "category": "Validation", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n exempt: false\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: prod.policy.example.com/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { - "name": "Namespace", - "data": "apiVersion: v1\nkind: Namespace\nmetadata:\n creationTimestamp: \"2023-03-10T13:50:03Z\"\n labels:\n kubernetes.io/metadata.name: default\n environment: prod\n name: default\n resourceVersion: \"5932\"\n uid: 01d428dd-9515-4e9c-98a3-d8a278ee0125\nspec:\n finalizers:\n - kubernetes\nstatus:\n phase: Active\n" - }, - { "name": "Request", "data": "" }, - { "name": "Authorizer", "data": "" } - ] + "vap": "apiVersion: admissionregistration.k8s.io/v1beta1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"image-matches-namespace-environment.policy.example.com\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"apps\"]\n apiVersions: [\"v1\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"deployments\"]\n variables:\n - name: environment\n expression: \"'environment' in namespaceObject.metadata.labels ? namespaceObject.metadata.labels['environment'] : 'prod'\"\n - name: exempt\n expression: \"'exempt' in object.metadata.labels && object.metadata.labels['exempt'] == true\"\n - name: containers\n expression: \"object.spec.template.spec.containers\"\n - name: containersToCheck\n expression: \"variables.containers.filter(c, c.image.contains('example.com/'))\"\n validations:\n - expression: \"variables.exempt || variables.containersToCheck.all(c, c.image.startsWith(variables.environment + '.'))\"\n messageExpression: \"'only ' + variables.environment + ' images are allowed in namespace ' + namespaceObject.metadata.name\"\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n exempt: false\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: prod.policy.example.com/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataNamespace": "apiVersion: v1\nkind: Namespace\nmetadata:\n creationTimestamp: \"2023-03-10T13:50:03Z\"\n labels:\n kubernetes.io/metadata.name: default\n environment: prod\n name: default\n resourceVersion: \"5932\"\n uid: 01d428dd-9515-4e9c-98a3-d8a278ee0125\nspec:\n finalizers:\n - kubernetes\nstatus:\n phase: Active\n", + "dataRequest": "", + "dataAuthorizer": "" }, { "name": "Match Conditions", - "data": "apiVersion: admissionregistration.k8s.io/v1alpha1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"demo-policy.example.com\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"*\"]\n apiVersions: [\"*\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"*\"]\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n validations:\n - expression: \"!object.metadata.name.contains('demo') || object.metadata.namespace == 'demo'\"\n", - "category": "Conditions", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n environment: prod\n exempt: false\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: prod.registry.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { "name": "Namespace", "data": "" }, - { - "name": "Request", - "data": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n" - }, - { "name": "Authorizer", "data": "" } - ] + "vap": "apiVersion: admissionregistration.k8s.io/v1alpha1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"demo-policy.example.com\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"*\"]\n apiVersions: [\"*\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"*\"]\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n validations:\n - expression: \"!object.metadata.name.contains('demo') || object.metadata.namespace == 'demo'\"\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n environment: prod\n exempt: false\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: prod.registry.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataNamespace": "", + "dataRequest": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n", + "dataAuthorizer": "" }, { "name": "Audit Annotations", - "data": "apiVersion: admissionregistration.k8s.io/v1alpha1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"demo-policy.example.com\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"apps\"]\n apiVersions: [\"v1\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"deployments\"]\n validations:\n - expression: \"object.spec.replicas > 50\"\n messageExpression: \"'Deployment spec.replicas set to ' + string(object.spec.replicas)\"\n auditAnnotations:\n - key: \"high-replica-count\"\n valueExpression: \"'Deployment spec.replicas set to ' + string(object.spec.replicas)\"\n", - "category": "Audit", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n environment: prod\n exempt: false\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: prod.registry.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { "name": "Namespace", "data": "" }, - { "name": "Request", "data": "" }, - { "name": "Authorizer", "data": "" } - ] + "vap": "apiVersion: admissionregistration.k8s.io/v1alpha1\nkind: ValidatingAdmissionPolicy\nmetadata:\n name: \"demo-policy.example.com\"\nspec:\n failurePolicy: Fail\n matchConstraints:\n resourceRules:\n - apiGroups: [\"apps\"]\n apiVersions: [\"v1\"]\n operations: [\"CREATE\", \"UPDATE\"]\n resources: [\"deployments\"]\n validations:\n - expression: \"object.spec.replicas > 50\"\n messageExpression: \"'Deployment spec.replicas set to ' + string(object.spec.replicas)\"\n auditAnnotations:\n - key: \"high-replica-count\"\n valueExpression: \"'Deployment spec.replicas set to ' + string(object.spec.replicas)\"\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n environment: prod\n exempt: false\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 3\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: prod.registry.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataNamespace": "", + "dataRequest": "", + "dataAuthorizer": "" } ], "versions": { diff --git a/web/assets/examples/web_hooks.json b/web/assets/examples/web_hooks.json index 3cd00ec..857932e 100644 --- a/web/assets/examples/web_hooks.json +++ b/web/assets/examples/web_hooks.json @@ -2,91 +2,43 @@ "examples": [ { "name": "Request Accept", - "data": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['*']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Ignore' # Fail-open (optional)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n", - "category": "Request", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { - "name": "Request", - "data": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n" - }, - { "name": "Authorizer", "data": "" } - ] + "webhooks": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['*']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Ignore' # Fail-open (optional)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataRequest": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n", + "dataAuthorizer": "" }, { "name": "Request Ignore Leases", - "data": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['*']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Ignore' # Fail-open (optional)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n", - "category": "Request", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: coordination.k8s.io/v1\nkind: Lease\nmetadata:\n name: ingress-nginx-leader\n namespace: ingress-nginx\nspec:\n acquireTime: \"2023-11-24T16:51:02.229818Z\"\n holderIdentity: ingress-nginx-controller-6597456577-s5h9w\n leaseDurationSeconds: 30\n leaseTransitions: 7\n renewTime: \"2024-04-09T21:59:30.694589Z\"\n" - }, - { - "name": "Request", - "data": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: coordination.k8s.io\n version: v1\n resource: leases\nresource:\n group: coordination.k8s.io\n version: v1\n resource: leases\nrequestKind:\n group: coordination.k8s.io\n version: v1\n resource: leases\nrequestResource:\n group: coordination.k8s.io\n version: v1\n resource: leases\nname: ingress-nginx-leader\nnamespace: ingress-nginx\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n" - }, - { "name": "Authorizer", "data": "" } - ] + "webhooks": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['*']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Ignore' # Fail-open (optional)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: coordination.k8s.io/v1\nkind: Lease\nmetadata:\n name: ingress-nginx-leader\n namespace: ingress-nginx\nspec:\n acquireTime: \"2023-11-24T16:51:02.229818Z\"\n holderIdentity: ingress-nginx-controller-6597456577-s5h9w\n leaseDurationSeconds: 30\n leaseTransitions: 7\n renewTime: \"2024-04-09T21:59:30.694589Z\"\n", + "dataRequest": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: coordination.k8s.io\n version: v1\n resource: leases\nresource:\n group: coordination.k8s.io\n version: v1\n resource: leases\nrequestKind:\n group: coordination.k8s.io\n version: v1\n resource: leases\nrequestResource:\n group: coordination.k8s.io\n version: v1\n resource: leases\nname: ingress-nginx-leader\nnamespace: ingress-nginx\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n", + "dataAuthorizer": "" }, { "name": "Request Ignore Kubelet", - "data": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['*']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Ignore' # Fail-open (optional)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n", - "category": "Request", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { - "name": "Request", - "data": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: node1\n uid: 014fbff9a07c\n groups:\n - system:nodes\n extra:\n some-key:\n - some-value1\n - some-value2\n" - }, - { "name": "Authorizer", "data": "" } - ] + "webhooks": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['*']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Ignore' # Fail-open (optional)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'exclude-leases' # Each match condition must have a unique name\n expression: '!(request.resource.group == \"coordination.k8s.io\" && request.resource.resource == \"leases\")' # Match non-lease resources.\n - name: 'exclude-kubelet-requests'\n expression: '!(\"system:nodes\" in request.userInfo.groups)' # Match requests made by non-node users.\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataRequest": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: node1\n uid: 014fbff9a07c\n groups:\n - system:nodes\n extra:\n some-key:\n - some-value1\n - some-value2\n", + "dataAuthorizer": "" }, { "name": "Authorizer Accept", - "data": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: rbac.my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['apps']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Fail' # Fail-closed (the default)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'breakglass'\n # Skip requests made by users authorized to 'breakglass' on this webhook.\n # The 'breakglass' API verb does not need to exist outside this check.\n expression: '!authorizer.group(\"admissionregistration.k8s.io\").resource(\"validatingwebhookconfigurations\").name(\"rbac.my-webhook.example.com\").check(\"breakglass\").allowed()'\n", - "category": "Authorizer", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { - "name": "Request", - "data": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n" - }, - { "name": "Authorizer", "data": "paths:\ngroups:\nserviceAccounts:\n" } - ] + "webhooks": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: rbac.my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['apps']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Fail' # Fail-closed (the default)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'breakglass'\n # Skip requests made by users authorized to 'breakglass' on this webhook.\n # The 'breakglass' API verb does not need to exist outside this check.\n expression: '!authorizer.group(\"admissionregistration.k8s.io\").resource(\"validatingwebhookconfigurations\").name(\"rbac.my-webhook.example.com\").check(\"breakglass\").allowed()'\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataRequest": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n", + "dataAuthorizer": "paths:\ngroups:\nserviceAccounts:\n" }, { "name": "Authorizer Ignore breakglass", - "data": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: rbac.my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['apps']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Fail' # Fail-closed (the default)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'breakglass'\n # Skip requests made by users authorized to 'breakglass' on this webhook.\n # The 'breakglass' API verb does not need to exist outside this check.\n expression: '!authorizer.group(\"admissionregistration.k8s.io\").resource(\"validatingwebhookconfigurations\").name(\"rbac.my-webhook.example.com\").check(\"breakglass\").allowed()'\n", - "category": "Authorizer", - "inputs": [ - { "name": "Original", "data": "" }, - { - "name": "Updated", - "data": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n" - }, - { - "name": "Request", - "data": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n" - }, - { - "name": "Authorizer", - "data": "paths:\ngroups:\n admissionregistration.k8s.io:\n resources:\n validatingwebhookconfigurations:\n checks:\n \"\":\n rbac.my-webhook.example.com:\n breakglass:\n decision: allow\nserviceAccounts:\n" - } - ] + "webhooks": "apiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nwebhooks:\n - name: rbac.my-webhook.example.com\n matchPolicy: Equivalent\n rules:\n - operations: ['CREATE','UPDATE']\n apiGroups: ['apps']\n apiVersions: ['*']\n resources: ['*']\n failurePolicy: 'Fail' # Fail-closed (the default)\n sideEffects: None\n clientConfig:\n service:\n namespace: my-namespace\n name: my-webhook\n caBundle: 'PGNhYnVuZGxlPgo='\n # You can have up to 64 matchConditions per webhook\n matchConditions:\n - name: 'breakglass'\n # Skip requests made by users authorized to 'breakglass' on this webhook.\n # The 'breakglass' API verb does not need to exist outside this check.\n expression: '!authorizer.group(\"admissionregistration.k8s.io\").resource(\"validatingwebhookconfigurations\").name(\"rbac.my-webhook.example.com\").check(\"breakglass\").allowed()'\n", + "dataOriginal": "", + "dataUpdated": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: kubernetes-bootcamp\n name: kubernetes-bootcamp\n namespace: default\nspec:\n progressDeadlineSeconds: 600\n replicas: 1\n revisionHistoryLimit: 10\n selector:\n matchLabels:\n app: kubernetes-bootcamp\n strategy:\n rollingUpdate:\n maxSurge: 25%\n maxUnavailable: 25%\n type: RollingUpdate\n template:\n metadata:\n creationTimestamp: null\n labels:\n app: kubernetes-bootcamp\n spec:\n containers:\n - image: gcr.io/google-samples/kubernetes-bootcamp:v1\n imagePullPolicy: IfNotPresent\n name: kubernetes-bootcamp\n resources: {}\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n dnsPolicy: ClusterFirst\n restartPolicy: Always\n schedulerName: default-scheduler\n securityContext: {}\n terminationGracePeriodSeconds: 30\n", + "dataRequest": "uid: 705ab4f5-6393-11e8-b7cc-42010a800002\nkind:\n group: apps\n version: v1\n resource: deployments\nresource:\n group: apps\n version: v1\n resource: deployments\nrequestKind:\n group: apps\n version: v1\n resource: deployments\nrequestResource:\n group: apps\n version: v1\n resource: deployments\nname: kubernetes-bootcamp\nnamespace: default\noperation: CREATE\nuserInfo:\n username: admin\n uid: 014fbff9a07c\n groups:\n - system:authenticated\n - my-admin-group\n extra:\n some-key:\n - some-value1\n - some-value2\n", + "dataAuthorizer": "paths:\ngroups:\n admissionregistration.k8s.io:\n resources:\n validatingwebhookconfigurations:\n checks:\n \"\":\n rbac.my-webhook.example.com:\n breakglass:\n decision: allow\nserviceAccounts:\n" } ], "versions": { diff --git a/web/assets/modes.json b/web/assets/modes.json index 7e91d78..2f3490d 100644 --- a/web/assets/modes.json +++ b/web/assets/modes.json @@ -1,14 +1,60 @@ [ { "id": "cel", - "name": "CEL Expression" + "name": "CEL Expression", + "tabs": [ + { + "id": "dataInput", + "Name": "Input" + } + ] }, { "id": "vap", - "name": "ValidatingAdmissionPolicy" + "name": "Validating Admission Policy", + "tabs": [ + { + "id": "dataOriginal", + "Name": "Original" + }, + { + "id": "dataUpdated", + "Name": "Updated" + }, + { + "id": "dataNamespace", + "Name": "Namespace" + }, + { + "id": "dataRequest", + "Name": "Request" + }, + { + "id": "dataAuthorizer", + "Name": "Authorizer" + } + ] }, { - "id": "web_hooks", - "name": "Web Hooks" + "id": "webhooks", + "name": "Web Hooks", + "tabs": [ + { + "id": "dataOriginal", + "Name": "Original" + }, + { + "id": "dataUpdated", + "Name": "Updated" + }, + { + "id": "dataRequest", + "Name": "Request" + }, + { + "id": "dataAuthorizer", + "Name": "Authorizer" + } + ] } ]