在 Fedora 中结合权能使用 Podman
Podman 权能
![](/data/attachment/album/202011/25/220701co4nmvtpkpjwzvno.jpg)


容器化是一项蓬勃发展的技术。在不久的将来，多达百分之七十五的全球组织可能会运行某种类型的容器化技术。由于广泛使用的技术更容易成为黑客攻击的目标，因此保护容器的安全就显得尤为重要。本文将演示如何使用 POSIX <ruby> <a href="https://www.linuxjournal.com/magazine/making-root-unprivileged">  权能 </a> <rt>  Capability </rt></ruby> 来保护 Podman 容器的安全。Podman 是 RHEL8 中默认的容器管理工具。


### 确定 Podman 容器的权限模式


容器以特权模式或无特权模式运行。在特权模式下，[容器的 uid 0 被映射到宿主机的 uid 0](https://linuxcontainers.org/lxc/security/#privileged-containers)。对于某些情况，无特权的容器[缺乏对宿主机资源的充分访问能力](https://github.com/containers/podman/blob/master/rootless.md)。但不管其操作模式如何，包括<ruby> 强制访问控制 <rt>  Mandatory Access Control </rt></ruby>（MAC：如 apparmor、SELinux 等）、seccomp 过滤器、删除<ruby> 权能 <rt>  Capability </rt></ruby>、命名空间等在内的技术有助于确保容器的安全。


要从容器外部确定特权模式：



```
$ podman inspect --format="{{.HostConfig.Privileged}}" <container id>

```

如果上面的命令返回 `true`，那么容器在特权模式下运行。如果返回 `false`，那么容器在非特权模式下运行。


要从容器内部确定特权模式：



```
$ ip link add dummy0 type dummy

```

如果该命令允许你创建一个接口，那么你运行的是一个特权容器，否则你运行的是一个非特权容器。


### 权能


命名空间隔离了容器的进程，使其无法任意访问宿主机的资源，也无法访问在同一宿主机上运行的其他容器的资源。然而，在**特权**容器内的进程仍然可以做一些事情，如改变 IP 路由表、跟踪任意进程和加载内核模块。<ruby> 权能 <rt>  Capability </rt></ruby>允许人们对容器内的进程可以访问或更改的资源施加更细微的限制，即使容器在特权模式下运行也一样。权能还允许人们为无特权的容器分配它本来不会拥有的特权。


例如，如果要将 `NET_ADMIN` 功能添加到一个无特权的容器中，以便在容器内部创建一个网络接口，你可以用下面的参数运行 `podman`：



```
[root@vm1 ~]# podman run -it --cap-add=NET_ADMIN centos
[root@b27fea33ccf1 /]# ip link add dummy0 type dummy
[root@b27fea33ccf1 /]# ip link

```

上面的命令演示了在一个无特权的容器中创建一个 `dummy0` 接口。如果没有 `NET_ADMIN` 权能，非特权容器将无法创建接口。上面的命令演示了如何将一个权能授予一个无特权的容器。


目前，大约有 [39 种权能](https://man7.org/linux/man-pages/man7/capabilities.7.html)可以被授予或拒绝。特权容器默认会被授予许多权能。建议从特权容器中删除不需要的权能，以使其更加安全。


要从容器中删除所有权能：



```
$ podman run -it -d --name mycontainer --cap-drop=all centos

```

列出一个容器的权能：



```
$ podman exec -it 48f11d9fa512 capsh --print

```

上述命令显示没有向容器授予任何权能。


请参考 `capabilities` 手册页以获取完整的权能列表：



```
$ man capabilities

```

可以使用 `capsh` 命令来列出目前拥有的权能：



```
$ capsh --print

```

作为另一个例子，下面的命令演示了如何从容器中删除 `NET_RAW` 权能。如果没有 `NET_RAW` 权能，就不能从容器中 `ping` 互联网上的服务器。



```
$ podman run -it --name mycontainer1 --cap-drop=net_raw centos
>>> ping google.com (will output error, operation not permitted)

```

最后一个例子，如果你的容器只需要 `SETUID` 和 `SETGID` 权能，你可以删除所有权能，然后只重新添加这两个权能来实现这样的权限设置。



```
$ podman run -d --cap-drop=all --cap-add=setuid --cap-add=setgid fedora sleep 5 > /dev/null; pscap | grep sleep

```

上面的 `pscap` 命令会显示容器被授予的权能。


我希望你喜欢这个关于如何使用权能来保护 Podman 容器的简短探索。


谢谢！




---


via: <https://fedoramagazine.org/podman-with-capabilities-on-fedora/>


作者：[shiwanibiradar](https://fedoramagazine.org/author/shiwanibiradar/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
Containerization is a booming technology. As many as seventy-five percent of global organizations could be running some type of containerization technology in the near future. Since widely used technologies are more likely to be targeted by hackers, securing containers is especially important. This article will demonstrate how [POSIX capabilities](https://www.linuxjournal.com/magazine/making-root-unprivileged) are used to secure Podman containers. Podman is the default container management tool in RHEL8.

## Determine the Podman container’s privilege mode

Containers run in either privileged or unprivileged mode. In privileged mode, [the container uid 0 is mapped to the host’s uid 0](https://linuxcontainers.org/lxc/security/#privileged-containers). For some use cases, unprivileged containers [lack sufficient access](https://github.com/containers/podman/blob/master/rootless.md) to the resources of the host machine. Technologies and techniques including Mandatory Access Control (apparmor, SELinux), seccomp filters, dropping of capabilities, and namespaces help to secure containers regardless of their mode of operation.

**To determine the privilege mode from outside the container:**

$ podman inspect --format="{{.HostConfig.Privileged}}" <container id>

If the above command returns *true* then the container is running in privileged mode. If it returns *false* then the container is running in unprivileged mode.

**To determine the privilege mode from inside the container:**

$ ip link add dummy0 type dummy

If this command allows you to create an interface then you are running a privileged container. Otherwise you are running an unprivileged container.

## Capabilities

Namespaces isolate a container’s processes from arbitrary access to the resources of its host and from access to the resources of other containers running on the same host. Processes within *privileged* containers, however, might still be able to do things like alter the IP routing table, trace arbitrary processes, and load kernel modules. Capabilities allow one to apply finer-grained restrictions on what resources the processes within a container can access or alter; even when the container is running in privileged mode. Capabilities also allow one to assign privileges to an unprivileged container that it would not otherwise have.

For example, to add the *NET_ADMIN* capability to an unprivileged container so that a network interface can be created inside of the container, you would run *podman* with parameters similar to the following:

[root@vm1 ~]# podman run -it --cap-add=NET_ADMIN centos [root@b27fea33ccf1 /]# ip link add dummy0 type dummy [root@b27fea33ccf1 /]# ip link

The above commands demonstrate a *dummy0* interface being created in an unprivileged container. Without the *NET_ADMIN* capability, an unprivileged container would not be able to create an interface. The above commands demonstrate how to grant a capability to an unprivileged container.

Currently, there are about [39 capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) that can be granted or denied. Privileged containers are granted many capabilities by default. It is advisable to drop unneeded capabilities from privileged containers to make them more secure.

**To drop all capabilities from a container:**

$ podman run -it -d --name mycontainer --cap-drop=all centos

**To list a container’s capabilities:**

$ podman exec -it 48f11d9fa512 capsh --print

The above command should show that no capabilities are granted to the container.

**Refer to the capabilities man page for a complete list of capabilities:**

$ man capabilities

**Use the capsh command to list the capabilities you currently possess:**

$ capsh --print

As another example, the below command demonstrates dropping the *NET_RAW* capability from a container. Without the *NET_RAW* capability, servers on the internet cannot be pinged from within the container.

$ podman run -it --name mycontainer1 --cap-drop=net_raw centos >>> ping google.com (will output error, operation not permitted)

As a final example, if your container were to only need the *SETUID* and *SETGID* capabilities, you could achieve such a permission set by dropping all capabilities and then re-adding only those two.

$ podman run -d --cap-drop=all --cap-add=setuid --cap-add=setgid fedora sleep 5 > /dev/null; pscap | grep sleep

The *pscap* command shown above should show the capabilities that have been granted to the container.

I hope you enjoyed this brief exploration of how capabilities are used to secure Podman containers.

Thank You!

## Jeffrey Goh

Thanks, finally switching from docker to podman everywhere on Fedora to reduce privilege whenever possible, so this handy guide is extremely timely.

## Pavan Wankhade

Nice, Helpful tricks are included.

## Joe

Thanks for that! A lot of good commands.

I also spent some time playing with getting a LAMP stack running in across 3 Podman containers. The SELinux and network setup threw me a bit, but got it working. Details below in case it’s helpful for anyone else.

https://opensourcetechtrn.blogspot.com/2020/08/yet-another-lamp-stack-build-podman.html

## Lakshya Tyagi

This article is very helpful

## heiko

Podman is really a great approch. Unfortunately I still don’t find a working CUDA intergration for GPU and have still to use Docker

## Anchit

Nvidia container toolkit supports Podman.

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/overview.html

## laolux

Great article. Setting capabilities in podman seems to be straight forward. However, I have trouble finding out which capabilities are actually needed. For example, when I want to run a postgres container which is only available in the same pod, then what capabilities are required to run and which are safe to drop?

## Stephen Snow

I believe that capabilities are more for the level of isolation between the host and the container. The infra container of the pod you want to run a postgres container in should be where the capabilities are set I would think. The containers in the pod would then only have the capabilities of the infra container. If you go to Opensource.com and search there is some article on this topic.

## laolux

Thanks for pointing me to opensource.com, where I have found some info related to SELinux, but capabilities with podman are quite scarce.

About trying to set the capabilities of an entire pod: podman pod create does not allow for capabilities to be set. And it works perfectly fine to set the capabilities of the containers added to a pod. They can even have different capabilities.

However, all of this does not solve my underlying problem of finding out which capabilities are required by a container during normal operation.

## Stephen Snow

Hello laolux,

sorry you were unable to find what you wanted there. I may have read it on the RedHat Developer site. In any case this post seems relevant to your question https://www.redhat.com/sysadmin/container-networking-podman. Or at least in the proximity of it. Or maybe this one that does talk directly about capabilities and containers https://www.redhat.com/sysadmin/privileged-flag-container-engines.

## laolux

Hello Stephen Snow,

thank you very much for the links! They are very informative. They also pointed me to another site where it is explained how to trace syscalls of a container in order to restrict those later: https://podman.io/blogs/2019/10/15/generate-seccomp-profiles.html

Not quite about capabilites, but similar direction. I guess a somewhat similar approach should work for finding out which capabilities are needed.

## Ondrej

Podman is so nice. I really love it. The way it integrates with systemd + auto-updates, it makes it very simple to create an deployment well integrated in one infra container.

I just really love it!

## William Whinn

Great stuff, thank you! I use toolbox more for bootstrapping an R/RStudio and C/C++ development environment but it has made me interested in containers as a technology. This’ll make a great first step in digging a bit deeper into the technology I take for granted everyday.