# User namespaces and CRI-O

The purpose of this document is to show how to configure user namespaces in CRI-O, as well as some of the options CRI-O supports for configuring user namespaces.

## Setup

### /etc/sub{g,u}id
To start, the host will have to have `/etc/subuid` and `/etc/subgid` files set correctly. By default, the [library CRI-O uses for container storage](https://github.com/containers/storage) assumes there will be entries in each of these files for the `containers` user. If one would like to have a different user's entries in `/etc/sub?id` files, then the field `remap-user` and `remap-group` can be configured in `/etc/containers/storage.conf` in the `[storage.options]` table.

Let's assume we want the IDs of the users and groups to begin on the host at 100000, and be each given ranges of 65536. For most containers, this will be more than enough. The contents of both `/etc/subuid` and `/etc/subgid` should be:
```
containers:100000:65536
```

### CRI-O configuration
To enable pods to be able to use the userns-mode annotation, the pod must be allowed to interpret the experimental annotation `io.kubernetes.cri-o.userns-mode`.
#### 1.23.0 and beyond
In CRI-O versions greater than 1.23.0, this can be done by creating a custom workload. This can be done by creating a file with the following contents in /etc/crio/crio.conf.d/01-userns-workload.conf
```
[crio.runtime.workloads.userns]
activation_annotation = "io.kubernetes.cri-o.userns-mode"
allowed_annotations = ["io.kubernetes.cri-o.userns-mode"]
```

This will allow any pod with the `io.kubernetes.cri-o.userns-mode` annotation to configure a user namespace. CRI-O opts for this approach to give admins the ability to toggle the behavior on their nodes, just in case an admin doesn't want their users to be able to create user namespace. An admin can also set a different `activation_annotation` if they'd like a different annotation to allow pods to configure user namespaces.

#### 1.20.0 - 1.22.z
CRI-O has supported this experimental annotation since 1.20.0. Originally, it was supported by setting allowed annotation in the runtime class, not the workload. Setting allowed_annotations on runtimes have been deprecated, and newer installations should use workloads instead. To create a runtime class that allows the user namespace annotation, the following file can be created:
```
[crio.runtime.runtimes.userns]
runtime_path = "/usr/bin/runc"
runtime_root = "/run/runc"
allowed_annotations = ["io.kubernetes.cri-o.userns-mode"]
```

`runtime_path` and `runtime_root` can be configured differently, but must be specified.

The name `userns` will be the one that must be specified in the pod's `runtimeClassName` field. See [this article](https://kubernetes.io/docs/concepts/containers/runtime-class/) for more details. The remainder of this document will assume workloads are being used.

### Pod Spec Changes
Now that the pod is allowed to specify the annotation, it must actually be done in the pod spec. We will use the simplest example "auto" for this pod spec:

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  annotations:
      io.kubernetes.cri-o.userns-mode: "auto"
```

In this case, upon pod creation, the pod will have a user namespace automatically configured for it. With a user on the host that is greater than 100000 and with a size of 65536.

## User Namespace Configuration

### Auto
The auto keyword tells CRI-O that a user namespace should be configured for the pod by CRI-O. This is a good option for users who are new to user namespaces, or don't have precise needs for the feature.

#### RunAs{User,Group} and User Namespaces
When RunAsUser or RunAsGroup are specified for a container in a pod, and the user namespace mode is "auto", the user namespace is configured to have that user inside of the user namespace, but the user in the host user namespace is in the range configured in `/etc/subuid`.

For instance, in RunAsUser is set to `1234` for a pod that specifies auto along with the `/etc/subuid` configuration above, the pod user inside the pod sees itself as `1234`. However, from the perspective of the host, the pod user could actually be `101234`.

This allows for the container process to think it is running as user 1234 for file access inside of the container, but actually be a much higher ID on the host.

