From 303471563fe3bd42af78dcf983ed38620c4992a1 Mon Sep 17 00:00:00 2001 From: Qian Deng Date: Tue, 30 Jul 2019 05:04:28 +0000 Subject: [PATCH] DB container run as non-root Signed-off-by: Qian Deng --- make/photon/core/Dockerfile | 2 +- make/photon/db/Dockerfile | 15 +- make/photon/db/docker-entrypoint.sh | 156 +++++++++--------- make/photon/portal/Dockerfile | 9 +- make/photon/prepare/g.py | 7 + make/photon/prepare/main.py | 2 + .../docker_compose/docker-compose.yml.jinja | 2 - make/photon/prepare/utils/db.py | 14 +- make/photon/prepare/utils/nginx.py | 2 +- make/photon/prepare/utils/redis.py | 14 ++ make/photon/redis/Dockerfile | 1 - 11 files changed, 121 insertions(+), 103 deletions(-) create mode 100644 make/photon/prepare/utils/redis.py diff --git a/make/photon/core/Dockerfile b/make/photon/core/Dockerfile index 40739acdc..7eaa4191c 100644 --- a/make/photon/core/Dockerfile +++ b/make/photon/core/Dockerfile @@ -12,5 +12,5 @@ COPY ./make/migrations /harbor/migrations RUN chmod u+x /harbor/harbor_core WORKDIR /harbor/ - +USER harbor ENTRYPOINT ["/harbor/harbor_core"] diff --git a/make/photon/db/Dockerfile b/make/photon/db/Dockerfile index 5672b2f25..6701520e5 100644 --- a/make/photon/db/Dockerfile +++ b/make/photon/db/Dockerfile @@ -18,15 +18,16 @@ RUN tdnf erase -y toybox && tdnf install -y util-linux net-tools VOLUME /var/lib/postgresql/data -ADD ./make/photon/db/docker-entrypoint.sh /entrypoint.sh -ADD ./make/photon/db/docker-healthcheck.sh /docker-healthcheck.sh -RUN chmod u+x /entrypoint.sh /docker-healthcheck.sh -ENTRYPOINT ["/entrypoint.sh"] -HEALTHCHECK CMD ["/docker-healthcheck.sh"] - +COPY ./make/photon/db/docker-entrypoint.sh /entrypoint.sh +COPY ./make/photon/db/docker-healthcheck.sh /docker-healthcheck.sh COPY ./make/photon/db/initial-notaryserver.sql /docker-entrypoint-initdb.d/ COPY ./make/photon/db/initial-notarysigner.sql /docker-entrypoint-initdb.d/ COPY ./make/photon/db/initial-registry.sql /docker-entrypoint-initdb.d/ +RUN chown -R postgres:postgres /entrypoint.sh /docker-healthcheck.sh /docker-entrypoint-initdb.d \ + && chmod u+x /entrypoint.sh /docker-healthcheck.sh + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD ["/docker-healthcheck.sh"] EXPOSE 5432 -CMD ["postgres"] +USER postgres diff --git a/make/photon/db/docker-entrypoint.sh b/make/photon/db/docker-entrypoint.sh index c8f667282..606b805ba 100644 --- a/make/photon/db/docker-entrypoint.sh +++ b/make/photon/db/docker-entrypoint.sh @@ -23,95 +23,89 @@ file_env() { unset "$fileVar" } -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - chown -R postgres:postgres $PGDATA - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - if [ "$POSTGRES_INITDB_XLOGDIR" ]; then - export POSTGRES_INITDB_ARGS="$POSTGRES_INITDB_ARGS --xlogdir $POSTGRES_INITDB_XLOGDIR" - fi - su - $1 -c "initdb -D $PGDATA -U postgres -E UTF-8 --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8 $POSTGRES_INITDB_ARGS" - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-EOF - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** +# chown -R postgres:postgres $PGDATA +# look specifically for PG_VERSION, as it is expected in the DB dir +if [ ! -s "$PGDATA/PG_VERSION" ]; then + file_env 'POSTGRES_INITDB_ARGS' + if [ "$POSTGRES_INITDB_XLOGDIR" ]; then + export POSTGRES_INITDB_ARGS="$POSTGRES_INITDB_ARGS --xlogdir $POSTGRES_INITDB_XLOGDIR" + fi + initdb -D $PGDATA -U postgres -E UTF-8 --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8 $POSTGRES_INITDB_ARGS + # check password first so we can output the warning before postgres + # messes it up + file_env 'POSTGRES_PASSWORD' + if [ "$POSTGRES_PASSWORD" ]; then + pass="PASSWORD '$POSTGRES_PASSWORD'" + authMethod=md5 + else + # The - option suppresses leading tabs but *not* spaces. :) + cat >&2 <<-EOF + **************************************************** + WARNING: No password has been set for the database. + This will allow anyone with access to the + Postgres port to access your database. In + Docker's default configuration, this is + effectively any other container on the same + system. + Use "-e POSTGRES_PASSWORD=password" to set + it in "docker run". + **************************************************** EOF - pass= - authMethod=trust - fi + pass= + authMethod=trust + fi - { - echo - echo "host all all all $authMethod" - } >> "$PGDATA/pg_hba.conf" - su postgres - echo `whoami` - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - su - $1 -c "pg_ctl -D \"$PGDATA\" -o \"-c listen_addresses='localhost'\" -w start" + { + echo + echo "host all all all $authMethod" + } >> "$PGDATA/pg_hba.conf" + echo `whoami` + # internal start of server in order to allow set-up using psql-client + # does not listen on external TCP/IP and waits until start finishes + pg_ctl -D "$PGDATA" -o "-c listen_addresses=''" -w start - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" + file_env 'POSTGRES_USER' 'postgres' + file_env 'POSTGRES_DB' "$POSTGRES_USER" - psql=( psql -v ON_ERROR_STOP=1 ) + psql=( psql -v ON_ERROR_STOP=1 ) - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; -EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi + if [ "$POSTGRES_DB" != 'postgres' ]; then "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; + CREATE DATABASE "$POSTGRES_DB" ; EOSQL echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - PGUSER="${PGUSER:-postgres}" \ - su - $1 -c "pg_ctl -D \"$PGDATA\" -m fast -w stop" - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo fi + + if [ "$POSTGRES_USER" = 'postgres' ]; then + op='ALTER' + else + op='CREATE' + fi + "${psql[@]}" --username postgres <<-EOSQL + $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; +EOSQL + echo + + psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; + *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + PGUSER="${PGUSER:-postgres}" \ + pg_ctl -D "$PGDATA" -m fast -w stop + + echo + echo 'PostgreSQL init process complete; ready for start up.' + echo fi -exec su - $1 -c "$@ -D $PGDATA" + +postgres -D $PGDATA diff --git a/make/photon/portal/Dockerfile b/make/photon/portal/Dockerfile index 5033bb9ff..7b7227338 100644 --- a/make/photon/portal/Dockerfile +++ b/make/photon/portal/Dockerfile @@ -21,11 +21,12 @@ COPY --from=nodeportal /build_dir/swagger.json /usr/share/nginx/html COPY make/photon/portal/nginx.conf /etc/nginx/nginx.conf -RUN tdnf install -y nginx >> /dev/null \ +RUN tdnf install -y nginx sudo >> /dev/null \ && ln -sf /dev/stdout /var/log/nginx/access.log \ && ln -sf /dev/stderr /var/log/nginx/error.log \ - && tdnf clean all \ - && chown -R 10000:10000 /etc/nginx + && groupadd -r -g 10000 nginx && useradd --no-log-init -r -g 10000 -u 10000 nginx \ + && chown -R nginx:nginx /etc/nginx \ + && tdnf clean all EXPOSE 80 VOLUME /var/cache/nginx /var/log/nginx /run @@ -33,6 +34,6 @@ VOLUME /var/cache/nginx /var/log/nginx /run STOPSIGNAL SIGQUIT HEALTHCHECK CMD curl --fail -s http://127.0.0.1:8080 || exit 1 - +USER nginx CMD ["nginx", "-g", "daemon off;"] diff --git a/make/photon/prepare/g.py b/make/photon/prepare/g.py index bb766f07b..f0eab0675 100644 --- a/make/photon/prepare/g.py +++ b/make/photon/prepare/g.py @@ -5,10 +5,17 @@ from pathlib import Path DEFAULT_UID = 10000 DEFAULT_GID = 10000 +PG_UID = 999 +PG_GID = 999 + +REDIS_UID = 999 +REDIS_GID = 999 + ## Global variable base_dir = '/harbor_make' templates_dir = "/usr/src/app/templates" config_dir = '/config' +data_dir = '/data' secret_dir = '/secret' secret_key_dir='/secret/keys' diff --git a/make/photon/prepare/main.py b/make/photon/prepare/main.py index 604d2735c..e617baebc 100644 --- a/make/photon/prepare/main.py +++ b/make/photon/prepare/main.py @@ -16,6 +16,7 @@ from utils.clair import prepare_clair from utils.chart import prepare_chartmuseum from utils.docker_compose import prepare_docker_compose from utils.nginx import prepare_nginx, nginx_confd_dir +from utils.redis import prepare_redis from g import (config_dir, input_config_path, private_key_pem_path, root_crt_path, secret_key_dir, old_private_key_pem_path, old_crt_path) @@ -38,6 +39,7 @@ def main(conf, with_notary, with_clair, with_chartmuseum): prepare_registry_ctl(config_dict) prepare_db(config_dict) prepare_job_service(config_dict) + prepare_redis(config_dict) get_secret_key(secret_key_dir) diff --git a/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja b/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja index 59725e3e3..9e70cc8de 100644 --- a/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja +++ b/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja @@ -133,7 +133,6 @@ services: env_file: - ./common/config/core/env restart: always - user: 10000:10000 cap_drop: - ALL cap_add: @@ -186,7 +185,6 @@ services: image: goharbor/harbor-portal:{{version}} container_name: harbor-portal restart: always - user: 10000:10000 cap_drop: - ALL cap_add: diff --git a/make/photon/prepare/utils/db.py b/make/photon/prepare/utils/db.py index 53ef3d93e..2721e10bd 100644 --- a/make/photon/prepare/utils/db.py +++ b/make/photon/prepare/utils/db.py @@ -1,20 +1,22 @@ import os -from g import config_dir, templates_dir +from g import config_dir, templates_dir, data_dir, PG_UID, PG_GID from utils.misc import prepare_config_dir from utils.jinja import render_jinja db_config_dir = os.path.join(config_dir, "db") db_env_template_path = os.path.join(templates_dir, "db", "env.jinja") db_conf_env = os.path.join(config_dir, "db", "env") +database_data_path = os.path.join(data_dir, 'database') def prepare_db(config_dict): - prepare_db_config_dir() - + prepare_config_dir(database_data_path) + stat_info = os.stat(database_data_path) + uid, gid = stat_info.st_uid, stat_info.st_gid + if not (uid == PG_UID and gid == PG_GID): + os.chown(database_data_path, PG_UID, PG_GID) + prepare_config_dir(db_config_dir) render_jinja( db_env_template_path, db_conf_env, harbor_db_password=config_dict['harbor_db_password']) - -def prepare_db_config_dir(): - prepare_config_dir(db_config_dir) \ No newline at end of file diff --git a/make/photon/prepare/utils/nginx.py b/make/photon/prepare/utils/nginx.py index 3705e31a7..ee40b5f2d 100644 --- a/make/photon/prepare/utils/nginx.py +++ b/make/photon/prepare/utils/nginx.py @@ -24,7 +24,7 @@ def prepare_nginx(config_dict): def render_nginx_template(config_dict): if config_dict['protocol'] == "https": render_jinja( - nginx_https_conf_template, + nginx_https_conf_template, nginx_conf, uid=DEFAULT_UID, gid=DEFAULT_GID, diff --git a/make/photon/prepare/utils/redis.py b/make/photon/prepare/utils/redis.py new file mode 100644 index 000000000..d8a5b562a --- /dev/null +++ b/make/photon/prepare/utils/redis.py @@ -0,0 +1,14 @@ +import os + +from g import data_dir, REDIS_UID, REDIS_GID +from utils.misc import prepare_config_dir + +redis_data_path = os.path.join(data_dir, 'redis') + +def prepare_redis(config_dict): + prepare_config_dir(redis_data_path) + + stat_info = os.stat(redis_data_path) + uid, gid = stat_info.st_uid, stat_info.st_gid + if not (uid == REDIS_UID and gid == REDIS_GID): + os.chown(redis_data_path, REDIS_UID, REDIS_GID) \ No newline at end of file diff --git a/make/photon/redis/Dockerfile b/make/photon/redis/Dockerfile index ff412831d..c866f9505 100644 --- a/make/photon/redis/Dockerfile +++ b/make/photon/redis/Dockerfile @@ -8,7 +8,6 @@ COPY ./make/photon/redis/docker-entrypoint.sh /usr/bin/ COPY ./make/photon/redis/redis.conf /etc/redis.conf RUN chmod +x /usr/bin/docker-entrypoint.sh \ && chown redis:redis /etc/redis.conf -ENTRYPOINT ["docker-entrypoint.sh"] USER redis EXPOSE 6379