diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..4444152 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,23 @@ +# Check shellcheck wiki at: +# https://github.com/koalaman/shellcheck/wiki/SCXXXX + +# Redirections are performed by the current shell before sudo is started. +disable=SC2024 + +# foo appears unused. Verify it or export it. +disable=SC2034 + +# Double quote array expansions to avoid re-splitting elements. +disable=SC2068 + +# Argument mixes string and array. +disable=SC2145 + +# Declare and assign separately to avoid masking return values. +disable=SC2155 + +# This redirection doesn't have a command. +disable=SC2188 + +# This is a file redirection. +disable=SC2210 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f352f8..3ce15ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ This file only reflects the changes that are made in this image. Please refer to the SaltStack [Release Notes](https://docs.saltstack.com/en/latest/topics/releases/3000.3.html) for the list of changes in SaltStack. +**3000.3_1** + +- Add support for `salt-api` service +- Add entrypoint support to restart services +- Use previous image as Docker cache +- Add `build-arg` to Makefile + **3000.3** - Upgrade SaltStack Master to `3000.3` diff --git a/Dockerfile b/Dockerfile index 8865b5c..32c49b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,7 +57,7 @@ COPY entrypoint.sh /sbin/entrypoint.sh RUN chmod +x /sbin/entrypoint.sh # Shared resources -EXPOSE 4505/tcp 4506/tcp +EXPOSE 4505 4506 8000 RUN mkdir -p ${SALT_DATA_DIR} ${SALT_BASE_DIR} ${SALT_KEYS_DIR} ${SALT_CONFS_DIR} ${SALT_LOGS_DIR} VOLUME [ "${SALT_BASE_DIR}" "${SALT_KEYS_DIR}" "${SALT_CONFS_DIR}" "${SALT_LOGS_DIR}" ] diff --git a/Makefile b/Makefile index 9c3283d..e9a1148 100644 --- a/Makefile +++ b/Makefile @@ -11,10 +11,14 @@ help: @echo " 5. make logs - view logs" build: - @docker build --tag=cdalvaro/saltstack-master . + @docker build --tag=cdalvaro/saltstack-master . \ + --build-arg=BUILD_DATE="$(shell date +"%Y-%m-%d %H:%M:%S%:z")" \ + --build-arg=VCS_REF="$(shell git rev-parse --short HEAD)" \ release: build - @docker build --tag=cdalvaro/saltstack-master:$(shell cat VERSION) . + @docker build --tag=cdalvaro/saltstack-master:$(shell cat VERSION) . \ + --build-arg=BUILD_DATE="$(shell date +"%Y-%m-%d %H:%M:%S%:z")" \ + --build-arg=VCS_REF="$(shell git rev-parse --short HEAD)" \ quickstart: @echo "Starting saltstack-master container..." diff --git a/README.md b/README.md index a247bb3..b8e78ec 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# SaltStack Master v3000.3 +[![SaltStack][saltstack_badge]][saltstack_release_notes] +[![Ubuntu Image][ubuntu_badge]][ubuntu_hub_docker] +[![Docker Build Status][docker_build_badge]][docker_hub] +[![CodeFactor][codefactor_badge]][codefactor_score] + +# SaltStack Master v3000.3_1 Dockerfile to build a [SaltStack](https://www.saltstack.com) Master image for the Docker opensource container platform. @@ -15,6 +20,8 @@ For other methods to install SaltStack please refer to the [Official SaltStack I - [Custom Recipes](#custom-recipes) - [Minion Keys](#minion-keys) - [Master Signed Keys](#master-signed-keys) + - [Salt API](#salt-api) + - [Salt Pepper](#salt-pepper) - [Host Mapping](#host-mapping) - [Git Fileserver](#git-fileserver) - [GitPython](#gitpython) @@ -23,6 +30,7 @@ For other methods to install SaltStack please refer to the [Official SaltStack I - [Available Configuration Parameters](#available-configuration-parameters) - [Usage](#usage) - [Shell Access](#shell-access) +- [Restart Services](#restart-services) - [References](#references) ## Installation @@ -30,7 +38,7 @@ For other methods to install SaltStack please refer to the [Official SaltStack I Automated builds of the image are available on [Dockerhub](https://hub.docker.com/r/cdalvaro/saltstack-master/) and is the recommended method of installation. ```sh -docker pull cdalvaro/saltstack-master:3000.3 +docker pull cdalvaro/saltstack-master:3000.3_1 ``` You can also pull the latest tag which is built from the repository `HEAD` @@ -69,63 +77,149 @@ Alternatively, you can manually launch the `saltstack-master` container: ```sh docker run --name salt_master --detach \ - --publish 4505:4505/tcp --publish 4506:4506/tcp \ + --publish 4505:4505 --publish 4506:4506 \ --env 'SALT_LOG_LEVEL=info' \ --volume $(pwd)/roots/:/home/salt/data/srv/ \ --volume $(pwd)/keys/:/home/salt/data/keys/ \ - cdalvaro/saltstack-master:3000.3 + cdalvaro/saltstack-master:3000.3_1 ``` ## Configuration ### Custom Recipes -In order to provide salt with your custom recipes you must mount the volume `/home/salt/data/srv/` with your `roots` directory. +In order to provide salt with your custom recipes you must mount the volume `/home/salt/data/srv/` +with your `roots` directory. ### Minion Keys -Minion keys can be added automatically on startup to SaltStack master by mounting the volume `/home/salt/data/keys` and copying the minion keys inside `keys/minions/` directory. +Minion keys can be added automatically on startup to SaltStack master by mounting the volume +`/home/salt/data/keys` and copying the minion keys inside `keys/minions/` directory. -It is also important to know that, in order to keep your keys after removing the container, the keys directory must be mounted. +It is also important to know that, in order to keep your keys after removing the container, +the keys directory must be mounted. ```sh mkdir -p keys/minions rsync root@minion1:/etc/salt/pki/minion/minion.pub keys/minions/minion1 docker run --name salt_master -d \ - --publish 4505:4505/tcp --publish 4506:4506/tcp \ + --publish 4505:4505 --publish 4506:4506 \ --env 'SALT_LOG_LEVEL=info' \ --volume $(pwd)/roots/:/home/salt/data/srv/ \ --volume $(pwd)/keys/:/home/salt/data/keys/ \ - cdalvaro/saltstack-master:3000.3 + cdalvaro/saltstack-master:3000.3_1 ``` ### Master Signed Keys -It is possible to use signed master keys by establishing the environment variable `SALT_MASTER_SIGN_PUBKEY` to `True`. +It is possible to use signed master keys by establishing the environment variable +`SALT_MASTER_SIGN_PUBKEY` to `True`. ```sh docker run --name salt_stack --detach \ - --publish 4505:4505/tcp --publish 4506:4506/tcp \ + --publish 4505:4505 --publish 4506:4506 \ --env 'SALT_LOG_LEVEL=info' \ --env 'SALT_MASTER_SIGN_PUBKEY=True' --volume $(pwd)/roots/:/home/salt/data/srv/ \ --volume $(pwd)/keys/:/home/salt/data/keys/ \ - cdalvaro/saltstack-master:3000.3 + cdalvaro/saltstack-master:3000.3_1 ``` -The container will create the `master_sign` key and its signature. More information about how to configure the minion service can be found [here](https://docs.saltstack.com/en/latest/topics/tutorials/multimaster_pki.html#prepping-the-minion-to-verify-received-public-keys). +The container will create the `master_sign` key and its signature. +More information about how to configure the minion service can be found +[here](https://docs.saltstack.com/en/latest/topics/tutorials/multimaster_pki.html#prepping-the-minion-to-verify-received-public-keys). Additionally, you can generate new keys by executing the following command: ```sh docker run --name salt_stack -it --rm \ --volume $(pwd)/keys/:/home/salt/data/keys/ \ - cdalvaro/saltstack-master:3000.3 app:gen-signed-keys other_master_sign + cdalvaro/saltstack-master:3000.3_1 app:gen-signed-keys other_master_sign ``` The newly created keys will appear inside `keys/generated/other_master_sign` directory. +### Salt API + +You can enable `salt-api` service by setting env variable `SALT_API_SERVICE_ENABLED` to `true`. + +A self-signed SSL certificate will be automatically generated and the following configuration +will be added to the master configuration file: + +```yml +rest_cherrypy: + port: 8000 + ssl_crt: /etc/pki/tls/certs/docker-salt-master.crt + ssl_key: /etc/pki/tls/certs/docker-salt-master.key +``` + +The container exposes port `8000` by default, although you can map this port to whatever port you like in +your `docker run` command or in your `docker-compose.yml` file. + +```sh +docker run --name salt_stack --detach \ + --publish 4505:4505 --publish 4506:4506 --publish 8000:8000 \ + --env 'SALT_API_SERVICE_ENABLED=true' \ + --env 'SALT_API_USER_PASS=SuperCool/Password10' + --volume $(pwd)/roots/:/home/salt/data/srv/ \ + --volume $(pwd)/keys/:/home/salt/data/keys/ \ + cdalvaro/saltstack-master:3000.3_1 +``` + +By default, user `salt_api` is created and you can set its password by setting the environment variable +`SALT_API_USER_PASS`. + +You can also change the salt-api _username_ by setting `SALT_API_USER`. +It is possible to disable this user by explicitly setting this variable to an empty string: `SALT_API_USER=''` if you are going to use an `LDAP` server. + +As a security measure, if `SALT_API_USER_PASS` is set to `true` and you don't disable `SALT_API_USER`, +you'll be required to set `SALT_API_USER_PASS`. Otherwise initialization will fail and your Docker image won't work. + +With all that set, you'll be able to provide your _salt-api_ custom configuration by creating the `salt-api.conf` +file inside your `conf` directory: + +```yml +external_auth: + pam: + salt_api: + - .* +``` + +More information is available in the following link: [External Authentication System (eAuth)](https://docs.saltstack.com/en/latest/topics/eauth/index.html#acl-eauth). + +Now you have your saltstack-master docker image ready to accept external authentications and to connect external tools such as [`saltstack/pepper`](https://github.com/saltstack/pepper). + +#### Salt Pepper + +The pepper CLI script allows users to execute Salt commands from computers that are external to computers running the salt-master or salt-minion daemons as though they were running Salt locally + +##### Installation: + +```sh +pip3 install salt-pepper +``` + +##### Configuration + +Then configure pepper by filling your `~/.pepperrc` file with your salt-api credentials: + +```conf +[main] +SALTAPI_URL=https://your.salt-master.hostname:8000/ +SALTAPI_USER=salt_api +SALTAPI_PASS=SuperCool/Password10 +SALTAPI_EAUTH=pam +``` + +##### Usage + +Beging executing salt recipes with `pepper`: + +```sh +pepper '*' test.ping +``` + ### Host Mapping Per default the container is configured to run `salt-master` as user and group `salt` with `uid` and `gid` `1000`. From the host it appears as if the mounted data volumes are owned by the host's user/group `1000` and maybe leading to unfavorable effects. @@ -137,7 +231,7 @@ docker run --name salt_stack -it --rm \ --env "USERMAP_UID=$(id -u)" --env "USERMAP_GID=$(id -g)" \ --volume $(pwd)/roots/:/home/salt/data/srv/ \ --volume $(pwd)/keys/:/home/salt/data/keys/ \ - cdalvaro/saltstack-master:3000.3 + cdalvaro/saltstack-master:3000.3_1 ``` ### Git Fileserver @@ -188,12 +282,12 @@ Inside that directory you could find `supervisor/` logs and `salt/` logs: ```sh docker run --name salt_master --detach \ - --publish 4505:4505/tcp --publish 4506:4506/tcp \ + --publish 4505:4505 --publish 4506:4506 \ --env 'SALT_LOG_LEVEL=info' \ --volume $(pwd)/roots/:/home/salt/data/srv/ \ --volume $(pwd)/keys/:/home/salt/data/keys/ \ --volume $(pwd)/logs/:/home/salt/data/logs/ \ - cdalvaro/saltstack-master:3000.3 + cdalvaro/saltstack-master:3000.3_1 ``` Check [Available Configuration Parameters](#available-configuration-parameters) section for configuring logrotate. @@ -212,6 +306,9 @@ Below is the list of available options that can be used to customize your SaltSt | `SALT_LOG_ROTATE_FREQUENCY` | Logrotate frequency for salt logs. Available options are 'daily', 'weekly', 'monthly', and 'yearly'. Default: `weekly` | | `SALT_LOG_ROTATE_RETENTION` | Keep x files before deleting old log files. Defaults: `52` | | `SALT_LEVEL_LOGFILE` | The level of messages to send to the log file. One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'. Default: `warning` | +| `SALT_API_SERVICE_ENABLED` | Enable `salt-api` service. Default: `false` | +| `SALT_API_USER` | Set username for `salt-api` service. Default: `salt_api` | +| `SALT_API_USER_PASS` | `SALT_API_USER` password. Required if `SALT_API_SERVICE_ENBALED` is `true` and `SALT_API_USER` is not empty. _Unset_ by default | | `SALT_MASTER_SIGN_PUBKEY` | Sign the master auth-replies with a cryptographic signature of the master's public key. Possible values: 'True' or 'False'. Default: `False` | | `SALT_MASTER_USE_PUBKEY_SIGNATURE` | Instead of computing the signature for each auth-reply, use a pre-calculated signature. This option requires `SALT_MASTER_SIGN_PUBKEY` set to 'True'. Possible values: 'True' or 'False'. Default: `True` | | `SALT_MASTER_SIGN_KEY_NAME` | The customizable name of the signing-key-pair without suffix. Default: `master_sign` | @@ -234,12 +331,12 @@ ret_port: 3506 EOF docker run --name salt_master -d \ - --publish 3505:3505/tcp --publish 3506:3506/tcp \ + --publish 3505:3505 --publish 3506:3506 \ --env 'SALT_LOG_LEVEL=info' \ --volume $(pwd)/roots/:/home/salt/data/srv/ \ --volume $(pwd)/keys/:/home/salt/data/keys/ \ --volume $(pwd)/config/:/home/salt/data/config/ \ - cdalvaro/saltstack-master:3000.3 + cdalvaro/saltstack-master:3000.3_1 ``` ## Usage @@ -264,8 +361,30 @@ For debugging and maintenance purposes you may want access the container shell. docker exec -it salt_master bash ``` +## Restart Services + +You can restart containers services by running the following command: + +```sh +docker exec -it salt_master entrypoint.sh app:restart [salt-service] +``` + +Where `salt-service` is one of: `salt-master` os `salt-api` (if `SALT_API_SERVICE_ENABLED` is set to `true`) + ## References - https://docs.saltstack.com/en/latest/topics/installation/index.html - https://docs.saltstack.com/en/latest/topics/tutorials/salt_bootstrap.html - https://github.com/saltstack/salt/releases + +[saltstack_badge]: https://img.shields.io/badge/SaltStack-v3000.3-lightgrey.svg?style=flat-square&logo=Saltstack +[saltstack_release_notes]: https://docs.saltstack.com/en/latest/topics/releases/3000.3.html "SaltStack Release Notes" + +[ubuntu_badge]: https://img.shields.io/badge/ubuntu-bionic--20200403-E95420.svg?style=flat-square&logo=Ubuntu +[ubuntu_hub_docker]: https://hub.docker.com/_/ubuntu/ "Ubuntu Image" + +[docker_build_badge]: https://img.shields.io/docker/build/cdalvaro/saltstack-master?logo=docker&style=flat-square +[docker_hub]: https://hub.docker.com/r/cdalvaro/saltstack-master/builds + +[codefactor_badge]: https://www.codefactor.io/repository/github/cdalvaro/saltstack-master/badge?style=flat-square +[codefactor_score]: https://www.codefactor.io/repository/github/cdalvaro/saltstack-master \ No newline at end of file diff --git a/VERSION b/VERSION index b2fab2c..8a335a4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3000.3 \ No newline at end of file +3000.3_1 \ No newline at end of file diff --git a/assets/build/functions.sh b/assets/build/functions.sh index a8a7bf6..300ddea 100755 --- a/assets/build/functions.sh +++ b/assets/build/functions.sh @@ -5,9 +5,9 @@ set -e # Execute a command as SALT_USER function exec_as_salt() { - if [[ $(whoami) == ${SALT_USER} ]]; then + if [[ $(whoami) == "${SALT_USER}" ]]; then $@ else - sudo -HEu ${SALT_USER} "$@" + sudo -HEu "${SALT_USER}" "$@" fi } diff --git a/assets/build/install.sh b/assets/build/install.sh index 121806d..94f6951 100755 --- a/assets/build/install.sh +++ b/assets/build/install.sh @@ -2,39 +2,41 @@ set -e -source ${SALT_BUILD_DIR}/functions.sh +source "${SALT_BUILD_DIR}/functions.sh" # Install build dependencies echo "Installing dependencies ..." -BUILD_DEPENDENCIES="cmake gcc g++ make \ - libhttp-parser-dev libssl-dev zlib1g-dev \ - libcurl4-openssl-dev libffi-dev swig" +BUILD_DEPENDENCIES=( + cmake gcc g++ make \ + libhttp-parser-dev libssl-dev zlib1g-dev \ + libcurl4-openssl-dev libffi-dev swig \ +) apt-get update -DEBIAN_FRONTEND=noninteractive apt-get install --yes --quiet --no-install-recommends ${BUILD_DEPENDENCIES} +DEBIAN_FRONTEND=noninteractive apt-get install --yes --quiet --no-install-recommends "${BUILD_DEPENDENCIES[@]}" # Create salt user echo "Creating ${SALT_USER} user ..." -useradd -d ${SALT_HOME} -ms /bin/bash -U -G root,sudo ${SALT_USER} +useradd -d "${SALT_HOME}" -ms /bin/bash -U -G root,sudo,shadow "${SALT_USER}" # Set PATH -exec_as_salt cat >> ${SALT_HOME}/.profile <> "${SALT_HOME}/.profile" <> /etc/ssh/ssh_config -echo " LogLevel ERROR" >> /etc/ssh/ssh_config -echo "# IdentityFile salt_ssh_key" >> /etc/ssh/ssh_config +{ + echo " UserKnownHostsFile /dev/null" + echo " LogLevel ERROR" + echo "# IdentityFile salt_ssh_key" +} >> /etc/ssh/ssh_config # Configure logrotate echo "Configuring logrotate ..." @@ -89,7 +96,7 @@ priority=5 directory=${SALT_HOME} environment=HOME=${SALT_HOME} command=/usr/local/bin/salt-master -user=${SALT_USER} +user=root autostart=true autorestart=true stopsignal=QUIT diff --git a/assets/runtime/env-defaults.sh b/assets/runtime/env-defaults.sh index 057947a..bae2f93 100755 --- a/assets/runtime/env-defaults.sh +++ b/assets/runtime/env-defaults.sh @@ -3,6 +3,9 @@ DEBUG=${DEBUG:-false} TIMEZONE=${TIMEZONE:-UTC} +SALT_API_SERVICE_ENABLED=${SALT_API_SERVICE_ENABLED:-false} +SALT_API_USER=${SALT_API_USER:-salt_api} + SALT_LOG_ROTATE_FREQUENCY=${SALT_LOG_ROTATE_FREQUENCY:-weekly} SALT_LOG_ROTATE_RETENTION=${SALT_LOG_ROTATE_RETENTION:-52} diff --git a/assets/runtime/functions.sh b/assets/runtime/functions.sh index a452159..b5c744f 100755 --- a/assets/runtime/functions.sh +++ b/assets/runtime/functions.sh @@ -1,30 +1,36 @@ #!/usr/bin/env bash set -e -source ${SALT_RUNTIME_DIR}/env-defaults.sh +source "${SALT_RUNTIME_DIR}/env-defaults.sh" # Execute a command as SALT_USER function exec_as_salt() { - if [[ $(whoami) == ${SALT_USER} ]]; then + if [[ $(whoami) == "${SALT_USER}" ]]; then $@ else - sudo -HEu ${SALT_USER} "$@" + sudo -HEu "${SALT_USER}" "$@" fi } +# Log error +function log_error() +{ + (>2& echo "ERROR: $*") +} + # Map salt user with host user function map_uidgid() { - USERMAP_ORIG_UID=$(id -u ${SALT_USER}) - USERMAP_ORIG_GID=$(id -g ${SALT_USER}) + USERMAP_ORIG_UID=$(id -u "${SALT_USER}") + USERMAP_ORIG_GID=$(id -g "${SALT_USER}") USERMAP_GID=${USERMAP_GID:-${USERMAP_UID:-$USERMAP_ORIG_GID}} USERMAP_UID=${USERMAP_UID:-$USERMAP_ORIG_UID} - if [[ ${USERMAP_UID} != ${USERMAP_ORIG_UID} ]] || [[ ${USERMAP_GID} != ${USERMAP_ORIG_GID} ]]; then + if [[ "${USERMAP_UID}" != "${USERMAP_ORIG_UID}" ]] || [[ "${USERMAP_GID}" != "${USERMAP_ORIG_GID}" ]]; then echo "Mapping UID and GID for ${SALT_USER}:${SALT_USER} to ${USERMAP_UID}:${USERMAP_GID} ..." - groupmod -o -g ${USERMAP_GID} ${SALT_USER} + groupmod -o -g "${USERMAP_GID}" "${SALT_USER}" sed -i -e "s|:${USERMAP_ORIG_UID}:${USERMAP_GID}:|:${USERMAP_UID}:${USERMAP_GID}:|" /etc/passwd - find ${SALT_HOME} -path ${SALT_DATA_DIR}/\* \( ! -uid ${USERMAP_ORIG_UID} -o ! -gid ${USERMAP_ORIG_GID} \) -print0 | xargs -0 chown -h ${SALT_USER}: ${SALT_HOME} + find "${SALT_HOME}" -path "${SALT_DATA_DIR}/*" \( ! -uid "${USERMAP_ORIG_UID}" -o ! -gid "${USERMAP_ORIG_GID}" \) -print0 | xargs -0 chown -h "${SALT_USER}": "${SALT_HOME}" fi } @@ -36,25 +42,25 @@ function update_template() local FILE=${1?missing argument} shift - [[ ! -f ${FILE} ]] && return 1 + [[ ! -f "${FILE}" ]] && return 1 - local VARIABLES=($@) - local USR=$(stat -c %U ${FILE}) + local VARIABLES=( "$@" ) + local USR=$(stat -c %U "${FILE}") local tmp_file=$(mktemp) - cp -a "${FILE}" ${tmp_file} + cp -a "${FILE}" "${tmp_file}" local variables - for variable in ${VARIABLES[@]}; do - sed -ri "s|[{}]{2}$variable[}]{2}|\${$variable}|g" ${tmp_file} + for variable in "${VARIABLES[@]}"; do + sed -ri "s|[{}]{2}${variable}[}]{2}|\${${variable}}|g" "${tmp_file}" done # Replace placeholders ( - export ${VARIABLES[@]} - local IFS=":"; sudo -HEu ${USR} envsubst "${VARIABLES[*]/#/$}" < ${tmp_file} > ${FILE} + export "${VARIABLES[@]}" + local IFS=":"; sudo -HEu "${USR}" envsubst "${VARIABLES[*]/#/$}" < "${tmp_file}" > "${FILE}" ) - rm -f ${tmp_file} + rm -f "${tmp_file}" } # This function configures containers timezone @@ -63,14 +69,14 @@ function configure_timezone() echo "Configuring container timezone ..." # Perform sanity check of provided timezone value - if [ -e /usr/share/zoneinfo/${TIMEZONE} ]; then + if [ -e "/usr/share/zoneinfo/${TIMEZONE}" ]; then echo "Setting TimeZone -> ${TIMEZONE} ..." # Set localtime - ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime + ln -snf "/usr/share/zoneinfo/${TIMEZONE}" /etc/localtime # Set timezone - echo ${TIMEZONE} > /etc/timezone + echo "${TIMEZONE}" > /etc/timezone else echo "Timezone: '${TIMEZONE}' is not valid. Check available timezones at: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones" return 1 @@ -82,39 +88,40 @@ function gen_signed_keys() { local key_name=${1:-master} - mkdir -p ${SALT_KEYS_DIR}/generated/ - GENERATED_KEYS_DIR=$(mktemp -d -p ${SALT_KEYS_DIR}/generated/ -t ${key_name}.XXXXX) + mkdir -p "${SALT_KEYS_DIR}/generated/" + GENERATED_KEYS_DIR=$(mktemp -d -p "${SALT_KEYS_DIR}/generated/" -t "${key_name}.XXXXX") - salt-key --gen-keys ${key_name} --gen-keys-dir ${GENERATED_KEYS_DIR} > /dev/null 2>&1 - salt-key --gen-signature --auto-create --pub ${GENERATED_KEYS_DIR}/${key_name}.pub --signature-path ${GENERATED_KEYS_DIR} > /dev/null 2>&1 + salt-key --gen-keys "${key_name}" --gen-keys-dir "${GENERATED_KEYS_DIR}" > /dev/null 2>&1 + salt-key --gen-signature --auto-create --pub "${GENERATED_KEYS_DIR}/${key_name}.pub" --signature-path "${GENERATED_KEYS_DIR}" > /dev/null 2>&1 - echo -n ${GENERATED_KEYS_DIR} + echo -n "${GENERATED_KEYS_DIR}" } # This function repairs keys permissions and creates keys if neaded function setup_salt_keys() { echo "Setting up salt keys ..." - if [ ! -f ${SALT_KEYS_DIR}/master.pem ]; then + if [ ! -f "${SALT_KEYS_DIR}/master.pem" ]; then echo "Generating keys ..." - salt-key --gen-keys master --gen-keys-dir ${SALT_KEYS_DIR} + salt-key --gen-keys master --gen-keys-dir "${SALT_KEYS_DIR}" fi - if [ ! -f "${SALT_KEYS_DIR}/${SALT_MASTER_SIGN_KEY_NAME}.pem" ] && [ ${SALT_MASTER_SIGN_PUBKEY} == True ]; then + if [ ! -f "${SALT_KEYS_DIR}/${SALT_MASTER_SIGN_KEY_NAME}.pem" ] && [ "${SALT_MASTER_SIGN_PUBKEY}" == True ]; then echo "Generating signed keys ..." - salt-key --gen-signature --auto-create --pub ${SALT_KEYS_DIR}/master.pub --signature-path ${SALT_KEYS_DIR} + salt-key --gen-signature --auto-create --pub "${SALT_KEYS_DIR}/master.pub" --signature-path "${SALT_KEYS_DIR}" fi - for pub_key in $(find ${SALT_KEYS_DIR} -maxdepth 1 -type f); do - if [[ ${pub_key} =~ .*\.pem$ ]]; then - chmod 400 ${pub_key} + while IFS= read -r -d '' pub_key + do + if [[ "${pub_key}" =~ .*\.pem$ ]]; then + chmod 400 "${pub_key}" else - chmod 644 ${pub_key} + chmod 644 "${pub_key}" fi - done + done < <(find "${SALT_KEYS_DIR}" -maxdepth 1 -type f -print0) - find ${SALT_KEYS_DIR}/minions* -maxdepth 1 -type f -exec chmod 644 {} \; - find ${SALT_HOME} -path ${SALT_KEYS_DIR}/\* -prune -o -print0 | xargs -0 chown -h ${SALT_USER}: + find "${SALT_KEYS_DIR}/minions"* -maxdepth 1 -type f -exec chmod 644 {} \; + find "${SALT_HOME}" -path "${SALT_KEYS_DIR}/*" -prune -o -print0 | xargs -0 chown -h "${SALT_USER}": } # This function configures ssh keys @@ -135,16 +142,16 @@ function setup_ssh_keys() fi } -# This functions cofigures master service +# This function cofigures master service function configure_salt_master() { - echo "Configuring salt-master ..." + echo "Configuring salt-master service ..." # https://docs.saltstack.com/en/latest/ref/configuration/master.html - exec_as_salt cp -p ${SALT_RUNTIME_DIR}/config/master.yml ${SALT_ROOT_DIR}/master + exec_as_salt cp -p "${SALT_RUNTIME_DIR}/config/master.yml" "${SALT_ROOT_DIR}/master" # Update main configuration - update_template ${SALT_ROOT_DIR}/master \ + update_template "${SALT_ROOT_DIR}/master" \ SALT_USER \ SALT_LOG_LEVEL \ SALT_LEVEL_LOGFILE \ @@ -155,13 +162,73 @@ function configure_salt_master() SALT_KEYS_DIR # Update keys configuration - update_template ${SALT_ROOT_DIR}/master \ + update_template "${SALT_ROOT_DIR}/master" \ SALT_MASTER_SIGN_PUBKEY \ SALT_MASTER_SIGN_KEY_NAME \ SALT_MASTER_PUBKEY_SIGNATURE \ SALT_MASTER_USE_PUBKEY_SIGNATURE } +# This function configures salt-api if service is set to be enabled +function configure_salt_api() +{ + [[ ${SALT_API_SERVICE_ENABLED} == true ]] || return 0 + + if [[ -n "${SALT_API_USER}" ]]; then + + if [[ ${SALT_API_USER} == "${SALT_USER}" ]]; then + log_error "SALT_API_USER cannot be the same as '${SALT_USER}'" + return 1 + fi + + if [[ -z "${SALT_API_USER_PASS}" ]]; then + log_error "SALT_API_USER_PASS env variable must be set to create '${SALT_API_USER}' user" + return 2 + fi + + echo "Creating '${SALT_API_USER}' user for salt-api ..." + adduser --quiet --disabled-password --gecos "Salt API" "${SALT_API_USER}" + echo "${SALT_API_USER}:${SALT_API_USER_PASS}" | chpasswd + unset SALT_API_USER_PASS + fi + + echo "Configuring salt-api service ..." + + CERTS_PATH=/etc/pki + rm -rf "${CERTS_PATH}/tls/certs/*" + salt-call --local tls.create_self_signed_cert cacert_path="${CERTS_PATH}" CN=docker-salt-master + + cat >> "${SALT_ROOT_DIR}/master" < /etc/supervisor/conf.d/salt-api.conf <> /etc/logrotate.d/salt < - Create a master_sign key pair and its signature inside ${SALT_KEYS_DIR}/generated/" echo " app:help - Displays this help." echo " [command] - Execute the specified command, eg. bash." diff --git a/hooks/build b/hooks/build index 4fbe91e..b984052 100644 --- a/hooks/build +++ b/hooks/build @@ -3,7 +3,10 @@ # Docker Daemon Build Hook # $IMAGE_NAME var is injected into the build so the tag is correct. +docker pull ${DOCKER_REPO}:latest + docker build \ + --cache-from=${DOCKER_REPO}:latest \ --build-arg=BUILD_DATE="$(date +"%Y-%m-%d %H:%M:%S%:z")" \ --build-arg=VCS_REF="$(git rev-parse --short HEAD)" \ -t ${IMAGE_NAME} .