file
First seen , last seen .
mission_portal.cf (5f86950afe86cd6c4e840cae5c404dbd829b0e63456cad9ad060506f9ca477cd)
See also: mission_portal.cf (filename)
The file mission_portal.cf (23.4 kB), identified by its SHA-256 checksum. This file is found on 100 hosts in your infrastructure, at 3 different paths.
23.4 kB, 542 lines, CFEngine policy:
bundle agent cfe_internal_enterprise_mission_portal { meta: "description" string => "Manage mission portal configuration"; classes: "mission_portal_http2_enabled" expression => and( fileexists("$(sys.workdir)/httpd/php/sbin/php-fpm"), fileexists("$(sys.workdir)/httpd/modules/mod_http2.so") ), scope => "namespace", # so it is visible in datastate() used in httpd.conf template rendering in bundle cfe_internal_enterprise_mission_portal_apache comment => "If php-fpm and mod_http2.so are present then http2 is enabled and we use this class in httpd.conf to configure accordingly."; vars: policy_server.enterprise_edition.mission_portal_http2_enabled:: "cpu_info_source" string => "/proc/cpuinfo"; "cpu_cores_number" int => int( execresult("grep -c ^processor $(cpu_info_source) 2>/dev/null", "useshell")), if => fileexists( $(cpu_info_source) ); "mem_info_source" string => "/proc/meminfo"; "mem_total_kb" int => int( execresult("grep ^MemTotal $(mem_info_source) | awk '{print $2}' 2>/dev/null", "useshell") ), if => fileexists( $(mem_info_source) ); "php_fpm_www_pool_min_spare_servers_calculated" int => int( ifelse( isvariable("cpu_cores_number"), eval("$(cpu_cores_number) * 2"), # min spare servers are cpu cores number * 2 "8" # fallback )); "php_fpm_www_pool_max_spare_servers_calculated" int => int( ifelse( isvariable("cpu_cores_number"), eval("$(cpu_cores_number) * 4"), # max spare servers are cpu cores number * 4 "16" # fallback )); #start servers between min & max spare "php_fpm_www_pool_start_servers_calculated" int => int( eval( "($(php_fpm_www_pool_min_spare_servers_calculated) + $(php_fpm_www_pool_max_spare_servers_calculated)) / 2") ); "fpm_children_average_memory_kb" int => "25600"; # average memory taken by one fpm process 25MB * 1024 "php_fpm_www_pool_max_children_calculated" int => int( ifelse( isvariable("mem_total_kb"), eval("$(mem_total_kb) * 0.6 / $(fpm_children_average_memory_kb)"), # get only 60% of total memory and devide by avarage memory taken by one fpm process "60" # fallback )); "php_fpm_pid_file" string => "$(sys.workdir)/httpd/php-fpm.pid"; "php_fpm_www_pool_max_children" string => ifelse( isvariable("default:def.php_fpm_www_pool_max_children"), "$(default:def.php_fpm_www_pool_max_children)", "${php_fpm_www_pool_max_children_calculated}"); "php_fpm_www_pool_start_servers" string => ifelse( isvariable("default:def.php_fpm_www_pool_start_servers"), "$(default:def.php_fpm_www_pool_start_servers)", "$(php_fpm_www_pool_start_servers_calculated)"); "php_fpm_www_pool_min_spare_servers" string => ifelse( isvariable("default:def.php_fpm_www_pool_min_spare_servers"), "$(default:def.php_fpm_www_pool_min_spare_servers)", "$(php_fpm_www_pool_min_spare_servers_calculated)"); "php_fpm_www_pool_max_spare_servers" string => ifelse( isvariable("default:def.php_fpm_www_pool_max_spare_servers"), "$(default:def.php_fpm_www_pool_max_spare_servers)", "$(php_fpm_www_pool_max_spare_servers_calculated)"); "php_fpm_state" data => mergedata( '{"vars": { "sys": { "workdir": "${default:sys.workdir}" } } }', '{ "max_children":"${php_fpm_www_pool_max_children}", "start_servers":"${php_fpm_www_pool_start_servers}", "min_spare_servers":"${php_fpm_www_pool_min_spare_servers}", "max_spare_servers":"${php_fpm_www_pool_max_spare_servers}" }'); files: # http -> https redirection moved from Apache to PHP # Here the flag files are managed so that PHP will know what to do cfe_enterprise_disable_http_redirect_to_https:: "/opt/cfengine/flags/." perms => mog("750", "root", "cfapache"), create => "true"; "/opt/cfengine/flags/http_redirect_to_https.disabled" -> { "ENT-11481" } perms => mog("660", "root", "cfapache"), create => "true"; !cfe_enterprise_disable_http_redirect_to_https:: "/opt/cfengine/flags/http_redirect_to_https.disabled" -> { "ENT-11481" } delete => tidy; reports: DEBUG:: "Using variable default:def.php_fpm_www_pool_max_children: ${default:def.php_fpm_www_pool_max_children} instead of built-in default" if => isvariable("default:def.php_fpm_www_pool_max_children"); "Using variable default:def.php_fpm_www_pool_start_servers: ${default:def.php_fpm_www_pool_start_servers} instead of built-in default" if => isvariable("default:def.php_fpm_www_pool_start_servers"); "Using variable default:def.php_fpm_www_pool_min_spare_servers: ${default:def.php_fpm_www_pool_min_spare_servers} instead of built-in default" if => isvariable("default:def.php_fpm_www_pool_min_spare_servers"); "Using variable default:def.php_fpm_www_pool_max_spare_servers: ${default:def.php_fpm_www_pool_max_spare_servers} instead of built-in default" if => isvariable("default:def.php_fpm_www_pool_max_spare_servers"); methods: policy_server:: "Apache Configuration" -> { "CFEngine Enterprise", "Mission Portal" } usebundle => cfe_internal_enterprise_mission_portal_apache; "Apache Service" -> { "CFEngine Enterprise", "Mission Portal" } usebundle => cfe_internal_webserver("on"), handle => "cfe_internal_management_web_server", comment => "Manage Apache Web server (on/off)"; "Port Configuration" -> { "CFEngine Enterprise", "Mission Portal" } usebundle => update_cli_rest_server_url_config, handle => "cfe_internal_management_update_cli_rest_server_url_config", comment => "Update the REST server URL port in the Mission Portal when cfe_internal_hub_vars.https_port is changed"; policy_server.mission_portal_http2_enabled:: "PHP FastCGI process manager" usebundle => service_config( "cf-php-fpm", "$(this.promise_dirname)/templates/php-fpm.conf.mustache", "$(sys.workdir)/httpd/php/etc/php-fpm.conf", "$(sys.workdir)/httpd/php/sbin/php-fpm -t --fpm-config ", @(php_fpm_state), "$(php_fpm_pid_file)" ); services: policy_server.mission_portal_http2_enabled:: "cf-php-fpm" service_policy => "start"; } bundle agent apachectl_patched_for_upgrade # @brief Ensure that apacehctl is patched so that it is able to re-start services # # @description This bundle addresses an issue where upgrades fail trying to stop # httpd. Versions prior to 3.20.0, 3.18.2, and 3.15.6 need to have apachectl # patched to make it wait for processes to shut down before exiting before # upgrading binaries to 3.20.0, 3.18.2, or 3.15.6. CFEngine packages for # versions after 3.20.0, 3.18.2, 3.15.6 ship with this patched apachectl which # should make this bundle a no-op. # # TODO Redact when 3.21.0 is the oldest supported version # # NOTE The rendering of apachectl is done slightly differently for different # versions of CFEngine. We need to maintain support for 3.15.x and many macros # were not available at 3.15.0, so we use classes instead of macros. # # Versions prior to CFEngine 3.20.0 do not create files by default when managed # by a template, if the file is absent but it's presence was desired the use of # create => "true" or some other machinery is necessary. # # When 3.15.0 (Currently oldest supported version) was released, 3.10.0 was supported. { vars: "considered_versions" slist => { "cfengine_3_10", "cfengine_3_11", "cfengine_3_12", "cfengine_3_13", "cfengine_3_14", "cfengine_3_15", "cfengine_3_16", "cfengine_3_17", "cfengine_3_18" }; classes: "_running_cfengine_version_where_templated_files_automatically_created" or => { @(considered_versions) }; "_running_cfengine_version_where_templated_files_NOT_automatically_created" not => or( @(considered_versions) ); files: _running_cfengine_version_where_templated_files_automatically_created:: "$(sys.workdir)/httpd/bin/apachectl" edit_template => "$(this.promise_dirname)/templates/apachectl.mustache", handle => "apachectl_content_pre_create_default_templated_files", template_method => "mustache", template_data => parsejson( '{ "cfengine_enterprise_mission_portal_httpd_dir": "$(sys.workdir)/httpd" }'), classes => results("bundle", "apachectl_file"); _running_cfengine_version_where_templated_files_NOT_automatically_created:: "$(sys.workdir)/httpd/bin/apachectl" create => "true", edit_template => "$(this.promise_dirname)/templates/apachectl.mustache", handle => "apachectl_content_post_create_default_templated_files", template_method => "mustache", template_data => parsejson( '{ "cfengine_enterprise_mission_portal_httpd_dir": "$(sys.workdir)/httpd" }'), classes => results("bundle", "apachectl_file"); cfengine:: "$(sys.workdir)/httpd/bin/apachectl" handle => "apachectl_perms", perms => mog( "0755", "root", "root" ); commands: # This only runs if apachectl touched (repaired) and restorecon path exists apachectl_file_repaired.default:_stdlib_path_exists_restorecon:: "$(default:paths.restorecon) $(sys.workdir)/httpd/bin/apachectl" comment => "Ensure the templated apachectl has the correct SELinux context."; } bundle agent cfe_internal_enterprise_mission_portal_apache # @brief Manage Apache instance that runs Mission Portal { vars: policy_server.enterprise_edition:: "template" string => "$(this.promise_dirname)/templates/httpd.conf.mustache", comment => "The template used to render the apache config file."; "config" string => "$(sys.workdir)/httpd/conf/httpd.conf", comment => "This is the location of the apache config file."; "staged_config" string => "$(config).staged", comment => "This is the temporary file we will render the config and valid against before deploying to the final $(config) location."; # TODO: Consider collecting the classes and variables used based on a tag # to prepare a smaller subset of data "data" data => datastate(); methods: "apachectl patched for resilient stop " -> { "ENT-8823" } usebundle => apachectl_patched_for_upgrade; "Stage Apache Config" usebundle => file_make_mustache( $(staged_config), $(template), @(data) ), comment => "We render the config to a staging location so that it can be validated before deploying the final apache config so that we don't end up with a broken service."; "Manage Final Apache Config" usebundle => mission_portal_apache_from_stage( $(config), $(staged_config) ); reports: DEBUG|DEBUG_cfe_internal_enterprise_mission_portal_apache:: "DEBUG $(this.bundle): Should stage '$(staged_config)' from '$(template)'."; classes: (policy_server|am_policy_hub).enterprise_edition:: "mission_portal_index_php_redirect_enabled" expression => isgreaterthan(countlinesmatching(".*config\['index_page'\] = \"\".*", "$(cfe_internal_hub_vars.docroot)/application/config/config.php"), 0), comment => "We need to know if index_page config in Mission Portal is empty to enable redirect from /index.php/path to /path in httpd.conf"; } bundle agent mission_portal_apache_from_stage(config, staged_config) # @brief Make sure the live Apache config is based on a staged config that has # been validated. # @param config Path to the live config # @param staged_config Path to the staged configuration # # **Example:** # # ```cf3 # bundle agent example # { # vars: # # "config" # string => "$(sys.workdir)/httpd/conf/httpd.conf", # comment => "This is the location of the apache config file."; # # "staged_config" # string => "$(config).staged", # comment => "This is the temporary file we will render the config and # valid against before deploying to the final $(config) # location."; # # methods: # # "Manage Final Apache Config" # usebundle => mission_portal_apache_from_stage( $(config), $(staged_config) ); # } #``` { meta: "description" string => "Configure apache based on successfully staged config"; classes: "systemd_supervised" expression => returnszero("$(paths.systemctl) -q is-active cf-apache > /dev/null 2>&1", "useshell"), if => fileexists( $(paths.systemctl) ); "httpd_config_validated" expression => strcmp("$(validate_result[exit_code])", "0"); "httpd_config_error" expression => not(strcmp("$(validate_result[exit_code])", "0")); vars: "validate_config" string => "$(sys.workdir)/httpd/bin/httpd -t -f $(staged_config)"; "validate_result" data => execresult_as_data("$(validate_config)", "useshell", "both"); # The location of the apache pid file moved from httpd/logs/httpd.pid to # httpd/httpd.pid in 3.15.5, 3.18.1 and, 3.19.0 "httpd_pid_file" -> { "ENT-7966" } string => ifelse( classmatch( "cfengine_3_1[0-4]" ), "$(sys.workdir)/httpd/logs/httpd.pid", classmatch( "cfengine_3_15_[0-4]" ), "$(sys.workdir)/httpd/logs/httpd.pid", "cfengine_3_18_0", "$(sys.workdir)/httpd/logs/httpd.pid", "$(sys.workdir)/httpd/httpd.pid" ); files: "$(config)" create => "true", comment => "Without an apache config, Mission Mortal and Enterprise API services will not work"; "$(config)" -> { "ENT-9686" } copy_from => local_dcp( $(staged_config) ), handle => "cfapache_httpd_conf_from_staged", if => and( or( "apache_stop_after_new_staged_config_repaired", not( fileexists( "$(httpd_pid_file)" ) ), isnewerthan( $(config), $(staged_config) ) ), "httpd_config_validated"), classes => results("bundle", "mission_portal_apache_config"), comment => "We make sure that the deployed config is a copy of the staged config if the staged config passes a syntax check. We redirect the output to keep policy runs clean and not generate lots of unnecessary email."; # Note: RPM package spec must align or the file will come up in rpm verification "$(config)" -> { "ENT-11096" } handle => "cfengine_mp_apache_config_ownership_perms", perms => mog( "400", "root", "root"); commands: !systemd_supervised:: "LD_LIBRARY_PATH=$(sys.workdir)/lib:$LD_LIBRARY_PATH $(sys.workdir)/httpd/bin/apachectl" args => "stop", if => and( "httpd_config_validated", isnewerthan( $(staged_config), $(config) ), fileexists( "$(httpd_pid_file)" ) ), contain => in_shell, classes => results( "bundle", "apache_stop_after_new_staged_config" ), comment => concat( "We have to stop apache before trying to start with a", "new config, or the new config could prevent apache from stopping."); "LD_LIBRARY_PATH=$(sys.workdir)/lib:$LD_LIBRARY_PATH $(sys.workdir)/httpd/bin/apachectl" args => "start", if => and( "mission_portal_apache_config_repaired", "apache_stop_after_new_staged_config_repaired"), contain => in_shell, comment => concat( "We start apache after the new valid config is in ", "place only if we have stopped apache already."); "LD_LIBRARY_PATH=$(sys.workdir)/lib:$LD_LIBRARY_PATH $(sys.workdir)/httpd/bin/apachectl" -> { "ENT-9686" } args => "graceful", if => and( "mission_portal_apache_config_repaired", not( "apache_stop_after_new_staged_config_repaired" ) ), contain => in_shell, comment => "We restart apache after the new valid config is in place"; services: systemd_supervised:: "cf-apache" service_policy => "stop", if => and( "httpd_config_validated", isnewerthan( $(staged_config), $(config) ) ), classes => results( "bundle", "apache_stop_after_new_staged_config" ), comment => concat( "We have to stop apache before trying to start with a", "new config, or the new config could prevent apache from stopping."); "cf-apache" service_policy => "start", if => and( "mission_portal_apache_config_repaired", "apache_stop_after_new_staged_config_repaired"), comment => concat( "We start apache after the new valid config is in ", "place only if we have stopped apache already."); "cf-apache" -> { "ENT-9686" } service_policy => "restart", if => and( "mission_portal_apache_config_repaired", not( "apache_stop_after_new_staged_config_repaired" ) ), comment => "We restart apache after the new valid config is in place"; reports: httpd_config_error:: "'$(staged_config)' failed to validate: $(validate_result[output])"; DEBUG|DEBUG_mission_portal_apache_from_stage:: "DEBUG $(this.bundle): '$(config)' should be a copy of '$(staged_config)' because it validates with '$(validate_config)'" if => "httpd_config_validated"; "DEBUG $(this.bundle): '$(config)' should *not* be a copy of '$(staged_config)' because it failed to validate with '$(validate_config)'" if => not( "httpd_config_validated" ); } ################################################################## # # cfe_internal_webserver(on/off) # ################################################################## bundle agent cfe_internal_webserver(state) { meta: "description" string => "Manage the Mission Portal webserver state"; classes: "on" expression => strcmp("$(state)","on"), comment => "Check if a keyword \"on\" is inputs", handle => "cfe_internal_webserver_classes_on"; "off" expression => strcmp("$(state)","off"), comment => "Check if a keyword \"off\" is inputs", handle => "cfe_internal_webserver_classes_off"; # processes: am_policy_hub.on:: ".*$(sys.workdir)/httpd/bin/httpd.*" restart_class => "start_cfe_httpd", comment => "Check if CFE httpd process exists or not", handle => "cfe_internal_webserver_processes_start_cfe_httpd"; # commands: start_cfe_httpd:: "LD_LIBRARY_PATH=$(sys.workdir)/lib:$LD_LIBRARY_PATH $(sys.workdir)/httpd/bin/apachectl start" comment => "Start CFE httpd process if not exist", classes => kept_successful_command, handle => "cfe_internal_webserver_commands_start_cfe_httpd", contain => in_shell; } bundle agent cfe_enterprise_selfsigned_cert # @brief Generate a self signed certificate for Mission Portal # # By default this bundle will only regenerate a certificate if one of the # necessary files is missing. To force certificate regeneration run with the # class '_cfe_enterprise_selfsigned_cert_regenerate_certificate' defined. { meta: "description" string => "Generate a self signed SSL certificate for secure hub communications."; vars: policy_server:: "SSLCertificateFile" string => "$(cfe_internal_hub_vars.SSLCertificateFile)"; "SSLCertificateKeyFile" string => "$(cfe_internal_hub_vars.SSLCertificateKeyFile)"; "SSLCertificatePasswdKeyFile" string => "$(cfe_internal_hub_vars.SSLCertificatePasswdKeyFile)"; "SSLCertificateKeySize" string => "$(cfe_internal_hub_vars.SSLCertificateKeySize)"; "SSLCertificateSigningRequest" string => "$(cfe_internal_hub_vars.SSLCertificateSigningRequest)"; "SSLCnf" string => "$(cfe_internal_hub_vars.SSLCnf)"; "SSLCertificateDaysValid" string => "$(cfe_internal_hub_vars.SSLCertificateDaysValid)"; "SSLCertificateFileSymlink" string => "$(sys.workdir)/ssl/cert.pem"; "openssl" string => "$(sys.workdir)/bin/openssl"; "_generated_files" slist => { $(SSLCertificateFile), $(SSLCertificateKeyFile), $(SSLCertificatePasswdKeyFile), $(SSLCertificateSigningRequest), }; classes: "_cfe_enterprise_selfsigned_cert_regenerate_certificate" not => filesexist( @(_generated_files) ), comment => "We only want to automatically regenerate the certificate if one of the files does not exist."; commands: policy_server._cfe_enterprise_selfsigned_cert_regenerate_certificate:: "$(openssl)" args => "genrsa -passout pass:x -out $(SSLCertificatePasswdKeyFile) $(SSLCertificateKeySize)"; # Strip password from key in ${CFENGINE_MP_PASS_KEY} and produce ${CFENGINE_MP_KEY} "$(openssl)" args => "rsa -passin pass:x -in $(SSLCertificatePasswdKeyFile) -out $(SSLCertificateKeyFile)"; # Generate a CSR in ${CFENGINE_MP_CSR} with key ${CFENGINE_MP_KEY} "$(openssl)" args => 'req -utf8 -sha256 -nodes -new -subj "/CN=$(sys.fqhost)" -key $(SSLCertificateKeyFile) -out $(SSLCertificateSigningRequest) -config $(SSLCnf)'; # Generate CRT "$(openssl)" args => "x509 -req -days $(SSLCertificateDaysValid) -in $(SSLCertificateSigningRequest) -signkey $(SSLCertificateKeyFile) -out $(SSLCertificateFile)"; files: "$(SSLCertificateFile)" -> { "jira:ENT-760" } perms => mog("644", "root", "root"), comment => "The SSL Certificate File needs to be readable so that it can be read by other services like Mission Portal."; "$(SSLCertificateKeyFile)" perms => mog("600", "root", "root"), comment => "The SSL Certificate Key should only be readable by root."; "$(SSLCertificatePasswdKeyFile)" perms => mog("600", "root", "root"), comment => "The SSL Certificate Key should only be readable by root."; "$(SSLCertificateFileSymlink)" -> { "jira:ENT-760" } link_from => ln_s( $(SSLCertificateFile) ), move_obstructions => "true", comment => "Mission Portal reads the certificate from this stable location, so it must always point to the current certificate."; reports: DEBUG|DEBUG_cfe_enterprise_selfsigned_cert:: "DEBUG $(this.bundle): Certificate Generation Requested" if => "_cfe_enterprise_selfsigned_cert_regenerate_certificate"; "DEBUG $(this.bundle): No Certificate Generation Requested" if => "!_cfe_enterprise_selfsigned_cert_regenerate_certificate"; }