Skip to content
This repository has been archived by the owner on Aug 23, 2020. It is now read-only.

Official Docker of IRI runs as user root #1519

Closed
KrzysztofHajdamowicz opened this issue Jul 15, 2019 · 6 comments
Closed

Official Docker of IRI runs as user root #1519

KrzysztofHajdamowicz opened this issue Jul 15, 2019 · 6 comments

Comments

@KrzysztofHajdamowicz
Copy link

KrzysztofHajdamowicz commented Jul 15, 2019

Bug description

Official docker image uses account root to run IOTA IRI

IRI version

1.8.0-RELEASE

Hardware Spec

CentOS 7

Steps To Reproduce

  1. docker pull iotaledger/iri
  2. docker run [...]
  3. ps auxf
root     31929  2.1  0.0 1460636 53488 ?       Ssl  09:59   6:17 /usr/bin/containerd
root      1494  0.0  0.0 108744  8556 ?        Sl   14:07   0:01  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/344dd1bae1b837d0c10b05fbf9c436d3a8101a5490e84a028bbeb21dc0101262 -addres
root      1513  210  3.6 12337432 2421652 pts/0 Ssl+ 14:07  92:43      \_ java -XX:+UnlockExperimentalVMOptions -XX:+DisableAttachMechanism -XX:InitiatingHeapOccupancyPercent=60 -XX:G1MaxNewSizePercent=75 -XX:MaxGCPauseMillis=10000 -XX:+U

Expected behaviour

IRI daemon should run at dedicated user with high UID

Actual behaviour

IRI daemon is started as root

@zoran
Copy link
Contributor

zoran commented Jul 15, 2019

In fact, it is often recommended to use an unprivileged user. However, this is rarely done in practice and many companies even consciously choose this way because it brings advantages and the risk is rather low.

@KrzysztofHajdamowicz
Copy link
Author

So, maybe there should be a feature switch for behavior?
By default it can run as root, but if requested docker with spawn IRI as other user?

@nuriel77
Copy link
Contributor

I completely agree that a user should be configured by default. This minimizes security risks.
It is common practice with all official software delivered to create a specific unprivileged user to run the software with.

With the iri-playbook I have specifically created an unprivileged user iri with which I run the container:
https://github.com/nuriel77/iri-playbook/blob/feat/docker/roles/iri/templates/iri.service.j2#L13

I agree that it should be taken care of by the official image.
I will try to push it into this pending PR as I have already done some changes to the Dockerfile #1496

@rajivshah3
Copy link
Member

puppeteer uses this to add an unprivileged user: https://github.com/GoogleChrome/puppeteer/blob/ad1802188dfbd91c59f02e6441e4d9fc24d35f28/.ci/node10/Dockerfile.linux#L11-L17

Maybe the same could be used for IRI?

@nuriel77
Copy link
Contributor

@rajivshah3 what I have done yesterday is add some information to the already pending PR I have for the Dockerfile/docs: #1496
With regards to the above PR, I thought it would have been a little too much to add at this time.

Nevertheless, consider that without having to go into manual setup of user remapping (docker<->host) a user that is created and assigned a UID within the container is the same UID on the host. In some cases this could end up being an already existing user on the system. And, the slightest chance that this user has some privileges on the host system: that might not be a desired situation.
Arguably, this is better than just running as root (UID 0 inside a container = UID 0 on the host).

My proposal is to set default ARGS in the Dockerfile using some arbitrary high UID/GID, e.g. 14265, and create the user within the container using these.
It would lower the risk of matching an existing user on the system. Moreover, this is configurable during build time using --build-arg, should anyone want to override the default UID/GID and create their own user on the system.

In any case, it is always possible to pass --user UID to docker cli to override (as done in the playbook installations).

In the example/proposal below I have added the ARG APP_UID and APP_GID, group and user creation, and finally USER iri...

FROM iotacafe/maven:3.5.4.oracle8u181.1.webupd8.1.1-1@sha256:5e30eb28d778a65af2498bf1b7ef594adf046d44a8e4f7b32b326d8d10626e93 as local_stage_build
MAINTAINER giorgio@iota.org

WORKDIR /iri

COPY . /iri
RUN mvn clean package

# execution image
FROM iotacafe/java:oracle8u181.1.webupd8.1-1@sha256:21b0fb1e5b5be7cd239a742238f346e076a46dc0003670cd50f079780288773f

# Default GID/UID. Can override when building the image
# e.g. `--build-arg APP_UID=1000` ...
ARG APP_UID=14265
ARG APP_GID=14265

RUN apt-get update && apt-get install -y --no-install-recommends \
        socat \
    && rm -rf /var/lib/apt/lists/* \
    && groupadd -g $APP_GID iri \
    && useradd -M -g $APP_GID -u $APP_UID iri

COPY --from=local_stage_build /iri/target/iri*.jar /iri/target/
COPY docker/entrypoint.sh /

# Default environment variables configuration. See DOCKER.md for details.
# Override these variables if required (e.g. docker run -e JAVA_OPTIONS="myoptions" ...)
# `JAVA_OPTIONS`                                 Java related options
# `JAVA_MIN_MEMORY` and `JAVA_MAX_MEMORY`        Settings for -Xms and -Xmx respectively.
#                                                See https://docs.oracle.com/cd/E21764_01/web.1111/e13814/jvm_tuning.htm#PERFM161
# `DOCKER_IRI_JAR_PATH`                          Path where the IRI jar file is located.
# `DOCKER_IRI_JAR_FILE`                          IRI jar file.
# `DOCKER_IRI_REMOTE_LIMIT_API`                  Sets the --remote-limit-api options.
#                                                (Deprecation warning, see https://github.com/iotaledger/iri/issues/1500)
# `DOCKER_IRI_MONITORING_API_PORT_ENABLE`        When using a docker bridged network setting this to 1 will have
#                                                socat exposing 14266 and pointing it on localhost. See /entrypoint.sh
#                                                Do not enable this option when running IRI's container on host network.
#                                                !!! DO NOT DOCKER EXPOSE (-p) 14266 as the remote api settings will
#                                                not be applied on that port !!!
#                                                You also have to maintain $DOCKER_IRI_MONITORING_API_PORT_DESTINATION
#                                                based on the actual API port exposed via IRI
# `DOCKER_IRI_MONITORING_API_PORT_DESTINATION`   Set this to the actual IRI API port. This is used to map port 14266.
# `DOCKER_IRI_REMOTE`                            When using a docker bridged network set this to true. Using host network
#                                                you may choose to set it to false to make sure the API port listens on
#                                                localhost only. If you want to bind your API (--api-host) to a specific interface
#                                                you will have to set this option to false.
# `DOCKER_JAVA_NET_PREFER_IPV4_STACK`            If set to true will allow usage of IPv4 only. Set to false to be able to use IPv6.
#                                                See https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
ENV JAVA_OPTIONS="-XX:+UnlockExperimentalVMOptions -XX:+DisableAttachMechanism -XX:InitiatingHeapOccupancyPercent=60 -XX:G1MaxNewSizePercent=75 -XX:MaxGCPauseMillis=10000 -XX:+UseG1GC" \
    JAVA_MIN_MEMORY=2G \
    JAVA_MAX_MEMORY=4G \
    DOCKER_IRI_JAR_PATH="/iri/target" \
    DOCKER_IRI_JAR_FILE="iri*.jar" \
    DOCKER_IRI_REMOTE_LIMIT_API="interruptAttachToTangle, attachToTangle, addNeighbors, removeNeighbors, getNeighbors" \
    DOCKER_IRI_MONITORING_API_PORT_ENABLE=0 \
    DOCKER_IRI_MONITORING_API_PORT_DESTINATION=14265 \
    DOCKER_IRI_REMOTE=true \
    DOCKER_JAVA_NET_PREFER_IPV4_STACK=true

# Default user to run as:
USER iri
WORKDIR /iri/data
ENTRYPOINT [ "/entrypoint.sh" ]

One caveat here is that a user must chown the directories that get mounted in to the container using the same UID (or create a user on the host with this UID, and grant permissions on the required directories).

Due to this extra "complexity", for now, I thought it would have been better to simply make note of recommended way to run docker with --user UID and consider this change for the release after the next one.

@jakubcech
Copy link
Contributor

Solved in #1496 by Nuriel. Changed the user and added security considerations section describing it. Thanks.

An unprivileged user can be created on the host and the UID passed to the docker command (e.g. `--user 1001`). Directories that are mounted to the container from the host should be owned by this user.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants