> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/cortex-cloud-runtime-security/rules-and-policies/cloud-workload-policies-and-rules/cloud-workload-rules/create-a-new-custom-detection-rule/configure-kubernetes-connector-rule.md).

# Configure Kubernetes connector rule

The **Kubernetes Connector** evaluates Kubernetes resources using rules written in **Rego**. The Kubernetes resource being evaluated is provided directly as the rule input. You can use the resource fields, such as `kind`, `metadata`, and `spec`, to define detection logic.

### Rule structure

A Kubernetes Connector rule must:

* Declare the `panw.compliance` package.
* Import `rego.v1`.
* Define one or more `match` rules to specify the detection logic.
* Assign a human-readable finding description to `msg`.

Use the following basic structure:

```rego
package panw.compliance

import rego.v1

match contains {"msg": msg} if {
    # Your detection logic here
    msg := "Description of the finding"
}
```

The rule is evaluated against each Kubernetes resource selected for the rule. When the detection conditions are satisfied, the `match` rule produces a finding containing the value assigned to `msg`.

### Input structure

The Kubernetes Connector passes the Kubernetes resource object being evaluated directly to the rule as `input`.

Unlike scanners that provide file-based input, the Kubernetes Connector does **not** use a `files` wrapper. Access fields directly from `input`, for example:

```rego
input.kind
input.metadata.name
input.metadata.namespace
input.spec
```

A typical input has the following structure:

```
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "example-app",
    "namespace": "default"
  },
  "spec": {
    "replicas": 2,
    "template": {
      "spec": {
        "containers": [
          {
            "name": "example-container",
            "image": "example/image:latest"
          }
        ]
      }
    }
  }
}
```

The exact fields available in `input` depend on the Kubernetes resource being evaluated.

#### Common input fields

| **Field**                  | **Description**                                                       |
| -------------------------- | --------------------------------------------------------------------- |
| `input.apiVersion`         | Kubernetes API version of the resource.                               |
| `input.kind`               | Kubernetes resource type, such as `Deployment`, `Service`, or `Role`. |
| `input.metadata.name`      | Name of the Kubernetes resource.                                      |
| `input.metadata.namespace` | Namespace containing the resource, when applicable.                   |
| `input.spec`               | Resource specification. The structure depends on the resource kind.   |

### Resource types

When you create a rule, select the Kubernetes resource types to which the rule applies. The rule is evaluated once for each matching resource.

<details>

<summary>Supported resource types</summary>

* **Namespaces**: Logical partitions within a Kubernetes cluster that allow resource isolation and organization.
* **ReplicaSets**: Ensures a specified number of pod replicas are running at all times by automatically scaling up or down.
* **Deployments**: Manages and control pod replicas by providing declarative updates for ReplicaSets, enabling rolling updates and rollbacks.
* **StatefulSets**: Deploys stateful applications that require persistent identity and storage, ensuring stable pod names and ordered scaling.
* **DaemonSets**: Ensures that a copy of a specific pod runs on all or selected nodes in the cluster, commonly used for logging and monitoring agents.
* **Jobs**: Runs one-time or short-lived workloads that complete execution and then terminate.
* **CronJobs**: Defines scheduled jobs that run at specified times or intervals, similar to Linux cron jobs.
* **ClusterRoles**: Defines permissions at the cluster level, granting access to resources across all namespaces.
* **Roles**: Defines permissions within a specific namespace, restricting access to resources within that namespace.
* **RoleBindings**: Associates a role with a user, group, or service account within a specific namespace.
* **ClusterRoleBindings**: Associates a cluster role with users, groups, or service accounts at the cluster-wide level.
* **NetworkPolicies**: Defines rules that control the communication between pods and other network entities within the cluster, enforcing security restrictions.
* **Services**: Exposes a set of pods as a network service, allowing stable communication within and outside the cluster.
* **ServiceAccounts**: Provides an identity for pods to authenticate against the Kubernetes API, allowing controlled access to resources.
* **Endpoints**: Represents the actual network addresses of the pods backing a service, dynamically updated as pods start or stop.
* **Ingresses**: Manages external access to services, providing HTTP/HTTPS routing, load balancing, and SSL termination.
* **ConfigMaps**: Stores non-sensitive configuration data in key-value pairs, allowing applications to retrieve configuration without modifying container images.
* **Secrets**: Securely stores and manage sensitive data, such as API keys, passwords, and certificates, in an encrypted format.
* **Nodes**: Defines the physical or virtual machines that run the workloads in a Kubernetes cluster.

</details>

The fields available in `input` depend on the selected resource type. For example, a `Service` provides service-specific fields under `input.spec`, while a `Deployment` provides its pod template under `input.spec.template`.

### Working with pod specifications

The location of the pod specification depends on the Kubernetes resource kind.

For workloads such as Deployments, DaemonSets, StatefulSets, and Jobs, the pod specification is located at:

```
input.spec.template.spec
```

For CronJobs, it is located at:

```
input.spec.jobTemplate.spec.template.spec
```

When a rule evaluates multiple workload types, normalize the pod specification with a helper rule. This allows the detection logic to use a single `pod_spec` reference.

```rego
pod_spec := input.spec.template.spec if {
    input.kind in {"Deployment", "DaemonSet", "StatefulSet", "Job"}
}

pod_spec := input.spec.jobTemplate.spec.template.spec if {
    input.kind == "CronJob"
}
```

### Examples

The following examples show the Kubernetes resource provided as input, the Rego rule that evaluates the resource, and the finding produced when the rule matches.

#### 1. Detect a privileged container

This example checks Deployments, DaemonSets, StatefulSets, Jobs, and CronJobs for containers with `securityContext.privileged` set to `true`.

**Input**

```
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "example-app",
    "namespace": "default"
  },
  "spec": {
    "template": {
      "spec": {
        "containers": [
          {
            "name": "app",
            "image": "example/app:latest",
            "securityContext": {
              "privileged": true
            }
          }
        ]
      }
    }
  }
}
```

**Rule**

```rego
package panw.compliance

import rego.v1

pod_spec := input.spec.template.spec if {
    input.kind in {"Deployment", "DaemonSet", "StatefulSet", "Job"}
}

pod_spec := input.spec.jobTemplate.spec.template.spec if {
    input.kind == "CronJob"
}

match contains {"msg": msg} if {
    some container in pod_spec.containers
    container.securityContext.privileged == true
    msg := sprintf(
        "%s '%s' in namespace '%s' has a privileged container '%s'",
        [input.kind, input.metadata.name, input.metadata.namespace, container.name],
    )
}
```

**Output**

```
{
  "match": [
    {
      "msg": "Deployment 'example-app' in namespace 'default' has a privileged container 'app'"
    }
  ]
}
```

#### 2. Detect a Service exposed through a LoadBalancer

This example checks whether a Kubernetes `Service` uses the `LoadBalancer` service type.

**Input**

```
{
  "apiVersion": "v1",
  "kind": "Service",
  "metadata": {
    "name": "public-api",
    "namespace": "production"
  },
  "spec": {
    "type": "LoadBalancer",
    "ports": [
      {
        "port": 443,
        "targetPort": 8443
      }
    ]
  }
}
```

**Rule**

```rego
package panw.compliance

import rego.v1

match contains {"msg": msg} if {
    input.kind == "Service"
    input.spec.type == "LoadBalancer"
    msg := sprintf(
        "Service '%s' in namespace '%s' is exposed through a LoadBalancer",
        [input.metadata.name, input.metadata.namespace],
    )
}
```

**Output**

```
{
  "match": [
    {
      "msg": "Service 'public-api' in namespace 'production' is exposed through a LoadBalancer"
    }
  ]
}
```

#### 3. Detect an elevated capability with exclusions

This example detects the `SYS_ADMIN` capability across standard, init, and ephemeral containers.

The rule also defines an explicit list of workload exceptions. Resources matching an exclusion are not reported.

**Input**

```
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "example-app",
    "namespace": "production"
  },
  "spec": {
    "template": {
      "spec": {
        "containers": [
          {
            "name": "app",
            "image": "example/app:latest",
            "securityContext": {
              "capabilities": {
                "add": [
                  "SYS_ADMIN"
                ]
              }
            }
          }
        ]
      }
    }
  }
}
```

**Rule**

```rego
package panw.compliance

import rego.v1

# Workloads that are permitted to hold the capability.
exclusions := [
    {"kind": "DaemonSet", "name": "^cortex-agent$", "namespace": "^cortex-xdr$"},
]

is_excluded(kind, name, namespace) if {
    some exclusion in exclusions
    regex.match(exclusion.kind, kind)
    regex.match(exclusion.name, name)
    regex.match(exclusion.namespace, namespace)
}

pod_spec := input.spec.template.spec if {
    input.kind in {"Deployment", "DaemonSet", "StatefulSet", "Job"}
}

pod_spec := input.spec.jobTemplate.spec.template.spec if {
    input.kind == "CronJob"
}

match contains {"msg": msg} if {
    not is_excluded(input.kind, input.metadata.name, input.metadata.namespace)
    some container in pod_spec.containers
    some cap in container.securityContext.capabilities.add
    cap == "SYS_ADMIN"
    msg := sprintf(
        "%s '%s' in namespace '%s' has container '%s' with the SYS_ADMIN capability added",
        [input.kind, input.metadata.name, input.metadata.namespace, container.name],
    )
}

match contains {"msg": msg} if {
    not is_excluded(input.kind, input.metadata.name, input.metadata.namespace)
    some container in pod_spec.initContainers
    some cap in container.securityContext.capabilities.add
    cap == "SYS_ADMIN"
    msg := sprintf(
        "%s '%s' in namespace '%s' has init container '%s' with the SYS_ADMIN capability added",
        [input.kind, input.metadata.name, input.metadata.namespace, container.name],
    )
}

match contains {"msg": msg} if {
    not is_excluded(input.kind, input.metadata.name, input.metadata.namespace)
    some container in pod_spec.ephemeralContainers
    some cap in container.securityContext.capabilities.add
    cap == "SYS_ADMIN"
    msg := sprintf(
        "%s '%s' in namespace '%s' has ephemeral container '%s' with the SYS_ADMIN capability added",
        [input.kind, input.metadata.name, input.metadata.namespace, container.name],
    )
}
```

**Output**

```
{
  "match": [
    {
      "msg": "Deployment 'example-app' in namespace 'production' has container 'app' with the SYS_ADMIN capability added"
    }
  ]
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://cortex-docs.paloaltonetworks.com/cortex-cloud-runtime-security/rules-and-policies/cloud-workload-policies-and-rules/cloud-workload-rules/create-a-new-custom-detection-rule/configure-kubernetes-connector-rule.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
