From fdd15359b72eb75cb8ff5460e6420e2856c3efa7 Mon Sep 17 00:00:00 2001 From: Madda Date: Wed, 21 Oct 2015 17:59:02 +0100 Subject: [PATCH] CFY-3237-Enable-enforcing-selinux --- new/components/amqpinflux/scripts/create.sh | 1 - .../elasticsearch/scripts/create.sh | 1 - new/components/influxdb/scripts/create.sh | 1 - new/components/java/scripts/create.sh | 5 -- new/components/logstash/scripts/create.sh | 1 - new/components/mgmtworker/scripts/create.sh | 1 - new/components/nginx/config/default.conf | 6 +- .../nginx/config/selinux/file-contexts | 3 + .../nginx/config/selinux/type-enforcement | 11 ++++ new/components/nginx/scripts/create.sh | 24 +++++-- new/components/python/scripts/create.sh | 1 - .../rabbitmq/config/selinux/file-contexts | 4 ++ .../rabbitmq/config/selinux/type-enforcement | 4 ++ new/components/rabbitmq/scripts/create.sh | 41 +++++++----- .../restservice/config/selinux/file-contexts | 10 +++ .../config/selinux/type-enforcement | 13 ++++ new/components/restservice/scripts/create.sh | 1 - .../restservice/scripts/preconfigure.sh | 17 ++++- new/components/riemann/scripts/create.sh | 1 - new/components/selinux/config/config | 11 ++++ new/components/selinux/scripts/create.sh | 38 ++++++++++++ new/components/utils | 62 ++++++++++--------- .../webui/config/selinux/file-contexts | 4 ++ .../webui/config/selinux/type-enforcement | 4 ++ new/components/webui/scripts/create.sh | 11 +++- new/simple-manager-blueprint.yaml | 41 ++++++++++++ new/types/manager-types.yaml | 29 ++++++++- 27 files changed, 277 insertions(+), 69 deletions(-) create mode 100644 new/components/nginx/config/selinux/file-contexts create mode 100644 new/components/nginx/config/selinux/type-enforcement create mode 100644 new/components/rabbitmq/config/selinux/file-contexts create mode 100644 new/components/rabbitmq/config/selinux/type-enforcement create mode 100644 new/components/restservice/config/selinux/file-contexts create mode 100644 new/components/restservice/config/selinux/type-enforcement create mode 100644 new/components/selinux/config/config create mode 100644 new/components/selinux/scripts/create.sh create mode 100644 new/components/webui/config/selinux/file-contexts create mode 100644 new/components/webui/config/selinux/type-enforcement diff --git a/new/components/amqpinflux/scripts/create.sh b/new/components/amqpinflux/scripts/create.sh index fe56dc920..d4653b5c9 100755 --- a/new/components/amqpinflux/scripts/create.sh +++ b/new/components/amqpinflux/scripts/create.sh @@ -17,7 +17,6 @@ export RABBITMQ_CERT_ENABLED="$(ctx -j node properties rabbitmq_ssl_enabled)" export RABBITMQ_CERT_PUBLIC="$(ctx node properties rabbitmq_cert_public)" ctx logger info "Installing AQMPInflux..." -set_selinux_permissive copy_notice "amqpinflux" create_dir "${AMQPINFLUX_HOME}" diff --git a/new/components/elasticsearch/scripts/create.sh b/new/components/elasticsearch/scripts/create.sh index fb2f30bf7..7f1f77078 100755 --- a/new/components/elasticsearch/scripts/create.sh +++ b/new/components/elasticsearch/scripts/create.sh @@ -25,7 +25,6 @@ export ES_CONF_PATH="/etc/elasticsearch" function install_elasticsearch() { ctx logger info "Installing Elasticsearch..." - set_selinux_permissive copy_notice "elasticsearch" create_dir ${ES_HOME} diff --git a/new/components/influxdb/scripts/create.sh b/new/components/influxdb/scripts/create.sh index c14864926..4ba79b33c 100755 --- a/new/components/influxdb/scripts/create.sh +++ b/new/components/influxdb/scripts/create.sh @@ -19,7 +19,6 @@ export INFLUXDB_LOG_PATH="/var/log/cloudify/influxdb" function install_influxdb() { ctx logger info "Installing InfluxDB..." - set_selinux_permissive copy_notice "influxdb" create_dir ${INFLUXDB_HOME} diff --git a/new/components/java/scripts/create.sh b/new/components/java/scripts/create.sh index b5c495f05..9169f4241 100755 --- a/new/components/java/scripts/create.sh +++ b/new/components/java/scripts/create.sh @@ -6,17 +6,12 @@ JAVA_SOURCE_URL=$(ctx node properties java_rpm_source_url) ctx logger info "Installing Java..." -set_selinux_permissive copy_notice "java" if [[ "$JAVA_SOURCE_URL" == *rpm ]]; then yum_install ${JAVA_SOURCE_URL} fi -# Make sure the cloudify logs dir exists before we try moving the java log there -# -p will cause it not to error if the dir already exists -create_dir "/var/log/cloudify" - # Java install log is dropped in /var/log. Move it to live with the rest of the cloudify logs if [ -f "/var/log/java_install.log" ]; then sudo mv "/var/log/java_install.log" "/var/log/cloudify" diff --git a/new/components/logstash/scripts/create.sh b/new/components/logstash/scripts/create.sh index cdd9b8747..9a0b9b317 100755 --- a/new/components/logstash/scripts/create.sh +++ b/new/components/logstash/scripts/create.sh @@ -26,7 +26,6 @@ if [[ -z "${RABBITMQ_USERNAME}" ]] || fi ctx logger info "Installing Logstash..." -set_selinux_permissive copy_notice "logstash" diff --git a/new/components/mgmtworker/scripts/create.sh b/new/components/mgmtworker/scripts/create.sh index 09f54c410..d560879ff 100755 --- a/new/components/mgmtworker/scripts/create.sh +++ b/new/components/mgmtworker/scripts/create.sh @@ -41,7 +41,6 @@ broker_ssl_enabled="$(echo ${RABBITMQ_SSL_ENABLED} | tr '[:upper:]' '[:lower:]') ctx instance runtime_properties rabbitmq_ssl_enabled "${broker_ssl_enabled}" ctx logger info "Installing Management Worker..." -set_selinux_permissive copy_notice "mgmtworker" create_dir ${MGMTWORKER_HOME} diff --git a/new/components/nginx/config/default.conf b/new/components/nginx/config/default.conf index ac29ed3e5..5977bb543 100644 --- a/new/components/nginx/config/default.conf +++ b/new/components/nginx/config/default.conf @@ -26,8 +26,8 @@ server { listen {{ ctx.instance.runtime_properties.ssl_rest_service_port }} ssl; server_name _; - ssl_certificate /root/cloudify/server.crt; - ssl_certificate_key /root/cloudify/server.key; + ssl_certificate /etc/nginx/cloudify.crt; + ssl_certificate_key /etc/nginx/cloudify.key; access_log /var/log/cloudify/nginx/cloudify.access.log; error_log /var/log/cloudify/nginx/cloudify.error.log; @@ -98,4 +98,4 @@ server { allow all; deny all; } -} \ No newline at end of file +} diff --git a/new/components/nginx/config/selinux/file-contexts b/new/components/nginx/config/selinux/file-contexts new file mode 100644 index 000000000..5edcb7131 --- /dev/null +++ b/new/components/nginx/config/selinux/file-contexts @@ -0,0 +1,3 @@ +# Ensure there is a new line at the end of this file or it may break when deployed +/var/log/cloudify/nginx(/.*)? gen_context(system_u:object_r:httpd_log_t,s0) + diff --git a/new/components/nginx/config/selinux/type-enforcement b/new/components/nginx/config/selinux/type-enforcement new file mode 100644 index 000000000..b81d16e9b --- /dev/null +++ b/new/components/nginx/config/selinux/type-enforcement @@ -0,0 +1,11 @@ +# This file must exist with the above line for the policy (with file contexts, etc) to be compiled +# Ensure there is a new line at the end of this file or it may break when deployed +policy_module(cloudify-nginx, 1.0.0) + +require { + type httpd_t; + type tor_port_t; +} + +allow httpd_t tor_port_t:tcp_socket name_connect; + diff --git a/new/components/nginx/scripts/create.sh b/new/components/nginx/scripts/create.sh index 089bf7bde..46cf750e2 100755 --- a/new/components/nginx/scripts/create.sh +++ b/new/components/nginx/scripts/create.sh @@ -13,7 +13,9 @@ export MANAGER_RESOURCES_HOME="/opt/manager/resources" export MANAGER_AGENTS_PATH="${MANAGER_RESOURCES_HOME}/packages/agents" export MANAGER_SCRIPTS_PATH="${MANAGER_RESOURCES_HOME}/packages/scripts" export MANAGER_TEMPLATES_PATH="${MANAGER_RESOURCES_HOME}/packages/templates" -export SSL_CERTS_ROOT="/root/cloudify" +export SSL_CERTS_ROOT="/etc/nginx" + +export SELINUX_ENFORCING="$(ctx -j node properties selinux_enforcing)" # this is propagated to the agent retrieval script later on so that it's not defined twice. ctx instance runtime_properties agent_packages_path "${MANAGER_AGENTS_PATH}" @@ -24,7 +26,6 @@ ctx instance runtime_properties ssl_rest_service_port "443" ctx instance runtime_properties internal_rest_service_port "8101" ctx logger info "Installing Nginx..." -set_selinux_permissive copy_notice "nginx" create_dir ${NGINX_LOG_PATH} @@ -45,8 +46,23 @@ deploy_blueprint_resource "${CONFIG_REL_PATH}/rest-location.cloudify" "/etc/ngin deploy_logrotate_config "nginx" ctx logger info "Copying SSL Certs..." -deploy_blueprint_resource "${SSL_RESOURCES_REL_PATH}/server.crt" "${SSL_CERTS_ROOT}/server.crt" -deploy_blueprint_resource "${SSL_RESOURCES_REL_PATH}/server.key" "${SSL_CERTS_ROOT}/server.key" +deploy_blueprint_resource "${SSL_RESOURCES_REL_PATH}/server.crt" "${SSL_CERTS_ROOT}/cloudify.crt" +sudo chown root.root "${SSL_CERTS_ROOT}/cloudify.crt" +deploy_blueprint_resource "${SSL_RESOURCES_REL_PATH}/server.key" "${SSL_CERTS_ROOT}/cloudify.key" +sudo chown root.root "${SSL_CERTS_ROOT}/cloudify.key" +sudo chmod 400 "${SSL_CERTS_ROOT}/cloudify.key" + +if [[ "${SELINUX_ENFORCING}" == 'true' ]]; then + apply_selinux_policy nginx "${CONFIG_REL_PATH}/selinux" + + fix_selinux_file_contexts /etc/nginx + fix_selinux_file_contexts /var/log/cloudify/nginx + + allow_selinux_port_tcp http_port_t 8101 + allow_selinux_port_tcp http_port_t 53229 + # tcp/9001 is required as well, but this is defined in another policy, from which it cannot be removed + # as a result, it access has been allowed for httpd_t to tor_port_t to allow use of this port +fi sudo systemctl enable nginx.service &>/dev/null diff --git a/new/components/python/scripts/create.sh b/new/components/python/scripts/create.sh index f046f270d..d84009490 100755 --- a/new/components/python/scripts/create.sh +++ b/new/components/python/scripts/create.sh @@ -7,7 +7,6 @@ PIP_SOURCE_RPM_URL=$(ctx node properties pip_source_rpm_url) INSTALL_PYTHON_COMPILERS=$(ctx node properties install_python_compilers) ctx logger info "Installing Python requirements..." -set_selinux_permissive copy_notice "python" yum_install ${PIP_SOURCE_RPM_URL} diff --git a/new/components/rabbitmq/config/selinux/file-contexts b/new/components/rabbitmq/config/selinux/file-contexts new file mode 100644 index 000000000..7dcf95711 --- /dev/null +++ b/new/components/rabbitmq/config/selinux/file-contexts @@ -0,0 +1,4 @@ +# Ensure there is a new line at the end of this file or it may break when deployed +/var/log/cloudify/rabbitmq(/.*)? gen_context(system_u:object_r:rabbitmq_var_log_t,s0) +/etc/rabbitmq(/.*)? gen_context(system_u:object_r:etc_t,s0) + diff --git a/new/components/rabbitmq/config/selinux/type-enforcement b/new/components/rabbitmq/config/selinux/type-enforcement new file mode 100644 index 000000000..90e116f6c --- /dev/null +++ b/new/components/rabbitmq/config/selinux/type-enforcement @@ -0,0 +1,4 @@ +# This file must exist with the above line for the policy (with file contexts, etc) to be compiled +# Ensure there is a new line at the end of this file or it may break when deployed +policy_module(cloudify-rabbitmq, 1.0.0) + diff --git a/new/components/rabbitmq/scripts/create.sh b/new/components/rabbitmq/scripts/create.sh index e358ab881..302b20dbf 100755 --- a/new/components/rabbitmq/scripts/create.sh +++ b/new/components/rabbitmq/scripts/create.sh @@ -10,9 +10,9 @@ export RABBITMQ_FD_LIMIT=$(ctx node properties rabbitmq_fd_limit) export RABBITMQ_LOG_PATH="/var/log/cloudify/rabbitmq" +export SELINUX_ENFORCING="$(ctx -j node properties selinux_enforcing)" ctx logger info "Installing RabbitMQ..." -set_selinux_permissive copy_notice "rabbitmq" create_dir "${RABBITMQ_LOG_PATH}" @@ -41,22 +41,6 @@ sudo systemctl daemon-reload ctx logger info "Chowning RabbitMQ logs path..." sudo chown rabbitmq:rabbitmq ${RABBITMQ_LOG_PATH} -ctx logger info "Starting RabbitMQ Server in Daemonized mode..." -sudo systemctl start cloudify-rabbitmq.service - -ctx logger info "Enabling RabbitMQ Plugins..." -# Occasional timing issues with rabbitmq starting have resulted in failures when first trying to enable plugins -run_command_with_retries "sudo rabbitmq-plugins enable rabbitmq_management" -run_command_with_retries "sudo rabbitmq-plugins enable rabbitmq_tracing" - -ctx logger info "Disabling RabbitMQ guest user" -run_command_with_retries "sudo rabbitmqctl clear_permissions guest" -run_command_with_retries "sudo rabbitmqctl delete_user guest" - -ctx logger info "Creating new RabbitMQ user and setting permissions" -run_command_with_retries sudo rabbitmqctl add_user ${RABBITMQ_USERNAME} ${RABBITMQ_PASSWORD} -run_noglob_command_with_retries sudo rabbitmqctl set_permissions ${RABBITMQ_USERNAME} '.*' '.*' '.*' - # Deploy certificates if both have been provided. Complain loudly if one has been provided and the other hasn't. if [[ "${RABBITMQ_SSL_ENABLED}" == 'true' ]]; then if [[ -n "${RABBITMQ_CERT_PRIVATE}" ]]; then @@ -81,6 +65,29 @@ else fi fi +if [[ "${SELINUX_ENFORCING}" == 'true' ]]; then + apply_selinux_policy rabbitmq "${CONFIG_REL_PATH}/selinux" + + fix_selinux_file_contexts /etc/rabbitmq + fix_selinux_file_contexts /var/log/cloudify/rabbitmq +fi + +ctx logger info "Starting RabbitMQ Server in Daemonized mode..." +sudo systemctl start cloudify-rabbitmq.service + +ctx logger info "Enabling RabbitMQ Plugins..." +# Occasional timing issues with rabbitmq starting have resulted in failures when first trying to enable plugins +run_command_with_retries "sudo rabbitmq-plugins enable rabbitmq_management" +run_command_with_retries "sudo rabbitmq-plugins enable rabbitmq_tracing" + +ctx logger info "Disabling RabbitMQ guest user" +run_command_with_retries "sudo rabbitmqctl clear_permissions guest" +run_command_with_retries "sudo rabbitmqctl delete_user guest" + +ctx logger info "Creating new RabbitMQ user and setting permissions" +run_command_with_retries sudo rabbitmqctl add_user ${RABBITMQ_USERNAME} ${RABBITMQ_PASSWORD} +run_noglob_command_with_retries sudo rabbitmqctl set_permissions ${RABBITMQ_USERNAME} '.*' '.*' '.*' + ctx logger info "Stopping RabbitMQ Service..." # Systemd service stopping has been returning non zero when successful set +e diff --git a/new/components/restservice/config/selinux/file-contexts b/new/components/restservice/config/selinux/file-contexts new file mode 100644 index 000000000..35fcdd83a --- /dev/null +++ b/new/components/restservice/config/selinux/file-contexts @@ -0,0 +1,10 @@ +# Ensure there is a new line at the end of this file or it may break when deployed +/opt/manager/resources(/.*)? gen_context(system_u:object_r:httpd_sys_rw_content_t,s0) +/usr/lib/systemd/system/cloudify-restservice.service gen_context(system_u:object_r:httpd_unit_file_t,s0) +/opt/manager/run_manager gen_context(system_u:object_r:httpd_exec_t,s0) +/opt/manager/env(/.*)? gen_context(system_u:object_r:httpd_var_lib_t,s0) +# This must come after the /env(/.*)? definition or it will be overridden +/opt/manager/env/bin/.* gen_context(system_u:object_r:httpd_exec_t,s0) +/opt/manager/.*\.conf gen_context(system_u:object_r:httpd_config_t,s0) +/var/log/cloudify/rest(/.*)? gen_context(system_u:object_r:httpd_log_t,s0) + diff --git a/new/components/restservice/config/selinux/type-enforcement b/new/components/restservice/config/selinux/type-enforcement new file mode 100644 index 000000000..654147fdc --- /dev/null +++ b/new/components/restservice/config/selinux/type-enforcement @@ -0,0 +1,13 @@ +# This file must exist with the above line for the policy (with file contexts, etc) to be compiled +# Ensure there is a new line at the end of this file or it may break when deployed +policy_module(cloudify-restservice, 1.0.0) + +require { + type httpd_t; + type httpd_var_lib_t; +} + +allow httpd_t httpd_var_lib_t:file entrypoint; +allow httpd_t httpd_var_lib_t:lnk_file read; +allow httpd_t httpd_var_lib_t:lnk_file getattr; + diff --git a/new/components/restservice/scripts/create.sh b/new/components/restservice/scripts/create.sh index 1a414d4ab..0c8ad6c7a 100755 --- a/new/components/restservice/scripts/create.sh +++ b/new/components/restservice/scripts/create.sh @@ -36,7 +36,6 @@ export MANAGER_REST_SECURITY_CONFIG_PATH="${REST_SERVICE_HOME}/rest-security.con export REST_SERVICE_LOG_PATH="/var/log/cloudify/rest" ctx logger info "Installing REST Service..." -set_selinux_permissive copy_notice "restservice" create_dir ${REST_SERVICE_HOME} diff --git a/new/components/restservice/scripts/preconfigure.sh b/new/components/restservice/scripts/preconfigure.sh index 4bf18409d..cd5d228d1 100644 --- a/new/components/restservice/scripts/preconfigure.sh +++ b/new/components/restservice/scripts/preconfigure.sh @@ -4,8 +4,23 @@ CONFIG_REL_PATH="components/restservice/config" REST_SERVICE_HOME="/opt/manager" +export SELINUX_ENFORCING="$(ctx -j source node properties selinux_enforcing)" + ctx logger info "Deploying REST Security configuration file..." sec_settings=$(ctx -j target node properties security) # TODO: do not print to stdout echo $sec_settings | sudo tee "${REST_SERVICE_HOME}/rest-security.conf" -configure_systemd_service "restservice" \ No newline at end of file +configure_systemd_service "restservice" + +if [[ "${SELINUX_ENFORCING}" == 'true' ]]; then + apply_selinux_policy restservice "${CONFIG_REL_PATH}/selinux" + + fix_selinux_file_contexts /usr/lib/systemd/system/cloudify-restservice.service + fix_selinux_file_contexts /opt/manager + fix_selinux_file_contexts /var/log/cloudify/rest + + allow_selinux_port_tcp http_port_t 9200 + allow_selinux_port_tcp http_port_t 8100 + allow_selinux_port_tcp http_port_t 5672 + allow_selinux_port_tcp http_port_t 5671 +fi diff --git a/new/components/riemann/scripts/create.sh b/new/components/riemann/scripts/create.sh index 30ba800d0..2833c9b6d 100755 --- a/new/components/riemann/scripts/create.sh +++ b/new/components/riemann/scripts/create.sh @@ -28,7 +28,6 @@ if [[ -z "${RABBITMQ_USERNAME}" ]] || fi ctx logger info "Installing Riemann..." -set_selinux_permissive copy_notice "riemann" create_dir ${RIEMANN_LOG_PATH} diff --git a/new/components/selinux/config/config b/new/components/selinux/config/config new file mode 100644 index 000000000..ff55a0ebc --- /dev/null +++ b/new/components/selinux/config/config @@ -0,0 +1,11 @@ +# This file controls the state of SELinux on the system. +# SELINUX= can take one of these three values: +# enforcing - SELinux security policy is enforced. +# permissive - SELinux prints warnings instead of enforcing. +# disabled - No SELinux policy is loaded. +SELINUX={{ ctx.instance.runtime_properties.selinux_mode }} +# SELINUXTYPE= can take one of three two values: +# targeted - Targeted processes are protected, +# minimum - Modification of targeted policy. Only selected processes are protected. +# mls - Multi Level Security protection. +SELINUXTYPE=targeted diff --git a/new/components/selinux/scripts/create.sh b/new/components/selinux/scripts/create.sh new file mode 100644 index 000000000..9c9589121 --- /dev/null +++ b/new/components/selinux/scripts/create.sh @@ -0,0 +1,38 @@ +#!/bin/bash -e + +. $(ctx download-resource "components/utils") + +CONFIG_REL_PATH="components/selinux/config" + +export SELINUX_ENFORCING="$(ctx -j node properties selinux_enforcing)" + +# Ensure log directories exist before we start (they may be needed here and will be needed elsewhere) +create_dir /var/log/cloudify + +if [[ "${SELINUX_ENFORCING}" == 'true' ]]; then + # Make SELinux enforce policy + ctx instance runtime_properties selinux_mode enforcing + + # Apply the change without a reboot + sudo setenforce 1 + + # Install required tools for managing SELinux + yum_install "policycoreutils-python" >/dev/null + yum_install "selinux-policy-devel" >/dev/null + + # Ensure general SELinux policies are set that apply across most applications + sudo semanage fcontext -a -s system_u -t var_log_t '/var/log/cloudify(/.*)?' + sudo restorecon -F -R -v /var/log/cloudify +else + # Make SELinux only log violations of policy + # This is preferred to 'disabled' as it allows enabling without a reboot if so desired later + ctx instance runtime_properties selinux_mode permissive + + # Apply the change without a reboot + sudo setenforce 0 +fi + +# Persist the setting after reboot +deploy_blueprint_resource "${CONFIG_REL_PATH}/config" "/etc/selinux/config" +sudo chown root.root /etc/selinux/config +sudo chmod 644 /etc/selinux/config diff --git a/new/components/utils b/new/components/utils index 9bb5f9b11..dbfb5b263 100644 --- a/new/components/utils +++ b/new/components/utils @@ -326,34 +326,6 @@ function inject_service_env_var() { replace "${field}" "${value}" $vars_path >/dev/null } -function get_selinux_state() { - ### - # This checks whether SELinux is Enforcing or Permissive - ### - set +e - selinux_mode=$(getenforce) - set -e - - if [[ ! -z ${selinux_mode} ]]; then - echo ${selinux_mode} - else - echo "None" - fi -} - -function set_selinux_permissive() { - # This will cause failures after reboots if a node has been manually set permissive using setenforce but - # not in the selinux config before running this - ctx logger info "Checking if SELinux is enforced..." - if [ "$(get_selinux_state)" == 'Enforcing' ]; then - ctx logger info "SELinux is enforcing, setting SELinux Permissive State..." - sudo setenforce Permissive - sudo sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config - else - ctx logger info "SELinux not enforced." - fi -} - function set_rabbitmq_policy() { ### # Sets RabbitMQ Policies @@ -515,5 +487,39 @@ function deploy_logrotate_config() { sudo chmod 644 ${logrotate_config_path} } +function allow_selinux_port_tcp() { + context=${1} + port=${2} + ctx logger info "Allowing SELinux context ${context} access to bind to tcp port ${port}" + # Permit use of a particular TCP port by a specified context + sudo semanage port -a -t ${context} -p tcp ${port} +} + +function fix_selinux_file_contexts() { + path=${1} + ctx logger info "Restoring SELinux file contexts for ${path} based on system policy." + # Recursively set SELinux file contexts based on those defined by policy + sudo restorecon -F -R ${path} +} + +function apply_selinux_policy() { + policy_name=${1} + selinux_config_path=${2} + + policy_path="/tmp/cloudify-selinux/${policy_name}" + # The make process will create a policy package with the ${policy_name} and a .pp extension + policy_package_path="${policy_path}/${policy_name}.pp" + + ctx logger info "Preparing SELinux policy for ${policy_name} in ${policy_path}" + create_dir "${policy_path}" + deploy_blueprint_resource "${selinux_config_path}/file-contexts" "${policy_path}/${policy_name}.fc" + deploy_blueprint_resource "${selinux_config_path}/type-enforcement" "${policy_path}/${policy_name}.te" + + ctx logger info "Compiling SELinux policy for ${policy_name} in ${policy_path}" + sudo make -f /usr/share/selinux/devel/Makefile -C "${policy_path}" + + ctx logger info "Enabling SELinux policy for ${policy_name} from ${policy_package_path}" + sudo semodule -i "${policy_package_path}" +} CLOUDIFY_SOURCES_PATH="/opt/cloudify/sources" diff --git a/new/components/webui/config/selinux/file-contexts b/new/components/webui/config/selinux/file-contexts new file mode 100644 index 000000000..1f9cd1e72 --- /dev/null +++ b/new/components/webui/config/selinux/file-contexts @@ -0,0 +1,4 @@ +# Ensure there is a new line at the end of this file or it may break when deployed +# Allow monitoring to be visible in the UI +/opt/cloudify-ui/grafana/config.js gen_context(system_u:object_r:httpd_config_t,s0) + diff --git a/new/components/webui/config/selinux/type-enforcement b/new/components/webui/config/selinux/type-enforcement new file mode 100644 index 000000000..1dd205cf4 --- /dev/null +++ b/new/components/webui/config/selinux/type-enforcement @@ -0,0 +1,4 @@ +# This file must exist with the above line for the policy (with file contexts, etc) to be compiled +# Ensure there is a new line at the end of this file or it may break when deployed +policy_module(cloudify-webui, 1.0.0) + diff --git a/new/components/webui/scripts/create.sh b/new/components/webui/scripts/create.sh index 7a713f496..1f45d0f57 100755 --- a/new/components/webui/scripts/create.sh +++ b/new/components/webui/scripts/create.sh @@ -9,6 +9,8 @@ export NODEJS_SOURCE_URL=$(ctx node properties nodejs_tar_source_url) export WEBUI_SOURCE_URL=$(ctx node properties webui_tar_source_url) export GRAFANA_SOURCE_URL=$(ctx node properties grafana_tar_source_url) +export SELINUX_ENFORCING="$(ctx -j node properties selinux_enforcing)" + # injected as an input to the script ctx instance runtime_properties influxdb_endpoint_ip ${INFLUXDB_ENDPOINT_IP} @@ -21,7 +23,6 @@ export WEBUI_USER="webui" export WEBUI_GROUP="webui" ctx logger info "Installing Cloudify's WebUI..." -set_selinux_permissive copy_notice "webui" webui_notice=$(ctx download-resource "components/webui/LICENSE") @@ -59,4 +60,10 @@ sudo chown -R "${WEBUI_USER}:${WEBUI_GROUP}" "${WEBUI_LOG_PATH}" deploy_logrotate_config "webui" -configure_systemd_service "webui" \ No newline at end of file +configure_systemd_service "webui" + +if [[ "${SELINUX_ENFORCING}" == 'true' ]]; then + apply_selinux_policy webui "${CONFIG_REL_PATH}/selinux" + + fix_selinux_file_contexts /opt/cloudify-ui +fi diff --git a/new/simple-manager-blueprint.yaml b/new/simple-manager-blueprint.yaml index ee396c945..af449be46 100644 --- a/new/simple-manager-blueprint.yaml +++ b/new/simple-manager-blueprint.yaml @@ -48,6 +48,15 @@ inputs: admin_password: default: admin + ############################# + # SELinux settings + ############################# + selinux_enforcing: + description: > + Determines whether SELinux will be enforcing (true) or permissive (false). + default: true + type: boolean + ############################# # Agent Packages ############################# @@ -417,6 +426,16 @@ node_templates: inputs: public_ip: { get_property: [manager_host, public_ip] } + ####################################################################### + # SELinux happens before the rest so that it can ensure all settings + # are in place before anything tries to happen. + ####################################################################### + selinux: + type: manager.nodes.SELinux + relationships: + - type: cloudify.relationships.contained_in + target: manager_host + # ##################################################################### # The Python and Java nodes are used to provide runtime environments # on specific hosts. It allows us to define the runtime environment @@ -431,12 +450,16 @@ node_templates: relationships: - type: cloudify.relationships.contained_in target: manager_host + - type: cloudify.relationships.depends_on + target: selinux java_runtime: type: manager.nodes.JavaRuntime relationships: - type: cloudify.relationships.contained_in target: manager_host + - type: cloudify.relationships.depends_on + target: selinux ###################################################################### # These are the nodes comprising the Cloudify Manager's components @@ -446,6 +469,8 @@ node_templates: relationships: - type: cloudify.relationships.contained_in target: manager_host + - type: cloudify.relationships.depends_on + target: selinux elasticsearch: type: manager.nodes.Elasticsearch @@ -454,6 +479,8 @@ node_templates: target: manager_host - type: cloudify.relationships.depends_on target: java_runtime + - type: cloudify.relationships.depends_on + target: selinux logstash: type: manager.nodes.Logstash @@ -464,12 +491,16 @@ node_templates: target: java_runtime - type: logstash_to_elasticsearch target: elasticsearch + - type: cloudify.relationships.depends_on + target: selinux influxdb: type: manager.nodes.InfluxDB relationships: - type: cloudify.relationships.contained_in target: manager_host + - type: cloudify.relationships.depends_on + target: selinux nginx: type: manager.nodes.Nginx @@ -495,6 +526,8 @@ node_templates: target: rabbitmq - type: riemann_to_nginx target: nginx + - type: cloudify.relationships.depends_on + target: selinux rest_service: type: manager.nodes.RestService @@ -509,6 +542,8 @@ node_templates: target: elasticsearch - type: restservice_to_rabbitmq target: rabbitmq + - type: cloudify.relationships.depends_on + target: selinux mgmt_worker: type: manager.nodes.ManagementWorker @@ -521,6 +556,8 @@ node_templates: target: rabbitmq - type: mgmtworker_to_nginx target: nginx + - type: cloudify.relationships.depends_on + target: selinux amqp_influx: type: manager.nodes.AmqpInfluxBroker @@ -533,6 +570,8 @@ node_templates: target: rabbitmq - type: amqpinflux_to_influxdb target: influxdb + - type: cloudify.relationships.depends_on + target: selinux webui: type: manager.nodes.WebUI @@ -543,6 +582,8 @@ node_templates: target: rest_service - type: webui_to_influxdb target: influxdb + - type: cloudify.relationships.depends_on + target: selinux ###################################################################### # Enable this node if you want to have the CLI installed within diff --git a/new/types/manager-types.yaml b/new/types/manager-types.yaml index 1908d532e..cddaf6897 100644 --- a/new/types/manager-types.yaml +++ b/new/types/manager-types.yaml @@ -139,6 +139,21 @@ node_types: always_use_pty: true hide: running + manager.nodes.SELinux: + derived_from: cloudify.nodes.SoftwareComponent + properties: + selinux_enforcing: + type: boolean + default: { get_input: selinux_enforcing } + interfaces: + cloudify.interfaces.lifecycle: + create: + implementation: fabric.fabric_plugin.tasks.run_script + inputs: + script_path: + default: components/selinux/scripts/create.sh + fabric_env: *simple_fabric_env + manager.nodes.JavaRuntime: derived_from: cloudify.nodes.SoftwareComponent properties: @@ -157,6 +172,9 @@ node_types: manager.nodes.RabbitMQ: derived_from: cloudify.nodes.MessageBusServer properties: + selinux_enforcing: + type: boolean + default: { get_input: selinux_enforcing } erlang_rpm_source_url: description: Erlang RPM to install. type: string @@ -362,6 +380,9 @@ node_types: manager.nodes.Nginx: derived_from: cloudify.nodes.WebServer properties: + selinux_enforcing: + type: boolean + default: { get_input: selinux_enforcing } nginx_rpm_source_url: description: Nginx RPM Source URL type: string @@ -453,6 +474,9 @@ node_types: manager.nodes.RestService: derived_from: cloudify.nodes.ApplicationModule properties: + selinux_enforcing: + type: boolean + default: { get_input: selinux_enforcing } rest_service_rpm_source_url: type: string default: { get_input: rest_service_rpm_source_url } @@ -660,6 +684,9 @@ node_types: manager.nodes.WebUI: derived_from: cloudify.nodes.ApplicationModule properties: + selinux_enforcing: + type: boolean + default: { get_input: selinux_enforcing } webui_tar_source_url: description: Cloudify's WebUI Source URL type: string @@ -796,4 +823,4 @@ relationships: derived_from: cloudify.relationships.connected_to webui_to_restservice: - derived_from: cloudify.relationships.connected_to \ No newline at end of file + derived_from: cloudify.relationships.connected_to