YARN-8520. Document best practice for user management. Contributed by Eric Yang
(cherry picked from commit e7951c69cb
)
This commit is contained in:
parent
734bc42289
commit
ba6b48e19f
|
@ -296,7 +296,8 @@ owner as the container user. If the application owner is not a valid user
|
||||||
in the Docker image, the application will fail. The container user is specified
|
in the Docker image, the application will fail. The container user is specified
|
||||||
by the user's UID. If the user's UID is different between the NodeManager host
|
by the user's UID. If the user's UID is different between the NodeManager host
|
||||||
and the Docker image, the container may be launched as the wrong user or may
|
and the Docker image, the container may be launched as the wrong user or may
|
||||||
fail to launch because the UID does not exist.
|
fail to launch because the UID does not exist. See
|
||||||
|
[User Management in Docker Container](#user-management) section for more details.
|
||||||
|
|
||||||
Second, the Docker image must have whatever is expected by the application
|
Second, the Docker image must have whatever is expected by the application
|
||||||
in order to execute. In the case of Hadoop (MapReduce or Spark), the Docker
|
in order to execute. In the case of Hadoop (MapReduce or Spark), the Docker
|
||||||
|
@ -412,6 +413,197 @@ the environment variable would be set to "/sys/fs/cgroup:/sys/fs/cgroup:ro".
|
||||||
The destination path is not restricted, "/sys/fs/cgroup:/cgroup:ro" would also
|
The destination path is not restricted, "/sys/fs/cgroup:/cgroup:ro" would also
|
||||||
be valid given the example admin whitelist.
|
be valid given the example admin whitelist.
|
||||||
|
|
||||||
|
<a href="#user-management"></a>User Management in Docker Container
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
YARN's Docker container support launches container processes using the uid:gid
|
||||||
|
identity of the user, as defined on the NodeManager host. User and group name
|
||||||
|
mismatches between the NodeManager host and container can lead to permission
|
||||||
|
issues, failed container launches, or even security holes. Centralizing user and
|
||||||
|
group management for both hosts and containers greatly reduces these risks. When
|
||||||
|
running containerized applications on YARN, it is necessary to understand which
|
||||||
|
uid:gid pair will be used to launch the container's process.
|
||||||
|
|
||||||
|
As an example of what is meant by uid:gid pair, consider the following. By
|
||||||
|
default, in non-secure mode, YARN will launch processes as the user `nobody`
|
||||||
|
(see the table at the bottom of
|
||||||
|
[Using CGroups with YARN](./NodeManagerCgroups.html) for how the run as user is
|
||||||
|
determined in non-secure mode). On CentOS based systems, the `nobody` user's uid
|
||||||
|
is `99` and the `nobody` group is `99`. As a result, YARN will call `docker run`
|
||||||
|
with `--user 99:99`. If the `nobody` user does not have the uid `99` in the
|
||||||
|
container, the launch may fail or have unexpected results.
|
||||||
|
|
||||||
|
One exception to this rule is the use of Privileged Docker containers.
|
||||||
|
Privileged containers will not set the uid:gid pair when launching the container
|
||||||
|
and will honor the USER or GROUP entries in the Dockerfile. This allows running
|
||||||
|
privileged containers as any user which has security implications. Please
|
||||||
|
understand these implications before enabling Privileged Docker containers.
|
||||||
|
|
||||||
|
There are many ways to address user and group management. Docker, by default,
|
||||||
|
will authenticate users against `/etc/passwd` (and `/etc/shadow`) within the
|
||||||
|
container. Using the default `/etc/passwd` supplied in the Docker image is
|
||||||
|
unlikely to contain the appropriate user entries and will result in launch
|
||||||
|
failures. It is highly recommended to centralize user and group management.
|
||||||
|
Several approaches to user and group management are outlined below.
|
||||||
|
|
||||||
|
### Static user management
|
||||||
|
|
||||||
|
The most basic approach to managing user and groups is to modify the user and
|
||||||
|
group within the Docker image. This approach is only viable in non-secure mode
|
||||||
|
where all container processes will be launched as a single known user, for
|
||||||
|
instance `nobody`. In this case, the only requirement is that the uid:gid pair
|
||||||
|
of the nobody user and group must match between the host and container. On a
|
||||||
|
CentOS based system, this means that the nobody user in the container needs the
|
||||||
|
UID `99` and the nobody group in the container needs GID `99`.
|
||||||
|
|
||||||
|
One approach to change the UID and GID is by leveraging `usermod` and
|
||||||
|
`groupmod`. The following sets the correct UID and GID for the nobody
|
||||||
|
user/group.
|
||||||
|
```
|
||||||
|
usermod -u 99 nobody
|
||||||
|
groupmod -g 99 nobody
|
||||||
|
```
|
||||||
|
|
||||||
|
This approach is not recommended beyond testing given the inflexibility to add
|
||||||
|
users.
|
||||||
|
|
||||||
|
### Bind mounting
|
||||||
|
|
||||||
|
When organizations already have automation in place to create local users on
|
||||||
|
each system, it may be appropriate to bind mount /etc/passwd and /etc/group
|
||||||
|
into the container as an alternative to modifying the container image directly.
|
||||||
|
To enable the ability to bind mount /etc/passwd and /etc/group, update
|
||||||
|
`docker.allowed.ro-mounts` in `container-executor.cfg` to include those paths.
|
||||||
|
When submitting the application, `YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS` will
|
||||||
|
need to include `/etc/passwd:/etc/passwd:ro` and `/etc/group:/etc/group:ro`.
|
||||||
|
|
||||||
|
There are several challenges with this bind mount approach that need to be
|
||||||
|
considered.
|
||||||
|
|
||||||
|
1. Any users and groups defined in the image will be overwritten by the host's users and groups
|
||||||
|
2. No users and groups can be added once the container is started, as /etc/passwd and /etc/group are immutible in the container. Do not mount these read-write as it can render the host inoperable.
|
||||||
|
|
||||||
|
This approach is not recommended beyond testing given the inflexibility to
|
||||||
|
modify running containers.
|
||||||
|
|
||||||
|
### SSSD
|
||||||
|
|
||||||
|
An alternative approach that allows for centrally managing users and groups is
|
||||||
|
SSSD. System Security Services Daemon (SSSD) provides access to different
|
||||||
|
identity and authentication providers, such as LDAP or Active Directory.
|
||||||
|
|
||||||
|
The traditional schema for Linux authentication is as follows:
|
||||||
|
```
|
||||||
|
application -> libpam -> pam_authenticate -> pam_unix.so -> /etc/passwd
|
||||||
|
```
|
||||||
|
|
||||||
|
If we use SSSD for user lookup, it becomes:
|
||||||
|
```
|
||||||
|
application -> libpam -> pam_authenticate -> pam_sss.so -> SSSD -> pam_unix.so -> /etc/passwd
|
||||||
|
```
|
||||||
|
|
||||||
|
We can bind-mount the UNIX sockets SSSD communicates over into the container.
|
||||||
|
This will allow the SSSD client side libraries to authenticate against the SSSD
|
||||||
|
running on the host. As a result, user information does not need to exist in
|
||||||
|
/etc/passwd of the docker image and will instead be serviced by SSSD.
|
||||||
|
|
||||||
|
Step by step configuration for host and container:
|
||||||
|
|
||||||
|
1. Host config
|
||||||
|
|
||||||
|
- Install packages
|
||||||
|
```
|
||||||
|
# yum -y install sssd-common sssd-proxy
|
||||||
|
```
|
||||||
|
- create a PAM service for the container.
|
||||||
|
```
|
||||||
|
# cat /etc/pam.d/sss_proxy
|
||||||
|
auth required pam_unix.so
|
||||||
|
account required pam_unix.so
|
||||||
|
password required pam_unix.so
|
||||||
|
session required pam_unix.so
|
||||||
|
```
|
||||||
|
- create SSSD config file, /etc/sssd/sssd.conf
|
||||||
|
Please note that the permissions must be 0600 and the file must be owned by root:root.
|
||||||
|
```
|
||||||
|
# cat /etc/sssd/sssd/conf
|
||||||
|
[sssd]
|
||||||
|
services = nss,pam
|
||||||
|
config_file_version = 2
|
||||||
|
domains = proxy
|
||||||
|
[nss]
|
||||||
|
[pam]
|
||||||
|
[domain/proxy]
|
||||||
|
id_provider = proxy
|
||||||
|
proxy_lib_name = files
|
||||||
|
proxy_pam_target = sss_proxy
|
||||||
|
```
|
||||||
|
- start sssd
|
||||||
|
```
|
||||||
|
# systemctl start sssd
|
||||||
|
```
|
||||||
|
- verify a user can be retrieved with sssd
|
||||||
|
```
|
||||||
|
# getent passwd -s sss localuser
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Container setup
|
||||||
|
|
||||||
|
It's important to bind-mount the /var/lib/sss/pipes directory from the host to the container since SSSD UNIX sockets are located there.
|
||||||
|
```
|
||||||
|
-v /var/lib/sss/pipes:/var/lib/sss/pipes:rw
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Container config
|
||||||
|
|
||||||
|
All the steps below should be executed on the container itself.
|
||||||
|
|
||||||
|
- Install only the sss client libraries
|
||||||
|
```
|
||||||
|
# yum -y install sssd-client
|
||||||
|
```
|
||||||
|
|
||||||
|
- make sure sss is configured for passwd and group databases in
|
||||||
|
```
|
||||||
|
/etc/nsswitch.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
- configure the PAM service that the application uses to call into SSSD
|
||||||
|
```
|
||||||
|
# cat /etc/pam.d/system-auth
|
||||||
|
#%PAM-1.0
|
||||||
|
# This file is auto-generated.
|
||||||
|
# User changes will be destroyed the next time authconfig is run.
|
||||||
|
auth required pam_env.so
|
||||||
|
auth sufficient pam_unix.so try_first_pass nullok
|
||||||
|
auth sufficient pam_sss.so forward_pass
|
||||||
|
auth required pam_deny.so
|
||||||
|
|
||||||
|
account required pam_unix.so
|
||||||
|
account [default=bad success=ok user_unknown=ignore] pam_sss.so
|
||||||
|
account required pam_permit.so
|
||||||
|
|
||||||
|
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
|
||||||
|
password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow
|
||||||
|
password sufficient pam_sss.so use_authtok
|
||||||
|
password required pam_deny.so
|
||||||
|
|
||||||
|
session optional pam_keyinit.so revoke
|
||||||
|
session required pam_limits.so
|
||||||
|
-session optional pam_systemd.so
|
||||||
|
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
|
||||||
|
session required pam_unix.so
|
||||||
|
session optional pam_sss.so
|
||||||
|
```
|
||||||
|
|
||||||
|
- Save the docker image and use the docker image as base image for your applications.
|
||||||
|
|
||||||
|
- test the docker image launched in YARN environment.
|
||||||
|
```
|
||||||
|
$ id
|
||||||
|
uid=5000(localuser) gid=5000(localuser) groups=5000(localuser),1337(hadoop)
|
||||||
|
```
|
||||||
|
|
||||||
Privileged Container Security Consideration
|
Privileged Container Security Consideration
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue