Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimise all root-owned files/directories in the running CKAN container #80

Merged
merged 14 commits into from
Nov 13, 2024
27 changes: 19 additions & 8 deletions ckan-2.10/base/Dockerfile.py3.10
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ RUN pip3 install -U pip && \
cd ${SRC_DIR} && \
pip3 install -e git+${GIT_URL}@${CKAN_VERSION}#egg=ckan && \
cd ckan && \
cp who.ini ${APP_DIR} && \
pip3 install --no-binary markdown -r requirements.txt && \
# Install CKAN envvars to support loading config from environment variables
pip3 install -e git+https://github.com/okfn/[email protected]#egg=ckanext-envvars && \
Expand All @@ -69,19 +68,31 @@ RUN pip3 install -U pip && \
ckan config-tool ${CKAN_INI} "beaker.session.secret = " && \
ckan config-tool ${CKAN_INI} "ckan.plugins = ${CKAN__PLUGINS}"

# Create a local user and group plus set up the storage path
RUN groupadd -g 92 ckan && \
useradd -rm -d /srv/app -s /bin/bash -g ckan -u 92 ckan && \
mkdir -p ${CKAN_STORAGE_PATH} && \
chown -R ckan:ckan ${CKAN_STORAGE_PATH}

# Create ckan and ckan-sys users and the ckan-sys group plus set up the storage path
RUN groupadd -g 502 ckan-sys && \
useradd -rm -d /srv/app -s /bin/bash -g ckan-sys -u 502 ckan-sys && \
useradd -rm -d /srv/app -s /bin/bash -g ckan-sys -u 503 ckan
Comment on lines +73 to +74
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having home directories owned by the user is nice for keeping track of things like .bash_history when logging in to the container

Copy link
Contributor

@wardi wardi Sep 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the ckan user has the same primary group as ckan-sys we'll need to make sure the group permissions on all the ckan source files prevent writing. I'm not used to setting things up this way but there may be other issues as well.

Copy link
Contributor Author

@kowh-ai kowh-ai Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is set up this way by default. The ckan user has write permissions only on the files/directories it needs to write into. The ckan-sys user does not have write access. However I have made the ckan-sys group the primary group for both ckan and ckan-sys users in case further down the track we need group write access for more granularity


COPY setup/prerun.py ${APP_DIR}
COPY setup/start_ckan.sh ${APP_DIR}
ADD https://raw.githubusercontent.com/ckan/ckan/${CKAN_VERSION}/wsgi.py ${APP_DIR}
RUN chmod 644 ${APP_DIR}/wsgi.py

# Create entrypoint directory for children image scripts
ONBUILD RUN mkdir /docker-entrypoint.d
RUN mkdir -p /docker-entrypoint.d && chmod 755 /docker-entrypoint.d

# Set the ownership of the app directory, usr/local and the entrypoint directory to the ckan-sys user
RUN chown -R ckan-sys:ckan-sys ${APP_DIR} && \
chown -R ckan-sys:ckan-sys /docker-entrypoint.d && \
chown -R ckan-sys:ckan-sys /usr/local

# Set the ownership of the CKAN config file, src and the storage path to the ckan user
wardi marked this conversation as resolved.
Show resolved Hide resolved
RUN chown ckan:ckan-sys ${APP_DIR}/ckan.ini && \
chown -R ckan:ckan-sys ${APP_DIR}/src && \
mkdir -p ${CKAN_STORAGE_PATH} && \
chown -R ckan:ckan-sys ${CKAN_STORAGE_PATH}

USER ckan

EXPOSE 5000

Expand Down
2 changes: 1 addition & 1 deletion ckan-2.10/base/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ help:
build: ## Build CKAN 2.x.x images , `make build`
echo "Building $(TAG_NAME) and $(ALT_TAG_NAME) and $(PYTHON_TAG_NAME) images"
docker build --build-arg="CKAN_VERSION=ckan-$(CKAN_VERSION)" -t $(TAG_NAME) -t $(ALT_TAG_NAME) .
# docker build --build-arg="CKAN_VERSION=ckan-$(CKAN_VERSION)" -t $(PYTHON_TAG_NAME) -t $(PYTHON_ALT_TAG_NAME) -f $(PYTHON.DOCKERFILE) .
docker build --build-arg="CKAN_VERSION=ckan-$(CKAN_VERSION)" -t $(PYTHON_TAG_NAME) -t $(PYTHON_ALT_TAG_NAME) -f $(PYTHON.DOCKERFILE) .

push: ## Push CKAN 2.x.x images to the DockerHub registry, `make push`
echo "Pushing $(TAG_NAME) image"
Expand Down
2 changes: 1 addition & 1 deletion ckan-2.10/base/setup/prerun.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def create_sysadmin():
# We're running as root before pivoting to uwsgi and dropping privs
data_dir = "%s/storage" % os.environ['CKAN_STORAGE_PATH']

command = ["chown", "-R", "ckan:ckan", data_dir]
command = ["chown", "-R", "ckan:ckan-sys", data_dir]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On 2.10, the prerun.py script will still be used by both the alpine (Dockerfile) and Python (Dockerfile.py3.10) based images but the ckan-sys user has only been added to the python one, so this command will fail in the Alpine images. We need two prerun.py files or some magic here that uses the right user

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subprocess.call(command)
print("[prerun] Ensured storage directory is owned by ckan")

Expand Down
5 changes: 1 addition & 4 deletions ckan-2.10/base/setup/start_ckan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ then
done
fi

# Set the common uwsgi options
UWSGI_OPTS="--plugins http,python \
--socket /tmp/uwsgi.sock \
UWSGI_OPTS="--socket /tmp/uwsgi.sock \
--wsgi-file /srv/app/wsgi.py \
--module wsgi:application \
--uid 92 --gid 92 \
--http [::]:5000 \
--master --enable-threads \
--lazy-apps \
Expand Down
2 changes: 1 addition & 1 deletion ckan-2.10/base/setup/supervisord.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[unix_http_server]
file = /tmp/supervisor.sock
chmod = 0777
wardi marked this conversation as resolved.
Show resolved Hide resolved
chown = nobody:nogroup
chown = ckan:ckan-sys

[supervisord]
logfile = /tmp/supervisord.log
Expand Down
15 changes: 9 additions & 6 deletions ckan-2.10/dev/Dockerfile.py3.10
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ ARG CKAN_VERSION=${CKAN_VERSION}
ENV APP_DIR=/srv/app
ENV SRC_EXTENSIONS_DIR=${APP_DIR}/src_extensions

USER root

# Install CKAN dev requirements
#RUN . ${APP_DIR}/bin/activate && \
RUN cd ${SRC_DIR}/ckan && \
pip3 install -r https://raw.githubusercontent.com/ckan/ckan/${CKAN_VERSION}/dev-requirements.txt

# Create folder for local extensions sources
RUN mkdir -p ${SRC_EXTENSIONS_DIR}
COPY --chown=ckan-sys:ckan-sys setup/unsafe.cert setup/unsafe.key setup/start_ckan_development.sh setup/install_src.sh ${APP_DIR}

# These are used to run https on development mode
COPY setup/unsafe.cert setup/unsafe.key ${APP_DIR}
# Update local directories
RUN mkdir -p ${SRC_EXTENSIONS_DIR} /var/lib/ckan && \
chown -R ckan-sys:ckan-sys ${SRC_EXTENSIONS_DIR} && \
chown -R ckan:ckan-sys /var/lib/ckan/ && \
chmod 775 ${SRC_EXTENSIONS_DIR}

COPY setup/start_ckan_development.sh ${APP_DIR}
USER ckan

CMD ["/srv/app/start_ckan_development.sh"]
2 changes: 1 addition & 1 deletion ckan-2.10/dev/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ help:
build: ## Build a CKAN 2.x-dev image , `make build`
echo "Building $(TAG_NAME) and $(ALT_TAG_NAME) images"
docker build --build-arg="CKAN_VERSION=ckan-$(CKAN_VERSION)" -t $(TAG_NAME) -t $(ALT_TAG_NAME) .
docker build --build-arg="CKAN_VERSION=ckan-$(CKAN_VERSION)" -t $(PYTHON_TAG_NAME) -t $(PYTHON_ALT_TAG_NAME) -f $(PYTHON.DOCKERFILE) --no-cache .
docker build --build-arg="CKAN_VERSION=ckan-$(CKAN_VERSION)" -t $(PYTHON_TAG_NAME) -t $(PYTHON_ALT_TAG_NAME) -f $(PYTHON.DOCKERFILE) .

push: ## Push a CKAN 2.x-dev image to the DockerHub registry, `make push`
echo "Pushing $(TAG_NAME) image"
Expand Down
58 changes: 58 additions & 0 deletions ckan-2.10/dev/setup/install_src.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash

if [ $(id -u) -ne 0 ]; then
echo "Please run as root"
exit 1
fi

# Install any local extensions in the src_extensions volume
echo "Looking for local extensions to install..."
echo "Extension dir contents:"
ls -la $SRC_EXTENSIONS_DIR
for i in $SRC_EXTENSIONS_DIR/*
do
if [ -d $i ];
then
if [ -d $SRC_DIR/$(basename $i) ];
then
pip uninstall -y "$(basename $i)"
fi

if [ -f $i/pip-requirements.txt ];
then
pip install -r $i/pip-requirements.txt
echo "Found requirements file in $i"
fi
if [ -f $i/requirements.txt ];
then
pip install -r $i/requirements.txt
echo "Found requirements file in $i"
fi
if [ -f $i/dev-requirements.txt ];
then
pip install -r $i/dev-requirements.txt
echo "Found dev-requirements file in $i"
fi
if [ -f $i/setup.py ];
then
cd $i
python3 $i/setup.py develop
echo "Found setup.py file in $i"
cd $APP_DIR
fi
if [ -f $i/pyproject.toml ];
then
cd $i
pip install -e .
echo "Found pyproject.toml file in $i"
cd $APP_DIR
fi

# Point `use` in test.ini to location of `test-core.ini`
if [ -f $i/test.ini ];
then
echo "Updating \`test.ini\` reference to \`test-core.ini\` for plugin $i"
ckan config-tool $i/test.ini "use = config:../../src/ckan/test-core.ini"
fi
fi
done
54 changes: 1 addition & 53 deletions ckan-2.10/dev/setup/start_ckan_development.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,6 @@ if [[ $CKAN__PLUGINS == *"datapusher"* ]]; then
ckan config-tool $CKAN_INI ckan.datapusher.api_token=xxx
fi

# Install any local extensions in the src_extensions volume
echo "Looking for local extensions to install..."
echo "Extension dir contents:"
ls -la $SRC_EXTENSIONS_DIR
for i in $SRC_EXTENSIONS_DIR/*
do
if [ -d $i ];
then
if [ -d $SRC_DIR/$(basename $i) ];
then
pip uninstall -y "$(basename $i)"
fi

if [ -f $i/pip-requirements.txt ];
then
pip install -r $i/pip-requirements.txt
echo "Found requirements file in $i"
fi
if [ -f $i/requirements.txt ];
then
pip install -r $i/requirements.txt
echo "Found requirements file in $i"
fi
if [ -f $i/dev-requirements.txt ];
then
pip install -r $i/dev-requirements.txt
echo "Found dev-requirements file in $i"
fi
if [ -f $i/setup.py ];
then
cd $i
python3 $i/setup.py develop
echo "Found setup.py file in $i"
cd $APP_DIR
fi
if [ -f $i/pyproject.toml ];
then
cd $i
pip install -e .
echo "Found pyproject.toml file in $i"
cd $APP_DIR
fi

# Point `use` in test.ini to location of `test-core.ini`
if [ -f $i/test.ini ];
then
echo "Updating \`test.ini\` reference to \`test-core.ini\` for plugin $i"
ckan config-tool $i/test.ini "use = config:../../src/ckan/test-core.ini"
fi
fi
done

# Set debug to true
echo "Enabling debug mode"
ckan config-tool $CKAN_INI -s DEFAULT "debug = true"
Expand Down Expand Up @@ -117,7 +65,7 @@ fi

# Start the development server as the ckan user with automatic reload
while true; do
su ckan -c "$CKAN_RUN $CKAN_OPTIONS"
$CKAN_RUN $CKAN_OPTIONS
echo Exit with status $?. Restarting.
sleep 2
done
28 changes: 20 additions & 8 deletions ckan-2.11/base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ RUN update-locale LANG=${LC_ALL}

# Install system libraries
RUN apt-get install --no-install-recommends -y \
apt-utils \
apt-utils \
git \
libpq-dev \
g++ \
Expand All @@ -61,20 +61,32 @@ RUN pip3 install -U pip && \
ckan config-tool ${CKAN_INI} "SECRET_KEY = " && \
ckan config-tool ${CKAN_INI} "ckan.plugins = ${CKAN__PLUGINS}"

# Create a local user and group plus set up the storage path
RUN groupadd -g 92 ckan && \
useradd -rm -d /srv/app -s /bin/bash -g ckan -u 92 ckan && \
mkdir -p ${CKAN_STORAGE_PATH} && \
chown -R ckan:ckan ${CKAN_STORAGE_PATH}
# Create ckan and ckan-sys users and the ckan-sys group plus set up the storage path
RUN groupadd -g 502 ckan-sys && \
useradd -rm -d /srv/app -s /bin/bash -g ckan-sys -u 502 ckan-sys && \
useradd -rm -d /srv/app -s /bin/bash -g ckan-sys -u 503 ckan
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment about home directories above


COPY setup/prerun.py ${APP_DIR}
COPY setup/start_ckan.sh ${APP_DIR}
ADD https://raw.githubusercontent.com/ckan/ckan/${CKAN_VERSION}/wsgi.py ${APP_DIR}
RUN chmod 644 ${APP_DIR}/wsgi.py

# Create entrypoint directory for children image scripts
ONBUILD RUN mkdir /docker-entrypoint.d
RUN mkdir -p /docker-entrypoint.d && chmod 755 /docker-entrypoint.d

# Set the ownership of the app directory, usr/local and the entrypoint directory to the ckan-sys user
RUN chown -R ckan-sys:ckan-sys ${APP_DIR} && \
chown -R ckan-sys:ckan-sys /docker-entrypoint.d && \
chown -R ckan-sys:ckan-sys /usr/local

# Set the ownership of the CKAN config file, src and the storage path to the ckan user
RUN chown ckan:ckan-sys ${APP_DIR}/ckan.ini && \
chown -R ckan:ckan-sys ${APP_DIR}/src && \
mkdir -p ${CKAN_STORAGE_PATH} && \
chown -R ckan:ckan-sys ${CKAN_STORAGE_PATH}

USER ckan

EXPOSE 5000

CMD ["/srv/app/start_ckan.sh"]
CMD ["/srv/app/start_ckan.sh"]
2 changes: 1 addition & 1 deletion ckan-2.11/base/setup/prerun.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def create_sysadmin():
# We're running as root before pivoting to uwsgi and dropping privs
data_dir = "%s/storage" % os.environ['CKAN_STORAGE_PATH']

command = ["chown", "-R", "ckan:ckan", data_dir]
command = ["chown", "-R", "ckan:ckan-sys", data_dir]
subprocess.call(command)
print("[prerun] Ensured storage directory is owned by ckan")

Expand Down
5 changes: 1 addition & 4 deletions ckan-2.11/base/setup/start_ckan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ then
done
fi

# Set the common uwsgi options
UWSGI_OPTS="--plugins http,python \
--socket /tmp/uwsgi.sock \
UWSGI_OPTS="--socket /tmp/uwsgi.sock \
--wsgi-file /srv/app/wsgi.py \
--module wsgi:application \
--uid 92 --gid 92 \
--http [::]:5000 \
--master --enable-threads \
--lazy-apps \
Expand Down
13 changes: 7 additions & 6 deletions ckan-2.11/dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ ARG CKAN_VERSION=${CKAN_VERSION}
ENV APP_DIR=/srv/app
ENV SRC_EXTENSIONS_DIR=${APP_DIR}/src_extensions

USER root

# Install CKAN dev requirements
#RUN . ${APP_DIR}/bin/activate && \
RUN cd ${SRC_DIR}/ckan && \
pip3 install -r https://raw.githubusercontent.com/ckan/ckan/${CKAN_VERSION}/dev-requirements.txt

# Create folder for local extensions sources
RUN mkdir -p ${SRC_EXTENSIONS_DIR}
COPY --chown=ckan-sys:ckan-sys setup/unsafe.cert setup/unsafe.key setup/start_ckan_development.sh setup/install_src.sh ${APP_DIR}

# These are used to run https on development mode
COPY setup/unsafe.cert setup/unsafe.key ${APP_DIR}
# Update local directories
RUN mkdir -p ${SRC_EXTENSIONS_DIR} /var/lib/ckan && \
chown -R ckan:ckan-sys ${SRC_EXTENSIONS_DIR} ${APP_DIR}/ckan.ini /var/lib/ckan/

COPY setup/start_ckan_development.sh ${APP_DIR}
USER ckan

CMD ["/srv/app/start_ckan_development.sh"]
Loading