diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 00000000..3de53f20 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,7 @@ +version: '3' + +services: + stackstorm: + image: stackstorm/stackstorm:${ST2_IMAGE_TAG:-xenial} + environment: + - ST2_ENABLE_SSHD=1 diff --git a/images/stackstorm-xenial/.circleci/config.yml b/images/stackstorm-xenial/.circleci/config.yml new file mode 100644 index 00000000..41d31625 --- /dev/null +++ b/images/stackstorm-xenial/.circleci/config.yml @@ -0,0 +1,15 @@ +version: 2 +jobs: + build: + docker: + - image: docker/compose:1.23.1 + steps: + - run: | + set -x + printenv | sort + - checkout + - setup_remote_docker: + docker_layer_caching: true + - run: + name: Install bash + command: apk add --no-cache bash diff --git a/images/stackstorm-xenial/.circleci/docker-compose.yml b/images/stackstorm-xenial/.circleci/docker-compose.yml new file mode 100644 index 00000000..3c1a67af --- /dev/null +++ b/images/stackstorm-xenial/.circleci/docker-compose.yml @@ -0,0 +1,74 @@ +version: '3' + +services: + stackstorm: + image: stackstorm/stackstorm:xenial + restart: always + environment: + - ST2_ENABLE_SSHD=1 + env_file: + - conf/stackstorm.env + - conf/mongo.env + - conf/rabbitmq.env + - conf/postgres.env + - conf/redis.env + volumes: + - ./packs.dev:/opt/stackstorm/packs.dev + - ./runtime/entrypoint.d:/st2-docker/entrypoint.d + - ./runtime/st2.d:/st2-docker/st2.d + - ./conf/stackstorm.env:/st2-docker/env + ports: + - "443:443" + depends_on: + - mongo + - postgres + - rabbitmq + - redis + networks: + - public + - private + dns_search: . + +### External Services + + mongo: + image: mongo:3.4 + env_file: + - conf/mongo.env + networks: + - private + dns_search: . + rabbitmq: + image: rabbitmq:3.6-management + env_file: + - conf/rabbitmq.env + networks: + - private + dns_search: . + postgres: + image: postgres:9.6 + env_file: + - conf/postgres.env + networks: + - private + dns_search: . + redis: + image: redis:4.0 + env_file: + - conf/redis.env + networks: + - private + dns_search: . + command: [ + "bash", "-c", + ' + docker-entrypoint.sh + --requirepass "$$REDIS_PASSWORD" + ' + ] + +networks: + public: + driver: bridge + private: + driver: bridge diff --git a/images/stackstorm-xenial/Dockerfile b/images/stackstorm-xenial/Dockerfile new file mode 100644 index 00000000..208e6d70 --- /dev/null +++ b/images/stackstorm-xenial/Dockerfile @@ -0,0 +1,110 @@ +FROM ubuntu:16.04 + +ARG DEBIAN_FRONTEND=noninteractive + +# Install essential packages +RUN set -eux && \ +apt-get update && \ +apt-get -y install --no-install-recommends \ + apache2-utils \ + apt-transport-https \ + ca-certificates \ + crudini \ + curl \ + supervisor \ + wget + +# Install nginx +RUN set -eux && \ +curl -sSL https://nginx.org/keys/nginx_signing.key | apt-key add - && \ +echo "deb https://nginx.org/packages/mainline/ubuntu/ xenial nginx" >> /etc/apt/sources.list.d/nginx.list && \ +apt-get update && \ +apt-get -y install --no-install-recommends nginx + +# Set nodejs version to install +# This can be overriden at build time by passing `--arg NODE_REPO=node_12.x` +ARG NODE_REPO=node_10.x + +# Install nodejs +RUN set -eux && \ +curl -sSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ +echo "deb https://deb.nodesource.com/${NODE_REPO}/ xenial main" > /etc/apt/sources.list.d/nodesource.list && \ +apt-get update && \ +apt-get -y install --no-install-recommends nodejs + +# Set st2 repo/version to install +# These can be overriden at build time +# If ST2_REPO=stable and ST2_VERSION left blank, then it picks the latest stable version +# available at build time +ARG ST2_REPO=stable +ARG ST2_VERSION= + +# Install stackstorm: st2, st2chatops, st2web, st2mistral +RUN set -eux && \ +curl -sSL https://packagecloud.io/StackStorm/${ST2_REPO}/gpgkey | apt-key add - && \ +echo "deb https://packagecloud.io/StackStorm/${ST2_REPO}/ubuntu/ xenial main" > /etc/apt/sources.list.d/st2.list && \ +apt-get update && \ +apt-get -y install --no-install-recommends \ + st2=${ST2_VERSION}* \ + st2chatops=${ST2_VERSION}* \ + st2mistral=${ST2_VERSION}* \ + st2web=${ST2_VERSION}* + +# Copy supervisord main config +# It switches source file between stable/unstable based on ST2_REPO var +# so that it can have different supervisord configs among `latest` and `dev` image +# which is useful especially when introducing a new st2 component +COPY ${ST2_REPO}/supervisord.conf /etc/supervisor/supervisord.conf + +# Copy supervisord config fragments +# These files are dynamically copied into /etc/supervisor/conf.d based on env vars and +# become effective to supervisord during the startup process +COPY supervisord.d/ /st2-docker/supervisord.d + +# Copy entrypoint shell scripts +# - entrypoint.sh: Main entrypoint +# - entrypoint-supervisord.sh: Starts supervisord. Called from entrypoint.sh +# - entrypoint-1ppc.sh: Handles 1ppc mode. Called from entrypoint.sh instead of +# entrypoint-supervisord.sh if running 1ppc mode +COPY bin/entrypoint.sh /st2-docker/bin/ +COPY bin/entrypoint-supervisord.sh /st2-docker/bin/ +COPY bin/entrypoint-1ppc.sh /st2-docker/bin/ + +# Copy shell scripts that are launched by supervisord +# - run-sshd: Starts sshd. It also does some initialization before starting daemon +# - run-postinit.sh: Run shell scripts in /st2-docker/st2.d/ *AFTER* st2 become ready +COPY bin/run-sshd.sh /st2-docker/bin/ +COPY bin/run-postinit.sh /st2-docker/bin/ + +# Copy shell scripts that are luunched by supervisord: for all st2 components +COPY bin/run-st2/ /st2-docker/bin/run-st2 + +# Replace st2ctl command +# This will become unnecessary when the modification is merged into upstream +COPY st2ctl /opt/stackstorm/st2/bin/st2ctl + +# Copy insecure keys +COPY insecure_keys/insecure_datastore_key.json /etc/st2/keys/datastore_key.json +COPY insecure_keys/insecure_ssl_st2.crt /etc/ssl/st2/st2.crt +COPY insecure_keys/insecure_ssl_st2.key /etc/ssl/st2/st2.key +COPY insecure_keys/insecure_stanley_rsa /home/stanley/.ssh/stanley_rsa +COPY insecure_keys/insecure_stanley_rsa.pub /home/stanley/.ssh/stanley_rsa.pub + +# Do post-install setup +RUN set -eux && \ +# Install redis client library for coordination backend +# see: https://docs.stackstorm.com/latest/reference/policies.html +bash -c 'source /opt/stackstorm/st2/bin/activate && pip install redis' && \ +# Enable authentication +crudini --set /etc/st2/st2.conf auth enable True && \ +# Enable datastore (st2kv) encryption by specifying encryption key +crudini --set /etc/st2/st2.conf keyvalue encryption_key_path /etc/st2/keys/datastore_key.json && \ +# Copy nginx config for st2web +cp /usr/share/doc/st2/conf/nginx/st2.conf /etc/nginx/conf.d/st2.conf && \ +# Set default locale to C.UTF-8 +echo LANG=C.UTF-8 > /etc/default/locale + +# Set LANG to C.UTF-8 +ENV LANG=C.UTF-8 + +ENTRYPOINT ["/st2-docker/bin/entrypoint.sh"] diff --git a/images/stackstorm-xenial/README.md b/images/stackstorm-xenial/README.md new file mode 100644 index 00000000..6c66a865 --- /dev/null +++ b/images/stackstorm-xenial/README.md @@ -0,0 +1,52 @@ + +## Building images + +``` +docker build -t stackstorm/stackstorm:xenial . + +docker build -t stackstorm/stackstorm:xenial-2.9.1 --build-arg ST2_VERSION=2.9.1 . +docker build -t stackstorm/stackstorm:xenial-2.9.0 --build-arg ST2_VERSION=2.9.0 . +docker build -t stackstorm/stackstorm:xenial-2.8.1 --build-arg ST2_VERSION=2.8.1 . + +docker build -t stackstorm/stackstorm:xenial-dev --build-arg ST2_REPO=unstable --build-arg NODE_REPO=node_8.x . +``` + +## Running `st2-self-test` + +``` +apt-get -y install uuid-runtime +export ST2_AUTH_TOKEN=$(st2 auth $ST2_USER -p $ST2_PASSWORD -t) +/opt/stackstorm/st2/bin/st2-self-check +``` + +## Insecure keys + +Introduce "insecure" keys in following places. + +- st2 datastore key +- SSL self-signed cert for nginx/st2web +- ssh key for stanley user + +The idea is like "insecure ssh key" of Vagrant. We save the pre-generated keys in this repo and copy them into the image. + +This helps those keys to be consistent among images of different versions/builds. Previously, those are dynamically generated during the docker build process, and it depends on the environment wheter it changes or not because of docker layer caching. This unstableness is considered harmful in both dev/ci and production use case. Leaving the default keys in production also makes the installation vulnerable. + +Unlike vagrant, these insecure keys are not replaced at runtime by default. For dev/ci use case, the default insecure key should just work fine. But for production usage, it is strongly recommended to replace them by the one that user generated by their own. This should be mentioned in main README.md to warn users. + +## New envvars + +- `ST2_DISABLE_MISTRAL` + - Controls whether to enable Mistral or not. If any value is set, following steps will be skipped during the container startup. + - Modification of `/etc/mistral/mistral.conf` to set PostgreSQL/RabbitMQ connection configs + - Invocation of `mistral-db-manage` for schema migration/data population + - Configuration of mistral-api, mistral-server process under supervisord: this means that those processes can't be started with `supervisorctl start`, even not be listed at all with `supervisorctl list` + - default: (not set) + +- `ST2_ENABLE_ST2CHATOPS` + - Controls whether to start `st2chatops` or not. If any value is set, supervisord will launch st2chatops. If not, it will even skip the configuration of supervisord for `st2chatops`, so that it prevents from `st2ctl reload` or `st2ctl restart` or any similar command to accidentaly starts `st2chatops` process + - default: (not set) + +- `ST2_ENABLE_SSHD` + - Controls whether to start sshd daemon or not. If any value is set, supervisord will launch sshd. **Only meant for testing purpose.** Need to be enabled when you run `st2-self-check`, since it uses some `core.remote` actions during the tests + - default: (not set) + diff --git a/images/stackstorm-xenial/bin/entrypoint-1ppc.sh b/images/stackstorm-xenial/bin/entrypoint-1ppc.sh new file mode 100755 index 00000000..9b39c1b4 --- /dev/null +++ b/images/stackstorm-xenial/bin/entrypoint-1ppc.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +ST2_CONF=/etc/st2/st2.conf +crudini --set ${ST2_CONF} auth api_url ${ST2_API_URL} +crudini --set ${ST2_CONF} mistral api_url ${ST2_API_URL} +crudini --set ${ST2_CONF} mistral v2_base_url ${ST2_MISTRAL_API_URL} + +# Configure CORS to accept any source +# st2api gunicorn process is directly exposed to clients in 1ppc mode +crudini --set ${ST2_CONF} api allow_origin '*' + +# Generate nginx config for st2web to support load balancing to st2api, st2auth and st2stream +/st2-docker/bin/inject_env.py \ + < /etc/nginx/conf.d/st2-1ppc.conf.tpl \ + > /etc/nginx/conf.d/st2.conf + +case "$ST2_SERVICE" in + "nop" ) + exec tail -f /dev/null + ;; + "st2api" ) + DAEMON_ARGS="-k eventlet -b 0.0.0.0:9101 --workers 1 --threads 1 --graceful-timeout 10 --timeout 30" + exec /opt/stackstorm/st2/bin/gunicorn st2api.wsgi:application $DAEMON_ARGS + ;; + "st2auth" ) + DAEMON_ARGS="-k eventlet -b 0.0.0.0:9100 --workers 1 --threads 1 --graceful-timeout 10 --timeout 30" + exec /opt/stackstorm/st2/bin/gunicorn st2auth.wsgi:application $DAEMON_ARGS + ;; + "st2stream" ) + DAEMON_ARGS="-k eventlet -b 0.0.0.0:9102 --workers 1 --threads 10 --graceful-timeout 10 --timeout 30" + exec /opt/stackstorm/st2/bin/gunicorn st2stream.wsgi:application $DAEMON_ARGS + ;; + "st2sensorcontainer" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2sensorcontainer ${DAEMON_ARGS} + ;; + "st2rulesengine" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2rulesengine ${DAEMON_ARGS} + ;; + "st2workflowengine" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2workflowengine ${DAEMON_ARGS} + ;; + "st2actionrunner" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2actionrunner ${DAEMON_ARGS} + ;; + "st2resultstracker" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2resultstracker ${DAEMON_ARGS} + ;; + "st2notifier" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2notifier ${DAEMON_ARGS} + ;; + "st2garbagecollector" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2garbagecollector ${DAEMON_ARGS} + ;; + "st2timersengine" ) + DAEMON_ARGS="--config-file /etc/st2/st2.conf" + exec /opt/stackstorm/st2/bin/st2timersengine ${DAEMON_ARGS} + ;; + "mistral-api" ) + set -e + /opt/stackstorm/mistral/bin/mistral-db-manage --config-file /etc/mistral/mistral.conf upgrade head + /opt/stackstorm/mistral/bin/mistral-db-manage --config-file /etc/mistral/mistral.conf populate + API_ARGS="--log-file /var/log/mistral/mistral-api.log -b 0.0.0.0:8989 -w 2 mistral.api.wsgi --graceful-timeout 10" + exec /opt/stackstorm/mistral/bin/gunicorn $API_ARGS + ;; + "mistral-server" ) + set -e + /opt/stackstorm/mistral/bin/mistral-db-manage --config-file /etc/mistral/mistral.conf upgrade head + /opt/stackstorm/mistral/bin/mistral-db-manage --config-file /etc/mistral/mistral.conf populate + SERVER_ARGS="--config-file /etc/mistral/mistral.conf --log-file /var/log/mistral/mistral-server.log" + exec /opt/stackstorm/mistral/bin/mistral-server --server engine,executor,notifier ${SERVER_ARGS} + ;; + "st2web" ) + exec /usr/sbin/nginx -g 'daemon off;' + ;; + "st2chatops" ) + set -e + export ST2_API=${ST2_API_URL} + cd /opt/stackstorm/chatops + exec bin/hubot $DAEMON_ARGS + ;; + "st2-register-content" ) + set -ex + PACKS=${PACKS:-"chatops core default linux packs"} + for PACK in ${PACKS}; do + st2-register-content --config-file /etc/st2/st2.conf \ + --register-all \ + --register-setup-virtualenvs \ + --register-pack /opt/stackstorm/packs/${PACK} + done + ;; + +esac diff --git a/images/stackstorm-xenial/bin/entrypoint-supervisord.sh b/images/stackstorm-xenial/bin/entrypoint-supervisord.sh new file mode 100755 index 00000000..cbf549b9 --- /dev/null +++ b/images/stackstorm-xenial/bin/entrypoint-supervisord.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +# set default path +export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +# set number of st2actionrunners to start +ST2ACTIONRUNNER_WORKERS=$(/usr/bin/nproc 2>/dev/null) +ST2ACTIONRUNNER_WORKERS=${ST2ACTIONRUNNER_WORKERS:-10} +export ST2ACTIONRUNNER_WORKERS + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/supervisord ] && . /etc/default/supervisord +set +o allexport + +# launch supervisord +exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf diff --git a/images/stackstorm-xenial/bin/entrypoint.sh b/images/stackstorm-xenial/bin/entrypoint.sh new file mode 100755 index 00000000..bbdcbe9b --- /dev/null +++ b/images/stackstorm-xenial/bin/entrypoint.sh @@ -0,0 +1,99 @@ +#!/bin/bash +set -e + +# Create htpasswd file for standalone mode auth with flat_file backend +htpasswd -b /etc/st2/htpasswd ${ST2_USER} ${ST2_PASSWORD} + +# Set credential +mkdir -p /root/.st2 +ROOT_CONF=/root/.st2/config +touch ${ROOT_CONF} +crudini --set ${ROOT_CONF} credentials username ${ST2_USER} +crudini --set ${ROOT_CONF} credentials password ${ST2_PASSWORD} + +# Set values into st2.conf +ST2_CONF=/etc/st2/st2.conf + +ST2_API_URL=${ST2_API_URL:-http://127.0.0.1:9101} +MISTRAL_BASE_URL=${MISTRAL_BASE_URL:-http://127.0.0.1:8989/v2} + +crudini --set ${ST2_CONF} auth api_url ${ST2_API_URL} +crudini --set ${ST2_CONF} mistral api_url ${ST2_API_URL} +crudini --set ${ST2_CONF} mistral v2_base_url ${MISTRAL_BASE_URL} +crudini --set ${ST2_CONF} messaging url \ + amqp://${RABBITMQ_DEFAULT_USER}:${RABBITMQ_DEFAULT_PASS}@${RABBITMQ_HOST}:${RABBITMQ_PORT} +crudini --set ${ST2_CONF} coordination url \ + redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT} +crudini --set ${ST2_CONF} database host ${MONGO_HOST} +crudini --set ${ST2_CONF} database port ${MONGO_PORT} +if [ ! -z ${MONGO_DB} ]; then + crudini --set ${ST2_CONF} database db_name ${MONGO_DB} +fi +if [ ! -z ${MONGO_USER} ]; then + crudini --set ${ST2_CONF} database username ${MONGO_USER} +fi +if [ ! -z ${MONGO_PASS} ]; then + crudini --set ${ST2_CONF} database password ${MONGO_PASS} +fi + +# NOTE: Only certain distros of MongoDB support SSL/TLS +# 1) enterprise versions +# 2) those built from source (https://github.com/mongodb/mongo/wiki/Build-Mongodb-From-Source) +# +#crudini --set ${ST2_CONF} database ssl True +#crudini --set ${ST2_CONF} database ssl_keyfile None +#crudini --set ${ST2_CONF} database ssl_certfile None +#crudini --set ${ST2_CONF} database ssl_cert_reqs None +#crudini --set ${ST2_CONF} database ssl_ca_certs None +#crudini --set ${ST2_CONF} database ssl_match_hostname True + + +if [ -z ${ST2_DISABLE_MISTRAL} ]; then + MISTRAL_CONF=/etc/mistral/mistral.conf + + crudini --set ${MISTRAL_CONF} DEFAULT transport_url \ + rabbit://${RABBITMQ_DEFAULT_USER}:${RABBITMQ_DEFAULT_PASS}@${RABBITMQ_HOST}:${RABBITMQ_PORT} + crudini --set ${MISTRAL_CONF} database connection \ + postgresql+psycopg2://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} + + cp /st2-docker/supervisord.d/st2mistral.conf /etc/supervisor/conf.d +fi + + +if [ ! -z ${ST2_ENABLE_ST2CHATOPS} ]; then + cp /st2-docker/supervisord.d/st2chatops.conf /etc/supervisor/conf.d +fi + + +if [ ! -z ${ST2_ENABLE_SSHD} ]; then + cp /st2-docker/supervisord.d/sshd.conf /etc/supervisor/conf.d +fi + +# Run custom init scripts +for f in /st2-docker/entrypoint.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *) echo "$0: ignoring $f" ;; + esac + echo +done + +# 1ppc: launch entrypoint-1ppc.sh via dumb-init if $ST2_SERVICE is set +if [ ! -z ${ST2_SERVICE} ]; then + exec /dumb-init -- /st2-docker/bin/entrypoint-1ppc.sh +fi + + +if [ -z ${ST2_DISABLE_MISTRAL} ]; then + echo "=========================================================" + echo "############## BEGIN mistral-db-manage ##################" + echo "=========================================================" + /opt/stackstorm/mistral/bin/mistral-db-manage --config-file /etc/mistral/mistral.conf upgrade head + /opt/stackstorm/mistral/bin/mistral-db-manage --config-file /etc/mistral/mistral.conf populate + echo "=========================================================" + echo "############## END mistral-db-manage ####################" + echo "=========================================================" +fi + +# switch to supervisord within sanitized environment +exec -c /st2-docker/bin/entrypoint-supervisord.sh diff --git a/images/stackstorm-xenial/bin/run-postinit.sh b/images/stackstorm-xenial/bin/run-postinit.sh new file mode 100755 index 00000000..d0949894 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-postinit.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -eux + +ENV_FILE=/st2-docker/env + +if [ -f ${ENV_FILE} ]; then + source ${ENV_FILE} +fi + +# Wait until st2api becomes ready. +# Assumes that st2api is listening on the default port, 9101. +# `wget` exits with code 6 when it fails to authenticate, which is expected here. +# TODO: Switch to check /healtzh or whatever the health check endpoint URI +# once that capability is implemented into st2api +wget --tries 5 --retry-connrefused -q -O /dev/null http://localhost:9101 || [ $? -eq 6 ] + +# Run custom init scripts which require ST2 to be running +for f in /st2-docker/st2.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *) echo "$0: ignoring $f" ;; + esac + echo +done diff --git a/images/stackstorm-xenial/bin/run-sshd.sh b/images/stackstorm-xenial/bin/run-sshd.sh new file mode 100755 index 00000000..d18e31fc --- /dev/null +++ b/images/stackstorm-xenial/bin/run-sshd.sh @@ -0,0 +1,59 @@ +#!/bin/bash +set -eux + +# https://github.com/StackStorm/st2-packages/blob/master/scripts/st2bootstrap-deb.sh +# Copied from: https://github.com/StackStorm/st2-packages/blob/51b57213406e12715f82e49f11dbc614280304c3/scripts/st2bootstrap-deb.sh#L261-L298 +configure_st2_user () { + # Create an SSH system user (default `stanley` user may be already created) + if (! id stanley 2>/dev/null); then + sudo useradd stanley + fi + + SYSTEM_HOME=$(echo ~stanley) + + sudo mkdir -p ${SYSTEM_HOME}/.ssh + + # Generate ssh keys on StackStorm box and copy over public key into remote box. + # NOTE: If the file already exists and is non-empty, then assume the key does not need + # to be generated again. + if ! sudo test -s ${SYSTEM_HOME}/.ssh/stanley_rsa; then + sudo ssh-keygen -f ${SYSTEM_HOME}/.ssh/stanley_rsa -P "" + fi + + if ! sudo grep -s -q -f ${SYSTEM_HOME}/.ssh/stanley_rsa.pub ${SYSTEM_HOME}/.ssh/authorized_keys; + then + # Authorize key-base access + sudo sh -c "cat ${SYSTEM_HOME}/.ssh/stanley_rsa.pub >> ${SYSTEM_HOME}/.ssh/authorized_keys" + fi + + sudo chmod 0600 ${SYSTEM_HOME}/.ssh/authorized_keys + sudo chmod 0700 ${SYSTEM_HOME}/.ssh + sudo chown -R stanley:stanley ${SYSTEM_HOME} + + # Enable passwordless sudo + local STANLEY_SUDOERS="stanley ALL=(ALL) NOPASSWD: SETENV: ALL" + if ! sudo grep -s -q ^"${STANLEY_SUDOERS}" /etc/sudoers.d/st2; then + sudo sh -c "echo '${STANLEY_SUDOERS}' >> /etc/sudoers.d/st2" + fi + + sudo chmod 0440 /etc/sudoers.d/st2 + + # Disable requiretty for all users + sudo sed -i -r "s/^Defaults\s+\+?requiretty/# Defaults requiretty/g" /etc/sudoers +} + + +configure_st2_user + +# Fix key permission +sudo chmod 0400 /home/stanley/.ssh/stanley_rsa + +# Delete IPv6 entry from hosts file +TMP_HOSTS=$(mktemp) +sed -e '/^[0-9a-f:]*:/d' /etc/hosts > $TMP_HOSTS +cp $TMP_HOSTS /etc/hosts +rm $TMP_HOSTS + +mkdir -p /var/run/sshd + +exec /usr/sbin/sshd -D diff --git a/images/stackstorm-xenial/bin/run-st2/mistral-api.sh b/images/stackstorm-xenial/bin/run-st2/mistral-api.sh new file mode 100755 index 00000000..237ba215 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/mistral-api.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +NAME=mistral +COMPONENTS="api,engine,executor,notifier" +API_ARGS="--log-file /var/log/mistral/mistral-api.log -b 127.0.0.1:8989 -w 2 mistral.api.wsgi --graceful-timeout 10" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +# NB! Exit if mistral-api is disabled +. /opt/stackstorm/mistral/share/sysvinit/helpers +enabled_list -q api || exit 0 + +exec /opt/stackstorm/mistral/bin/gunicorn $API_ARGS diff --git a/images/stackstorm-xenial/bin/run-st2/mistral-server.sh b/images/stackstorm-xenial/bin/run-st2/mistral-server.sh new file mode 100755 index 00000000..e73064e3 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/mistral-server.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +NAME=mistral +COMPONENTS="api,engine,executor,notifier" +SERVER_ARGS="--config-file /etc/mistral/mistral.conf --log-file /var/log/mistral/mistral-server.log" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +# Exit if server components are disabled, otherwise inject them into args. +. /opt/stackstorm/mistral/share/sysvinit/helpers +enabled_list -q server || exit 0 + +exec /opt/stackstorm/mistral/bin/mistral-server --server $(enabled_list server) ${SERVER_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2actionrunner.sh b/images/stackstorm-xenial/bin/run-st2/st2actionrunner.sh new file mode 100755 index 00000000..5e9e25b2 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2actionrunner.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +NAME=st2actionrunner +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +# Load global locale settings +test -f /etc/default/locale && . /etc/default/locale || true + +# +LANG=$LANG LC_ALL=$LANG exec /sbin/start-stop-daemon --start \ + --pidfile /dev/null \ + --group st2packs \ + --umask 002 \ + --exec /opt/stackstorm/st2/bin/$NAME -- ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2api.sh b/images/stackstorm-xenial/bin/run-st2/st2api.sh new file mode 100755 index 00000000..ed8531b2 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2api.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2api +DAEMON_ARGS="-k eventlet -b 127.0.0.1:9101 --workers 1 --threads 1 --graceful-timeout 10 --timeout 30 --log-config /etc/st2/logging.api.gunicorn.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/gunicorn st2api.wsgi:application $DAEMON_ARGS diff --git a/images/stackstorm-xenial/bin/run-st2/st2auth.sh b/images/stackstorm-xenial/bin/run-st2/st2auth.sh new file mode 100755 index 00000000..00e1aa2d --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2auth.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2auth +DAEMON_ARGS="-k eventlet -b 127.0.0.1:9100 --workers 1 --threads 1 --graceful-timeout 10 --timeout 30 --log-config /etc/st2/logging.auth.gunicorn.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/gunicorn st2auth.wsgi:application $DAEMON_ARGS diff --git a/images/stackstorm-xenial/bin/run-st2/st2chatops.sh b/images/stackstorm-xenial/bin/run-st2/st2chatops.sh new file mode 100755 index 00000000..e923d6e3 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2chatops.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +NAME=st2chatops +DAEMON_ARGS="" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +cd /opt/stackstorm/chatops + +exec bin/hubot $DAEMON_ARGS >> /var/log/st2/st2chatops.log 2>&1 diff --git a/images/stackstorm-xenial/bin/run-st2/st2garbagecollector.sh b/images/stackstorm-xenial/bin/run-st2/st2garbagecollector.sh new file mode 100755 index 00000000..b188ac14 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2garbagecollector.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2garbagecollector +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2notifier.sh b/images/stackstorm-xenial/bin/run-st2/st2notifier.sh new file mode 100755 index 00000000..3cb9d0e9 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2notifier.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2notifier +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2resultstracker.sh b/images/stackstorm-xenial/bin/run-st2/st2resultstracker.sh new file mode 100755 index 00000000..1f2fa39f --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2resultstracker.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2resultstracker +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2rulesengine.sh b/images/stackstorm-xenial/bin/run-st2/st2rulesengine.sh new file mode 100755 index 00000000..dcd1db07 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2rulesengine.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2rulesengine +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2scheduler.sh b/images/stackstorm-xenial/bin/run-st2/st2scheduler.sh new file mode 100755 index 00000000..a4af7c1c --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2scheduler.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2scheduler +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2sensorcontainer.sh b/images/stackstorm-xenial/bin/run-st2/st2sensorcontainer.sh new file mode 100755 index 00000000..4a5c1c58 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2sensorcontainer.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2sensorcontainer +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2stream.sh b/images/stackstorm-xenial/bin/run-st2/st2stream.sh new file mode 100755 index 00000000..1a28e6e5 --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2stream.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2stream +DAEMON_ARGS="-k eventlet -b 127.0.0.1:9102 --workers 1 --threads 10 --graceful-timeout 10 --timeout 30 --log-config /etc/st2/logging.stream.gunicorn.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/gunicorn st2stream.wsgi:application $DAEMON_ARGS diff --git a/images/stackstorm-xenial/bin/run-st2/st2timersengine.sh b/images/stackstorm-xenial/bin/run-st2/st2timersengine.sh new file mode 100755 index 00000000..110df30d --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2timersengine.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2timersengine +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/bin/run-st2/st2workflowengine.sh b/images/stackstorm-xenial/bin/run-st2/st2workflowengine.sh new file mode 100755 index 00000000..466ec19d --- /dev/null +++ b/images/stackstorm-xenial/bin/run-st2/st2workflowengine.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +NAME=st2workflowengine +DAEMON_ARGS="--config-file /etc/st2/st2.conf" + +# Read configuration variable file if it is present +set -o allexport +[ -r /etc/default/$NAME ] && . /etc/default/$NAME +set +o allexport + +exec /opt/stackstorm/st2/bin/$NAME ${DAEMON_ARGS} diff --git a/images/stackstorm-xenial/insecure_keys/insecure_datastore_key.json b/images/stackstorm-xenial/insecure_keys/insecure_datastore_key.json new file mode 100644 index 00000000..ef05d65b --- /dev/null +++ b/images/stackstorm-xenial/insecure_keys/insecure_datastore_key.json @@ -0,0 +1,9 @@ +{ + "aesKeyString": "N2LDQAzbod42IEfrX0iDX69E6Ff-jG0azc3_6q8w2Gc", + "hmacKey": { + "hmacKeyString": "UMXEKxIQR-XxQUU2euYMaGnLGJFK2vFhaW01kobt1ZI", + "size": 256 + }, + "mode": "CBC", + "size": 256 +} diff --git a/images/stackstorm-xenial/insecure_keys/insecure_ssl_st2.crt b/images/stackstorm-xenial/insecure_keys/insecure_ssl_st2.crt new file mode 100644 index 00000000..503d8575 --- /dev/null +++ b/images/stackstorm-xenial/insecure_keys/insecure_ssl_st2.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIJAPG0ffy/LNgfMA0GCSqGSIb3DQEBCwUAMEcxEzARBgNV +BAoMClN0YWNrU3Rvcm0xHDAaBgNVBAsME3N0Mi1kb2NrZXIgaW5zZWN1cmUxEjAQ +BgNVBAMMCWxvY2FsaG9zdDAeFw0xODExMjAwMjM0MDNaFw0yODExMTcwMjM0MDNa +MEcxEzARBgNVBAoMClN0YWNrU3Rvcm0xHDAaBgNVBAsME3N0Mi1kb2NrZXIgaW5z +ZWN1cmUxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKlJ8WysiU4lMQHylPzsUy6U5Lfes2fxtDQnNMQWXfs0nBk2djcF +xI7yiqjKXFr8qL/R58pNJpsDXa86F/rlcqgvsarQzQxetB/R94IAB9fih/wiJUuJ +JuDpLxgw6J9BhmW2Y0U4yUQyKZg+fO+V8NNTjcV6Hf+1r1Dh8RC2H/yoU0TOk71n +M1ukdXVCLZ7srCj47yT81AfOoq+2re25LqFKbFdbeclDN6kIW/pwizStbXgiqXzG +i6GaFvF2eQoOGQm7aewm4r0oCVAXIr35GpXi3sARHHBdnszXgeJ14neJAUA8TxEJ +xmD41ge8sz2YwrLtH3IUQ7Xt/+ypBLETKXUCAwEAAaNQME4wHQYDVR0OBBYEFKMm +oySZ1iXywC42+1XmErf4oHXuMB8GA1UdIwQYMBaAFKMmoySZ1iXywC42+1XmErf4 +oHXuMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKAM3FZLomnCoXhD +3tOxpmWsrk0CHPs4sLGN4NumMBzUy1y/q8Y6+Wj7O1XbTqRCz7gOwV6de7CagyVq +rfVCtQglwuElM6K/FDpcISFCMvenZzXU2IrVJb2rSFZmRFyBMkIiNP4DCuHmiS+P +26jAYJuQWA4qwbKqylhWcuTTO4UKk6+VuRnlVx8IguOI3EHwSWPH0kGB9vhbDj2n +R2VyBJnxGR4n+/UDlmJQCHQUkTKywptYv3lMGzk5+cps4UOo/J/AZKs/5IVtOHYG +bATIGmnmKGZHCPtufEJUo5zn01NoiPCARJn9cYp+WzoGHJZOmiikn44JkQZMXJNv +Zetm5t0= +-----END CERTIFICATE----- diff --git a/images/stackstorm-xenial/insecure_keys/insecure_ssl_st2.key b/images/stackstorm-xenial/insecure_keys/insecure_ssl_st2.key new file mode 100644 index 00000000..10851ac3 --- /dev/null +++ b/images/stackstorm-xenial/insecure_keys/insecure_ssl_st2.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpSfFsrIlOJTEB +8pT87FMulOS33rNn8bQ0JzTEFl37NJwZNnY3BcSO8oqoylxa/Ki/0efKTSabA12v +Ohf65XKoL7Gq0M0MXrQf0feCAAfX4of8IiVLiSbg6S8YMOifQYZltmNFOMlEMimY +PnzvlfDTU43Feh3/ta9Q4fEQth/8qFNEzpO9ZzNbpHV1Qi2e7Kwo+O8k/NQHzqKv +tq3tuS6hSmxXW3nJQzepCFv6cIs0rW14Iql8xouhmhbxdnkKDhkJu2nsJuK9KAlQ +FyK9+RqV4t7AERxwXZ7M14HideJ3iQFAPE8RCcZg+NYHvLM9mMKy7R9yFEO17f/s +qQSxEyl1AgMBAAECggEAGGsG/MLiRzhMGljQLq8zzFtDplXkENEnSgKBtOr5AVv0 +TBqz8HnPgULwxynxKlqZSJnRUjfQorlYkQbTIKhp4mKGwPm/KdKbLp/NkJ3Kg9Q0 +AyU1tfCBgB2CYn3jf90mspMdPIXVWhXWNBSHVtOM2h6KK3rSyuh88jC04dEzSfEN +fJqI5+h4AlvrwBeuVgcDYBSBpHJS5GC8nqjN7cl5mUnxGAPBOG+K29Sbu+m8M84y +IwKwr3hcEeyZhUgYDngx1a3Dqz6x4BHMp0C60mNRbdISvKGa3/3RMvif5N0jFCj/ +nB+tJqHqfsHMobKFdUATTF1iRpVO1EQ95FckpigVwQKBgQDZiOGhLXo1mPm4AszM +mVnyfsRvE+n5qBHWBDuxmJZ9+4IuyNhx2yhPekw2DtJHLzrCxQDllol/CPBKJXrU +3RjLHs0KovYj5na0/FutdoS0YmaUxwUAffDjfqZgw+A95HyWAe16PsGBy2DofeFf +Ax2YHs9Wp7j3DoFWnfCog/qLMQKBgQDHOR9AODL4wUmmgkMol5YZeeUoz9XpKyDk +aNJce3+0Oo1vvVbvqPkMHAJT4/EF76nqEINY+lTkq7XdwMEwyzb+1/U90CdtHQ8Q +wfhVwNRaeJxPpA6IZEGIIJ5oAVX55lJSdeze4yb0UvciqJ31XmBlJMQ1fvJETCGd +WU7Z9f4phQKBgQC0uw3CbFc5ioQGhoUCg3IAj6PCKYhd/G39In052u1FdB0/o2x4 +g71k8tW4n+3CaJHoWeaZ2M0ZdyK0Z5k6mwrLTybJbIUVZJdBXN0KLAqrF4nkl8kn +FHt7drDiejqnEVsVAjr8MoFwxbkYz+TbnGoNBaP7edOppyp7/TKBv0z8MQKBgFgG +cD1y12q8FKvCsKPV3pdhGZTfyBdfXAgwHIqKctGScX3mvevk0C2+jnS8qXlC/OOT +6kU9Tpc/G3tguLuzfpg5mX13ZIQ8q7Ru0CgrrGhRFFfIGDfBfIcGSpePx4pEbylK +O5/74/FeWx3wPOL2kUb/aMZuUeNFdDDPDh0WKPf1AoGAbOb4tEmq4WpNgV6UEkv4 +mfa3iCcfZRiNIVHyYChtpm+oztQ/Rkb3zzWl1CeQIkFIP1Ka4hdcfyD46i92c8tN +0d/YSExs39C87k3m8n0z5Mag8dqlcwUw0algNt+qPORiEQV25bRIi9epsGLAYu0x +1gdHvszAQCb//BoPiZxP3xw= +-----END PRIVATE KEY----- diff --git a/images/stackstorm-xenial/insecure_keys/insecure_stanley_rsa b/images/stackstorm-xenial/insecure_keys/insecure_stanley_rsa new file mode 100644 index 00000000..b1eb7681 --- /dev/null +++ b/images/stackstorm-xenial/insecure_keys/insecure_stanley_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEApm1z3NcuFOvwWqs23wxNZRzGjJl9rbUMfzPzHt8RWWDJmh6K +pwq75rGdA/LcU4NrksBAlQAfB8ujFg3WUVUbM/pmXPaA3ADivJBAqSR5o43jiILa +ae64WrhAN3I5S5kufmgYmu2OfFeEsCT7PWu76H8jKcqAOZPSVu4bb+gLehfRTtjx +yBSdkdUzQ3YVzkqe8CPh5XmqtSu1Kk3DiUcp3IyUAG5Sp7aO9AgAE3RV4EqXYvS1 +0QYjHPmo1gxk5aiV3kl88pNVkbEdbaH1nCnLIpIj0Bu/RSM2ZZ2sF7WJaKufesoc +q+3Gzdm2l+mA0f6aOLO9l3ej5qM/G6r6zZYrQwIDAQABAoIBABPk3Ya2iiGiGncc +JFEBTXcau3kvF+Dd1YKXGSbFj3NZqH+tyvEwzUlETfqc2014VjGSnaWyAAOUiggm +20mZnMjX08ilBr5FtNTJgZE2dPviCCLXUXh8OrlNcQ+vrb2lr/MYSmiqoO+oHopX +wViUOkAOgouKU02OqAQQLmNwH38WjFYc77qGG7GhvCHknvUBsON3lHVR2B/tEaNM +BjVbFldqCQ5mSMc9AN3wvywqAKauilY5Cwp+qrvkQ4VQarnFindIciLLC58vo/Ln +RSABnJLLmXyig6REqER7JWe7+G2oxFXte+2GVlQpOZ0EZRMbgioRhhnQ3U9PUC8Y +VsmJVlECgYEA2s8/ZApI6hvgb9Z4w5FAT+MlCl/cWgBcn6kVecSypR54Y0+OLnBU +AE4VYLcy732NZDo+xB6kjUtyXG/kTEsBGaZ2/K8tZBdjwdB6CuzqbD9L3wts20px +qzRU/1kyiKvA/j/xhbhJxMo0mw38s54Y2hKjY6I7dgbWiDiK/O8BxJ8CgYEAwrb6 +8IMceV4eqhRoSA4X6AL7Dbz2FkkQIKswhuVpdW7KIFZxt2n6T4x4smojTzot5+i/ +UGm29y5NN02E90Qt6kA5Mcugjd4PTDzH+RYozcirPBF6AiXzFBOQ5aP/XswruYUH ++kKVC80nCv7ph+BJtDPMgZXZUuzqd84g6Rcb0t0CgYEAgyNezKhVVunqM10I97zg +HID4PCWDvPUmjhIaauZ2YvvGD08o2bA8yAoESfjCMELBMOavo37yBDTJj5kH7Kmv +OR5Jhdu/ipNyGEDIRDAFt2agJEeGsE8HnSI6Jufgn4TAoCDWsdvnamf960gQwd3o +6xnsjtQ2auBiRzYMJtdf6eUCgYAOn6N1EMPAsbrn1ySF1NkiyaaFP53TyqT1byXz +26Lx+OIhT5y2w7TS6J/f9my0dJAiDK7hoS7mnYmbD61ezLYOE8i33q0uOnE3rpDu +OiXSXrHNjxp0stjwtw94z7pMKlVWV5Fj0EBVZJD8GGz9kXC3ofRH/zMVMUniuY5r +MxsZ2QKBgQC5HDVFHjrKVR9IEm5UJMSFmPNqp41It7rQYP9uQ6pd2Kq+5e149d/B +WkARsYx2F8hr7pJCf1B/zH2miiROMsGTzKaqz2jbTtYXtzacz4Ny5qTBObCDvmLW +BshPKGsk7Kk8hEzgX30BeKPMKuA/g1Ii9e2UWoDbaWSl+dKZamE+jA== +-----END RSA PRIVATE KEY----- diff --git a/images/stackstorm-xenial/insecure_keys/insecure_stanley_rsa.pub b/images/stackstorm-xenial/insecure_keys/insecure_stanley_rsa.pub new file mode 100644 index 00000000..c4901f8e --- /dev/null +++ b/images/stackstorm-xenial/insecure_keys/insecure_stanley_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCmbXPc1y4U6/BaqzbfDE1lHMaMmX2ttQx/M/Me3xFZYMmaHoqnCrvmsZ0D8txTg2uSwECVAB8Hy6MWDdZRVRsz+mZc9oDcAOK8kECpJHmjjeOIgtpp7rhauEA3cjlLmS5+aBia7Y58V4SwJPs9a7vofyMpyoA5k9JW7htv6At6F9FO2PHIFJ2R1TNDdhXOSp7wI+Hleaq1K7UqTcOJRyncjJQAblKnto70CAATdFXgSpdi9LXRBiMc+ajWDGTlqJXeSXzyk1WRsR1tofWcKcsikiPQG79FIzZlnawXtYloq596yhyr7cbN2baX6YDR/po4s72Xd6Pmoz8bqvrNlitD insecure_stanley_rsa diff --git a/images/stackstorm-xenial/misc/build.sh b/images/stackstorm-xenial/misc/build.sh new file mode 100755 index 00000000..044664f2 --- /dev/null +++ b/images/stackstorm-xenial/misc/build.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -euo pipefail + +IMAGE_BASE=${IMAGE_BASE:-xenial} +BUILD_TARGET=${BUILD_TARGET:-stable} + +BUILD_ARGS= +IMAGE_TAG_POSTFIX= +ST2_REPO= +ST2_VERSION= +NODE_REPO= + +if [ "${BUILD_TARGET}" = "stable" ]; then + ST2_REPO="stable" + ST2_VERSION= + NODE_REPO="node_10.x" + IMAGE_TAG_POSTFIX= +elif [[ ${BUILD_TARGET} =~ ^v(.+)$ ]]; then + ST2_REPO="stable" + ST2_VERSION=${BASH_REMATCH[1]} + NODE_REPO="node_10.x" + IMAGE_TAG_POSTFIX="-${ST2_VERSION}" +elif [ "${BUILD_TARGET}" = "unstable" ]; then + ST2_REPO="unstable" + ST2_VERSION= + NODE_REPO="node_10.x" + IMAGE_TAG_POSTFIX="-dev" +else + exit 1 +fi + +BUILD_ARGS="--build-arg ST2_REPO=${ST2_REPO}" +BUILD_ARGS="${BUILD_ARGS} --build-arg ST2_VERSION=${ST2_VERSION}" +BUILD_ARGS="${BUILD_ARGS} --build-arg NODE_REPO=${NODE_REPO}" + +IMAGE_TAG="${IMAGE_BASE}${IMAGE_TAG_POSTFIX}" + +set -x +docker build -t stackstorm/stackstorm:${IMAGE_TAG} ${BUILD_ARGS} . diff --git a/images/stackstorm-xenial/misc/gen-run-st2/.gitignore b/images/stackstorm-xenial/misc/gen-run-st2/.gitignore new file mode 100644 index 00000000..f9606a37 --- /dev/null +++ b/images/stackstorm-xenial/misc/gen-run-st2/.gitignore @@ -0,0 +1 @@ +/venv diff --git a/images/stackstorm-xenial/misc/gen-run-st2/gen_run_st2.py b/images/stackstorm-xenial/misc/gen-run-st2/gen_run_st2.py new file mode 100755 index 00000000..2096d7af --- /dev/null +++ b/images/stackstorm-xenial/misc/gen-run-st2/gen_run_st2.py @@ -0,0 +1,117 @@ +#!env python + +import glob +from collections import OrderedDict +import re +import shlex +import textwrap + +import jinja2 + + +def main(): + # paths = glob.glob('/Users/shu/workspaces/st2/st2-packages/packages/st2/debian/st2*.service') + # for path in paths: + # sh = SystemdUnitParser(path).to_script() + # print(sh) + mistral_paths = glob.glob('/Users/shu/workspaces/st2/st2-packages/packages/st2mistral/debian/mistral-*.upstart') + for path in mistral_paths: + sh = UpstartJobParser(path).to_script() + print(sh) + + +class UpstartJobParser: + tmpl_str = ''' +#!/bin/bash +set -e + +{{ data }} +'''.strip() + + def __init__(self, target): + self.target = target + self.parse() + + def parse(self): + option_format = re.compile('.*^script$(.*)^end script$.*', flags=(re.MULTILINE | re.DOTALL)) + with open(self.target, 'r') as f: + lines = f.read() + option_kv = option_format.match(lines) + if option_kv: + script_block = option_kv.group(1) + script_block = textwrap.dedent(script_block).strip() + self.data = script_block + + def to_script(self): + tmpl = jinja2.Template(self.tmpl_str) + return tmpl.render(data=self.data) + + +class SystemdUnitParser: + + tmpl_str = ''' +#!/bin/bash +set -e + +# asdf +{%- for k, v in data.get('Environment', {}).items() %} +{{ k }}="{{ v }}" +{%- endfor %} + +{%- if data.get('EnvironmentFile') %} +# Read configuration variable file if it is present +set -o allexport +[ -r {{ data['EnvironmentFile'] }} ] && . {{ data['EnvironmentFile'] }} +set +o allexport +{%- endif %} + +exec {{ data['ExecStart'] }} +'''.strip() + + def __init__(self, target): + self.target = target + self.parse() + + def parse(self): + res = {} + option_format = re.compile('^([a-zA-Z0-9]+)=(.*)') + + with open(self.target, 'r') as f: + lines = f.readlines() + for line in lines: + option_kv = option_format.match(line) + if option_kv: + key = option_kv.group(1) + val = option_kv.group(2) + if key == 'Environment': + if key not in res: + res[key] = OrderedDict() + + res[key].update(self.parse_env(val)) + + elif key == 'EnvironmentFile': + res[key] = val.lstrip('-') + + else: + res[key] = val + self.data = res + + def parse_env(self, env): + res = {} + env_format = re.compile('^([a-zA-Z0-9_]+)=(.*)') + + for elm in shlex.split(env): + env_kv = env_format.match(elm) + key = env_kv.group(1) + val = env_kv.group(2) + res[key] = val + + return res + + def to_script(self): + tmpl = jinja2.Template(self.tmpl_str) + return tmpl.render(data=self.data) + + +if __name__ == '__main__': + main() diff --git a/images/stackstorm-xenial/misc/gen-run-st2/requirements.txt b/images/stackstorm-xenial/misc/gen-run-st2/requirements.txt new file mode 100644 index 00000000..c6442a44 --- /dev/null +++ b/images/stackstorm-xenial/misc/gen-run-st2/requirements.txt @@ -0,0 +1,11 @@ +astroid==2.2.5 +isort==4.3.20 +Jinja2==2.10.1 +lazy-object-proxy==1.4.1 +MarkupSafe==1.1.1 +mccabe==0.6.1 +pycodestyle==2.5.0 +pylint==2.3.1 +six==1.12.0 +typed-ast==1.4.0 +wrapt==1.11.2 diff --git a/images/stackstorm-xenial/st2ctl b/images/stackstorm-xenial/st2ctl new file mode 100755 index 00000000..91ad72c7 --- /dev/null +++ b/images/stackstorm-xenial/st2ctl @@ -0,0 +1,272 @@ +#!/bin/bash +# Licensed to the StackStorm, Inc ('StackStorm') under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +COMPONENTS="st2actionrunner st2api st2stream st2auth st2garbagecollector st2notifier st2resultstracker st2rulesengine st2sensorcontainer st2chatops st2timersengine st2workflowengine st2scheduler mistral" +ST2_CONF="/etc/st2/st2.conf" + +# Installations which use Python 3 (e.g. Ubuntu Bionic) ship without Mistral +PYTHON_VERSION=$(/opt/stackstorm/st2/bin/python --version 2>&1 | awk '{print $2'} | awk -F"." '{print $1}') + +if [ "${PYTHON_VERSION}" = "3" ]; then + COMPONENTS=${COMPONENTS/mistral} +fi + +# Ensure global environment is sourced if exists +# Does not happen consistently with all OSes we support. +[ -r /etc/environment ] && source /etc/environment + +# load in environment to allow override of COMPONENTS and ST2_CONF above +# Ubuntu/Debian +[ -r /etc/default/st2ctl ] && source /etc/default/st2ctl +# RHEL/CentOS +[ -r /etc/sysconfig/st2ctl ] && source /etc/sysconfig/st2ctl + + +function print_usage() { + echo "Usage: st2ctl {start, stop, restart, status}" + echo + echo "Usage: st2ctl {restart-component}" + echo "positional arguments:" + echo " component Name of the st2 service to restart." + echo " ${COMPONENTS}" + echo + echo "Usage: st2ctl {reopen-log-files}" + echo "positional arguments:" + echo " component Name of the st2 service to reopen the log files for." + echo " ${COMPONENTS/mistral}" + echo + echo "Usage: st2ctl {reload, clean}" + echo "optional arguments:" + echo " --register-all Register all." + echo " --register-triggers Register all triggers." + echo " --register-sensors Register all sensors." + echo " --register-rules Register all rules." + echo " --register-runners Register all runners." + echo " --register-actions Register all actions." + echo " --register-aliases Register all aliases." + echo " --register-policies Register all policies." + echo " --register-configs Register all configuration files." + echo " --register-setup-virtualenvs Create Python virtual environments for all the registered packs." + echo " --register-fail-on-failure Exit with non-zero if some resource registration fails. Deprecated. This is now a default behavior." + echo " --register-no-fail-on-failure Don't exit with non-zero if some resource registration fails." + echo " --verbose Output additional debug and informational messages." + echo "" + echo "Most commands require elevated privileges." +} + +function must_be_root() { + if [ $(id -u) -ne 0 ]; then + echo "Please run this command with root privileges" + exit 1 + fi +} + +function validate_in_components() { + COM=${1} + + if [ -z ${COM} ]; then + echo -e "\e[31mError: Component is required! \e[0m\n" + print_usage + exit 1 + fi + + if [[ " ${COMPONENTS} " != *" ${COM} "* ]]; then + echo -e "\e[31mError: Invalid component provided: ${COM} \e[0m\n" + print_usage + exit 1 + fi +} + +function st2start() { + for COM in ${COMPONENTS}; do + service_manager ${COM} start + done +} + +function st2stop() { + for COM in ${COMPONENTS}; do + service_manager ${COM} stop + done +} + +function service_manager() { + local svcname=$1 action=$2 + if [ -d /run/systemd/system ]; then + # systemd is running + systemctl $action $svcname + elif [ $(cat /proc/1/comm) = init ] && (/sbin/initctl version 2>/dev/null | grep -q upstart) && + [ -f /etc/init/${svcname}.conf ]; then + # init is running, and is upstart and service config is available + # ! upstart running detection is a MUST, since upstart can be just + # ! installed on a platform but not used (ex: docker container, centos). + /sbin/initctl $action $svcname + elif [ -S /var/run/supervisord.sock ]; then + # supervisord is running (for st2-docker) + supervisorctl $action "$svcname:*" + elif command -v service > /dev/null 2>&1; then + service $svcname $action + elif [ -x /etc/init.d/${1} ]; then + /etc/init.d/$svcname $action + else + echo -e "\e[31mError: Unknown service manager, we ONLY support systemd, upstart and sysv! \e[0m\n" + exit 1 + fi +} + +# Next candidate for removal +# after we implement native `service st2component reopen` (nginx example) for each component +function reopen_component_log_files() { + COM=${1} + + if [[ "$COM" == "mistral" ]]; then + echo "Sorry, Mistral does not yet support gracefully reopening log files" + return 1 + fi + + PID=`ps ax | grep -v grep | grep -v st2ctl | grep -E "(${COM}\.wsgi)|(bin/${COM})|(hubot .*${COM})" | awk '{print $1}'` + if [[ ! -z ${PID} ]]; then + for p in ${PID}; do + echo "Sending SIGUSR1 to ${COM} PID: ${p}" + kill -USR1 ${p} + done + else + echo "${COM} is not running" + return 1 + fi +} + +function register_content() { + ALLOWED_REGISTER_FLAGS='--register-all --register-actions --register-aliases --register-runners --register-policies --register-rules --register-sensors --register-triggers --register-configs --register-setup-virtualenvs --register-fail-on-failure --register-no-fail-on-failure --verbose' + DEFAULT_REGISTER_FLAGS='--register-runners --register-actions --register-aliases --register-sensors --register-triggers --register-configs --register-rules' + + SUDO_FLAGS='--register-setup-virtualenvs' + flags="${@}" + + if [ ! -z ${1} ]; then + for flag in ${flags}; do + if [[ " ${SUDO_FLAGS} " == *" $flag "* && "$(id -u)" != "0" ]]; then + echo -e "\e[31mError: \"sudo\" required for: ${flag} \e[0m\n" + exit 1 + fi + if [[ " ${ALLOWED_REGISTER_FLAGS} " != *" $flag "* ]]; then # argument not allowed + echo -e "\e[31mError: Invalid flag provided: ${flag} \e[0m\n" + print_usage + exit 1 + fi + done + fi + + if [ -z ${1} ]; then + REGISTER_FLAGS=${DEFAULT_REGISTER_FLAGS} + elif [ ${1} == '--verbose' ] && [ -z ${2} ]; then + REGISTER_FLAGS="$DEFAULT_REGISTER_FLAGS ${1}" + else + REGISTER_FLAGS=${flags} + fi + + echo "Registering content...[flags = --config-file ${ST2_CONF} ${REGISTER_FLAGS}]" + st2-register-content --config-file ${ST2_CONF} ${REGISTER_FLAGS} +} + +function clean_db() { + echo "Dropping st2 Database..." + /opt/stackstorm/st2/bin/st2-cleanup-db --config-file ${ST2_CONF} +} + +function clean_logs() { + echo "Cleaning st2 Logs..." + rm -Rf /var/log/st2/* +} + +function getpids() { + echo "##### st2 components status #####" + COMPONENTS=${COMPONENTS/mistral/mistral-server mistral.api} + + for COM in ${COMPONENTS}; do + PID=`ps ax | grep -v grep | grep -v st2ctl | grep -E "(${COM}\.wsgi)|(bin/${COM})|(hubot .*${COM})" | awk '{print $1}'` + + if [[ ! -z ${PID} ]]; then + for p in ${PID}; do + echo "${COM} PID: ${p}" + done + else + echo "${COM} is not running." + fi + done +} + + +case ${1} in + start) + must_be_root + st2start + getpids + ;; + stop) + must_be_root + st2stop + ;; + restart) + must_be_root + st2stop + sleep 1 + st2start + getpids + ;; + restart-component) + must_be_root + validate_in_components ${2} + service_manager ${2} restart + ;; + reopen-log-files) + must_be_root + validate_in_components ${2} + if reopen_component_log_files ${2}; then + sleep 1 + getpids + fi + ;; + reload) + register_content ${@:2} + exit_code=$? + getpids + # Note: We want to preserve st2-register-content "fail on failure" behavior + # and propagate the correct exit code and exit with non zero on failure + exit ${exit_code} + ;; + clean) + must_be_root + echo "This will drop the database and delete all logs. Are you sure [y/n]?" + read verify + if [[ "$verify" == "y" ]]; then + st2stop + clean_db + clean_logs + register_content ${@:2} + st2start + getpids + else + exit + fi + ;; + status) + getpids + ;; + *) + print_usage + exit 1 + ;; +esac diff --git a/images/stackstorm-xenial/stable/supervisord.conf b/images/stackstorm-xenial/stable/supervisord.conf new file mode 100644 index 00000000..40aa6939 --- /dev/null +++ b/images/stackstorm-xenial/stable/supervisord.conf @@ -0,0 +1,89 @@ +[supervisord] +nodaemon = true +logfile = /var/log/supervisord.log +pidfile = /var/run/supervisord.pid +childlogdir = /var/log/supervisor + +[unix_http_server] +file = /var/run/supervisord.sock + +[supervisorctl] +serverurl = unix:///var/run/supervisord.sock + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[program:st2api] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2auth] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2stream] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2sensorcontainer] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2rulesengine] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2timersengine] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2workflowengine] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2actionrunner] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +numprocs = %(ENV_ST2ACTIONRUNNER_WORKERS)s +process_name = %(program_name)s%(process_num)d +environment = WORKERID="%(process_num)d" +redirect_stderr = true + +[program:st2scheduler] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2resultstracker] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2notifier] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2garbagecollector] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:nginx] +command = /usr/sbin/nginx -g 'daemon off;' +redirect_stderr = true + +[program:run-postinit] +command = /st2-docker/bin/run-postinit.sh +startsecs = 0 +exitcodes = 0 +redirect_stderr = true + +[include] +files = /etc/supervisor/conf.d/*.conf diff --git a/images/stackstorm-xenial/supervisord.d/sshd.conf b/images/stackstorm-xenial/supervisord.d/sshd.conf new file mode 100644 index 00000000..01b30237 --- /dev/null +++ b/images/stackstorm-xenial/supervisord.d/sshd.conf @@ -0,0 +1,6 @@ + +[program:sshd] +command = /st2-docker/bin/run-sshd.sh +startsecs = 0 +exitcodes = 0 +redirect_stderr = true diff --git a/images/stackstorm-xenial/supervisord.d/st2chatops.conf b/images/stackstorm-xenial/supervisord.d/st2chatops.conf new file mode 100644 index 00000000..b4fe60f5 --- /dev/null +++ b/images/stackstorm-xenial/supervisord.d/st2chatops.conf @@ -0,0 +1,4 @@ +[program:st2chatops] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true diff --git a/images/stackstorm-xenial/supervisord.d/st2mistral.conf b/images/stackstorm-xenial/supervisord.d/st2mistral.conf new file mode 100644 index 00000000..d20ef74c --- /dev/null +++ b/images/stackstorm-xenial/supervisord.d/st2mistral.conf @@ -0,0 +1,12 @@ +[program:mistral-api] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = mistral +redirect_stderr = true + +[program:mistral-server] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = mistral +redirect_stderr = true + +[group:mistral] +programs = mistral-api,mistral-server diff --git a/images/stackstorm-xenial/unstable/supervisord.conf b/images/stackstorm-xenial/unstable/supervisord.conf new file mode 100644 index 00000000..40aa6939 --- /dev/null +++ b/images/stackstorm-xenial/unstable/supervisord.conf @@ -0,0 +1,89 @@ +[supervisord] +nodaemon = true +logfile = /var/log/supervisord.log +pidfile = /var/run/supervisord.pid +childlogdir = /var/log/supervisor + +[unix_http_server] +file = /var/run/supervisord.sock + +[supervisorctl] +serverurl = unix:///var/run/supervisord.sock + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[program:st2api] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2auth] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2stream] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2sensorcontainer] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2rulesengine] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2timersengine] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2workflowengine] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2actionrunner] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +numprocs = %(ENV_ST2ACTIONRUNNER_WORKERS)s +process_name = %(program_name)s%(process_num)d +environment = WORKERID="%(process_num)d" +redirect_stderr = true + +[program:st2scheduler] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2resultstracker] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2notifier] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:st2garbagecollector] +command = /st2-docker/bin/run-st2/%(program_name)s.sh +user = st2 +redirect_stderr = true + +[program:nginx] +command = /usr/sbin/nginx -g 'daemon off;' +redirect_stderr = true + +[program:run-postinit] +command = /st2-docker/bin/run-postinit.sh +startsecs = 0 +exitcodes = 0 +redirect_stderr = true + +[include] +files = /etc/supervisor/conf.d/*.conf