diff --git a/doc/source/configuration/openbao.rst b/doc/source/configuration/openbao.rst index e83185019d..32dd871e7a 100644 --- a/doc/source/configuration/openbao.rst +++ b/doc/source/configuration/openbao.rst @@ -460,6 +460,8 @@ Enable the required TLS variables in kayobe and kolla kayobe overcloud host command run --command "systemctl restart kolla-nova_compute-container.service" --become --show-output -l compute +.. _openbao-pulp-tls: + Pulp TLS ======== diff --git a/doc/source/configuration/stackhpc-mixin-environments.rst b/doc/source/configuration/stackhpc-mixin-environments.rst index fa8950e8b7..bc8ed55900 100644 --- a/doc/source/configuration/stackhpc-mixin-environments.rst +++ b/doc/source/configuration/stackhpc-mixin-environments.rst @@ -33,3 +33,10 @@ baremetal-policy ---------------- .. include:: ../../../etc/kayobe/environments/baremetal-policy/README.rst + +.. _mixin-security: + +security +-------- + +.. include:: ../../../etc/kayobe/environments/security/README.rst diff --git a/etc/kayobe/environments/security/README.rst b/etc/kayobe/environments/security/README.rst new file mode 100644 index 0000000000..b753aea27a --- /dev/null +++ b/etc/kayobe/environments/security/README.rst @@ -0,0 +1,96 @@ +Security stack +~~~~~~~~~~~~~~ + +Mixin environment that applies a security baseline to new and existing +deployments. It bundles several security-related configuration modules into a +single, opinionated environment: + +* **Firewall** — firewalld is enabled on all host types (controllers, compute, + storage, monitoring, infrastructure VMs, seed, and seed hypervisor) using the + standardised StackHPC firewalld zones and rules. Kolla Ansible is configured + to open ports in firewalld for services on the public API network. See + :ref:`firewall` for details. + +* **CIS benchmark hardening** — the + ``stackhpc_enable_cis_benchmark_hardening_hook`` flag is set to ``true``, + which means the CIS hardening playbooks run automatically as part of + ``kayobe * host configure``. See :doc:`security-hardening` for details. + +* **Walled garden** — a Squid caching proxy is enabled on the seed, and + overcloud hosts are configured to route HTTP/HTTPS traffic through it. NTP is + sourced from the seed node. Network connectivity checks are redirected to + ``localhost`` so they pass in environments without external Internet access. + See :doc:`walled-garden` for background. + +* **Pulp TLS** — TLS is enabled for the local Pulp server. Certificates must be + provided before deploying Pulp. See `Prerequisites`_ below. + +Prerequisites +^^^^^^^^^^^^^ + +Before activating this environment, ensure the following requirements are met. + +Pulp TLS certificates +""""""""""""""""""""" + +TLS is enabled for Pulp. Certificates must be generated and configured before +deploying Pulp. See :ref:`openbao-pulp-tls` for the full procedure. + +Pulp stack user password +"""""""""""""""""""""""" + +The ``pulp_stack_password`` variable is mandatory and must be set before +running any Pulp-related playbooks. Define it in a secrets file or via the +environment (never commit it to source control): + +.. code-block:: yaml + :caption: $KAYOBE_CONFIG_PATH/$KAYOBE_ENVIRONMENT/secrets.yml + + pulp_stack_password: + +Firewall network zones +"""""""""""""""""""""" + +Every network in ``networks.yml`` must have a zone defined. The standard +approach is to assign the internal network zone to ``trusted`` and every other +zone to the name of the network. See the :ref:`firewall` documentation and +``etc/kayobe/environments/ci-multinode/networks.yml`` for a practical example. + +Consuming this environment +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Add the ``security`` environment to your ``.kayobe-environment`` file: + +.. code-block:: yaml + :caption: $KAYOBE_CONFIG_PATH/$KAYOBE_ENVIRONMENT/.kayobe-environment + + dependencies: + - security + +Apply host configuration to enable the firewall and CIS hardening across all +host types: + +.. code-block:: console + + kayobe seed hypervisor host configure -t network,firewall + kayobe seed host configure -t network,firewall + kayobe infra vm host configure -t network,firewall + kayobe overcloud host configure -t network,firewall + +.. note:: + + Applying the firewall for the first time carries a risk of locking yourself + out of hosts. Read the safety guidance in :ref:`firewall` — in particular + the sections on using the ``firewalld-watchdog.yml`` playbook and applying + controller changes one at a time — before proceeding. + +.. note:: + + CIS hardening may require a reboot to take full effect. The CIS roles will + warn you when this is necessary. + +Redeploy Pulp to pick up the TLS and credential changes: + +.. code-block:: console + + kayobe seed service deploy -t seed-deploy-containers -kt none diff --git a/etc/kayobe/environments/security/compute.yml b/etc/kayobe/environments/security/compute.yml new file mode 100644 index 0000000000..286c863045 --- /dev/null +++ b/etc/kayobe/environments/security/compute.yml @@ -0,0 +1,23 @@ +--- +############################################################################### +# Compute node firewalld configuration. + +# Whether to install and enable firewalld. +compute_firewalld_enabled: true + +# A list of zones to create. Each item is a dict containing a 'zone' item. +compute_firewalld_zones: "{{ stackhpc_firewalld_zones }}" + +# A firewalld zone to set as the default. Default is unset, in which case +# the default zone will not be changed. +# Predefined zones are listed here: +# https://firewalld.org/documentation/zone/predefined-zones.html +compute_firewalld_default_zone: trusted + +# A list of firewall rules to apply. Each item is a dict containing +# arguments to pass to the firewalld module. Arguments are omitted if not +# provided, with the following exceptions: +# - offline: true +# - permanent: true +# - state: enabled +compute_firewalld_rules: "{{ stackhpc_firewalld_rules }}" diff --git a/etc/kayobe/environments/security/controllers.yml b/etc/kayobe/environments/security/controllers.yml new file mode 100644 index 0000000000..1a02bddef2 --- /dev/null +++ b/etc/kayobe/environments/security/controllers.yml @@ -0,0 +1,23 @@ +--- +############################################################################### +# Controller node firewalld configuration. + +# Whether to install and enable firewalld. +controller_firewalld_enabled: true + +# A list of zones to create. Each item is a dict containing a 'zone' item. +controller_firewalld_zones: "{{ stackhpc_firewalld_zones }}" + +# A firewalld zone to set as the default. Default is unset, in which case +# the default zone will not be changed. +# Predefined zones are listed here: +# https://firewalld.org/documentation/zone/predefined-zones.html +controller_firewalld_default_zone: trusted + +# A list of firewall rules to apply. Each item is a dict containing +# arguments to pass to the firewalld module. Arguments are omitted if not +# provided, with the following exceptions: +# - offline: true +# - permanent: true +# - state: enabled +controller_firewalld_rules: "{{ stackhpc_firewalld_rules }}" diff --git a/etc/kayobe/environments/security/infra-vms.yml b/etc/kayobe/environments/security/infra-vms.yml new file mode 100644 index 0000000000..11f5ae3956 --- /dev/null +++ b/etc/kayobe/environments/security/infra-vms.yml @@ -0,0 +1,23 @@ +--- +############################################################################### +# Infrastructure VM node firewalld configuration + +# Whether to install and enable firewalld. +infra_vm_firewalld_enabled: true + +# A list of zones to create. Each item is a dict containing a 'zone' item. +infra_vm_firewalld_zones: "{{ stackhpc_firewalld_zones }}" + +# A firewalld zone to set as the default. Default is unset, in which case +# the default zone will not be changed. +# Predefined zones are listed here: +# https://firewalld.org/documentation/zone/predefined-zones.html +infra_vm_firewalld_default_zone: trusted + +# A list of firewall rules to apply. Each item is a dict containing +# arguments to pass to the firewalld module. Arguments are omitted if not +# provided, with the following exceptions: +# - offline: true +# - permanent: true +# - state: enabled +infra_vm_firewalld_rules: "{{ stackhpc_firewalld_rules }}" diff --git a/etc/kayobe/environments/security/inventory/group_vars/overcloud/proxy.yml b/etc/kayobe/environments/security/inventory/group_vars/overcloud/proxy.yml new file mode 100644 index 0000000000..bab048b5fd --- /dev/null +++ b/etc/kayobe/environments/security/inventory/group_vars/overcloud/proxy.yml @@ -0,0 +1,32 @@ +--- +# HTTP proxy URL (format: http(s)://[user:password@]proxy_name:port). By +# default no proxy is used. +http_proxy: "http://{{ lookup('vars', admin_oc_net_name ~ '_ips')[groups.seed.0] }}:3128" + +# HTTPS proxy URL (format: http(s)://[user:password@]proxy_name:port). By +# default no proxy is used. +https_proxy: "{{ http_proxy }}" + +# List of domains, hostnames, IP addresses and networks for which no proxy is +# used. Defaults to ["127.0.0.1", "localhost", "{{ ('http://' ~ +# docker_registry) | urlsplit('hostname') }}"] if docker_registry is set, or +# ["127.0.0.1", "localhost"] otherwise. This is configured only if either +# http_proxy or https_proxy is set. +no_proxy: + - "127.0.0.1" + - "localhost" + - "{{ ('http://' ~ docker_registry) | urlsplit('hostname') if docker_registry else '' }}" + - "{{ lookup('vars', admin_oc_net_name ~ '_ips')[groups.seed.0] }}" + - "{{ lookup('vars', admin_oc_net_name ~ '_ips')[inventory_hostname] }}" + - "{{ lookup('vars', internal_net_name ~ '_ips')[groups.controllers.0] }}" + - "{{ kolla_external_fqdn }}" + - "{{ kolla_internal_fqdn }}" + +# PyPI proxy URL (format: http(s)://[user:password@]proxy_name:port) +pip_proxy: "{{ https_proxy }}" + +# Apt proxy URL for HTTP. Default is empty (no proxy). +apt_proxy_http: "{{ http_proxy }}" + +# Apt proxy URL for HTTPS. Default is {{ apt_proxy_http }}. +apt_proxy_https: "{{ https_proxy }}" diff --git a/etc/kayobe/environments/security/inventory/group_vars/overcloud/time.yml b/etc/kayobe/environments/security/inventory/group_vars/overcloud/time.yml new file mode 100644 index 0000000000..dec9761369 --- /dev/null +++ b/etc/kayobe/environments/security/inventory/group_vars/overcloud/time.yml @@ -0,0 +1,7 @@ +--- +# NTP services for overcloud hosts +# During early initialisation we use the seed Node +# Following deployment we include the OpenStack VIP + +chrony_ntp_servers: + - server: "{{ lookup('vars', admin_oc_net_name ~ '_ips')[groups.seed.0] }}" diff --git a/etc/kayobe/environments/security/inventory/hosts b/etc/kayobe/environments/security/inventory/hosts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/etc/kayobe/environments/security/kolla/globals.yml b/etc/kayobe/environments/security/kolla/globals.yml new file mode 100644 index 0000000000..ae457b6a60 --- /dev/null +++ b/etc/kayobe/environments/security/kolla/globals.yml @@ -0,0 +1,3 @@ +--- +enable_external_api_firewalld: true +external_api_firewalld_zone: "{{ public_net_name | net_zone }}" diff --git a/etc/kayobe/environments/security/monitoring.yml b/etc/kayobe/environments/security/monitoring.yml new file mode 100644 index 0000000000..7057bb8fe9 --- /dev/null +++ b/etc/kayobe/environments/security/monitoring.yml @@ -0,0 +1,23 @@ +--- +############################################################################### +# Monitoring node firewalld configuration. + +# Whether to install and enable firewalld. +monitoring_firewalld_enabled: true + +# A list of zones to create. Each item is a dict containing a 'zone' item. +monitoring_firewalld_zones: "{{ stackhpc_firewalld_zones }}" + +# A firewalld zone to set as the default. Default is unset, in which case +# the default zone will not be changed. +# Predefined zones are listed here: +# https://firewalld.org/documentation/zone/predefined-zones.html +monitoring_firewalld_default_zone: trusted + +# A list of firewall rules to apply. Each item is a dict containing +# arguments to pass to the firewalld module. Arguments are omitted if not +# provided, with the following exceptions: +# - offline: true +# - permanent: true +# - state: enabled +monitoring_firewalld_rules: "{{ stackhpc_firewalld_rules }}" diff --git a/etc/kayobe/environments/security/networks.yml b/etc/kayobe/environments/security/networks.yml new file mode 100644 index 0000000000..77f91c5d02 --- /dev/null +++ b/etc/kayobe/environments/security/networks.yml @@ -0,0 +1,11 @@ +--- +# Kayobe network configuration. + +############################################################################### +# Network connectivity check configuration. + +# External IP address to check. Default is 8.8.8.8. +nc_external_ip: 127.0.0.1 + +# External hostname to check. Default is google.com. +nc_external_hostname: localhost diff --git a/etc/kayobe/environments/security/pulp.yml b/etc/kayobe/environments/security/pulp.yml new file mode 100644 index 0000000000..70e071d3d8 --- /dev/null +++ b/etc/kayobe/environments/security/pulp.yml @@ -0,0 +1,19 @@ +--- +############################################################################### +# Local Pulp server configuration + +# Whether to enable TLS for Pulp. +pulp_enable_tls: true + +# Path to a TLS certificate to use when TLS is enabled. +pulp_cert_path: "{{ kayobe_env_config_path ~ '/pulp/certificates/pulp.crt' if pulp_enable_tls | bool else '' }}" + +# Path to a TLS key to use when TLS is enabled. +pulp_key_path: "{{ kayobe_env_config_path ~ '/pulp/certificates/pulp.key' if pulp_enable_tls | bool else '' }}" + +############################################################################### +# Local Pulp access credentials + +# Credentials for non-admin user within Pulp. +pulp_stack_username: stack +pulp_stack_password: "{{ notdefined | mandatory(msg='Please set a password for the stack pulp user') }}" diff --git a/etc/kayobe/environments/security/seed-hypervisor.yml b/etc/kayobe/environments/security/seed-hypervisor.yml new file mode 100644 index 0000000000..4aa9b534b7 --- /dev/null +++ b/etc/kayobe/environments/security/seed-hypervisor.yml @@ -0,0 +1,33 @@ +--- +############################################################################### +# Seed hypervisor node firewalld configuration. + +# Whether to install and enable firewalld. +seed_hypervisor_firewalld_enabled: true + +# A list of zones to create. Each item is a dict containing a 'zone' item. +seed_hypervisor_firewalld_zones: "{{ stackhpc_firewalld_zones }}" + +# A firewalld zone to set as the default. Default is unset, in which case +# the default zone will not be changed. +# Predefined zones are listed here: +# https://firewalld.org/documentation/zone/predefined-zones.html +seed_hypervisor_firewalld_default_zone: trusted + +# A list of firewall rules to apply. Each item is a dict containing +# arguments to pass to the firewalld module. Arguments are omitted if not +# provided, with the following exceptions: +# - offline: true +# - permanent: true +# - state: enabled +seed_hypervisor_firewalld_rules: "{{ stackhpc_firewalld_rules }}" + +############################################################################### +# Seed hypervisor sysctl configuration. + +# Dict of sysctl parameters to set. +seed_hypervisor_sysctl_parameters: + # By default this is 1, which causes layer 2 traffic flowing through Linux + # bridges to pass through iptables. This blocks traffic from VMs (seed, wazuh) to + # the Internet. + net.bridge.bridge-nf-call-iptables: 0 diff --git a/etc/kayobe/environments/security/seed.yml b/etc/kayobe/environments/security/seed.yml new file mode 100644 index 0000000000..939ded7d9b --- /dev/null +++ b/etc/kayobe/environments/security/seed.yml @@ -0,0 +1,30 @@ +--- +############################################################################### +# Seed node firewalld configuration. + +# Whether to install and enable firewalld. +seed_firewalld_enabled: true + +# A list of zones to create. Each item is a dict containing a 'zone' item. +seed_firewalld_zones: "{{ stackhpc_firewalld_zones }}" + +# A firewalld zone to set as the default. Default is unset, in which case +# the default zone will not be changed. +# Predefined zones are listed here: +# https://firewalld.org/documentation/zone/predefined-zones.html +seed_firewalld_default_zone: trusted + +# A list of firewall rules to apply. Each item is a dict containing +# arguments to pass to the firewalld module. Arguments are omitted if not +# provided, with the following exceptions: +# - offline: true +# - permanent: true +# - state: enabled +seed_firewalld_rules: "{{ stackhpc_firewalld_rules }}" + +############################################################################### +# Seed node additional containers configuration + +# Seed container running a Squid caching proxy. This can be used to proxy +# HTTP(S) requests from control plane hosts. +seed_squid_container_enabled: true diff --git a/etc/kayobe/environments/security/stackhpc.yml b/etc/kayobe/environments/security/stackhpc.yml new file mode 100644 index 0000000000..0b612b6a04 --- /dev/null +++ b/etc/kayobe/environments/security/stackhpc.yml @@ -0,0 +1,6 @@ +--- +############################################################################### +# Feature flags + +# Whether or not to run CIS benchmark hardening playbooks. Default is false. +stackhpc_enable_cis_benchmark_hardening_hook: true diff --git a/etc/kayobe/environments/security/storage.yml b/etc/kayobe/environments/security/storage.yml new file mode 100644 index 0000000000..63c94d56a2 --- /dev/null +++ b/etc/kayobe/environments/security/storage.yml @@ -0,0 +1,23 @@ +--- +############################################################################### +# Storage node firewalld configuration. + +# Whether to install and enable firewalld. +storage_firewalld_enabled: true + +# A list of zones to create. Each item is a dict containing a 'zone' item. +storage_firewalld_zones: "{{ stackhpc_firewalld_zones }}" + +# A firewalld zone to set as the default. Default is unset, in which case +# the default zone will not be changed. +# Predefined zones are listed here: +# https://firewalld.org/documentation/zone/predefined-zones.html +storage_firewalld_default_zone: trusted + +# A list of firewall rules to apply. Each item is a dict containing +# arguments to pass to the firewalld module. Arguments are omitted if not +# provided, with the following exceptions: +# - offline: true +# - permanent: true +# - state: enabled +storage_firewalld_rules: "{{ stackhpc_firewalld_rules }}" diff --git a/releasenotes/notes/add-security-mixin-9ca2c2b29364b427.yaml b/releasenotes/notes/add-security-mixin-9ca2c2b29364b427.yaml new file mode 100644 index 0000000000..e553ba02c1 --- /dev/null +++ b/releasenotes/notes/add-security-mixin-9ca2c2b29364b427.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Introduce the security enviroment mixin which aims to provide an easy + approach for bringing a deployment inline with security baseline and + best practices.