From dc76000f28cfbb59f58a4ed0aabc228702ab0216 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Mon, 17 Jun 2019 20:14:13 +0100 Subject: [PATCH 01/15] #805: Deprecates SSH_AUTOSTART_* env variables; replaced with ENABLE_*. --- .env.example | 4 ++-- CHANGELOG.md | 5 ++++- Dockerfile | 6 +++--- README.md | 12 ++++++------ default.mk | 6 +++--- docker-compose.yml | 4 ++-- environment.mk | 6 +++--- src/etc/supervisord.conf | 1 + src/etc/supervisord.d/00-supervisor_stdout.conf | 2 +- src/etc/supervisord.d/sshd-bootstrap.conf | 2 +- src/etc/supervisord.d/sshd-wrapper.conf | 2 +- src/etc/systemd/system/centos-ssh@.service | 12 ++++++------ src/opt/scmi/default.sh | 6 +++--- src/opt/scmi/environment.sh | 6 +++--- src/opt/scmi/service-unit.sh | 6 +++--- src/usr/bin/healthcheck | 4 ++-- src/usr/sbin/sshd-wrapper | 10 +++++----- test/shpec/operation_shpec.sh | 14 +++++++------- 18 files changed, 56 insertions(+), 52 deletions(-) diff --git a/.env.example b/.env.example index 590a183..0c27bd5 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ +ENABLE_SSHD_BOOTSTRAP=true +ENABLE_SSHD_WRAPPER=true SSH_AUTHORIZED_KEYS= -SSH_AUTOSTART_SSHD=true -SSH_AUTOSTART_SSHD_BOOTSTRAP=true SSH_CHROOT_DIRECTORY=%h SSH_INHERIT_ENVIRONMENT=false SSH_PASSWORD_AUTHENTICATION=false diff --git a/CHANGELOG.md b/CHANGELOG.md index bd30aba..d4d5317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,12 @@ Summary of release changes for Version 2 - CentOS-7 ### 2.6.0 - Unreleased +- Deprecates `SSH_AUTOSTART_SSHD`, replaced with `ENABLE_SSHD_WRAPPER`. +- Deprecates `SSH_AUTOSTART_SSHD_BOOTSTRAP`, replaced with `ENABLE_SSHD_BOOTSTRAP`. +- Deprecates `SSH_AUTOSTART_SUPERVISOR_STDOUT`, replaced with `ENABLE_SUPERVISOR_STDOUT`. - Updates source tag to CentOS 7.6.1810. - Updates supervisord to 4.0.3. -- Updates default value of `SSH_AUTOSTART_SUPERVISOR_STDOUT` to false. +- Updates default value of `ENABLE_SUPERVISOR_STDOUT` to false. - Updates `sshd-bootstrap` and `sshd-wrapper` configuration to send error log output to stderr. - Updates order of values in SSH/SFTP Details log output. - Adds reference to `python-setuptools` in README; removed in error. diff --git a/Dockerfile b/Dockerfile index bb69eef..e47c415 100644 --- a/Dockerfile +++ b/Dockerfile @@ -91,10 +91,10 @@ EXPOSE 22 # Set default environment variables # ------------------------------------------------------------------------------ ENV \ + ENABLE_SSHD_BOOTSTRAP="true" \ + ENABLE_SSHD_WRAPPER="true" \ + ENABLE_SUPERVISOR_STDOUT="false" \ SSH_AUTHORIZED_KEYS="" \ - SSH_AUTOSTART_SSHD="true" \ - SSH_AUTOSTART_SSHD_BOOTSTRAP="true" \ - SSH_AUTOSTART_SUPERVISOR_STDOUT="false" \ SSH_CHROOT_DIRECTORY="%h" \ SSH_INHERIT_ENVIRONMENT="false" \ SSH_PASSWORD_AUTHENTICATION="false" \ diff --git a/README.md b/README.md index 5eaca93..66b0032 100644 --- a/README.md +++ b/README.md @@ -327,20 +327,20 @@ Using `SSH_AUTHORIZED_KEYS` with a container file path allows for the authorized ... ``` -##### SSH_AUTOSTART_SSHD & SSH_AUTOSTART_SSHD_BOOTSTRAP +##### ENABLE_SSHD_BOOTSTRAP & ENABLE_SSHD_WRAPPER -It may be desirable to prevent the startup of the sshd daemon and/or sshd-bootstrap script. For example, when using an image built from this Dockerfile as the source for another Dockerfile you could disable both sshd and sshd-booststrap from startup by setting `SSH_AUTOSTART_SSHD` and `SSH_AUTOSTART_SSHD_BOOTSTRAP` to `false`. The benefit of this is to reduce the number of running processes in the final container. +It may be desirable to prevent the startup of the sshd-bootstrap script and/or sshd daemon. For example, when using an image built from this Dockerfile as the source for another Dockerfile you could disable both sshd-booststrap and sshd from startup by setting `ENABLE_SSHD_BOOTSTRAP` and `ENABLE_SSHD_WRAPPER` to `false`. The benefit of this is to reduce the number of running processes in the final container. ``` ... - --env "SSH_AUTOSTART_SSHD=false" \ - --env "SSH_AUTOSTART_SSHD_BOOTSTRAP=false" \ + --env "ENABLE_SSHD_BOOTSTRAP=false" \ + --env "ENABLE_SSHD_WRAPPER=false" \ ... ``` -##### SSH_AUTOSTART_SUPERVISOR_STDOUT +##### ENABLE_SUPERVISOR_STDOUT -This image has `supervisor_stdout` installed which can be used to allow a process controlled by supervisord to send output to both a log file and stdout. It is recommended to simply output to stdout in order to reduce the number of running processes to a minimum. Setting `SSH_AUTOSTART_SUPERVISOR_STDOUT` to "false" will prevent the startup of `supervisor_stdout`. Where an image requires this feature for its logging output `SSH_AUTOSTART_SUPERVISOR_STDOUT` should be set to "true". +This image has `supervisor_stdout` installed which can be used to allow a process controlled by supervisord to send output to both a log file and stdout. It is recommended to simply output to stdout in order to reduce the number of running processes to a minimum. Setting `ENABLE_SUPERVISOR_STDOUT` to "false" will prevent the startup of `supervisor_stdout`. Where an image requires this feature for its logging output `ENABLE_SUPERVISOR_STDOUT` should be set to "true". ##### SSH_CHROOT_DIRECTORY diff --git a/default.mk b/default.mk index 380e2c7..bd32933 100644 --- a/default.mk +++ b/default.mk @@ -41,10 +41,10 @@ DOCKER_PUBLISH := $(shell \ define DOCKER_CONTAINER_PARAMETERS --name $(DOCKER_NAME) \ --restart $(DOCKER_RESTART_POLICY) \ +--env "ENABLE_SSHD_BOOTSTRAP=$(ENABLE_SSHD_BOOTSTRAP)" \ +--env "ENABLE_SSHD_WRAPPER=$(ENABLE_SSHD_WRAPPER)" \ +--env "ENABLE_SUPERVISOR_STDOUT=$(ENABLE_SUPERVISOR_STDOUT)" \ --env "SSH_AUTHORIZED_KEYS=$(SSH_AUTHORIZED_KEYS)" \ ---env "SSH_AUTOSTART_SSHD=$(SSH_AUTOSTART_SSHD)" \ ---env "SSH_AUTOSTART_SSHD_BOOTSTRAP=$(SSH_AUTOSTART_SSHD_BOOTSTRAP)" \ ---env "SSH_AUTOSTART_SUPERVISOR_STDOUT=$(SSH_AUTOSTART_SUPERVISOR_STDOUT)" \ --env "SSH_CHROOT_DIRECTORY=$(SSH_CHROOT_DIRECTORY)" \ --env "SSH_INHERIT_ENVIRONMENT=$(SSH_INHERIT_ENVIRONMENT)" \ --env "SSH_PASSWORD_AUTHENTICATION=$(SSH_PASSWORD_AUTHENTICATION)" \ diff --git a/docker-compose.yml b/docker-compose.yml index a95abaa..e1060b0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,9 +28,9 @@ services: context: "." dockerfile: "Dockerfile" environment: + ENABLE_SSHD_BOOTSTRAP: "${ENABLE_SSHD_BOOTSTRAP}" + ENABLE_SSHD_WRAPPER: "${ENABLE_SSHD_WRAPPER}" SSH_AUTHORIZED_KEYS: "${SSH_AUTHORIZED_KEYS}" - SSH_AUTOSTART_SSHD: "${SSH_AUTOSTART_SSHD}" - SSH_AUTOSTART_SSHD_BOOTSTRAP: "${SSH_AUTOSTART_SSHD_BOOTSTRAP}" SSH_CHROOT_DIRECTORY: "${SSH_CHROOT_DIRECTORY}" SSH_INHERIT_ENVIRONMENT: "${SSH_INHERIT_ENVIRONMENT}" SSH_PASSWORD_AUTHENTICATION: "${SSH_PASSWORD_AUTHENTICATION}" diff --git a/environment.mk b/environment.mk index c62c8a8..2925b3e 100644 --- a/environment.mk +++ b/environment.mk @@ -23,10 +23,10 @@ STARTUP_TIME ?= 2 # ------------------------------------------------------------------------------ # Application container configuration # ------------------------------------------------------------------------------ +ENABLE_SSHD_BOOTSTRAP ?= true +ENABLE_SSHD_WRAPPER ?= true +ENABLE_SUPERVISOR_STDOUT ?= false SSH_AUTHORIZED_KEYS ?= -SSH_AUTOSTART_SSHD ?= true -SSH_AUTOSTART_SSHD_BOOTSTRAP ?= true -SSH_AUTOSTART_SUPERVISOR_STDOUT ?= false SSH_CHROOT_DIRECTORY ?= %h SSH_INHERIT_ENVIRONMENT ?= false SSH_PASSWORD_AUTHENTICATION ?= false diff --git a/src/etc/supervisord.conf b/src/etc/supervisord.conf index 944c30c..e9384f8 100755 --- a/src/etc/supervisord.conf +++ b/src/etc/supervisord.conf @@ -1,4 +1,5 @@ [supervisord] +environment = SSH_AUTOSTART_SSHD="%(ENV_ENABLE_SSHD_WRAPPER)s",SSH_AUTOSTART_SSHD_BOOTSTRAP="%(ENV_ENABLE_SSHD_BOOTSTRAP)s",SSH_AUTOSTART_SUPERVISOR_STDOUT="%(ENV_ENABLE_SSHD_BOOTSTRAP)s" logfile = /dev/null logfile_maxbytes = 0 logfile_backups = 0 diff --git a/src/etc/supervisord.d/00-supervisor_stdout.conf b/src/etc/supervisord.d/00-supervisor_stdout.conf index 98bbcac..f904819 100644 --- a/src/etc/supervisord.d/00-supervisor_stdout.conf +++ b/src/etc/supervisord.d/00-supervisor_stdout.conf @@ -1,5 +1,5 @@ [eventlistener:supervisor_stdout] -autostart = %(ENV_SSH_AUTOSTART_SUPERVISOR_STDOUT)s +autostart = %(ENV_ENABLE_SUPERVISOR_STDOUT)s buffer_size = 100 command = /usr/bin/supervisor_stdout events = PROCESS_LOG diff --git a/src/etc/supervisord.d/sshd-bootstrap.conf b/src/etc/supervisord.d/sshd-bootstrap.conf index 4eb6159..6470f74 100644 --- a/src/etc/supervisord.d/sshd-bootstrap.conf +++ b/src/etc/supervisord.d/sshd-bootstrap.conf @@ -1,6 +1,6 @@ [program:sshd-bootstrap] autorestart = false -autostart = %(ENV_SSH_AUTOSTART_SSHD_BOOTSTRAP)s +autostart = %(ENV_ENABLE_SSHD_BOOTSTRAP)s command = /usr/sbin/sshd-bootstrap --verbose priority = 5 startretries = 0 diff --git a/src/etc/supervisord.d/sshd-wrapper.conf b/src/etc/supervisord.d/sshd-wrapper.conf index a219c7b..c35d688 100644 --- a/src/etc/supervisord.d/sshd-wrapper.conf +++ b/src/etc/supervisord.d/sshd-wrapper.conf @@ -1,6 +1,6 @@ [program:sshd-wrapper] autorestart = true -autostart = %(ENV_SSH_AUTOSTART_SSHD)s +autostart = %(ENV_ENABLE_SSHD_WRAPPER)s command = /usr/sbin/sshd-wrapper --verbose priority = 10 startsecs = 0 diff --git a/src/etc/systemd/system/centos-ssh@.service b/src/etc/systemd/system/centos-ssh@.service index c6f54c1..c259a10 100644 --- a/src/etc/systemd/system/centos-ssh@.service +++ b/src/etc/systemd/system/centos-ssh@.service @@ -56,10 +56,10 @@ Environment="DOCKER_IMAGE_PACKAGE_PATH=/var/opt/scmi/packages" Environment="DOCKER_IMAGE_TAG={{RELEASE_VERSION}}" Environment="DOCKER_PORT_MAP_TCP_22=2020" Environment="DOCKER_USER=jdeathe" +Environment="ENABLE_SSHD_BOOTSTRAP=true" +Environment="ENABLE_SSHD_WRAPPER=true" +Environment="ENABLE_SUPERVISOR_STDOUT=false" Environment="SSH_AUTHORIZED_KEYS=" -Environment="SSH_AUTOSTART_SSHD=true" -Environment="SSH_AUTOSTART_SSHD_BOOTSTRAP=true" -Environment="SSH_AUTOSTART_SUPERVISOR_STDOUT=false" Environment="SSH_CHROOT_DIRECTORY=%%h" Environment="SSH_INHERIT_ENVIRONMENT=false" Environment="SSH_PASSWORD_AUTHENTICATION=false" @@ -129,10 +129,10 @@ ExecStartPre=-/bin/bash -c \ ExecStart=/bin/bash -c \ "exec /usr/bin/docker run \ --name %p.%i \ + --env \"ENABLE_SSHD_BOOTSTRAP=${ENABLE_SSHD_BOOTSTRAP}\" \ + --env \"ENABLE_SSHD_WRAPPER=${ENABLE_SSHD_WRAPPER}\" \ + --env \"ENABLE_SUPERVISOR_STDOUT=${ENABLE_SUPERVISOR_STDOUT}\" \ --env \"SSH_AUTHORIZED_KEYS=${SSH_AUTHORIZED_KEYS}\" \ - --env \"SSH_AUTOSTART_SSHD=${SSH_AUTOSTART_SSHD}\" \ - --env \"SSH_AUTOSTART_SSHD_BOOTSTRAP=${SSH_AUTOSTART_SSHD_BOOTSTRAP}\" \ - --env \"SSH_AUTOSTART_SUPERVISOR_STDOUT=${SSH_AUTOSTART_SUPERVISOR_STDOUT}\" \ --env \"SSH_CHROOT_DIRECTORY=${SSH_CHROOT_DIRECTORY}\" \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ diff --git a/src/opt/scmi/default.sh b/src/opt/scmi/default.sh index 652b1ce..a667e3d 100644 --- a/src/opt/scmi/default.sh +++ b/src/opt/scmi/default.sh @@ -46,10 +46,10 @@ fi # Common parameters of create and run targets DOCKER_CONTAINER_PARAMETERS="--name ${DOCKER_NAME} \ --restart ${DOCKER_RESTART_POLICY} \ +--env \"ENABLE_SSHD_BOOTSTRAP=${ENABLE_SSHD_BOOTSTRAP}\" \ +--env \"ENABLE_SSHD_WRAPPER=${ENABLE_SSHD_WRAPPER}\" \ +--env \"ENABLE_SUPERVISOR_STDOUT=${ENABLE_SUPERVISOR_STDOUT}\" \ --env \"SSH_AUTHORIZED_KEYS=${SSH_AUTHORIZED_KEYS}\" \ ---env \"SSH_AUTOSTART_SSHD=${SSH_AUTOSTART_SSHD}\" \ ---env \"SSH_AUTOSTART_SSHD_BOOTSTRAP=${SSH_AUTOSTART_SSHD_BOOTSTRAP}\" \ ---env \"SSH_AUTOSTART_SUPERVISOR_STDOUT=${SSH_AUTOSTART_SUPERVISOR_STDOUT}\" \ --env \"SSH_CHROOT_DIRECTORY=${SSH_CHROOT_DIRECTORY}\" \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ diff --git a/src/opt/scmi/environment.sh b/src/opt/scmi/environment.sh index cebeca3..4e88bf0 100644 --- a/src/opt/scmi/environment.sh +++ b/src/opt/scmi/environment.sh @@ -24,10 +24,10 @@ STARTUP_TIME="${STARTUP_TIME:-2}" # ------------------------------------------------------------------------------ # Application container configuration # ------------------------------------------------------------------------------ +ENABLE_SSHD_BOOTSTRAP="${ENABLE_SSHD_BOOTSTRAP:-true}" +ENABLE_SSHD_WRAPPER="${ENABLE_SSHD_WRAPPER:-true}" +ENABLE_SUPERVISOR_STDOUT="${ENABLE_SUPERVISOR_STDOUT:-false}" SSH_AUTHORIZED_KEYS="${SSH_AUTHORIZED_KEYS:-}" -SSH_AUTOSTART_SSHD="${SSH_AUTOSTART_SSHD:-true}" -SSH_AUTOSTART_SSHD_BOOTSTRAP="${SSH_AUTOSTART_SSHD_BOOTSTRAP:-true}" -SSH_AUTOSTART_SUPERVISOR_STDOUT="${SSH_AUTOSTART_SUPERVISOR_STDOUT:-false}" SSH_CHROOT_DIRECTORY="${SSH_CHROOT_DIRECTORY:-%h}" SSH_INHERIT_ENVIRONMENT="${SSH_INHERIT_ENVIRONMENT:-false}" SSH_PASSWORD_AUTHENTICATION="${SSH_PASSWORD_AUTHENTICATION:-false}" diff --git a/src/opt/scmi/service-unit.sh b/src/opt/scmi/service-unit.sh index 6e04daf..87b86d7 100644 --- a/src/opt/scmi/service-unit.sh +++ b/src/opt/scmi/service-unit.sh @@ -6,10 +6,10 @@ readonly SERVICE_UNIT_ENVIRONMENT_KEYS=" DOCKER_IMAGE_PACKAGE_PATH DOCKER_IMAGE_TAG DOCKER_PORT_MAP_TCP_22 + ENABLE_SSHD_BOOTSTRAP + ENABLE_SSHD_WRAPPER + ENABLE_SUPERVISOR_STDOUT SSH_AUTHORIZED_KEYS - SSH_AUTOSTART_SSHD - SSH_AUTOSTART_SSHD_BOOTSTRAP - SSH_AUTOSTART_SUPERVISOR_STDOUT SSH_CHROOT_DIRECTORY SSH_INHERIT_ENVIRONMENT SSH_PASSWORD_AUTHENTICATION diff --git a/src/usr/bin/healthcheck b/src/usr/bin/healthcheck index 99f164f..e90588e 100755 --- a/src/usr/bin/healthcheck +++ b/src/usr/bin/healthcheck @@ -43,7 +43,7 @@ function main () exit 1 fi - if [[ ${SSH_AUTOSTART_SSHD_BOOTSTRAP} == true ]] + if [[ ${ENABLE_SSHD_BOOTSTRAP} == true ]] then if [[ -e /var/lock/subsys/sshd-bootstrap ]] then @@ -62,7 +62,7 @@ function main () fi fi - if [[ ${SSH_AUTOSTART_SSHD} == true ]] + if [[ ${ENABLE_SSHD_WRAPPER} == true ]] then if ! ps axo command | grep -qE '^/usr/sbin/sshd -D' \ || [[ ! -s /var/run/sshd.pid ]] diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index 5bb757c..c3a515d 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -33,13 +33,13 @@ function __get_options () "${options}" } -function __get_ssh_autostart_sshd_bootstrap () +function __get_enable_sshd_bootstrap () { local -r default_value="${1:-true}" - local value="${SSH_AUTOSTART_SSHD_BOOTSTRAP}" + local value="${ENABLE_SSHD_BOOTSTRAP}" - if ! __is_valid_ssh_autostart_sshd_bootstrap "${value}" + if ! __is_valid_enable_sshd_bootstrap "${value}" then value="${default_value}" fi @@ -47,7 +47,7 @@ function __get_ssh_autostart_sshd_bootstrap () printf -- '%s' "${value}" } -function __is_valid_ssh_autostart_sshd_bootstrap () +function __is_valid_enable_sshd_bootstrap () { local -r boolean_value='^(true|false)$' local -r value="${1}" @@ -63,7 +63,7 @@ function __is_valid_ssh_autostart_sshd_bootstrap () function main () { local -r autostart_bootstrap="$( - __get_ssh_autostart_sshd_bootstrap + __get_enable_sshd_bootstrap )" local -r bin="/usr/sbin/sshd" local -r bootstrap_state_file="/var/lib/misc/sshd-bootstrap" diff --git a/test/shpec/operation_shpec.sh b/test/shpec/operation_shpec.sh index fdaf3f6..ca93617 100644 --- a/test/shpec/operation_shpec.sh +++ b/test/shpec/operation_shpec.sh @@ -1741,7 +1741,7 @@ function test_custom_ssh_configuration () docker run \ --detach \ --name ssh.1 \ - --env "SSH_AUTOSTART_SUPERVISOR_STDOUT=true" \ + --env "ENABLE_SUPERVISOR_STDOUT=true" \ --publish ${DOCKER_PORT_MAP_TCP_22}:22 \ jdeathe/centos-ssh:latest \ &> /dev/null @@ -1764,7 +1764,7 @@ function test_custom_ssh_configuration () docker run \ --detach \ --name ssh.1 \ - --env "SSH_AUTOSTART_SUPERVISOR_STDOUT=false" \ + --env "ENABLE_SUPERVISOR_STDOUT=false" \ --publish ${DOCKER_PORT_MAP_TCP_22}:22 \ jdeathe/centos-ssh:latest \ &> /dev/null @@ -1787,7 +1787,7 @@ function test_custom_ssh_configuration () docker run \ --detach \ --name ssh.1 \ - --env "SSH_AUTOSTART_SSHD_BOOTSTRAP=false" \ + --env "ENABLE_SSHD_BOOTSTRAP=false" \ --publish ${DOCKER_PORT_MAP_TCP_22}:22 \ jdeathe/centos-ssh:latest \ &> /dev/null @@ -1811,7 +1811,7 @@ function test_custom_ssh_configuration () docker run \ --detach \ --name ssh.1 \ - --env "SSH_AUTOSTART_SSHD=false" \ + --env "ENABLE_SSHD_WRAPPER=false" \ --publish ${DOCKER_PORT_MAP_TCP_22}:22 \ jdeathe/centos-ssh:latest \ &> /dev/null @@ -2090,8 +2090,8 @@ function test_custom_sftp_configuration () docker run \ --detach \ --name www-data.pool-1.1.1 \ - --env "SSH_AUTOSTART_SSHD=false" \ - --env "SSH_AUTOSTART_SSHD_BOOTSTRAP=true" \ + --env "ENABLE_SSHD_WRAPPER=false" \ + --env "ENABLE_SSHD_BOOTSTRAP=true" \ --volume www-data.pool-1.1.1:/var/www \ jdeathe/centos-ssh:latest \ &> /dev/null @@ -2283,7 +2283,7 @@ function test_healthcheck () docker run \ --detach \ --name ssh.1 \ - --env SSH_AUTOSTART_SSHD=false \ + --env ENABLE_SSHD_WRAPPER=false \ jdeathe/centos-ssh:latest \ &> /dev/null From 80dd7627537837723c4394106ad35859e40469d9 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Mon, 17 Jun 2019 22:56:40 +0100 Subject: [PATCH 02/15] #805: Renames local variable to clarify meaning. --- src/usr/sbin/sshd-wrapper | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index c3a515d..e3df672 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -62,10 +62,10 @@ function __is_valid_enable_sshd_bootstrap () function main () { - local -r autostart_bootstrap="$( + local -r bin="/usr/sbin/sshd" + local -r bootstrap_enabled="$( __get_enable_sshd_bootstrap )" - local -r bin="/usr/sbin/sshd" local -r bootstrap_state_file="/var/lib/misc/sshd-bootstrap" local -r lock_file="/var/lock/subsys/sshd-wrapper" local -r nice="/bin/nice" @@ -101,7 +101,7 @@ function main () __get_options )" - if [[ ${autostart_bootstrap} == false ]] + if [[ ${bootstrap_enabled} == false ]] then # block. sleep infinity From 092bc53eacbd9e064154b87f323565c9731f6262 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Mon, 17 Jun 2019 22:57:32 +0100 Subject: [PATCH 03/15] #805 Remove unnecessary comment. --- src/usr/sbin/sshd-wrapper | 1 - 1 file changed, 1 deletion(-) diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index e3df672..929ee11 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -103,7 +103,6 @@ function main () if [[ ${bootstrap_enabled} == false ]] then - # block. sleep infinity fi From 835aea128047e8201f84aac71d2a314545b7fb3c Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 00:52:24 +0100 Subject: [PATCH 04/15] #807: Adds improved wait on bootstrap completion in wrapper script. --- CHANGELOG.md | 1 + Dockerfile | 5 ++ README.md | 29 ++++++----- src/etc/supervisord.d/sshd-wrapper.conf | 3 +- src/usr/sbin/sshd-wrapper | 69 ++++++++++++------------- 5 files changed, 55 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d5317..fc01d35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Summary of release changes for Version 2 - CentOS-7 - Adds `inspect`, `reload` and `top` Makefile targets. - Adds improved lock/state file implementation in bootstrap and wrapper scripts. - Adds improved `clean` Makefile target; includes exited containers and dangling images. +- Adds improved wait on bootstrap completion in wrapper script. - Fixes port incrementation failures when installing systemd units via `scmi`. - Fixes etcd port registration failures when installing systemd units via `scmi` with the `--register` option. - Fixes binary paths in systemd unit files for compatibility with both EL and Ubuntu hosts. diff --git a/Dockerfile b/Dockerfile index e47c415..537a83f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,10 @@ RUN rpm --rebuilddb \ centos-release-scl-rh \ epel-release \ https://centos7.iuscommunity.org/ius-release.rpm \ + && yum -y install \ + --setopt=tsflags=nodocs \ + --disableplugin=fastestmirror \ + inotify-tools-3.14-8.el7 \ openssh-clients-7.4p1-16.el7 \ openssh-server-7.4p1-16.el7 \ openssl-1.0.2k-16.el7 \ @@ -30,6 +34,7 @@ RUN rpm --rebuilddb \ sudo-1.8.23-3.el7 \ yum-plugin-versionlock-1.1.31-50.el7 \ && yum versionlock add \ + inotify-tools \ openssh \ openssh-server \ openssh-clients \ diff --git a/README.md b/README.md index 66b0032..34aa6e8 100644 --- a/README.md +++ b/README.md @@ -254,14 +254,16 @@ $ docker logs ssh.1 The output of the logs will show the auto-generated password for the user specified by `SSH_USER` on first run. ``` -2019-06-09 10:20:09,504 WARN No file matches via include "/etc/supervisord.d/*.ini" -2019-06-09 10:20:09,504 INFO Included extra file "/etc/supervisord.d/00-supervisor_stdout.conf" during parsing -2019-06-09 10:20:09,504 INFO Included extra file "/etc/supervisord.d/sshd-bootstrap.conf" during parsing -2019-06-09 10:20:09,504 INFO Included extra file "/etc/supervisord.d/sshd-wrapper.conf" during parsing -2019-06-09 10:20:09,504 INFO Set uid to user 0 succeeded -2019-06-09 10:20:09,506 INFO supervisord started with pid 1 -2019-06-09 10:20:10,510 INFO spawned: 'sshd-bootstrap' with pid 9 -2019-06-09 10:20:10,513 INFO spawned: 'sshd-wrapper' with pid 10 +2019-06-17 23:41:07,498 WARN No file matches via include "/etc/supervisord.d/*.ini" +2019-06-17 23:41:07,499 INFO Included extra file "/etc/supervisord.d/00-supervisor_stdout.conf" during parsing +2019-06-17 23:41:07,499 INFO Included extra file "/etc/supervisord.d/sshd-bootstrap.conf" during parsing +2019-06-17 23:41:07,499 INFO Included extra file "/etc/supervisord.d/sshd-wrapper.conf" during parsing +2019-06-17 23:41:07,499 INFO Set uid to user 0 succeeded +2019-06-17 23:41:07,501 INFO supervisord started with pid 1 +2019-06-17 23:41:08,505 INFO spawned: 'sshd-bootstrap' with pid 8 +2019-06-17 23:41:08,508 INFO spawned: 'sshd-wrapper' with pid 9 +INFO: sshd-wrapper waiting on sshd-bootstrap +2019-06-17 23:41:08,519 INFO success: sshd-bootstrap entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) ================================================================================ SSH Details @@ -271,25 +273,24 @@ home : /home/app-admin id : 500:500 key fingerprints : dd:3b:b8:2e:85:04:06:e9:ab:ff:a8:0a:c0:04:6e:d6 (insecure key) -password : buSoRzQB3dyXw67L +password : 1RZuwErfrDA9kF3U password authentication : no rsa private key fingerprint : N/A rsa host key fingerprint : -5d:29:c0:f0:ee:4b:6a:d5:fe:76:a4:1d:1e:c4:e8:4d +1e:7d:6d:38:0a:7b:7b:df:73:51:e9:d4:ba:84:ce:ba shell : /bin/bash sudo : ALL=(ALL) ALL timezone : UTC user : app-admin -------------------------------------------------------------------------------- -0.355662 +0.377392 -2019-06-09 10:20:10,880 INFO success: sshd-bootstrap entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) -2019-06-09 10:20:10,880 INFO success: sshd-wrapper entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) -2019-06-09 10:20:10,883 INFO exited: sshd-bootstrap (exit status 0; expected) INFO: sshd-wrapper starting sshd +2019-06-17 23:41:08,901 INFO exited: sshd-bootstrap (exit status 0; expected) Server listening on 0.0.0.0 port 22. Server listening on :: port 22. +2019-06-17 23:41:13,893 INFO success: sshd-wrapper entered RUNNING state, process has stayed up for > than 5 seconds (startsecs) ``` #### Environment Variables diff --git a/src/etc/supervisord.d/sshd-wrapper.conf b/src/etc/supervisord.d/sshd-wrapper.conf index c35d688..7aab8ca 100644 --- a/src/etc/supervisord.d/sshd-wrapper.conf +++ b/src/etc/supervisord.d/sshd-wrapper.conf @@ -3,7 +3,8 @@ autorestart = true autostart = %(ENV_ENABLE_SSHD_WRAPPER)s command = /usr/sbin/sshd-wrapper --verbose priority = 10 -startsecs = 0 +startretries = 0 +startsecs = 5 stderr_logfile = /dev/stderr stderr_logfile_maxbytes = 0 stdout_logfile = /dev/stdout diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index 929ee11..ef61e1d 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -33,40 +33,11 @@ function __get_options () "${options}" } -function __get_enable_sshd_bootstrap () -{ - local -r default_value="${1:-true}" - - local value="${ENABLE_SSHD_BOOTSTRAP}" - - if ! __is_valid_enable_sshd_bootstrap "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - -function __is_valid_enable_sshd_bootstrap () -{ - local -r boolean_value='^(true|false)$' - local -r value="${1}" - - if [[ ${value} =~ ${boolean_value} ]] - then - return 0 - fi - - return 1 -} - function main () { local -r bin="/usr/sbin/sshd" - local -r bootstrap_enabled="$( - __get_enable_sshd_bootstrap - )" local -r bootstrap_state_file="/var/lib/misc/sshd-bootstrap" + local -r bootstrap_timeout="4" local -r lock_file="/var/lock/subsys/sshd-wrapper" local -r nice="/bin/nice" local -r niceness="10" @@ -74,7 +45,6 @@ function main () local options local verbose="false" - # Parse options while [[ "${#}" -gt 0 ]] do case "${1}" in @@ -101,16 +71,41 @@ function main () __get_options )" - if [[ ${bootstrap_enabled} == false ]] - then - sleep infinity - fi - until [[ -e ${bootstrap_state_file} ]] do - sleep 0.1 + set +e + + if [[ ${verbose} == true ]] + then + printf -- \ + 'INFO: %s waiting on %s\n' \ + "${0##*/}" \ + "${bootstrap_state_file##*/}" + fi + + inotifywait \ + -qq \ + -t ${bootstrap_timeout} \ + -e "create" \ + "${bootstrap_state_file%/*}" + + if [[ ${?} -eq 2 ]] + then + break + fi + + set -e done + if ! [[ -e ${bootstrap_state_file} ]] + then + >&2 printf -- \ + 'ERROR: %s timed out - aborting %s\n' \ + "${bootstrap_state_file##*/}" \ + "${0##*/}" + exit 1 + fi + if [[ ${verbose} == true ]] then printf -- \ From 55fcad8dea78bdfa4df1ce6fc617f0275c3d91e3 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 01:05:01 +0100 Subject: [PATCH 05/15] #807: Disables exit on error specifically for inotifywait call. --- src/usr/sbin/sshd-wrapper | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index ef61e1d..33f043a 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -73,8 +73,6 @@ function main () until [[ -e ${bootstrap_state_file} ]] do - set +e - if [[ ${verbose} == true ]] then printf -- \ @@ -83,18 +81,18 @@ function main () "${bootstrap_state_file##*/}" fi + set +e inotifywait \ -qq \ -t ${bootstrap_timeout} \ -e "create" \ "${bootstrap_state_file%/*}" + set -e if [[ ${?} -eq 2 ]] then break fi - - set -e done if ! [[ -e ${bootstrap_state_file} ]] From 3af29acf7f5167a5dda7202c2660656c3561f32f Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 01:27:07 +0100 Subject: [PATCH 06/15] #807: Adds readable exit code and prevent repeating message unnecessarily. --- src/usr/sbin/sshd-wrapper | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index 33f043a..c2af3c8 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -41,6 +41,7 @@ function main () local -r lock_file="/var/lock/subsys/sshd-wrapper" local -r nice="/bin/nice" local -r niceness="10" + local -r timed_out_with_no_events="2" local options local verbose="false" @@ -71,16 +72,16 @@ function main () __get_options )" + if [[ ${verbose} == true ]] + then + printf -- \ + 'INFO: %s waiting on %s\n' \ + "${0##*/}" \ + "${bootstrap_state_file##*/}" + fi + until [[ -e ${bootstrap_state_file} ]] do - if [[ ${verbose} == true ]] - then - printf -- \ - 'INFO: %s waiting on %s\n' \ - "${0##*/}" \ - "${bootstrap_state_file##*/}" - fi - set +e inotifywait \ -qq \ @@ -89,7 +90,7 @@ function main () "${bootstrap_state_file%/*}" set -e - if [[ ${?} -eq 2 ]] + if [[ ${?} -eq ${timed_out_with_no_events} ]] then break fi From fb0e2f8872d4f23fb4e1f4b3d0fc9255ae42aedd Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 02:01:00 +0100 Subject: [PATCH 07/15] #807: Fixes wrapper exiting preamturly. --- src/usr/sbin/sshd-wrapper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index c2af3c8..c9ef5d7 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -88,12 +88,12 @@ function main () -t ${bootstrap_timeout} \ -e "create" \ "${bootstrap_state_file%/*}" - set -e if [[ ${?} -eq ${timed_out_with_no_events} ]] then break fi + set -e done if ! [[ -e ${bootstrap_state_file} ]] From 1d7ce70b4830763ae8410f56ad9112424d0bebd4 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 08:27:19 +0100 Subject: [PATCH 08/15] #807: Adds note about inclusion of inotify-tools in README. --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 34aa6e8..1a4c7a4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The latest CentOS-6 / CentOS-7 based releases can be pulled from the `centos-6` The Dockerfile can be used to build a base image that is the bases for several other docker images. -Included in the build are the [SCL](https://www.softwarecollections.org/), [EPEL](http://fedoraproject.org/wiki/EPEL) and [IUS](https://ius.io) repositories. Installed packages include [OpenSSH](http://www.openssh.com/portable.html) secure shell, [Sudo](http://www.courtesan.com/sudo/) and [vim-minimal](http://www.vim.org/) are along with python-setuptools, [supervisor](http://supervisord.org/) and [supervisor-stdout](https://github.com/coderanger/supervisor-stdout). +Included in the build are the [SCL](https://www.softwarecollections.org/), [EPEL](http://fedoraproject.org/wiki/EPEL) and [IUS](https://ius.io) repositories. Installed packages include [inotify-tools](https://github.com/rvoicilas/inotify-tools/wiki), [OpenSSH](http://www.openssh.com/portable.html) secure shell, [Sudo](http://www.courtesan.com/sudo/), [vim-minimal](http://www.vim.org/), python-setuptools, [supervisor](http://supervisord.org/) and [supervisor-stdout](https://github.com/coderanger/supervisor-stdout). [Supervisor](http://supervisord.org/) is used to start and the sshd daemon when a docker container based on this image is run. @@ -297,6 +297,21 @@ Server listening on :: port 22. There are several environmental variables defined at runtime these allow the operator to customise the running container. +##### ENABLE_SSHD_BOOTSTRAP & ENABLE_SSHD_WRAPPER + +It may be desirable to prevent the startup of the sshd-bootstrap script and/or sshd daemon. For example, when using an image built from this Dockerfile as the source for another Dockerfile you could disable both sshd-booststrap and sshd from startup by setting `ENABLE_SSHD_BOOTSTRAP` and `ENABLE_SSHD_WRAPPER` to `false`. The benefit of this is to reduce the number of running processes in the final container. + +``` +... + --env "ENABLE_SSHD_BOOTSTRAP=false" \ + --env "ENABLE_SSHD_WRAPPER=false" \ +... +``` + +##### ENABLE_SUPERVISOR_STDOUT + +This image has `supervisor_stdout` installed which can be used to allow a process controlled by supervisord to send output to both a log file and stdout. It is recommended to simply output to stdout in order to reduce the number of running processes to a minimum. Setting `ENABLE_SUPERVISOR_STDOUT` to "false" will prevent the startup of `supervisor_stdout`. Where an image requires this feature for its logging output `ENABLE_SUPERVISOR_STDOUT` should be set to "true". + ##### SSH_AUTHORIZED_KEYS As detailed below the public key added for the SSH user is insecure by default. This is intentional and allows for access using a known private key. Using `SSH_AUTHORIZED_KEYS` you can replace the insecure public key with another one (or several). Further details on how to create your own private + public key pair are provided below. If adding more than one key it is recommended to either base64 encode the value or use a container file path in combination with a bind mounted file or Docker Swarm config etc. @@ -328,21 +343,6 @@ Using `SSH_AUTHORIZED_KEYS` with a container file path allows for the authorized ... ``` -##### ENABLE_SSHD_BOOTSTRAP & ENABLE_SSHD_WRAPPER - -It may be desirable to prevent the startup of the sshd-bootstrap script and/or sshd daemon. For example, when using an image built from this Dockerfile as the source for another Dockerfile you could disable both sshd-booststrap and sshd from startup by setting `ENABLE_SSHD_BOOTSTRAP` and `ENABLE_SSHD_WRAPPER` to `false`. The benefit of this is to reduce the number of running processes in the final container. - -``` -... - --env "ENABLE_SSHD_BOOTSTRAP=false" \ - --env "ENABLE_SSHD_WRAPPER=false" \ -... -``` - -##### ENABLE_SUPERVISOR_STDOUT - -This image has `supervisor_stdout` installed which can be used to allow a process controlled by supervisord to send output to both a log file and stdout. It is recommended to simply output to stdout in order to reduce the number of running processes to a minimum. Setting `ENABLE_SUPERVISOR_STDOUT` to "false" will prevent the startup of `supervisor_stdout`. Where an image requires this feature for its logging output `ENABLE_SUPERVISOR_STDOUT` should be set to "true". - ##### SSH_CHROOT_DIRECTORY This option is only applicable when `SSH_USER_FORCE_SFTP` is set to `true`. When using the SFTP option the user is jailed into the ChrootDirectory. The value can contain the placeholders `%h` and `%u` which will be replaced with the values of `SSH_USER_HOME` and `SSH_USER` respectively. The default value of `%h` is the best choice in most cases but the user requires a sub-directory in their HOME directory which they have write access to. If no volume is mounted into the path of the SSH user's HOME directory then a directory named `_data` is created automatically. If you need the user to be able to write to their HOME directory then use an alternative value such as `/chroot/%u` so that the user's HOME path, (relative to the ChrootDirectory), becomes `/chroot/app-admin/home/app-admin` by default. From e0d32714e7c2b4ace2d95de36f75c893903363c6 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 15:43:04 +0100 Subject: [PATCH 09/15] #807: Adds simplified loop and more consistent error message. --- src/usr/sbin/sshd-wrapper | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/usr/sbin/sshd-wrapper b/src/usr/sbin/sshd-wrapper index c9ef5d7..6f6c815 100755 --- a/src/usr/sbin/sshd-wrapper +++ b/src/usr/sbin/sshd-wrapper @@ -41,7 +41,6 @@ function main () local -r lock_file="/var/lock/subsys/sshd-wrapper" local -r nice="/bin/nice" local -r niceness="10" - local -r timed_out_with_no_events="2" local options local verbose="false" @@ -80,28 +79,25 @@ function main () "${bootstrap_state_file##*/}" fi + set +e until [[ -e ${bootstrap_state_file} ]] do - set +e - inotifywait \ - -qq \ - -t ${bootstrap_timeout} \ + if ! inotifywait -qq \ -e "create" \ + -t "${bootstrap_timeout}" \ "${bootstrap_state_file%/*}" - - if [[ ${?} -eq ${timed_out_with_no_events} ]] then break fi - set -e done + set -e if ! [[ -e ${bootstrap_state_file} ]] then >&2 printf -- \ - 'ERROR: %s timed out - aborting %s\n' \ - "${bootstrap_state_file##*/}" \ - "${0##*/}" + 'ERROR: %s timed out waiting on %s\n' \ + "${0##*/}" \ + "${bootstrap_state_file##*/}" exit 1 fi From 7c12389279433f454c9791a7292f17e240d48c88 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 18:19:23 +0100 Subject: [PATCH 10/15] #801: Updates bootstrap timer to use UTC date timestamps. --- CHANGELOG.md | 1 + src/usr/sbin/sshd-bootstrap | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc01d35..b7d83bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Summary of release changes for Version 2 - CentOS-7 - Updates default value of `ENABLE_SUPERVISOR_STDOUT` to false. - Updates `sshd-bootstrap` and `sshd-wrapper` configuration to send error log output to stderr. - Updates order of values in SSH/SFTP Details log output. +- Updates bootstrap timer to use UTC date timestamps. - Adds reference to `python-setuptools` in README; removed in error. - Adds `inspect`, `reload` and `top` Makefile targets. - Adds improved lock/state file implementation in bootstrap and wrapper scripts. diff --git a/src/usr/sbin/sshd-bootstrap b/src/usr/sbin/sshd-bootstrap index 674b70d..e26a33c 100755 --- a/src/usr/sbin/sshd-bootstrap +++ b/src/usr/sbin/sshd-bootstrap @@ -586,7 +586,7 @@ function __get_ssh_user_uid () function __get_timer_total () { local -r timer_end="$( - date +%s.%N + date -u +%s.%N )" local -r timer_start="${1}" @@ -985,7 +985,7 @@ function main () local -r redacted_value="********" local -r state_file="/var/lib/misc/sshd-bootstrap" local -r timer_start="$( - date +%s.%N + date -u +%s.%N )" local env From 8a79599b5f06b7727fa97272c5944060bf6d6124 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Tue, 18 Jun 2019 20:25:47 +0100 Subject: [PATCH 11/15] #803: Restructures existing supervisord configuration files/priorities. --- CHANGELOG.md | 2 ++ Dockerfile | 2 +- .../{sshd-bootstrap.conf => 20-sshd-bootstrap.conf} | 2 +- .../supervisord.d/{sshd-wrapper.conf => 50-sshd-wrapper.conf} | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) rename src/etc/supervisord.d/{sshd-bootstrap.conf => 20-sshd-bootstrap.conf} (95%) rename src/etc/supervisord.d/{sshd-wrapper.conf => 50-sshd-wrapper.conf} (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7d83bd..3fc99ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ Summary of release changes for Version 2 - CentOS-7 - Updates `sshd-bootstrap` and `sshd-wrapper` configuration to send error log output to stderr. - Updates order of values in SSH/SFTP Details log output. - Updates bootstrap timer to use UTC date timestamps. +- Updates bootstrap supervisord configuration file/priority to `20-sshd-bootstrap.conf`/`20`. +- Updates wrapper supervisord configuration file/priority to `50-sshd-wrapper.conf`/`50`. - Adds reference to `python-setuptools` in README; removed in error. - Adds `inspect`, `reload` and `top` Makefile targets. - Adds improved lock/state file implementation in bootstrap and wrapper scripts. diff --git a/Dockerfile b/Dockerfile index 537a83f..bc879b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -86,7 +86,7 @@ RUN ln -sf \ -e "s~{{RELEASE_VERSION}}~${RELEASE_VERSION}~g" \ /etc/systemd/system/centos-ssh@.service \ && chmod 644 \ - /etc/{supervisord.conf,supervisord.d/sshd-{bootstrap,wrapper}.conf} \ + /etc/{supervisord.conf,supervisord.d/{20-sshd-bootstrap,50-sshd-wrapper}.conf} \ && chmod 700 \ /usr/{bin/healthcheck,sbin/{scmi,sshd-{bootstrap,wrapper}}} diff --git a/src/etc/supervisord.d/sshd-bootstrap.conf b/src/etc/supervisord.d/20-sshd-bootstrap.conf similarity index 95% rename from src/etc/supervisord.d/sshd-bootstrap.conf rename to src/etc/supervisord.d/20-sshd-bootstrap.conf index 6470f74..fe79ae6 100644 --- a/src/etc/supervisord.d/sshd-bootstrap.conf +++ b/src/etc/supervisord.d/20-sshd-bootstrap.conf @@ -2,7 +2,7 @@ autorestart = false autostart = %(ENV_ENABLE_SSHD_BOOTSTRAP)s command = /usr/sbin/sshd-bootstrap --verbose -priority = 5 +priority = 20 startretries = 0 startsecs = 0 stderr_logfile = /dev/stderr diff --git a/src/etc/supervisord.d/sshd-wrapper.conf b/src/etc/supervisord.d/50-sshd-wrapper.conf similarity index 95% rename from src/etc/supervisord.d/sshd-wrapper.conf rename to src/etc/supervisord.d/50-sshd-wrapper.conf index 7aab8ca..9375cb2 100644 --- a/src/etc/supervisord.d/sshd-wrapper.conf +++ b/src/etc/supervisord.d/50-sshd-wrapper.conf @@ -2,7 +2,7 @@ autorestart = true autostart = %(ENV_ENABLE_SSHD_WRAPPER)s command = /usr/sbin/sshd-wrapper --verbose -priority = 10 +priority = 50 startretries = 0 startsecs = 5 stderr_logfile = /dev/stderr From 664fd2c4d5616df9ff7c304cc373042665fc8a4e Mon Sep 17 00:00:00 2001 From: James Deathe Date: Thu, 20 Jun 2019 02:24:43 +0100 Subject: [PATCH 12/15] #803: Adds independent system time zone setup. --- .env.example | 4 +- CHANGELOG.md | 4 + Dockerfile | 6 +- README.md | 61 ++-- default.mk | 4 +- docker-compose.yml | 2 +- environment.mk | 2 +- src/etc/supervisord.conf | 2 +- .../10-system-timezone-wrapper.conf | 11 + src/etc/systemd/system/centos-ssh@.service | 4 +- src/opt/scmi/default.sh | 2 +- src/opt/scmi/environment.sh | 2 +- src/opt/scmi/service-unit.sh | 2 +- src/usr/bin/healthcheck | 46 +++ src/usr/sbin/sshd-bootstrap | 71 ----- src/usr/sbin/system-timezone | 268 ++++++++++++++++++ src/usr/sbin/system-timezone-wrapper | 205 ++++++++++++++ test/shpec/operation_shpec.sh | 2 +- 18 files changed, 586 insertions(+), 112 deletions(-) create mode 100644 src/etc/supervisord.d/10-system-timezone-wrapper.conf create mode 100755 src/usr/sbin/system-timezone create mode 100755 src/usr/sbin/system-timezone-wrapper diff --git a/.env.example b/.env.example index 0c27bd5..fd2a94c 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,6 @@ SSH_CHROOT_DIRECTORY=%h SSH_INHERIT_ENVIRONMENT=false SSH_PASSWORD_AUTHENTICATION=false SSH_SUDO=ALL=(ALL) ALL -SSH_TIMEZONE=UTC SSH_USER=app-admin SSH_USER_FORCE_SFTP=false SSH_USER_HOME=/home/%u @@ -13,4 +12,5 @@ SSH_USER_ID=500:500 SSH_USER_PASSWORD= SSH_USER_PASSWORD_HASHED=false SSH_USER_PRIVATE_KEY= -SSH_USER_SHELL=/bin/bash \ No newline at end of file +SSH_USER_SHELL=/bin/bash +SYSTEM_TIMEZONE=UTC diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fc99ac..1b88fac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Summary of release changes for Version 2 - CentOS-7 - Deprecates `SSH_AUTOSTART_SSHD`, replaced with `ENABLE_SSHD_WRAPPER`. - Deprecates `SSH_AUTOSTART_SSHD_BOOTSTRAP`, replaced with `ENABLE_SSHD_BOOTSTRAP`. - Deprecates `SSH_AUTOSTART_SUPERVISOR_STDOUT`, replaced with `ENABLE_SUPERVISOR_STDOUT`. +- Deprecates `SSH_TIMEZONE`, replaced with `SYSTEM_TIMEZONE`. - Updates source tag to CentOS 7.6.1810. - Updates supervisord to 4.0.3. - Updates default value of `ENABLE_SUPERVISOR_STDOUT` to false. @@ -22,12 +23,15 @@ Summary of release changes for Version 2 - CentOS-7 - Adds improved lock/state file implementation in bootstrap and wrapper scripts. - Adds improved `clean` Makefile target; includes exited containers and dangling images. - Adds improved wait on bootstrap completion in wrapper script. +- Adds `system-timezone` and `system-timezone-wrapper` to handle system time zone setup. +- Adds system time zone validation to healthcheck. - Fixes port incrementation failures when installing systemd units via `scmi`. - Fixes etcd port registration failures when installing systemd units via `scmi` with the `--register` option. - Fixes binary paths in systemd unit files for compatibility with both EL and Ubuntu hosts. - Fixes use of printf binary instead of builtin in systemd unit files. - Fixes docker host connection status check in Makefile. - Removes support for long image tags (i.e. centos-7-2.x.x). +- Removes system time zone setup from `sshd-bootstrap`. ### 2.5.1 - 2019-02-28 diff --git a/Dockerfile b/Dockerfile index bc879b6..55a6ef2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -88,7 +88,7 @@ RUN ln -sf \ && chmod 644 \ /etc/{supervisord.conf,supervisord.d/{20-sshd-bootstrap,50-sshd-wrapper}.conf} \ && chmod 700 \ - /usr/{bin/healthcheck,sbin/{scmi,sshd-{bootstrap,wrapper}}} + /usr/{bin/healthcheck,sbin/{scmi,sshd-{bootstrap,wrapper},system-{timezone,timezone-wrapper}}} EXPOSE 22 @@ -104,7 +104,6 @@ ENV \ SSH_INHERIT_ENVIRONMENT="false" \ SSH_PASSWORD_AUTHENTICATION="false" \ SSH_SUDO="ALL=(ALL) ALL" \ - SSH_TIMEZONE="UTC" \ SSH_USER="app-admin" \ SSH_USER_FORCE_SFTP="false" \ SSH_USER_HOME="/home/%u" \ @@ -112,7 +111,8 @@ ENV \ SSH_USER_PASSWORD="" \ SSH_USER_PASSWORD_HASHED="false" \ SSH_USER_PRIVATE_KEY="" \ - SSH_USER_SHELL="/bin/bash" + SSH_USER_SHELL="/bin/bash" \ + SYSTEM_TIMEZONE="UTC" # ------------------------------------------------------------------------------ # Set image metadata diff --git a/README.md b/README.md index 1a4c7a4..8396a15 100644 --- a/README.md +++ b/README.md @@ -254,16 +254,28 @@ $ docker logs ssh.1 The output of the logs will show the auto-generated password for the user specified by `SSH_USER` on first run. ``` -2019-06-17 23:41:07,498 WARN No file matches via include "/etc/supervisord.d/*.ini" -2019-06-17 23:41:07,499 INFO Included extra file "/etc/supervisord.d/00-supervisor_stdout.conf" during parsing -2019-06-17 23:41:07,499 INFO Included extra file "/etc/supervisord.d/sshd-bootstrap.conf" during parsing -2019-06-17 23:41:07,499 INFO Included extra file "/etc/supervisord.d/sshd-wrapper.conf" during parsing -2019-06-17 23:41:07,499 INFO Set uid to user 0 succeeded -2019-06-17 23:41:07,501 INFO supervisord started with pid 1 -2019-06-17 23:41:08,505 INFO spawned: 'sshd-bootstrap' with pid 8 -2019-06-17 23:41:08,508 INFO spawned: 'sshd-wrapper' with pid 9 +2019-06-20 00:10:35,306 WARN No file matches via include "/etc/supervisord.d/*.ini" +2019-06-20 00:10:35,306 INFO Included extra file "/etc/supervisord.d/00-supervisor_stdout.conf" during parsing +2019-06-20 00:10:35,307 INFO Included extra file "/etc/supervisord.d/10-system-timezone-wrapper.conf" during parsing +2019-06-20 00:10:35,307 INFO Included extra file "/etc/supervisord.d/20-sshd-bootstrap.conf" during parsing +2019-06-20 00:10:35,307 INFO Included extra file "/etc/supervisord.d/50-sshd-wrapper.conf" during parsing +2019-06-20 00:10:35,307 INFO Set uid to user 0 succeeded +2019-06-20 00:10:35,310 INFO supervisord started with pid 1 +2019-06-20 00:10:36,315 INFO spawned: 'system-timezone-wrapper' with pid 9 +2019-06-20 00:10:36,318 INFO spawned: 'sshd-bootstrap' with pid 10 +2019-06-20 00:10:36,320 INFO spawned: 'sshd-wrapper' with pid 11 INFO: sshd-wrapper waiting on sshd-bootstrap -2019-06-17 23:41:08,519 INFO success: sshd-bootstrap entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) +2019-06-20 00:10:36,328 INFO success: system-timezone-wrapper entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) +2019-06-20 00:10:36,328 INFO success: sshd-bootstrap entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) + +================================================================================ +System Time Zone Details +-------------------------------------------------------------------------------- +timezone : UTC +-------------------------------------------------------------------------------- +0.00640178 + +2019-06-20 00:10:36,346 INFO exited: system-timezone-wrapper (exit status 0; expected) ================================================================================ SSH Details @@ -273,24 +285,23 @@ home : /home/app-admin id : 500:500 key fingerprints : dd:3b:b8:2e:85:04:06:e9:ab:ff:a8:0a:c0:04:6e:d6 (insecure key) -password : 1RZuwErfrDA9kF3U +password : uIEqLkiacCvxaN45 password authentication : no rsa private key fingerprint : N/A rsa host key fingerprint : -1e:7d:6d:38:0a:7b:7b:df:73:51:e9:d4:ba:84:ce:ba +7d:6f:d2:e8:7e:84:dd:ff:98:05:5e:6f:35:66:51:53 shell : /bin/bash sudo : ALL=(ALL) ALL -timezone : UTC user : app-admin -------------------------------------------------------------------------------- -0.377392 +0.516901 INFO: sshd-wrapper starting sshd -2019-06-17 23:41:08,901 INFO exited: sshd-bootstrap (exit status 0; expected) +2019-06-20 00:10:36,852 INFO exited: sshd-bootstrap (exit status 0; expected) Server listening on 0.0.0.0 port 22. Server listening on :: port 22. -2019-06-17 23:41:13,893 INFO success: sshd-wrapper entered RUNNING state, process has stayed up for > than 5 seconds (startsecs) +2019-06-20 00:10:41,872 INFO success: sshd-wrapper entered RUNNING state, process has stayed up for > than 5 seconds (startsecs) ``` #### Environment Variables @@ -383,16 +394,6 @@ On first run the SSH user is created with a the sudo rule `ALL=(ALL) ALL` which ... ``` -##### SSH_TIMEZONE - -If you require a locale based system time zone `SSH_TIMEZONE` can be used when running the container. - -``` -... - --env "SSH_TIMEZONE=Europe/London" \ -... -``` - ##### SSH_USER On first run the SSH user is created with the default username of "app-admin". If you require an alternative username `SSH_USER` can be used when running the container. @@ -476,6 +477,16 @@ If set to a valid container file path the value will be read from the file - thi ... ``` +##### SYSTEM_TIMEZONE + +If you require a locale based system time zone `SYSTEM_TIMEZONE` can be used when running the container. + +``` +... + --env "SYSTEM_TIMEZONE=Europe/London" \ +... +``` + ###### Generating a crypt SHA-512 password hash To generate a hashed password string for the password `Passw0rd!`, use the following method. diff --git a/default.mk b/default.mk index bd32933..29c97fe 100644 --- a/default.mk +++ b/default.mk @@ -49,7 +49,6 @@ define DOCKER_CONTAINER_PARAMETERS --env "SSH_INHERIT_ENVIRONMENT=$(SSH_INHERIT_ENVIRONMENT)" \ --env "SSH_PASSWORD_AUTHENTICATION=$(SSH_PASSWORD_AUTHENTICATION)" \ --env "SSH_SUDO=$(SSH_SUDO)" \ ---env "SSH_TIMEZONE=$(SSH_TIMEZONE)" \ --env "SSH_USER=$(SSH_USER)" \ --env "SSH_USER_FORCE_SFTP=$(SSH_USER_FORCE_SFTP)" \ --env "SSH_USER_HOME=$(SSH_USER_HOME)" \ @@ -57,5 +56,6 @@ define DOCKER_CONTAINER_PARAMETERS --env "SSH_USER_PASSWORD=$(SSH_USER_PASSWORD)" \ --env "SSH_USER_PASSWORD_HASHED=$(SSH_USER_PASSWORD_HASHED)" \ --env "SSH_USER_PRIVATE_KEY=$(SSH_USER_PRIVATE_KEY)" \ ---env "SSH_USER_SHELL=$(SSH_USER_SHELL)" +--env "SSH_USER_SHELL=$(SSH_USER_SHELL)" \ +--env "SYSTEM_TIMEZONE=$(SYSTEM_TIMEZONE)" endef diff --git a/docker-compose.yml b/docker-compose.yml index e1060b0..e96ea99 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,7 +35,6 @@ services: SSH_INHERIT_ENVIRONMENT: "${SSH_INHERIT_ENVIRONMENT}" SSH_PASSWORD_AUTHENTICATION: "${SSH_PASSWORD_AUTHENTICATION}" SSH_SUDO: "${SSH_SUDO}" - SSH_TIMEZONE: "${SSH_TIMEZONE}" SSH_USER: "${SSH_USER}" SSH_USER_FORCE_SFTP: "${SSH_USER_FORCE_SFTP}" SSH_USER_HOME: "${SSH_USER_HOME}" @@ -44,6 +43,7 @@ services: SSH_USER_PASSWORD_HASHED: "${SSH_USER_PASSWORD_HASHED}" SSH_USER_PRIVATE_KEY: "${SSH_USER_PRIVATE_KEY}" SSH_USER_SHELL: "${SSH_USER_SHELL}" + SYSTEM_TIMEZONE: "${SYSTEM_TIMEZONE}" image: "jdeathe/centos-ssh:latest" ports: - "2020:22" diff --git a/environment.mk b/environment.mk index 2925b3e..36ed28e 100644 --- a/environment.mk +++ b/environment.mk @@ -31,7 +31,6 @@ SSH_CHROOT_DIRECTORY ?= %h SSH_INHERIT_ENVIRONMENT ?= false SSH_PASSWORD_AUTHENTICATION ?= false SSH_SUDO ?= ALL=(ALL) ALL -SSH_TIMEZONE ?= UTC SSH_USER ?= app-admin SSH_USER_FORCE_SFTP ?= false SSH_USER_HOME ?= /home/%u @@ -40,3 +39,4 @@ SSH_USER_PASSWORD ?= SSH_USER_PASSWORD_HASHED ?= false SSH_USER_PRIVATE_KEY ?= SSH_USER_SHELL ?= /bin/bash +SYSTEM_TIMEZONE ?= UTC diff --git a/src/etc/supervisord.conf b/src/etc/supervisord.conf index e9384f8..8923827 100755 --- a/src/etc/supervisord.conf +++ b/src/etc/supervisord.conf @@ -1,5 +1,5 @@ [supervisord] -environment = SSH_AUTOSTART_SSHD="%(ENV_ENABLE_SSHD_WRAPPER)s",SSH_AUTOSTART_SSHD_BOOTSTRAP="%(ENV_ENABLE_SSHD_BOOTSTRAP)s",SSH_AUTOSTART_SUPERVISOR_STDOUT="%(ENV_ENABLE_SSHD_BOOTSTRAP)s" +environment = SSH_AUTOSTART_SSHD="%(ENV_ENABLE_SSHD_WRAPPER)s",SSH_AUTOSTART_SSHD_BOOTSTRAP="%(ENV_ENABLE_SSHD_BOOTSTRAP)s",SSH_AUTOSTART_SUPERVISOR_STDOUT="%(ENV_ENABLE_SSHD_BOOTSTRAP)s",SSH_TIMEZONE="%(ENV_SYSTEM_TIMEZONE)s" logfile = /dev/null logfile_maxbytes = 0 logfile_backups = 0 diff --git a/src/etc/supervisord.d/10-system-timezone-wrapper.conf b/src/etc/supervisord.d/10-system-timezone-wrapper.conf new file mode 100644 index 0000000..0280685 --- /dev/null +++ b/src/etc/supervisord.d/10-system-timezone-wrapper.conf @@ -0,0 +1,11 @@ +[program:system-timezone-wrapper] +autorestart = false +autostart = true +command = /usr/sbin/system-timezone-wrapper --verbose +priority = 10 +startretries = 0 +startsecs = 0 +stderr_logfile = /dev/stderr +stderr_logfile_maxbytes = 0 +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 diff --git a/src/etc/systemd/system/centos-ssh@.service b/src/etc/systemd/system/centos-ssh@.service index c259a10..9787182 100644 --- a/src/etc/systemd/system/centos-ssh@.service +++ b/src/etc/systemd/system/centos-ssh@.service @@ -64,7 +64,6 @@ Environment="SSH_CHROOT_DIRECTORY=%%h" Environment="SSH_INHERIT_ENVIRONMENT=false" Environment="SSH_PASSWORD_AUTHENTICATION=false" Environment="SSH_SUDO=ALL=(ALL) ALL" -Environment="SSH_TIMEZONE=UTC" Environment="SSH_USER=app-admin" Environment="SSH_USER_FORCE_SFTP=false" Environment="SSH_USER_HOME=/home/%%u" @@ -73,6 +72,7 @@ Environment="SSH_USER_PASSWORD=" Environment="SSH_USER_PASSWORD_HASHED=false" Environment="SSH_USER_PRIVATE_KEY=" Environment="SSH_USER_SHELL=/bin/bash" +Environment="SYSTEM_TIMEZONE=UTC" # Initialisation: Load image from local storage if available, otherwise pull. ExecStartPre=/bin/bash -c \ @@ -137,7 +137,7 @@ ExecStart=/bin/bash -c \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ --env \"SSH_SUDO=${SSH_SUDO}\" \ - --env \"SSH_TIMEZONE=${SSH_TIMEZONE}\" \ + --env \"SYSTEM_TIMEZONE=${SYSTEM_TIMEZONE}\" \ --env \"SSH_USER=${SSH_USER}\" \ --env \"SSH_USER_FORCE_SFTP=${SSH_USER_FORCE_SFTP}\" \ --env \"SSH_USER_HOME=${SSH_USER_HOME}\" \ diff --git a/src/opt/scmi/default.sh b/src/opt/scmi/default.sh index a667e3d..977a152 100644 --- a/src/opt/scmi/default.sh +++ b/src/opt/scmi/default.sh @@ -54,7 +54,6 @@ DOCKER_CONTAINER_PARAMETERS="--name ${DOCKER_NAME} \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ --env \"SSH_SUDO=${SSH_SUDO}\" \ ---env \"SSH_TIMEZONE=${SSH_TIMEZONE}\" \ --env \"SSH_USER=${SSH_USER}\" \ --env \"SSH_USER_FORCE_SFTP=${SSH_USER_FORCE_SFTP}\" \ --env \"SSH_USER_HOME=${SSH_USER_HOME}\" \ @@ -63,4 +62,5 @@ DOCKER_CONTAINER_PARAMETERS="--name ${DOCKER_NAME} \ --env \"SSH_USER_PASSWORD_HASHED=${SSH_USER_PASSWORD_HASHED}\" \ --env \"SSH_USER_PRIVATE_KEY=${SSH_USER_PRIVATE_KEY}\" \ --env \"SSH_USER_SHELL=${SSH_USER_SHELL}\" \ +--env \"SYSTEM_TIMEZONE=${SYSTEM_TIMEZONE}\" \ ${DOCKER_PUBLISH}" diff --git a/src/opt/scmi/environment.sh b/src/opt/scmi/environment.sh index 4e88bf0..433c68e 100644 --- a/src/opt/scmi/environment.sh +++ b/src/opt/scmi/environment.sh @@ -32,7 +32,6 @@ SSH_CHROOT_DIRECTORY="${SSH_CHROOT_DIRECTORY:-%h}" SSH_INHERIT_ENVIRONMENT="${SSH_INHERIT_ENVIRONMENT:-false}" SSH_PASSWORD_AUTHENTICATION="${SSH_PASSWORD_AUTHENTICATION:-false}" SSH_SUDO="${SSH_SUDO:-ALL=(ALL) ALL}" -SSH_TIMEZONE="${SSH_TIMEZONE:-UTC}" SSH_USER="${SSH_USER:-app-admin}" SSH_USER_FORCE_SFTP="${SSH_USER_FORCE_SFTP:-false}" SSH_USER_HOME="${SSH_USER_HOME:-/home/%u}" @@ -41,3 +40,4 @@ SSH_USER_PASSWORD="${SSH_USER_PASSWORD:-}" SSH_USER_PASSWORD_HASHED="${SSH_USER_PASSWORD_HASHED:-false}" SSH_USER_PRIVATE_KEY="${SSH_USER_PRIVATE_KEY:-}" SSH_USER_SHELL="${SSH_USER_SHELL:-/bin/bash}" +SYSTEM_TIMEZONE="${SYSTEM_TIMEZONE:-UTC}" diff --git a/src/opt/scmi/service-unit.sh b/src/opt/scmi/service-unit.sh index 87b86d7..6c6c131 100644 --- a/src/opt/scmi/service-unit.sh +++ b/src/opt/scmi/service-unit.sh @@ -14,7 +14,6 @@ readonly SERVICE_UNIT_ENVIRONMENT_KEYS=" SSH_INHERIT_ENVIRONMENT SSH_PASSWORD_AUTHENTICATION SSH_SUDO - SSH_TIMEZONE SSH_USER SSH_USER_FORCE_SFTP SSH_USER_HOME @@ -23,6 +22,7 @@ readonly SERVICE_UNIT_ENVIRONMENT_KEYS=" SSH_USER_PASSWORD_HASHED SSH_USER_PRIVATE_KEY SSH_USER_SHELL + SYSTEM_TIMEZONE " readonly SERVICE_UNIT_REGISTER_ENVIRONMENT_KEYS=" REGISTER_ETCD_PARAMETERS diff --git a/src/usr/bin/healthcheck b/src/usr/bin/healthcheck index e90588e..375300f 100755 --- a/src/usr/bin/healthcheck +++ b/src/usr/bin/healthcheck @@ -29,11 +29,49 @@ function __get_ssh_user () printf -- '%s' "${value}" } +function __get_system_timezone () +{ + local -r default_value="${1:-UTC}" + + local value="${SYSTEM_TIMEZONE}" + + if ! __is_valid_system_timezone "${value}" + then + value="${default_value}" + fi + + printf -- '%s' "${value}" +} + +function __is_valid_system_timezone () +{ + __is_valid_zone "${@}" +} + +function __is_valid_zone () +{ + local zone="${1}" + + if [[ -n ${zone} ]] \ + && [[ -f /usr/share/zoneinfo/${zone} ]] + then + return 0 + fi + + return 1 +} + function main () { + local -r system_zone="$( + system-timezone -qq + )" local -r user="$( __get_ssh_user )" + local -r zone="$( + __get_system_timezone + )" if ! ps axo command | grep -qE '^/usr/bin/python /usr/bin/supervisord' then @@ -43,6 +81,14 @@ function main () exit 1 fi + if [[ ${system_zone} != "${zone}" ]] + then + >&2 printf -- \ + '%s\n' \ + "system-timezone zone mismatch." + exit 1 + fi + if [[ ${ENABLE_SSHD_BOOTSTRAP} == true ]] then if [[ -e /var/lock/subsys/sshd-bootstrap ]] diff --git a/src/usr/sbin/sshd-bootstrap b/src/usr/sbin/sshd-bootstrap index e26a33c..26d52c9 100755 --- a/src/usr/sbin/sshd-bootstrap +++ b/src/usr/sbin/sshd-bootstrap @@ -397,20 +397,6 @@ function __get_ssh_sudo () printf -- '%s' "${value}" } -function __get_ssh_timezone () -{ - local -r default_value="${1:-UTC}" - - local value="${SSH_TIMEZONE}" - - if ! __is_valid_ssh_timezone "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - function __get_ssh_user () { local -r default_value="${1:-app-admin}" @@ -745,23 +731,6 @@ function __is_valid_ssh_sudo () return 1 } -function __is_valid_ssh_timezone () -{ - local -r zone="${1}" - - if [[ -z ${zone} ]] - then - return 1 - fi - - if [[ -f /usr/share/zoneinfo/${zone} ]] - then - return 0 - fi - - return 1 -} - function __is_valid_ssh_user () { local -r safe_user='^[a-z_][a-z0-9_-]{0,29}[$a-z0-9_]?$' @@ -892,32 +861,6 @@ function __is_valid_ssh_user_shell () return 1 } -function __set_ssh_timezone () -{ - local -r zone="${1:-UTC}" - - if ! __is_valid_ssh_timezone "${zone}" - then - >&2 printf -- \ - 'ERROR: Unknown time zone: %s\n' \ - "${zone}" - return 1 - else - if [[ -f /etc/sysconfig/clock ]] - then - sed -i \ - -e "s~^\(ZONE=\).*$~\1${zone}~" \ - /etc/sysconfig/clock - fi - - ln -sf \ - /usr/share/zoneinfo/"${zone}" \ - /etc/localtime - - return "${?}" - fi -} - function __set_ssh_user_password () { local -r password_hashed="${2:-"$( @@ -993,7 +936,6 @@ function main () [SSH_CHROOT_DIRECTORY]=__is_valid_ssh_chroot_directory [SSH_PASSWORD_AUTHENTICATION]=__is_valid_ssh_password_authentication [SSH_SUDO]=__is_valid_ssh_sudo - [SSH_TIMEZONE]=__is_valid_ssh_timezone [SSH_USER]=__is_valid_ssh_user [SSH_USER_FORCE_SFTP]=__is_valid_ssh_user_force_sftp [SSH_USER_HOME]=__is_valid_ssh_user_home @@ -1012,7 +954,6 @@ function main () local ssh_key_fingerprints local ssh_password_authentication local ssh_sudo - local ssh_timezone local ssh_user local ssh_user_force_sftp local ssh_user_groups="users,wheel" @@ -1027,7 +968,6 @@ function main () local sshd_command="SSH" local timer_total - # Parse options while [[ "${#}" -gt 0 ]] do case "${1}" in @@ -1079,9 +1019,6 @@ function main () ssh_sudo="$( __get_ssh_sudo )" - ssh_timezone="$( - __get_ssh_timezone - )" ssh_user="$( __get_ssh_user )" @@ -1151,13 +1088,6 @@ function main () done fi - if ! __set_ssh_timezone "${ssh_timezone}" - then - >&2 printf -- \ - 'ERROR: Could not set timezone - aborting.\n' - exit 1 - fi - $( __generate_ssh_host_keys ) & @@ -1448,7 +1378,6 @@ function main () ${ssh_host_key_fingerprint_rsa} shell : ${ssh_user_shell} sudo : ${ssh_sudo} - timezone : ${ssh_timezone} user : ${ssh_user} -------------------------------------------------------------------------------- ${timer_total} diff --git a/src/usr/sbin/system-timezone b/src/usr/sbin/system-timezone new file mode 100755 index 0000000..2cd686f --- /dev/null +++ b/src/usr/sbin/system-timezone @@ -0,0 +1,268 @@ +#!/usr/bin/env bash + +set -e + +function __cleanup () +{ + local -r exit_code="${?}" + + __delete_lock +} + +function __create_lock () +{ + if [[ -n ${lock_file} ]] + then + touch "${lock_file}" + fi +} + +function __delete_lock () +{ + if [[ -f ${lock_file} ]] + then + rm -f "${lock_file}" + fi +} + +function __get_timezone () +{ + local -r link_name="/etc/localtime" + + local localtime="$( + readlink -f "${link_name}" + )" + local zone="${localtime/"/usr/share/zoneinfo/"/}" + + if [[ ! -h ${link_name} ]] \ + || ! __is_valid_zone "${zone}" + then + __print_message \ + "error" \ + "corrupt/invalid symbolic link: ${link_name}" + exit 1 + fi + + printf -- \ + '%s\n' \ + "${zone}" +} + +function __is_valid_zone () +{ + local zone="${1}" + + if [[ -n ${zone} ]] \ + && [[ -f /usr/share/zoneinfo/${zone} ]] + then + return 0 + fi + + return 1 +} + +function __print_message () +{ + local -r type="${1}" + + local message="${2}" + local prefix="" + local quiet="${quiet:-false}" + local silent="${silent:-false}" + + case "${type}" in + error) + prefix="ERROR: " + ;; + info) + prefix="INFO: " + ;; + *) + message="${type}" + ;; + esac + + if [[ ${quiet} == true ]] \ + || [[ ${silent} == true ]] \ + && [[ ${type} != error ]] + then + return 0 + elif [[ ${silent} == true ]] \ + && [[ ${type} == error ]] + then + return 1 + elif [[ ${type} == error ]] + then + >&2 printf -- \ + '%s%s\n' \ + "${prefix}" \ + "${message}" + else + printf -- \ + '%s%s\n' \ + "${prefix}" \ + "${message}" + fi +} + +function __set_timezone () +{ + local zone="${1}" + + if ! __is_valid_zone "${zone}" + then + return 1 + fi + + if [[ -f /etc/sysconfig/clock ]] + then + sed -r -i \ + -e "s~^(ZONE=).*$~\1${zone}~" \ + /etc/sysconfig/clock + fi + + ln -sf \ + /usr/share/zoneinfo/"${zone}" \ + /etc/localtime +} + +function __usage () +{ + local help="${help:-false}" + local quiet="${quiet:-false}" + local silent="${silent:-false}" + + if [[ ${silent} != true ]] \ + || [[ ${help} == true ]] + then + cat <<-USAGE + + Usage: ${0##*/} [OPTIONS] + ${0##*/} [-h|--help] + + ${0##*/} is a utility to manage the system time zone. + It will output the current system time zone if run without options. + + Options: + -h, --help Show this help and exit. + -q, --quiet Do not print information message output. + -qq, --silent Do not print error message output. + -z, --zone ZONE Set the system time zone. e.g: + 'UTC', 'Europe/London' etc. + + USAGE + fi + + if [[ ${help} != true ]] + then + exit 1 + fi + + exit 0 +} + +function main () +{ + local -r lock_file="/var/lock/subsys/system-timezone" + + local help + local quiet="false" + local silent="false" + local system_zone + local zone + + if [[ ${EUID} -ne 0 ]] + then + __print_message \ + "error" \ + "${0##*/} must be run as root." + exit 1 + fi + + while [[ "${#}" -gt 0 ]] + do + case "${1}" in + -h|--help) + help="true" + __usage + break + ;; + -z|--zone) + zone="${2}" + if [[ -z ${zone} ]] + then + __usage + fi + shift 2 || break + ;; + --zone=*) + zone="${1#*=}" + if [[ -z ${zone} ]] + then + __usage + fi + shift 1 + ;; + -q|--quiet) + quiet="true" + shift 1 + ;; + -qq|--silent) + quiet="true" + silent="true" + shift 1 + ;; + *) + __usage + ;; + esac + done + + if [[ -f ${lock_file} ]] + then + __print_message \ + "error" \ + "${0##*/} lock detected - aborting." + exit 1 + fi + + trap "__cleanup" \ + EXIT INT TERM + __create_lock + + if [[ -z ${zone} ]] + then + __get_timezone + exit 0 + fi + + if ! __is_valid_zone "${zone}" + then + __print_message \ + "error" \ + "${0##*/} invalid zone: ${zone}" + exit 1 + else + __print_message \ + "info" \ + "${0##*/} setting zone: ${zone}" + + __set_timezone "${zone}" + + system_zone="$( + __get_timezone + )" + + if [[ ${system_zone} != "${zone}" ]] + then + __print_message \ + "error" \ + "${0##*/} failed setting zone: ${zone}" + exit 1 + fi + fi + + exit 0 +} + +main "${@}" diff --git a/src/usr/sbin/system-timezone-wrapper b/src/usr/sbin/system-timezone-wrapper new file mode 100755 index 0000000..02bc694 --- /dev/null +++ b/src/usr/sbin/system-timezone-wrapper @@ -0,0 +1,205 @@ +#!/usr/bin/env bash + +set -e + +function __cleanup () +{ + local -r exit_code="${?}" + + __delete_lock + + if [[ ${exit_code} -eq 0 ]] + then + __create_state + fi +} + +function __create_lock () +{ + if [[ -n ${lock_file} ]] + then + touch "${lock_file}" + fi +} + +function __create_state () +{ + if [[ -n ${state_file} ]] + then + touch "${state_file}" + fi +} + +function __delete_lock () +{ + if [[ -f ${lock_file} ]] + then + rm -f "${lock_file}" + fi +} + +function __get_system_timezone () +{ + local -r default_value="${1:-UTC}" + + local value="${SYSTEM_TIMEZONE}" + + if ! __is_valid_system_timezone "${value}" + then + value="${default_value}" + fi + + printf -- '%s' "${value}" +} + +function __get_options () +{ + local -r zone="${1:-"$( + __get_system_timezone + )"}" + + printf -- \ + '--silent --zone %s' \ + "${zone}" +} + +function __get_timer_total () +{ + local -r timer_end="$( + date -u +%s.%N + )" + local -r timer_start="${1}" + + if [[ -z ${timer_start} ]] \ + || [[ ${timer_start//.} -gt ${timer_end//.} ]] + then + >&2 printf -- \ + 'ERROR: invalid timer start: %s\n' \ + "${timer_start}" + printf -- \ + '0.000000' + else + awk \ + -v timer_end="${timer_end}" \ + -v timer_start="${timer_start}" \ + 'BEGIN { print \ + timer_end - timer_start; + }' + fi +} + +function __is_valid_system_timezone () +{ + __is_valid_zone "${@}" +} + +function __is_valid_zone () +{ + local zone="${1}" + + if [[ -n ${zone} ]] \ + && [[ -f /usr/share/zoneinfo/${zone} ]] + then + return 0 + fi + + return 1 +} + +function main () +{ + local -r bin="/usr/sbin/system-timezone" + local -r lock_file="/var/lock/subsys/system-timezone-wrapper" + local -r state_file="/var/lib/misc/system-timezone-wrapper" + local -r timer_start="$( + date -u +%s.%N + )" + + local system_timezone + local options + local timer_total + local verbose="false" + + while [[ "${#}" -gt 0 ]] + do + case "${1}" in + -v|--verbose) + verbose="true" + shift 1 + ;; + esac + done + + if [[ -f ${state_file} ]] + then + if [[ ${verbose} == true ]] + then + printf -- \ + 'INFO: %s finished - skipping.\n' \ + "${0##*/}" + fi + exit 0 + fi + + if [[ -f ${lock_file} ]] + then + >&2 printf -- \ + 'ERROR: %s lock detected - aborting.\n' \ + "${0##*/}" + exit 1 + fi + + trap "__cleanup" \ + EXIT INT TERM + __create_lock + + if [[ ${verbose} == true ]] + then + system_timezone="$( + __get_system_timezone + )" + + options="$( + __get_options \ + "${system_timezone}" + )" + + timer_total="$( + __get_timer_total \ + "${timer_start}" + )" + else + options="$( + __get_options + )" + fi + + if ! ${bin} \ + ${options} + then + >&2 printf -- \ + 'ERROR: %s failed setting zone: %s\n' \ + "${bin##*/}" \ + "${system_timezone}" + exit 1 + fi + + if [[ ${verbose} == true ]] + then + cat \ + <<-EOT + + ================================================================================ + System Time Zone Details + -------------------------------------------------------------------------------- + timezone : ${system_timezone} + -------------------------------------------------------------------------------- + ${timer_total} + + EOT + fi + + exit 0 +} + +main "${@}" diff --git a/test/shpec/operation_shpec.sh b/test/shpec/operation_shpec.sh index ca93617..586324c 100644 --- a/test/shpec/operation_shpec.sh +++ b/test/shpec/operation_shpec.sh @@ -1693,7 +1693,7 @@ function test_custom_ssh_configuration () docker run \ --detach \ --name ssh.1 \ - --env "SSH_TIMEZONE=Europe/London" \ + --env "SYSTEM_TIMEZONE=Europe/London" \ --publish ${DOCKER_PORT_MAP_TCP_22}:22 \ jdeathe/centos-ssh:latest \ &> /dev/null From 0d0792377e28a5a3f3ca8853ea93e654787d8328 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Thu, 20 Jun 2019 02:35:13 +0100 Subject: [PATCH 13/15] #803: Adds more consistently named variable to healthcheck. --- src/usr/bin/healthcheck | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/usr/bin/healthcheck b/src/usr/bin/healthcheck index 375300f..c2d6189 100755 --- a/src/usr/bin/healthcheck +++ b/src/usr/bin/healthcheck @@ -63,14 +63,14 @@ function __is_valid_zone () function main () { - local -r system_zone="$( - system-timezone -qq + local -r system_timezone="$( + __get_system_timezone )" local -r user="$( __get_ssh_user )" local -r zone="$( - __get_system_timezone + system-timezone -qq )" if ! ps axo command | grep -qE '^/usr/bin/python /usr/bin/supervisord' @@ -81,7 +81,7 @@ function main () exit 1 fi - if [[ ${system_zone} != "${zone}" ]] + if [[ ${system_timezone} != "${zone}" ]] then >&2 printf -- \ '%s\n' \ From 74062815bad82708b5a4f6c6c6a6cbe39f0dc51e Mon Sep 17 00:00:00 2001 From: James Deathe Date: Thu, 20 Jun 2019 14:11:38 +0100 Subject: [PATCH 14/15] #818: Fixes make clean error thrown when removing exited containers. --- CHANGELOG.md | 1 + Makefile | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b88fac..ab46787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Summary of release changes for Version 2 - CentOS-7 - Fixes binary paths in systemd unit files for compatibility with both EL and Ubuntu hosts. - Fixes use of printf binary instead of builtin in systemd unit files. - Fixes docker host connection status check in Makefile. +- Fixes make clean error thrown when removing exited containers. - Removes support for long image tags (i.e. centos-7-2.x.x). - Removes system time zone setup from `sshd-bootstrap`. diff --git a/Makefile b/Makefile index 79a2fb0..6416f1b 100644 --- a/Makefile +++ b/Makefile @@ -745,9 +745,9 @@ rm-exited: \ "$(PREFIX_STEP)" \ "Removing exited containers"; \ $(docker) rm -f \ - "$$($(docker) ps -aq \ + $$($(docker) ps -aq \ --filter "status=exited" \ - )" \ + ) \ 1> /dev/null; \ fi From b3aaee1dc62fbcaf5f425553ef58b82cdd4b29f1 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Thu, 20 Jun 2019 15:07:46 +0100 Subject: [PATCH 15/15] #816: Removes redundant directory test from sshd-bootstrap --- CHANGELOG.md | 1 + src/usr/sbin/sshd-bootstrap | 680 ++++++++++++++++++------------------ 2 files changed, 339 insertions(+), 342 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab46787..bd081c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Summary of release changes for Version 2 - CentOS-7 - Fixes make clean error thrown when removing exited containers. - Removes support for long image tags (i.e. centos-7-2.x.x). - Removes system time zone setup from `sshd-bootstrap`. +- Removes redundant directory test from `sshd-bootstrap`; state file ensures it's a one-shot process. ### 2.5.1 - 2019-02-28 diff --git a/src/usr/sbin/sshd-bootstrap b/src/usr/sbin/sshd-bootstrap index 26d52c9..d849ef9 100755 --- a/src/usr/sbin/sshd-bootstrap +++ b/src/usr/sbin/sshd-bootstrap @@ -1001,401 +1001,397 @@ function main () EXIT INT TERM __create_lock + ssh_authorized_keys="$( + __get_ssh_authorized_keys + )" + ssh_inherit_environment="$( + __get_ssh_inherit_environment + )" + ssh_password_authentication="$( + __get_ssh_password_authentication + )" + ssh_sudo="$( + __get_ssh_sudo + )" + ssh_user="$( + __get_ssh_user + )" + ssh_user_force_sftp="$( + __get_ssh_user_force_sftp + )" ssh_user_home="$( __get_ssh_user_home )" + ssh_user_password_hashed="$( + __get_ssh_user_password_hashed + )" + ssh_user_password="${SSH_USER_PASSWORD:-"$( + __get_password "${password_length}" + )"}" + ssh_user_private_key="$( + __get_ssh_user_private_key + )" + ssh_user_shell="$( + __get_ssh_user_shell + )" + ssh_user_uid="$( + __get_ssh_user_uid + )" + ssh_user_gid="$( + __get_ssh_user_gid + )" - if [[ ! -d ${ssh_user_home}/.ssh ]] + if [[ ${ssh_inherit_environment} == true ]] then - ssh_authorized_keys="$( - __get_ssh_authorized_keys - )" - ssh_inherit_environment="$( - __get_ssh_inherit_environment - )" - ssh_password_authentication="$( - __get_ssh_password_authentication - )" - ssh_sudo="$( - __get_ssh_sudo - )" - ssh_user="$( - __get_ssh_user - )" - ssh_user_force_sftp="$( - __get_ssh_user_force_sftp - )" - ssh_user_password_hashed="$( - __get_ssh_user_password_hashed - )" - ssh_user_password="${SSH_USER_PASSWORD:-"$( - __get_password "${password_length}" - )"}" - ssh_user_private_key="$( - __get_ssh_user_private_key - )" - ssh_user_shell="$( - __get_ssh_user_shell - )" - ssh_user_uid="$( - __get_ssh_user_uid - )" - ssh_user_gid="$( - __get_ssh_user_gid - )" - - if [[ ${ssh_inherit_environment} == true ]] - then - env \ - | grep -Ev "${env_exclude_pattern}" \ - > /etc/environment - fi + env \ + | grep -Ev "${env_exclude_pattern}" \ + > /etc/environment + fi - if [[ ${ssh_password_authentication} == true ]] - then - password_authentication="yes" + if [[ ${ssh_password_authentication} == true ]] + then + password_authentication="yes" - if [[ ${ssh_user} == root ]] - then - sed -i \ - -e 's~^\(PasswordAuthentication \)no$~\1yes~g' \ - -e 's~^\(PermitRootLogin \)no$~\1yes~g' \ - /etc/ssh/sshd_config - else - sed -i \ - -e 's~^\(PasswordAuthentication \)no$~\1yes~g' \ - /etc/ssh/sshd_config - fi - elif [[ ${ssh_user} == root ]] + if [[ ${ssh_user} == root ]] then sed -i \ - -e 's~^\(PermitRootLogin \)no$~\1without-password~g' \ + -e 's~^\(PasswordAuthentication \)no$~\1yes~g' \ + -e 's~^\(PermitRootLogin \)no$~\1yes~g' \ + /etc/ssh/sshd_config + else + sed -i \ + -e 's~^\(PasswordAuthentication \)no$~\1yes~g' \ /etc/ssh/sshd_config fi + elif [[ ${ssh_user} == root ]] + then + sed -i \ + -e 's~^\(PermitRootLogin \)no$~\1without-password~g' \ + /etc/ssh/sshd_config + fi - # Warn operator if any supplied environment variable values failed - # validation and have been set to a safe default. - if [[ ${verbose} == true ]] - then - for env in "${!env_validation_with_defaults[@]}" - do - if ! ${env_validation_with_defaults[${env}]} "${!env}" - then - printf -- \ - 'WARNING: Validation failed on %s - setting to default.\n' \ - "${env}" - fi - done - fi - - $( - __generate_ssh_host_keys - ) & - pids[0]="${!}" - - if [[ ${ssh_user} == root ]] - then - chsh \ - -s "${ssh_user_shell}" \ - "${ssh_user}" \ - &> /dev/null - else - # Create base directory for home - if [[ -n ${ssh_user_home%/*} ]] \ - && [[ ! -d ${ssh_user_home%/*} ]] + # Warn operator if any supplied environment variable values failed + # validation and have been set to a safe default. + if [[ ${verbose} == true ]] + then + for env in "${!env_validation_with_defaults[@]}" + do + if ! ${env_validation_with_defaults[${env}]} "${!env}" then - mkdir -pm 755 \ - "${ssh_user_home%/*}" + printf -- \ + 'WARNING: Validation failed on %s - setting to default.\n' \ + "${env}" fi + done + fi - groupadd \ - -f \ - -g "${ssh_user_gid}" \ - "${ssh_user}" - - useradd \ - -u "${ssh_user_uid}" \ - -g "${ssh_user_gid}" \ - -m \ - -G "${ssh_user_groups}" \ - -d "${ssh_user_home}" \ - -s "${ssh_user_shell}" \ - "${ssh_user}" - - # Set root user password - $( - printf -- \ - '%s:%s\n' \ - "root" \ - "$( - __get_password "${password_length}" - )" \ - | chpasswd - ) & - pids[1]="${!}" - fi + $( + __generate_ssh_host_keys + ) & + pids[0]="${!}" - if ! __set_ssh_user_password "${ssh_user_password}" + if [[ ${ssh_user} == root ]] + then + chsh \ + -s "${ssh_user_shell}" \ + "${ssh_user}" \ + &> /dev/null + else + # Create base directory for home + if [[ -n ${ssh_user_home%/*} ]] \ + && [[ ! -d ${ssh_user_home%/*} ]] then - >&2 printf -- \ - 'ERROR: Could not set password - aborting.\n' - exit 1 + mkdir -pm 755 \ + "${ssh_user_home%/*}" fi - if [[ ${ssh_user_force_sftp} == true ]] - then - sshd_command="SFTP" - ssh_sudo="N/A" - ssh_user_groups="users" - ssh_chroot_directory="$( - __get_ssh_chroot_directory - )" - ssh_chroot_directory_path="$( - __get_ssh_chroot_directory_path "${ssh_chroot_directory}" - )" - - if [[ ! -d ${ssh_chroot_directory_path} ]] \ - || [[ ${ssh_chroot_directory_path} != "${ssh_user_home}" ]] - then - # ChrootDirectory like /chroot/%u or /home/chroot/%u - printf -v ssh_chroot_home_directory_path \ - -- \ - '%s%s' \ - "${ssh_chroot_directory_path}" \ - "${ssh_user_home}" - mkdir -pm 711 \ - "${ssh_chroot_directory_path}" - mkdir -pm 755 \ - "${ssh_chroot_home_directory_path}" - else - # ChrootDirectory %h - ssh_chroot_home_directory_path="${ssh_user_home}" - chmod 750 \ - "${ssh_chroot_home_directory_path}" - fi + groupadd \ + -f \ + -g "${ssh_user_gid}" \ + "${ssh_user}" + + useradd \ + -u "${ssh_user_uid}" \ + -g "${ssh_user_gid}" \ + -m \ + -G "${ssh_user_groups}" \ + -d "${ssh_user_home}" \ + -s "${ssh_user_shell}" \ + "${ssh_user}" + + # Set root user password + $( + printf -- \ + '%s:%s\n' \ + "root" \ + "$( + __get_password "${password_length}" + )" \ + | chpasswd + ) & + pids[1]="${!}" + fi - # Create a user writeable data directory if no other directories - # are mounted. - if ! grep -q '^d' <<< "$( - ls -l "${ssh_chroot_home_directory_path}"/ - )" - then - # Make and set user permissions on new _data directory - mkdir -m 700 \ - "${ssh_chroot_home_directory_path}"/_data - chown -R \ - "${ssh_user}":"${ssh_user}" \ - "${ssh_chroot_home_directory_path}"/_data - elif [[ -d ${ssh_chroot_home_directory_path}/_data ]] - then - # Set user permissions on _data directory where it exists - chmod 700 \ - "${ssh_chroot_home_directory_path}"/_data - chown -R \ - "${ssh_user}":"${ssh_user}" \ - "${ssh_chroot_home_directory_path}"/_data - fi + if ! __set_ssh_user_password "${ssh_user_password}" + then + >&2 printf -- \ + 'ERROR: Could not set password - aborting.\n' + exit 1 + fi - # ChrootDirectory must be owned by root user - if [[ ${ssh_chroot_directory_path} != "${ssh_user_home}" ]] - then - chown \ - root:root \ - "${ssh_chroot_directory_path}" - chmod 711 \ - "${ssh_chroot_directory_path}" - else - chown \ - root:"${ssh_user}" \ - "${ssh_chroot_directory_path}" - fi + if [[ ${ssh_user_force_sftp} == true ]] + then + sshd_command="SFTP" + ssh_sudo="N/A" + ssh_user_groups="users" + ssh_chroot_directory="$( + __get_ssh_chroot_directory + )" + ssh_chroot_directory_path="$( + __get_ssh_chroot_directory_path "${ssh_chroot_directory}" + )" - # Add user specific sshd configuration - tee -a /etc/ssh/sshd_config > /dev/null <<-EOT - # Force SFTP - Match User ${ssh_user} - AllowTcpForwarding no - X11Forwarding no - ChrootDirectory ${ssh_chroot_directory} - ForceCommand internal-sftp - EOT + if [[ ! -d ${ssh_chroot_directory_path} ]] \ + || [[ ${ssh_chroot_directory_path} != "${ssh_user_home}" ]] + then + # ChrootDirectory like /chroot/%u or /home/chroot/%u + printf -v ssh_chroot_home_directory_path \ + -- \ + '%s%s' \ + "${ssh_chroot_directory_path}" \ + "${ssh_user_home}" + mkdir -pm 711 \ + "${ssh_chroot_directory_path}" + mkdir -pm 755 \ + "${ssh_chroot_home_directory_path}" else - sed -i \ - -e '/# Force SFTP/,/ForceCommand internal-sftp/ { d; }' \ - /etc/ssh/sshd_config + # ChrootDirectory %h + ssh_chroot_home_directory_path="${ssh_user_home}" + chmod 750 \ + "${ssh_chroot_home_directory_path}" fi - # SSH require files - mkdir -m 700 \ - "${ssh_user_home}"/.ssh - touch \ - "${ssh_user_home}"/.ssh/authorized_keys - chown -R \ - "${ssh_user}":"${ssh_user}" \ - "${ssh_user_home}"/.ssh - chmod 600 \ - "${ssh_user_home}"/.ssh/authorized_keys - - # Details output for SSH public key fingerprints - if [[ ${ssh_password_authentication} == true ]] \ - && [[ -z ${SSH_AUTHORIZED_KEYS} ]] + # Create a user writeable data directory if no other directories + # are mounted. + if ! grep -q '^d' <<< "$( + ls -l "${ssh_chroot_home_directory_path}"/ + )" then - if [[ ${verbose} == true ]] - then - ssh_key_fingerprints="N/A" - fi - elif ! __is_valid_ssh_authorized_keys "${ssh_authorized_keys}" + # Make and set user permissions on new _data directory + mkdir -m 700 \ + "${ssh_chroot_home_directory_path}"/_data + chown -R \ + "${ssh_user}":"${ssh_user}" \ + "${ssh_chroot_home_directory_path}"/_data + elif [[ -d ${ssh_chroot_home_directory_path}/_data ]] then - if [[ ${verbose} == true ]] - then - printf -v ssh_key_fingerprints \ - -- \ - '%s\nUnable to populate %s/.ssh/authorized_key' \ - "ERROR: Public key validation failed." \ - "${ssh_user_home}" - fi - else - printf -- \ - '%s\n' \ - "${ssh_authorized_keys}" \ - > "${ssh_user_home}"/.ssh/authorized_keys - - if [[ ${verbose} == true ]] - then - ssh_key_fingerprints="$( - __get_ssh_authorized_key_fingerprints - )" - fi + # Set user permissions on _data directory where it exists + chmod 700 \ + "${ssh_chroot_home_directory_path}"/_data + chown -R \ + "${ssh_user}":"${ssh_user}" \ + "${ssh_chroot_home_directory_path}"/_data fi - # Details output for SSH private key fingerprint - if [[ -z ${ssh_user_private_key} ]] \ - || [[ ${ssh_user_force_sftp} == true ]] - then - if [[ ${verbose} == true ]] - then - ssh_user_private_key_fingerprint="N/A" - fi - elif ! __is_valid_ssh_key "${ssh_user_private_key}" + # ChrootDirectory must be owned by root user + if [[ ${ssh_chroot_directory_path} != "${ssh_user_home}" ]] then - if [[ ${verbose} == true ]] - then - printf -v ssh_user_private_key_fingerprint \ - -- \ - '%s\nUnable to populate %s/.ssh/id_rsa' \ - "ERROR: Private key validation failed." \ - "${ssh_user_home}" - fi + chown \ + root:root \ + "${ssh_chroot_directory_path}" + chmod 711 \ + "${ssh_chroot_directory_path}" else - printf -- \ - '%s\n' \ - "${ssh_user_private_key}" \ - > "${ssh_user_home}"/.ssh/id_rsa chown \ - "${ssh_user}":"${ssh_user}" \ - "${ssh_user_home}"/.ssh/id_rsa - chmod 600 \ - "${ssh_user_home}"/.ssh/id_rsa - - if [[ ${verbose} == true ]] - then - ssh_user_private_key_fingerprint="$( - __get_ssh_key_fingerprint_hash_output \ - "${ssh_user_private_key}" - )" - fi + root:"${ssh_user}" \ + "${ssh_chroot_directory_path}" fi - # Set sudo access for the wheel group - sed -i \ - -e "s~^%wheel\\t.*$~%wheel\\t${ssh_sudo}~g" \ - /etc/sudoers - - tee -a /etc/sudoers > /dev/null <<-EOT - - # ${ssh_user} - Defaults:root secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + # Add user specific sshd configuration + tee -a /etc/ssh/sshd_config > /dev/null <<-EOT + # Force SFTP + Match User ${ssh_user} + AllowTcpForwarding no + X11Forwarding no + ChrootDirectory ${ssh_chroot_directory} + ForceCommand internal-sftp EOT + else + sed -i \ + -e '/# Force SFTP/,/ForceCommand internal-sftp/ { d; }' \ + /etc/ssh/sshd_config + fi - # Wait for background processes - Host key generation - wait ${pids[0]} - + # SSH require files + mkdir -m 700 \ + "${ssh_user_home}"/.ssh + touch \ + "${ssh_user_home}"/.ssh/authorized_keys + chown -R \ + "${ssh_user}":"${ssh_user}" \ + "${ssh_user_home}"/.ssh + chmod 600 \ + "${ssh_user_home}"/.ssh/authorized_keys + + # Details output for SSH public key fingerprints + if [[ ${ssh_password_authentication} == true ]] \ + && [[ -z ${SSH_AUTHORIZED_KEYS} ]] + then if [[ ${verbose} == true ]] then - ssh_host_key_fingerprint_rsa="$( - __get_ssh_host_key_fingerprint rsa - )" + ssh_key_fingerprints="N/A" fi - - # Wait for background processes - Set password for root user - if [[ -n ${pids[1]+isset} ]] + elif ! __is_valid_ssh_authorized_keys "${ssh_authorized_keys}" + then + if [[ ${verbose} == true ]] then - wait ${pids[1]} + printf -v ssh_key_fingerprints \ + -- \ + '%s\nUnable to populate %s/.ssh/authorized_key' \ + "ERROR: Public key validation failed." \ + "${ssh_user_home}" fi + else + printf -- \ + '%s\n' \ + "${ssh_authorized_keys}" \ + > "${ssh_user_home}"/.ssh/authorized_keys - # Only show user password if auto-generated and password is required - # for password authentication or sudo. - if [[ -n ${SSH_USER_PASSWORD} ]] - then - ssh_user_password="${redacted_value}" - elif [[ ${ssh_password_authentication} == false ]] \ - && [[ ${ssh_user_force_sftp} == true ]] + if [[ ${verbose} == true ]] then - ssh_user_password="${redacted_value}" - elif [[ ${ssh_password_authentication} == false ]] \ - && [[ ${ssh_user} != root ]] \ - && __is_sudo_no_password_all "${ssh_sudo}" + ssh_key_fingerprints="$( + __get_ssh_authorized_key_fingerprints + )" + fi + fi + + # Details output for SSH private key fingerprint + if [[ -z ${ssh_user_private_key} ]] \ + || [[ ${ssh_user_force_sftp} == true ]] + then + if [[ ${verbose} == true ]] then - ssh_user_password="${redacted_value}" - elif [[ ${ssh_password_authentication} == false ]] \ - && [[ ${ssh_user} == root ]] + ssh_user_private_key_fingerprint="N/A" + fi + elif ! __is_valid_ssh_key "${ssh_user_private_key}" + then + if [[ ${verbose} == true ]] then - ssh_user_password="${redacted_value}" + printf -v ssh_user_private_key_fingerprint \ + -- \ + '%s\nUnable to populate %s/.ssh/id_rsa' \ + "ERROR: Private key validation failed." \ + "${ssh_user_home}" fi + else + printf -- \ + '%s\n' \ + "${ssh_user_private_key}" \ + > "${ssh_user_home}"/.ssh/id_rsa + chown \ + "${ssh_user}":"${ssh_user}" \ + "${ssh_user_home}"/.ssh/id_rsa + chmod 600 \ + "${ssh_user_home}"/.ssh/id_rsa if [[ ${verbose} == true ]] then - timer_total="$( - __get_timer_total \ - "${timer_start}" + ssh_user_private_key_fingerprint="$( + __get_ssh_key_fingerprint_hash_output \ + "${ssh_user_private_key}" )" + fi + fi - cat <<-EOT - - ================================================================================ - ${sshd_command} Details - -------------------------------------------------------------------------------- - chroot path : ${ssh_chroot_directory_path} - home : ${ssh_user_home} - id : ${ssh_user_uid}:${ssh_user_gid} - key fingerprints : - ${ssh_key_fingerprints} - password : ${ssh_user_password} - password authentication : ${password_authentication} - rsa private key fingerprint : - ${ssh_user_private_key_fingerprint} - rsa host key fingerprint : - ${ssh_host_key_fingerprint_rsa} - shell : ${ssh_user_shell} - sudo : ${ssh_sudo} - user : ${ssh_user} - -------------------------------------------------------------------------------- - ${timer_total} - - EOT - elif [[ ${ssh_user_password} != "${redacted_value}" ]] - then - # Mininal ouput when required - cat <<-EOT + # Set sudo access for the wheel group + sed -i \ + -e "s~^%wheel\\t.*$~%wheel\\t${ssh_sudo}~g" \ + /etc/sudoers - ================================================================================ - ${sshd_command} Details - -------------------------------------------------------------------------------- - password : ${ssh_user_password} - -------------------------------------------------------------------------------- + tee -a /etc/sudoers > /dev/null <<-EOT - EOT - fi + # ${ssh_user} + Defaults:root secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + EOT + + # Wait for background processes - Host key generation + wait ${pids[0]} + + if [[ ${verbose} == true ]] + then + ssh_host_key_fingerprint_rsa="$( + __get_ssh_host_key_fingerprint rsa + )" + fi + + # Wait for background processes - Set password for root user + if [[ -n ${pids[1]+isset} ]] + then + wait ${pids[1]} + fi + + # Only show user password if auto-generated and password is required + # for password authentication or sudo. + if [[ -n ${SSH_USER_PASSWORD} ]] + then + ssh_user_password="${redacted_value}" + elif [[ ${ssh_password_authentication} == false ]] \ + && [[ ${ssh_user_force_sftp} == true ]] + then + ssh_user_password="${redacted_value}" + elif [[ ${ssh_password_authentication} == false ]] \ + && [[ ${ssh_user} != root ]] \ + && __is_sudo_no_password_all "${ssh_sudo}" + then + ssh_user_password="${redacted_value}" + elif [[ ${ssh_password_authentication} == false ]] \ + && [[ ${ssh_user} == root ]] + then + ssh_user_password="${redacted_value}" + fi + + if [[ ${verbose} == true ]] + then + timer_total="$( + __get_timer_total \ + "${timer_start}" + )" + + cat <<-EOT + + ================================================================================ + ${sshd_command} Details + -------------------------------------------------------------------------------- + chroot path : ${ssh_chroot_directory_path} + home : ${ssh_user_home} + id : ${ssh_user_uid}:${ssh_user_gid} + key fingerprints : + ${ssh_key_fingerprints} + password : ${ssh_user_password} + password authentication : ${password_authentication} + rsa private key fingerprint : + ${ssh_user_private_key_fingerprint} + rsa host key fingerprint : + ${ssh_host_key_fingerprint_rsa} + shell : ${ssh_user_shell} + sudo : ${ssh_sudo} + user : ${ssh_user} + -------------------------------------------------------------------------------- + ${timer_total} + + EOT + elif [[ ${ssh_user_password} != "${redacted_value}" ]] + then + # Mininal ouput when required + cat <<-EOT + + ================================================================================ + ${sshd_command} Details + -------------------------------------------------------------------------------- + password : ${ssh_user_password} + -------------------------------------------------------------------------------- + + EOT fi # Trigger cleanup trap.