docs: add agent policy and genpolicy docs

Add docs for the Agent Policy and for the genpolicy tool.

Signed-off-by: Dan Mihai <dmihai@microsoft.com>
This commit is contained in:
Dan Mihai 2023-12-06 01:10:02 +00:00
parent 57f93195ef
commit 9eb6fd4c24
6 changed files with 822 additions and 12 deletions

View File

@ -27,6 +27,10 @@
Refer to the following guides for additional configuration steps:
- [Kata Containers with ACRN Hypervisor](how-to-use-kata-containers-with-acrn.md)
## Confidential Containers Policy
- [How to auto-generate policy](../../src/tools/genpolicy/README.md)
## Advanced Topics
- [How to use Kata Containers with virtio-fs](how-to-use-virtio-fs-with-kata.md)

View File

@ -14,6 +14,10 @@ When compiled with default settings, the Kata Containers code doesn't include th
1. The Kata Agent gets built using `AGENT_POLICY=yes`, and therefore includes Policy support. If the `AGENT_INIT=yes` build parameter was specified in addition to `AGENT_POLICY=yes`, the Kata Agent will start `OPA` during the Kata Containers sandbox creation.
# Policy format
The Policy document is a text file using the [`Rego` policy language](https://www.openpolicyagent.org/docs/latest/policy-language/). See [Creating the Policy document](#creating-the-policy-document) for information related to creating Policy files.
# Providing the Policy to the Kata Agent
There are two methods for providing the Policy document to the Kata Agent:
@ -66,4 +70,127 @@ While creating the Pod sandbox, the Kata Shim will notice the `io.katacontainers
# How is the Policy being enforced?
The Kata Agent is responsible for enforcing the Policy, working together with `OPA`. The Agent checks the Policy for each [ttRPC API](../../src/libs/protocols/protos/agent.proto) request. Before carrying out the actions corresponding to the request, the Agent uses the [`OPA REST API`](https://www.openpolicyagent.org/docs/latest/rest-api/) to check if the Policy allows or blocks the call. The Agent rejects requests that are not allowed by the Policy.
The Kata Agent is responsible for enforcing the Policy, working together with [`OPA`](https://www.openpolicyagent.org/). The Agent checks the Policy for each [ttRPC API](../../src/libs/protocols/protos/agent.proto) request. Before carrying out the actions corresponding to the request, the Agent uses the [`OPA REST API`](https://www.openpolicyagent.org/docs/latest/rest-api/) to check if the Policy allows or blocks the request. The Agent rejects requests that are not allowed by the Policy.
# Creating the Policy document
## Creating the Policy document manually
For relatively simple uses cases, users can write the Policy text using the [`Rego` policy language documentation](https://www.openpolicyagent.org/docs/latest/policy-language/) as reference.
See [Policy contents](#policy-contents) for additional information.
## Using auto-generated Policy
The [`genpolicy`](../../src/tools/genpolicy/) application can be used to generate automatically a Policy matching an input Kubernetes `YAML` file. The Policy generated by this application is typically used for implementing confidential containers, where the Kata Shim and the Kata Agent have different trust properties.
**Warning** Users should review carefully the automatically-generated Policy, and modify the Policy file if needed to match better their use case, before using this Policy.
See the [`genpolicy` documentation](../../src/tools/genpolicy/README.md) and the [Policy contents examples](#policy-contents) for additional information.
## Policy contents
### The [`Rego`](https://www.openpolicyagent.org/docs/latest/policy-language/) package name
The name of the Kata Agent Policy package must be `agent_policy`. Therefore, all Agent Policy documents must start with:
```
package agent_policy
```
### Default values
When the Kata Shim sends a [ttRPC API](../../src/libs/protocols/protos/agent.proto) request to the Kata Agent, the [Policy rules](#rules) corresponding to that request type are evaluated. For example, when the Agent receives a `CopyFile` request, any rules defined in the Policy that are using the name `CopyFileRequest` are evaluated. [`OPA`](https://www.openpolicyagent.org/) evaluates these rules and tries to find at least one `CopyFileRequest` rule that returns value `true`:
1. If at least one `CopyFileRequest` rule returns `true`, `OPA` returns a `true` result to the Kata Agent, and the Agent carries out the file copy requested by the Shim.
1. If all the `CopyFileRequest` rules return `false`:
- If the Policy includes a default value for `CopyFileRequest`, `OPA` returns that value to the Agent.
- If the Policy doesn't include a default value for `CopyFileRequest`, `OPA` returns an empty response to the Agent. The Agent treats the empty response the same way as a `false` response, so it rejects the `CopyFile` request.
**Tip:** Although the Kata Agent treats empty responses from `OPA` similarly to `false` responses, it is recommended to always provide default values. With default values, the Policy document and the logs from `OPA` and Kata Agent are easier to understand.
Examples of default values:
```
default WaitProcessRequest := true
default ExecProcessRequest := false
```
### Policy data
Policy data is optional. It typically contains values that are compared by the [Policy rules](#rules) with the input parameters of a [ttRPC API](../../src/libs/protocols/protos/agent.proto) request. Based on this comparison, a rule can either allow or deny the request, by returning `true` or `false`.
Example of Policy data:
```
policy_data := {
"common": {
"cpath": "/run/kata-containers/shared/containers"
},
"request_defaults": {
"CopyFileRequest": [
"^$(cpath)/"
],
"ExecProcessRequest": {
"commands": [
"/bin/foo"
],
"regex": []
}
}
}
```
### Rules
Policy rules are optional. They typically compare the input parameters of a [ttRPC API](../../src/libs/protocols/protos/agent.proto) request with values from the [policy data](#policy-data). Based on this comparison, a rule can either allow or deny the request, by returning `true` or `false`.
Multiple rules having the same name can be defined in the same Policy. As described [above](#default-values), when the Kata Agent queries [`OPA`](https://www.openpolicyagent.org/) by using the [`OPA REST API`](https://www.openpolicyagent.org/docs/latest/rest-api/), `OPA` tries to find at least one rule having the same name as the request that returns `true` given the API input parameters defined by the [ttRPC API](../../src/libs/protocols/protos/agent.proto).
Examples of rules, corresponding to the Kata Agent `CopyFile` and `ExecProcess` requests:
```
import future.keywords.in
import input
CopyFileRequest {
print("CopyFileRequest: input.path =", input.path)
some regex1 in policy_data.request_defaults.CopyFileRequest
regex2 := replace(regex1, "$(cpath)", policy_data.common.cpath)
regex.match(regex2, input.path)
print("CopyFileRequest: true")
}
ExecProcessRequest {
print("ExecProcessRequest 1: input =", input)
i_command = concat(" ", input.process.Args)
print("ExecProcessRequest 1: i_command =", i_command)
some p_command in policy_data.request_defaults.ExecProcessRequest.commands
p_command == i_command
print("ExecProcessRequest 1: true")
}
ExecProcessRequest {
print("ExecProcessRequest 2: input =", input)
i_command = concat(" ", input.process.Args)
print("ExecProcessRequest 2: i_command =", i_command)
some p_regex in policy_data.request_defaults.ExecProcessRequest.regex
print("ExecProcessRequest 2: p_regex =", p_regex)
regex.match(p_regex, i_command)
print("ExecProcessRequest 2: true")
}
```
The `input` data from these examples is provided to `OPA` by the Kata Agent, as a ``JSON`` format representation of the API request parameters.
For additional examples of Policy rules, see [`rules.rego`](../../src/tools/genpolicy/rules.rego).

View File

@ -1,7 +1,7 @@
[package]
name = "genpolicy"
version = "0.1.0"
authors = ["The Confidential Containers community https://github.com/confidential-containers"]
authors = ["The Kata Containers community <kata-dev@lists.katacontainers.io>"]
edition = "2021"
[dependencies]

View File

@ -1,25 +1,57 @@
# Agent Policy generation tool
The Kata Containers policy generation tool (`genpolicy`):
The Kata Containers Policy generation tool (`genpolicy`):
1. Reads user's Kubernetes YAML file.
1. Reads user's Kubernetes (`K8s`) `YAML` file.
1. Infers user's intentions based on the contents of that file.
1. Generates a Kata Containers Agent (`kata-agent`) policy file
corresponding to the input YAML, using the Rego/Open Policy Agent
format.
1. Generates a Kata Containers Agent (`kata-agent`) Policy file corresponding to the input `YAML`, using the [Open Policy Agent format](https://www.openpolicyagent.org/docs/latest/policy-language/).
1. Appends the policy as an annotation to user's YAML file.
1. Encodes the auto-generated Policy text in base64 format and appends the encoded string as an annotation to user's `YAML` file.
When the user deploys that YAML file, the Kata Agent uses the attached
policy to reject possible Agent API calls that are not consistent with
the policy.
When the user deploys that `YAML` file through `K8s`, the Kata Agent uses the Policy specified by the `YAML` annotation to reject possible Agent API calls that are not consistent with the policy. For additional information, see [How to use the Kata Agent Policy](../../../docs/how-to/how-to-use-the-kata-agent-policy.md).
The Policy auto-generated by `genpolicy` is typically used for implementing confidential containers, where the Kata Shim and the Kata Agent have different trust properties.
**Warning** Users should review carefully the automatically-generated Policy, and modify the Policy file if needed to match better their use case, before using this Policy.
# Building `genpolicy` from source code
## Install build dependencies
Example for Ubuntu 22.04.3:
```bash
$ sudo apt-get update
$ sudo apt-get install -y build-essential cmake curl git musl-dev musl-tools
$ curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh
$ source "$HOME/.cargo/env"
$ arch=$(uname -m)
$ rustup target add "${arch}-unknown-linux-musl"
```
# Build `genpolicy`
```bash
$ git clone https://github.com/kata-containers/kata-containers.git
$ cd kata-containers/src/tools/genpolicy
$ source "$HOME/.cargo/env"
$ make && make install
```
If you want to use `LIBC=gnu` instead of the default `LIBC=musl`, change the last step above to:
```bash
$ LIBC=gnu make && LIBC=gnu make install
```
# Executing `genpolicy`
Example:
```sh
$ genpolicy -y samples/pod-one-container.yaml
$ genpolicy -y test.yaml
```
For a usage statement, run:
@ -27,3 +59,14 @@ For a usage statement, run:
```sh
$ genpolicy --help
```
For advanced command line parameters, see [`genpolicy` advanced command line parameters](genpolicy-advanced-command-line-parameters.md).
# Supported Kubernetes `YAML` file types
`genpolicy` has support for automatic Policy generation based on Kubernetes `DaemonSet`, `Deployment`, `Job`, `Pod`, `ReplicaSet`, `ReplicationController`, and `StatefulSet` input `YAML` files.
# Policy details
See [auto-generated Policy details](genpolicy-auto-generated-policy-details.md).

View File

@ -0,0 +1,216 @@
# Agent Policy generation tool - advanced command line parameters
See [`genpolicy`](README.md) for general information about the Kata Agent Policy generation tool.
# Basic `genpolicy` usage
The most basic way to use `genpolicy` is to provide just a Kubernetes YAML file as command line parameter - e.g.,
```bash
$ genpolicy -y test.yaml
```
`genpolicy` encodes the auto-generated Policy text in base64 format and appends the encoded string as an annotation to user's `YAML` file.
# Enable `genpolicy` logging
`genpolicy` is using standard Rust logging. To enable logging, use the RUST_LOG environment variable - e.g.,
```bash
$ RUST_LOG=info genpolicy -y test.yaml
```
or
```bash
$ RUST_LOG=debug genpolicy -y test.yaml
```
`RUST_LOG=debug` logs are more detailed than the `RUST_LOG=info` logs.
# Cache container image information
See [`genpolicy` Policy details](genpolicy-auto-generated-policy-details.md) for information regarding the contents of the auto-generated Policy. Part of the Policy contents is information used to verify the integrity of container images. In order to calculate the image integrity information, `genpolicy` needs to download the container images referenced by the `YAML` file. For example, when specifying the following YAML file as parameter:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: policy-test
spec:
runtimeClassName: kata
containers:
- name: first-test-container
image: quay.io/prometheus/busybox:latest
command:
- sleep
- "120"
```
`genpolicy` downloads the `quay.io/prometheus/busybox:latest` container image.
Depending on the size of the container images and the speed of the network connection to the container registry, downloading these images might take several minutes. For testing scenarios where `genpolicy` gets executed several times, it can be useful to cache the container images after downloading them, in order to avoid most of the time needed to download the same container images multiple times. If a container image layer was already cached locally, `genpolicy` uses the local copy of that container layer. The application caches the image information under the `./layers_cache` directory.
**Warning** Using cached image layers can lead to undesirable results. For example, if one or more locally cached layers have been modified (e.g., by an attacker) then the auto-generated Policy will allow those modified container images to be executed on the Guest VM.
To enable caching, use the `-u` command line parameter - e.g.,
```bash
$ RUST_LOG=info genpolicy -u -y test.yaml
```
# Print the Policy text
To print the auto-generated Policy text, in addition to adding its `base64` encoding into the `YAML` file, specify the `-r` parameter - e.g.,
```bash
$ genpolicy -r -y test.yaml
```
# Print the `base64` encoded Policy
To print the `base64` encoded Policy, in addition to adding it into the `YAML` file, specify the `-b` parameter - e.g.,
```bash
$ genpolicy -b -y test.yaml
```
# Use a custom `genpolicy` settings file
The default `genpolicy` settings file is `./genpolicy-settings.json`. Users can specify in the command line a different settings file by using the `-j` parameter - e.g.,
```bash
$ genpolicy -j my-settings.json -y test.yaml
```
# Use a custom path to `genpolicy` input files
By default, the `genpolicy` input files [`rules.rego`](rules.rego) and [`genpolicy-settings.json`](genpolicy-settings.json) must be present in the current directory - otherwise `genpolicy` returns an error. Users can specify a different path to these two files, using the `-i` command line parameter - e.g.,
```bash
$ genpolicy -i /tmp -y test.yaml
```
# Silently ignore unsupported input `YAML` fields
As described by the [Kubernetes docs](https://kubernetes.io/docs/reference/), K8s supports a very large number of fields in `YAML` files. `genpolicy` supports just a subset of these fields (hopefully the most commonly used fields!). The `genpolicy` authors reviewed the `YAML` fields that are supported as inputs to this tool, and evaluated the impact of each field for confidential containers. Some other input fields were not evaluated and/or don't make much sense when present in an input `YAML` file. By default, when `genpolicy` encounters an unsupported field in its input `YAML` file, the application returns an error.
For example, when the input `YAML` contains:
```yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2023-09-18T23:08:02Z"
```
`genpolicy` returns an error, because:
1. Specifying a fixed creation timestamp as input for a pod doesn't seem very helpful.
1. The `genpolicy` authors did not evaluate the potential effects of this field when creating a confidential containers pod.
Users can choose to silently ignore unsupported fields by using the `-s` parameter:
```bash
$ genpolicy -s -y test.yaml
```
**Warning** Ignoring unsupported input `YAML` fields can result in generating an unpredictably incorrect Policy. The `-s` parameter should be used just by expert `K8s` and confidential container users, and only after they carefully evaluate the effects of ignoring these fields.
**Tip** The `-s` parameter can be helpful for example when investigating a problem related to an already created Kubernetes pod - e.g.,:
1. Obtain the existing pod YAML from Kubernetes:
```bash
kubectl get pod my-pod -o yaml > my-pod.yaml
```
2. Auto-generate a Policy corresponding to that `YAML` file:
```bash
$ genpolicy -s -y my-pod.yaml
```
# Specify an input `ConfigMap YAML` file
`genpolicy` doesn't attach a Policy to [`ConfigMap`](https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/config-map-v1/) `YAML` files. However, a `ConfigMap` `YAML` file might be required for generating a reasonable Policy for other types of `YAML` files.
For example, given just this `Pod` input file (`test.yaml`):
```yaml
apiVersion: v1
kind: Pod
metadata:
name: policy-test
spec:
runtimeClassName: kata
containers:
- name: first-test-container
image: quay.io/prometheus/busybox:latest
command:
- sleep
- "120"
env:
- name: CONFIG_MAP_VALUE1
valueFrom:
configMapKeyRef:
key: simple_value1
name: config-map1
```
`genpolicy` is not able to generate the Policy data used to verify the expected value of the CONFIG_MAP_VALUE1 environment variable. There are two ways to specify the required `ConfigMap` information:
## Specify a `ConfigMap` input `YAML` file in the command line
A user can create for example `test-config.yaml` with the following contents:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: config-map1
data:
simple_value1: value1
```
and specify that file in the `genpolicy` command line using the `-c` parameter:
```bash
$ genpolicy -c test-config.yaml -y test.yaml
```
## Add the `ConfigMap` information into the input `YAML` file
The same `ConfigMap` information above can be added to `test.yaml`:
```yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: config-map1
data:
simple_value1: value1
---
apiVersion: v1
kind: Pod
metadata:
name: policy-test
spec:
runtimeClassName: kata
containers:
- name: first-test-container
image: quay.io/prometheus/busybox:latest
command:
- sleep
- "120"
env:
- name: CONFIG_MAP_VALUE1
valueFrom:
configMapKeyRef:
key: simple_value1
name: config-map1
```
and then the `-c` parameter is no longer needed:
```bash
$ genpolicy -y test.yaml
```

View File

@ -0,0 +1,420 @@
# High level overview
This document describes some of the details of the Kata Agent Policy documents auto-generated by the `genpolicy` tool. See [`genpolicy`](README.md) for general information about the Kata Agent Policy generation tool.
See [Policy contents](../../../docs/how-to/how-to-use-the-kata-agent-policy.md#policy-contents) for an introduction to typical Kata Agent Policy document contents.
## Package name
The name of the Kata Agent Policy [`Rego`](https://www.openpolicyagent.org/docs/latest/policy-language/) package must be `agent_policy`:
```
package agent_policy
```
## Default values
For an introduction to Policy default values, see [default values](../../../docs/how-to/how-to-use-the-kata-agent-policy.md#default-values).
`genpolicy` copies the default values from [`rules.rego`](rules.rego) into the auto-generated Policy. Therefore, all Policies generated using the same `rules.rego` file are using the same default values.
Some of the [ttRPC API](../../libs/protocols/protos/agent.proto) requests are always allowed by the auto-generated Policy. Those requests have a default value of `true` and there aren't any rules associated with them. Examples:
```
default CreateSandboxRequest := true
default DestroySandboxRequest := true
```
Other requests have a default value of `false` and there is at least one [rule](#rules) associated with these requests that allows such requests depending on the request input parameters. Examples:
```
default CopyFileRequest := false
default CreateContainerRequest := false
```
## Rules
For an introduction to Policy rules, see [rules](../../../docs/how-to/how-to-use-the-kata-agent-policy.md#rules).
`genpolicy` copies the rules from [`rules.rego`](rules.rego) into the auto-generated Policy. Therefore, all Policies generated using the same `rules.rego` file are using the same rules.
For additional details about the `genpolicy` rules see [`genpolicy` rules details](#rules-details).
## Data
Unlike the [default values](#default-values) and [rules](#rules), the Policy data is specific to each input `YAML` file. `genpolicy` generates Policy data that the [rules](#rules) can use to allow some of the Kata Agent [ttRPC API](../../libs/protocols/protos/agent.proto) requests depending on the input data of these requests. Any unexpected requests are rejected by the Policy.
# Rules details
This section provides details about the [rules](#rules) used by the Policy documents auto-generated by the `genpolicy` tool.
## `CopyFileRequest`
`CopyFile` requests are rejected by the auto-generated Policy unless the destination path of the file being copied matches at least one regular expression from `policy_data.request_defaults.CopyFileRequest`. By default, there is a single regex in `policy_data.request_defaults.CopyFileRequest`, copied by `genpolicy` from [`genpolicy-settings.json`](genpolicy-settings.json):
```
policy_data := {
...
"request_defaults": {
...
"CopyFileRequest": [
"^$(cpath)/"
],
...
},
...
}
```
The tool defines `$(cpath)` by copying its value from the same settings file into Policy's `policy_data.common.cpath`:
```
common := {
...
"cpath": "/run/kata-containers/shared/containers",
...
}
```
Therefore, by default the auto-generated Policy allows the Host to copy any files under `/run/kata-containers/shared/containers` and rejects any other `CopyFile` requests. A user can alter this behavior by using a custom settings file including a different `policy_data.request_defaults.CopyFileRequest` field value, instead of using the default from `genpolicy-settings.json`.
## `CreateContainerRequest`
Most of the rules from [`rules.rego`](rules.rego) are applicable to the `CreateContainer` request, because:
1. The inputs of `CreateContainer` are very complex - e.g., see the Spec data structure from the [OCI protocol](../../libs/protocols/protos/oci.proto).
1. Those complex inputs could allow a buggy or malicious Host to alter the intended behavior of user's Kubernetes (K8s) pods.
For example, the Host could try to start in a confidential containers K8s pod a different container image than the image specified by user's `YAML`. Therefore, the Policy used by each pod has to verify that all the container images being used are exactly those that were referenced by the input `YAML` at the time when the Policy was created.
The auto-generated Policy data contains descriptions of the [`OCI Spec`](../../libs/protocols/protos/oci.proto) data structure corresponding to every container referenced by user's `YAML` file. For example, if `genpolicy` creates a Policy corresponding to a `Pod` that just starts a `busybox` shell, the tool will generate two `OCI` data structures in the Policy - one for the K8s `pause` container and another for the `busybox` shell. Example:
```
policy_data := {
"containers": [
{
"OCI": {
"Version": "1.1.0-rc.1",
"Process": {
"Terminal": false,
"User": {
"UID": 65535,
"GID": 65535,
"AdditionalGids": [],
"Username": ""
},
"Args": [
"/pause"
],
...
},
...
},
...
},
{
"OCI": {
"Version": "1.1.0-rc.1",
"Process": {
"Terminal": false,
"User": {
"UID": 0,
"GID": 0,
"AdditionalGids": [],
"Username": ""
},
"Args": [
"/bin/sh"
],
...
},
...
},
...
}
],
...
```
The auto-generated Policy rules allow the creation of any container that matches at least one of the OCI Policy data structures.
**Warning** The auto-generated Policy doesn't keep track of which containers are already running in a pod. Therefore, in the example above the Kata Shim could start two shell containers instead of just one shell in a single pod - as long as both of these containers match the Policy data for user's shell container.
### [`OCI Spec`](../../libs/protocols/protos/oci.proto) validation
Following are examples of auto-generated Policy rules that check some of the `CreateContainer` input `OCI Spec` data structure fields:
1. The `Version` fields of the `OCI` Policy data and of the input `CreateContainer` data should match.
1. The container `OCI.Root.Readonly` field from the Policy and the input data should have the same value.
1. Each annotation of the container being created should match an annotation from the Policy data. **Warning** Container creation is allowed even if some of the Policy data annotations ***are not present*** in the input `OCI` data annotations. The auto-generated Policy just checks that those annotations that ***are present*** in the input `OCI` are allowed by the Policy data.
1. Verify that the values of the following annotations are consistent with the Policy data:
- `io.katacontainers.pkg.oci.bundle_path`
- `io.katacontainers.pkg.oci.container_type`
- `io.kubernetes.cri.container-name`
- `io.kubernetes.cri.container-type`
- `io.kubernetes.cri.sandbox-log-directory`
- `io.kubernetes.cri.sandbox-id`
- `io.kubernetes.cri.sandbox-name`
- `io.kubernetes.cri.sandbox-namespace`
- `nerdctl/network-namespace`
5. The input `OCI.Linux.Namespaces` information matches the Policy.
5. All the Policy `OCI.Linux.MaskedPaths` paths are present in the input `MaskedPaths` too. **Warning** The input `OCI.Linux.MaskedPaths` is allowed by the auto-generated Policy to include ***more*** paths than the Policy data. But, if a path is masked by the Policy's `oci.Linux.MaskedPaths`, a `CreateContainer` request is rejected if its input data doesn't mask the same path.
5. All the Policy `OCI.Linux.ReadonlyPaths` paths are present either in the input `ReadonlyPaths` or the input `MaskedPaths`. **Warning** the input `ReadonlyPaths` can contain ***more*** paths than the Policy `ReadonlyPaths`, but if the Policy designates a path as `Readonly` then that path must be designated either as `Readonly` or `Masked` by the `CreateContainer` input data.
5. The `Args`, `Cwd`, `NoNewPrivileges`, `Env` and other `OCI.Process` input field values are consistent with the Policy.
5. The input `OCI.Root.Path` matches the Policy data.
5. The input `OCI.Mounts` are allowed by Policy.
### `Storages` validation
`Storages` is another input field of Kata Agent's `CreateContainer` requests. The `Storages` Policy data for each container gets generated by `genpolicy` based on:
1. The container images referenced by user's `YAML` file.
1. Any `volumes` and `volumeMounts` information that might be present in user's `YAML` file.
1. The `volumes` data from [`genpolicy-settings.json`](genpolicy-settings.json).
Example of `Storages` data from an auto-generated Policy file:
```
policy_data := {
"containers": [
...
{
"OCI": {
...
},
"storages": [
{
"driver": "blk",
"driver_options": [],
"source": "",
"fstype": "tar",
"options": [
"$(hash0)"
],
"mount_point": "$(layer0)",
"fs_group": null
},
{
"driver": "blk",
"driver_options": [],
"source": "",
"fstype": "tar",
"options": [
"$(hash1)"
],
"mount_point": "$(layer1)",
"fs_group": null
},
{
"driver": "overlayfs",
"driver_options": [],
"source": "",
"fstype": "fuse3.kata-overlay",
"options": [
"2c342a137e693c7898aec36da1047f191dc7c1687e66198adacc439cf4adf379:2570e3a19e1bf20ddda45498a9627f61555d2d6c01479b9b76460b679b27d552",
"8568c70c0ccfe0051092e818da769111a59882cd19dd799d3bca5ffa82791080:b643b6217748983830b26ac14a35a3322dd528c00963eaadd91ef55f513dc73f"
],
"mount_point": "$(cpath)/$(bundle-id)",
"fs_group": null
},
{
"driver": "local",
"driver_options": [],
"source": "local",
"fstype": "local",
"options": [
"mode=0777"
],
"mount_point": "^$(cpath)/$(sandbox-id)/local/data$",
"fs_group": null
},
{
"driver": "ephemeral",
"driver_options": [],
"source": "tmpfs",
"fstype": "tmpfs",
"options": [],
"mount_point": "^/run/kata-containers/sandbox/ephemeral/data2$",
"fs_group": null
}
],
...
}
],
...
}
```
In this example, the corresponding `CreateContainer` request input is expected to include the following Kata Containers `Storages`:
1. Corresponding to container image layer 0.
1. Corresponding to container image layer 1.
1. Corresponding to the `overlay` of the container images.
1. For the `data` volume of the `YAML` example below.
1. For the `data2` volume of the `YAML` example below.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: persistent
spec:
...
containers:
...
volumeMounts:
- mountPath: /busy1
name: data
- mountPath: /busy2
name: data2
volumes:
- name: data
emptyDir: {}
- name: data2
emptyDir:
medium: Memory
```
`genpolicy` auto-generates the Policy `overlay` layer storage data structure. That structure provides some of the information used to validate the integrity of each container image referenced by user's `YAML` file:
1. An ordered collection of layer IDs.
1. For each layer ID, a `dm-verity` root hash value.
Each container image layer is exposed by the Kata Shim to the Guest VM as a `dm-verity` protected block storage device. If the `CreateContainer` input layer IDs and `dm-verity` root hashes match those from the Policy:
1. The Kata Agent uses the IDs and root hashes and to mount the container image layer storage devices.
1. The Guest kernel ensures the integrity of the container image, by checking the `dm-verity` information of each layer.
## `ExecProcessRequest`
`ExecProcess` requests are rejected by the auto-generated Policy unless:
1. They correspond to an `exec` K8s `livenessProbe`, `readinessProbe` or `startupProbe`, or
1. They correspond to the `policy_data.request_defaults.ExecProcessRequest` data from Policy.
### `exec` probes
Given this example `genpolicy` input `YAML` file as input:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: exec-test
spec:
containers:
...
- command:
- /bin/sh
env:
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
readinessProbe:
exec:
command:
- echo
- "Ready ${POD_IP}!"
failureThreshold: 1
periodSeconds: 5
timeoutSeconds: 10
```
the tool generates the following `ExecProcessRequest` Policy data:
```
policy_data := {
"containers": [
...
{
"OCI": {
...
},
"storages": [
...
],
"exec_commands": [
"echo Ready ${POD_IP}!",
]
}
]
}
```
### `policy_data.request_defaults.ExecProcessRequest`
An `ExecProcess` request is allowed by the auto-generated Policy if its command line matches at least one entry from the `commands` and/or the `regex` fields of the `policy_data.request_defaults.ExecProcessRequest` data structure.
The `commands` and the `regex` entries get copied by `genpolicy` from [`genpolicy-settings.json`](genpolicy-settings.json). By default there are no such entries (both the `commands` and the `regex` collections are empty), so no `ExecProcess` requests are allowed by these two collections.
A user that wants to allow some of the `ExecProcess` requests can specify a modified copy of `genpolicy-settings.json` as parameter to `genpolicy`.
**Warning** The `commands` are easier to use, but require specifying the full command line being allowed by the Policy. The `regex` entries are more flexible - because a single entry can allow multiple `ExecProcess` command lines - but are easier to misuse e.g., by users that are not regular expression experts.
Examples of `policy_data.request_defaults.ExecProcessRequest.commands` entries:
```
policy_data := {
...
"request_defaults": {
...
"ExecProcessRequest": {
"commands": [
"/bin/bash",
"/bin/myapp -p1 -p2"
],
"regex": []
},
...
}
}
```
Examples of `policy_data.request_defaults.ExecProcessRequest.regex` entries:
```
policy_data := {
...
"request_defaults": {
...
"ExecProcessRequest": {
"commands": [],
"regex": [
"^/bin/sh -x -c echo hostName \\| nc -v -t -w 2 externalname-service [0-9]+$",
"^/bin/sh -x -c echo hostName \\| nc -v -t -w 2 [0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+ [0-9]+$"
]
},
...
}
}
```
## `ReadStreamRequest`
`ReadStream` requests are rejected by the default auto-generated Policy. A user can allow the Kata Containers Shim to read the `stdout`/`stderr` streams of the Guest VM containers by allowing these requests using a modified [`genpolicy-settings.json`](genpolicy-settings.json) - e.g.,
```
policy_data := {
...
"request_defaults": {
...
"ReadStreamRequest": true,
...
}
}
```
## `WriteStreamRequest`
By default, `WriteStream` requests are rejected by the auto-generated Policy. A user can allow the Kata Containers Shim to send input to the `stdin` of Guest VM containers by allowing these requests using a modified [`genpolicy-settings.json`](genpolicy-settings.json) - e.g.,
```
policy_data := {
...
"request_defaults": {
...
"WriteStreamRequest": true,
...
}
}
```