Apply DISA STIG hardening on host operating systems

This section describes how to apply Defense Information Systems Agency (DISA) Security Technical Implementation Guide (STIG) hardening on host operating systems (OS) of MOSK and management clusters.

Mirantis offers a set of recipes automated using host OS configuration modules for MOSK (see Host operating system configuration) that help you configure cluster hosts according to the DISA STIG requirements so that benchmark tools report a higher pass rate than for the default MOSK host OS configuration.

MOSK does not apply these recipes out of the box. The provisioned Ubuntu host OS already follows a CIS-aligned baseline that is suitable for most deployments. DISA STIG adds DoD-oriented controls that depend on site-specific infrastructure, such as DoD-approved NTP servers and a remote audit log collector, and that can change host behavior in ways that are not appropriate for every cluster.

Use the following modules: disa_stig, auditd, linux_hard_limits, and ntp.

The configuration process is cluster-specific. Repeat the following steps for every MOSK and management cluster that must meet DISA STIG requirements, using the appropriate namespace and target machine names.

Warning

The LCM Ansible operations can overwrite settings applied by the disa_stig module. You must re-apply the disa_stig HostOSConfiguration object after every LCM operation. For details, see Retrigger a module configuration.

Prerequisites

  1. Obtain the required number of DoD-approved NTP servers.

  2. Prepare a remote auditd log collector host that must meet the following requirements:

    • A non-Ubuntu operating system. Reason: Ubuntu upstream auditd .deb packages omit network listener support (--with-listener=no), preventing remote log ingestion. Optionally, you can build custom auditd .deb packages, but Mirantis does not recommend this approach for production environments.

    • The auditd and audispd-plugins packages installed.

    • Daemon binding. Enable remote TCP ingestion by setting the following values in /etc/audit/auditd.conf on the remote server:

      tcp_listen_port = 60
      tcp_listen_queue = 5
      tcp_max_per_addr = 1
      tcp_client_max_idle = 0
      

      Note

      Adjust the tcp_listen_port value to match the port number in your network structure and firewall configuration.

  3. Prepare a log collector host for weekly auditd log offloads that must meet the following requirements:

    Note

    You can use the same host as the remote auditd log collector described in the previous step.

    • Ensure a functional OpenSSH daemon (sshd) is running and rsync is available on the system default $PATH.

    • Generate an SSH key pair and append the public key to the target user authorized_keys file on the receiver machine.

  4. For every target cluster and namespace, create a Kubernetes secret containing a private SSH key generated in the previous step under the weeklyLogUploadRsyncPrivateKey key. For example:

    kubectl create secret generic auditd-weekly-upload \
      --namespace default \
      --from-file=weeklyLogUploadRsyncPrivateKey=/home/ubuntu/.ssh/auditd_weekly_upload
    

Apply DISA STIG hardening

  1. Configure the following modules provided by Mirantis for the target cluster:

    For more details on the host OS configuration API and application of the modules, see Host OS configuration management workflow.

  2. Use the following example to create a HostOSConfiguration object in the YAML format for the target cluster. Adjust the cluster-specific parameters to match your deployment.

    Note

    If you already use a HostOSConfigurationModules object with the same moduleVersion, reuse and update that object instead of creating a new one.

    Example of the HostOSConfiguration manifest
    apiVersion: kaas.mirantis.com/v1alpha1
    kind: HostOSConfiguration
    metadata:
      name: auditd-mgmt
      namespace: default
    spec:
      configs:
      - module: auditd
        moduleVersion: 2.0.0
        secretValues:
          name: auditd-weekly-upload
          namespace: default
        values:
          enabled: true
          enabledAtBoot: true
          presetRules: all
          remoteUpload:
            enabled: true
            port: "60"
            server: <IP address of the DoD-approved NTP server>
          weeklyLogUpload:
            enabled: true
            rsyncRemoteUser: debian
            rsyncRemoteHost: <IP address of the auditd log collector host>
            rsyncDest: /home/debian/auditd_logs
      machineSelector:
        matchLabels:
          auditd-label: "true"
    ---
    apiVersion: kaas.mirantis.com/v1alpha1
    kind: HostOSConfiguration
    metadata:
      name: disa-stig-mgmt
      namespace: default
    spec:
      configs:
      - module: disa_stig
        moduleVersion: 1.0.0
        values:
          enabled: true
          disableUsbStorage: true
      machineSelector:
        matchLabels:
          disa-stig-label: "true"
    ---
    apiVersion: kaas.mirantis.com/v1alpha1
    kind: HostOSConfiguration
    metadata:
      name: lhl-mgmt
      namespace: default
    spec:
      configs:
      - module: linux_hard_limits
        moduleVersion: 1.0.0
        values:
          system:
            maxlogins: 10
      machineSelector:
        matchLabels:
          lhl-label: "true"
    ---
    apiVersion: kaas.mirantis.com/v1alpha1
    kind: HostOSConfiguration
    metadata:
      name: ntp-mgmt
      namespace: default
    spec:
      configs:
      - module: ntp
        moduleVersion: 1.1.0
        values:
          ntp_servers:
          - use.DoD.approved.ntp.server.0
          - use.DoD.approved.ntp.server.1
          - use.DoD.approved.ntp.server.2
          stigHardening: true
      machineSelector:
        matchLabels:
          ntp-label: "true"
    
  3. Apply the required module labels to the target machines. For example:

    kubectl -n <target_namespace> patch machine <target_machine> --type=merge -p '{"metadata":{"labels":{"disa-stig-label":"true"}}}'
    

    Mirantis recommends using a separate target label for each HostOSConfigurationModules object.

  4. Apply the configuration to the labeled machines:

    kubectl -n <target_namespace> create -f <hoc_name>.yaml
    
  5. Monitor the execution progress to ensure that all objects reach the Success status:

    kubectl -n <target_namespace> get hoc <auditd-hoc-name> <disa-stig-hoc-name> <linux-hard-limits-hoc-name> <ntp-hoc-name> \
    -o json | jq '.items[].status.machinesStates? // empty | .[].configStateItemsStatuses'
    
  6. Reboot the labeled cluster machines to finalize the changes. For the procedure, see Operations Guide: Graceful reboot.