Guide to the Secure Configuration of Red Hat OpenShift Container Platform 3

with profile Open Computing Information Security Profile for OpenShift Master Node
This baseline was inspired by the Center for Internet Security (CIS) Kubernetes Benchmark, v1.2.0 - 01-31-2017. For the ComplianceAsCode project to remain in compliance with CIS' terms and conditions, specifically Restrictions(8), note there is no representation or claim that the OpenCIS profile will ensure a system is in compliance or consistency with the CIS baseline.
This guide presents a catalog of security-relevant configuration settings for Red Hat OpenShift Container Platform 3. It is a rendering of content structured in the eXtensible Configuration Checklist Description Format (XCCDF) in order to support security automation. The SCAP content is is available in the scap-security-guide package which is developed at https://www.open-scap.org/security-policies/scap-security-guide.

Providing system administrators with such guidance informs them how to securely configure systems under their control in a variety of network roles. Policy makers and baseline creators can use this catalog of settings, with its associated references to higher-level security control catalogs, in order to assist them in security baseline creation. This guide is a catalog, not a checklist, and satisfaction of every item is not likely to be possible or sensible in many operational scenarios. However, the XCCDF format enables granular selection and adjustment of settings, and their association with OVAL and OCIL content provides an automated checking capability. Transformations of this document, and its associated automated checking content, are capable of providing baselines that meet a diverse set of policy objectives. Some example XCCDF Profiles, which are selections of items that form checklists and can be used as baselines, are available with this guide. They can be processed, in an automated fashion, with tools that support the Security Content Automation Protocol (SCAP). The NIST National Checklist Program (NCP), which provides required settings for the United States Government, is one example of a baseline created from this guidance.
Do not attempt to implement any of the settings in this guide without first testing them in a non-operational environment. The creators of this guidance assume no responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic.
Profile TitleOpen Computing Information Security Profile for OpenShift Master Node
Profile IDxccdf_org.ssgproject.content_profile_opencis-ocp-master

Revision History

Current version: 0.1.42

  • draft (as of 2018-12-11)

Platforms

  • cpe:/a:redhat:openshift_container_platform:3.10
  • cpe:/a:redhat:openshift_container_platform:3.11

Table of Contents

  1. OpenShift Settings
    1. OpenShift etcd Settings
    2. Kubernetes Kubelet Settings
    3. OpenShift Controller Settings
    4. OpenShift - Kubernetes - Scheduler Settings
    5. Permissions
    6. OpenShift API Server

Checklist

contains 109 rules

OpenShift Settings   [ref]group

Contains rules that check correct OpenShift settings.

contains 109 rules

OpenShift etcd Settings   [ref]group

Contains rules that check correct OpenShift etcd settings.

contains 11 rules

Configure etcd Log Storage   [ref]rule

To ensure the etcd service is storing logs separate from data, set ETCD_WAL_DIR to /var/lib/etcd/member/wal in /etc/etcd/etcd.conf on the master node:

ETCD_WAL_DIR=/var/lib/etcd/member/wal

Rationale:

etcd log files should be stored in a separate location from the etcd data. This not only ensures data integrity but also helps to prevent IO degradation.

Severity:  medium

References:  1.5.7

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_WAL_DIR=' '/var/lib/etcd/member/wal' '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Configure etcd Log Storage"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_WAL_DIR='
    line: "ETCD_WAL_DIR=/var/lib/etcd/member/wal"
    create: yes
  tags:
    - etcd_wal_dir
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Enable The Client Certificate Authentication   [ref]rule

To ensure the etcd service is serving TLS to clients, edit the etcd configuration file /etc/etcd/etcd.conf on the master node and set ETCD_CLIENT_CERT_AUTH to true.

ETCD_CLIENT_CERT_AUTH=true

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  1.5.2

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_CLIENT_CERT_AUTH=' 'true' '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Enable The Client Certificate Authentication"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_CLIENT_CERT_AUTH='
    line: "ETCD_CLIENT_CERT_AUTH=true"
    create: yes
  tags:
    - etcd_client_cert_auth
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Ensure That The etcd Peer Key File Is Correctly Set   [ref]rule

To ensure the etcd service is serving TLS to clients, edit the etcd configuration file /etc/etcd/etcd.conf on the master on the master and adding a key file to ETCD_PEER_KEY_FILE:

ETCD_PEER_KEY_FILE /etc/etcd/peer.key

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  1.5.4

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_PEER_KEY_FILE' /etc/etcd/peer.key '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict

- name: "Ensure That The etcd Peer Key File Is Correctly Set"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_PEER_KEY_FILE'
    line: "ETCD_PEER_KEY_FILE /etc/etcd/peer.key"
    create: yes
  tags:
    - etcd_peer_key_file
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Ensure That The etcd Peer Client Certificate Is Correctly Set   [ref]rule

To ensure the etcd service is serving TLS to clients, edit the etcd configuration file /etc/etcd/etcd.conf on the master and adding a certificate to ETCD_PEER_CERT_FILE:

ETCD_PEER_CERT_FILE /etc/etcd/peer.crt

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  1.5.4

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_PEER_CERT_FILE' /etc/etcd/peer.crt '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict

- name: "Ensure That The etcd Peer Client Certificate Is Correctly Set"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_PEER_CERT_FILE'
    line: "ETCD_PEER_CERT_FILE /etc/etcd/peer.crt"
    create: yes
  tags:
    - etcd_peer_cert_file
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Disable etcd Peer Self-Signed Certificates   [ref]rule

To ensure the etcd service is not using self-signed certificates, edit the etcd configuration file /etc/etcd/etcd.conf from the master node and set ETCD_PEER_AUTO_TLS to false:

ETCD_PEER_AUTO_TLS=false

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection. Using self-signed certificates ensures that the certificates are never validated against a certificate authority and could lead to compromised and invalidated data.

Severity:  medium

References:  1.5.6

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_PEER_AUTO_TLS=' 'false' '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Disable etcd Peer Self-Signed Certificates"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_PEER_AUTO_TLS='
    line: "ETCD_PEER_AUTO_TLS=false"
    create: yes
  tags:
    - etcd_peer_auto_tls
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Configure A Unique CA Certificate for etcd   [ref]rule

A unique and different CA certificate should be created for etcd. To ensure the etcd service is using a unique certificate, , set ETCD_TRUSTED_CA_FILE to /etc/etcd/ca.crt in /etc/etcd/etcd.conf on the master node that does NOT match the OpenShift CA certificate:

ETCD_TRUSTED_CA_FILE=/etc/etcd/ca.crt

Rationale:

A unique CA certificate that is utilized by etcd and is different from OpenShift ensures that the etcd data is still protected in the event that the OpenShift certificate is compromised.

Severity:  medium

References:  1.5.9

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_TRUSTED_CA_FILE=' '/etc/etcd/ca.crt' '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Configure A Unique CA Certificate for etcd"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_TRUSTED_CA_FILE='
    line: "ETCD_TRUSTED_CA_FILE=/etc/etcd/ca.crt"
    create: yes
  tags:
    - etcd_unique_ca
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Disable etcd Auto Log Rotation   [ref]rule

To ensure the etcd service is not auto-rotating logs, edit the etcd configuration file /etc/etcd/etcd.conf on the master node and set ETCD_MAX_WALS to 0:

ETCD_MAX_WALS=0

Rationale:

Ensure data integrity by preventing logs from being overwritten which allows reconstructing events should the data be compromised.

Severity:  medium

References:  1.5.8

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_MAX_WALS=' '0' '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Disable etcd Auto Log Rotation"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_MAX_WALS='
    line: "ETCD_MAX_WALS=0"
    create: yes
  tags:
    - etcd_max_wals
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Enable The Peer Client Certificate Authentication   [ref]rule

To ensure the etcd service is serving TLS to clients, edit the etcd configuration file /etc/etcd/etcd.conf on the master node and set ETCD_PEER_CLIENT_CERT_AUTH to true.

ETCD_PEER_CLIENT_CERT_AUTH=true

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  1.5.5

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_PEER_CLIENT_CERT_AUTH=' 'true' '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Enable The Peer Client Certificate Authentication"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_PEER_CLIENT_CERT_AUTH='
    line: "ETCD_PEER_CLIENT_CERT_AUTH=true"
    create: yes
  tags:
    - etcd_peer_client_cert_auth
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Ensure That The etcd Client Certificate Is Correctly Set   [ref]rule

To ensure the etcd service is serving TLS to clients, edit the etcd configuration file /etc/etcd/etcd.conf on the master and adding a certificate to ETCD_CERT_FILE:

ETCD_CERT_FILE /etc/etcd/server.crt

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  1.5.1

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_CERT_FILE' /etc/etcd/server.crt '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict

- name: "Ensure That The etcd Client Certificate Is Correctly Set"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_CERT_FILE'
    line: "ETCD_CERT_FILE /etc/etcd/server.crt"
    create: yes
  tags:
    - etcd_cert_file
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Disable etcd Self-Signed Certificates   [ref]rule

To ensure the etcd service is not using self-signed certificates, edit the etcd configuration file /etc/etcd/etcd.conf from the master node and set ETCD_AUTO_TLS to false:

ETCD_AUTO_TLS=false

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection. Using self-signed certificates ensures that the certificates are never validated against a certificate authority and could lead to compromised and invalidated data.

Severity:  medium

References:  1.5.3

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_AUTO_TLS=' 'false' '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict
- name: "Disable etcd Self-Signed Certificates"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_AUTO_TLS='
    line: "ETCD_AUTO_TLS=false"
    create: yes
  tags:
    - etcd_auto_tls
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Ensure That The etcd Key File Is Correctly Set   [ref]rule

To ensure the etcd service is serving TLS to clients, edit the etcd configuration file /etc/etcd/etcd.conf on the master on the master and adding a key file to ETCD_KEY_FILE:

ETCD_KEY_FILE /etc/etcd/server.key

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  1.5.1

Remediation Shell script:   (show)

# Function to replace configuration setting in config file or add the configuration setting if
# it does not exist.
#
# Expects arguments:
#
# config_file:		Configuration file that will be modified
# key:			Configuration option to change
# value:		Value of the configuration option to change
# cce:			The CCE identifier or '@CCENUM@' if no CCE identifier exists
# format:		The printf-like format string that will be given stripped key and value as arguments,
#			so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
#
# Optional arugments:
#
# format:		Optional argument to specify the format of how key/value should be
# 			modified/appended in the configuration file. The default is key = value.
#
# Example Call(s):
#
#     With default format of 'key = value':
#     replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
#
#     With custom key/value format:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
#
#     With a variable:
#     replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
#
function replace_or_append {
  local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
  local config_file=$1
  local key=$2
  local value=$3
  local cce=$4
  local format=$5

  if [ "$case_insensitive_mode" = yes ]; then
    sed_case_insensitive_option="i"
    grep_case_insensitive_option="-i"
  fi
  [ -n "$format" ] || format="$default_format"
  # Check sanity of the input
  [ $# -ge "3" ] || { echo "Usage: replace_or_append <config_file_location> <key_to_search> <new_value> [<CCE number or literal '@CCENUM@' if unknown>] [printf-like format, default is '$default_format']" >&2; exit 1; }

  # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
  # Otherwise, regular sed command will do.
  sed_command=('sed' '-i')
  if test -L "$config_file"; then
    sed_command+=('--follow-symlinks')
  fi

  # Test that the cce arg is not empty or does not equal @CCENUM@.
  # If @CCENUM@ exists, it means that there is no CCE assigned.
  if [ -n "$cce" ] && [ "$cce" != '@CCENUM@' ]; then
    cce="CCE-${cce}"
  else
    cce="CCE"
  fi

  # Strip any search characters in the key arg so that the key can be replaced without
  # adding any search characters to the config file.
  stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "$key")

  # shellcheck disable=SC2059
  printf -v formatted_output "$format" "$stripped_key" "$value"

  # If the key exists, change it. Otherwise, add it to the config_file.
  # We search for the key string followed by a word boundary (matched by \>),
  # so if we search for 'setting', 'setting2' won't match.
  if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\>" "$config_file"; then
    "${sed_command[@]}" "s/${key}\\>.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
  else
    # \n is precaution for case where file ends without trailing newline
    printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" >> "$config_file"
    printf '%s\n' "$formatted_output" >> "$config_file"
  fi
}

replace_or_append '/etc/etcd/etcd.conf' '^ETCD_KEY_FILE=' /etc/etcd/server.key '' '%s=%s'
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:restrict

- name: "Ensure That The etcd Key File Is Correctly Set"
  lineinfile:
    path: /etc/etcd/etcd.conf
    regexp: '^ETCD_KEY_FILE='
    line: "ETCD_KEY_FILE /etc/etcd/server.key"
    create: yes
  tags:
    - etcd_key_file
    - medium_severity
    - restrict_strategy
    - low_complexity
    - low_disruption
  

Kubernetes Kubelet Settings   [ref]group

The Kubernetes Kubelet is an agent that runs on each node in the cluster. It makes sure that containers are running in a pod. The kubelet takes a set of PodSpecs that are provided through various mechanisms and ensures that the containers described in those PodSpecs are running and healthy. The kubelet doesn’t manage containers which were not created by Kubernetes.

contains 15 rules

kubelet - Configure the Client CA Certificate   [ref]rule

By default, the kubelet is not configured with a CA certificate which can subject the kubelet to man-in-the-middle attacks. To configure a client CA certificate, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

  servingInfo:
  clientCA: client-ca.crt

Rationale:

Not having a CA certificate for the kubelet will subject the kubelet to possible man-in-the-middle attacks especially on unsafe or untrusted networks. Certificate validation for the kubelet allows the API server to validate the kubelet's identity.

Severity:  medium

References:  2.1.4

kubelet - Disable the Read-Only Port   [ref]rule

To disable the read-only port, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  read-only-port:
  - '0'

Rationale:

Not having a CA certificate for the kubelet will subject the kubelet to possible man-in-the-middle attacks especially on unsafe or untrusted networks. Certificate validation for the kubelet allows the API server to validate the kubelet's identity.

Severity:  medium

References:  2.1.5

kubelet - Prevent Kernel Settings Modification   [ref]rule

By default, the kubelet has the ability to configure the kernel's settings and parameters potentially creating a security incident. To prevent the kubelet from changing kernel parameters, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  protect-kernel-defaults:
  - 'true'

Rationale:

Preventing the kubelet from modifying kernel parameters or tunables will ensure that system stays in its existing tuned and hardened state. Allowing kubelets to configure the kernel settings not only generates actionable audit records but also could open the system up to new vectors of attack.

Severity:  medium

References:  2.1.7

kubelet - Allow Automatic Firewall Configuration   [ref]rule

The kubelet has the ability to automatically configure the firewall to allow the containers required ports and connections to networking resources and destinations parameters potentially creating a security incident. To allow the kubelet to modify the firewall, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  make-iptables-util-chains:
  - 'true'

Warning:  -| IT IS NOT RECOMMENDED FOR ANY REASON to manually configure firewall ports for running pods and containers as this not only can create conflicts with firewall rules but can also introduce inconsistences into the allowed/disabled ports on the firewall.
Rationale:

The kubelet should automatically configure the firewall settings to allow access and networking traffic through. This ensures that when a pod or container is running that the correct ports are configured as well as removing the ports when a pod or container is no longer in existence.

Severity:  medium

References:  2.1.8

kubelet - Disable Anonymous Access   [ref]rule

By default, anonymous access to the kubelet is enabled. This configuration check ensures that anonymous requests to the kubelet are disabled. Edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  anonymous-auth:
  - 'false'

Rationale:

When enabled, requests that are not rejected by other configured authentication methods are treated as anonymous requests. OpenShift Operators should rely on authentication to authorize access and disallow anonymous requests.

Severity:  medium

References:  2.1.2

kubelet - Enable Server Certificate Rotation   [ref]rule

To enable the kubelet to rotate server certificates, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and ensure RotateKubeletServerCertificate is included in the feature-gates arguments:

kubeletArguments:
  feature-gates:
    - RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true

Rationale:

Allowing the kubelet to auto-update the certificates ensure that there is no downtime in certificate renewal as well as ensures confidentiality and integrity.

Severity:  medium

References:  2.1.15

Ensure That The kubelet Client Certificate Is Correctly Set   [ref]rule

To ensure the kubelet TLS client certificate is configured, edit the kubelet configuration file /etc/origin/node/node-config.yaml and configure the cert-dir path for the kubelet certificates. For example:

  cert-dir:
  - /etc/origin/node/certificates
A corresponding certificate should exist in the cert-dir. For example:
/etc/origin/node/certificates/kubelet-client-current.pem

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  2.1.12

kubelet - Disable Privileged Containers   [ref]rule

To disable privileged containers, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  allow-privileged:
  - 'false'

Rationale:

When enabled, privileged containers have unrestricted access and should be disabled. A privileged continer will run with security mechanisms disabled which will put the system at risk.

Severity:  medium

References:  2.1.1

kubelet - Do Not Disable Streaming Timeouts   [ref]rule

Timouts for streaming connections should not be disabled as they help to prevent denial-of-service attacks. To configure streaming connection timeouts, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  streaming-connection-timeout:
  - '4h'

Rationale:

Ensuring connections have timeouts helps to protect against denial-of-service attacks as well as disconnect inactive connections. In addition, setting connections timeouts helps to prevent from running out of ephemeral ports.

Severity:  medium

References:  2.1.6

kubelet - Ensure AlwaysAllow Is Not Set   [ref]rule

By default, the kubelet allows all types of authentication requests including anonymous requests. The AlwaysAll option should not be used as it will allow all types of authentication requests. To require authorization requests, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  authorization-mode:
  - 'Webhook'

Rationale:

When enabled, all type of authentication requests including anonymous requests are enabled regardless of what is configured on the API server. OpenShift Operators should rely on authentication to authorize access and disallow anonymous requests.

Severity:  medium

References:  2.1.3

kubelet - Do Not Limit Event Creation   [ref]rule

All events should be captured and not restricted as this helps in reconstucting the chain-of-events. To prevent log creation limiting, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  event-qps:
  - '0'

Rationale:

All events should be captured and not restricted as this helps in reconstucting the chain-of-events.

Severity:  medium

References:  2.1.11

Ensure That The kubelet Server Key Is Correctly Set   [ref]rule

To ensure the kubelet TLS server key certificate is configured, edit the kubelet configuration file /etc/origin/node/node-config.yaml and configure the cert-dir path for the kubelet certificates. For example:

  cert-dir:
  - /etc/origin/node/certificates
A corresponding certificate should exist in the cert-dir. For example:
/etc/origin/node/certificates/kubelet-server-current.pem

Rationale:

Without cryptographic integrity protections, information can be altered by unauthorized users without detection.

Severity:  medium

References:  2.1.12

kubelet - Disable Hostname Override   [ref]rule

To prevent the hostname from being overrided, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and remove the hostname-override option if it exists.

Rationale:

Allowing hostnames to be overrided creates issues around resolving nodes in addition to TLS configuration, certificate validation, and log correlation and validation.

Severity:  medium

References:  2.1.10

kubelet - Enable Client Certificate Rotation   [ref]rule

To enable the kubelet to rotate client certificates, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  feature-gates:
    - RotateKubeletClientCertificate=true

Rationale:

Allowing the kubelet to auto-update the certificates ensure that there is no downtime in certificate renewal as well as ensures confidentiality and integrity.

Severity:  medium

References:  2.1.14

kubelet - Disable cAdvisor Port   [ref]rule

The cAdvisor port should be disabled as it does not require any authentication to connect to the port. To disable the cAdvisor port, edit the kubelet configuration file /etc/origin/node/node-config.yaml on the kubelet node(s) and set the below parameter:

kubeletArguments:
  cadvisor-port:
  - '0'

Rationale:

Any form of authentication to ports anonymously should be disabled. An attacker could connect to the port and gain cluster information anonymously.

Severity:  high

References:  2.1.13

OpenShift Controller Settings   [ref]group

This section contains recommendations for the kube-controller-manager configuration

contains 4 rules

Ensure Controller bind-address argument is set   [ref]rule

To ensure the Controller Manager service is bound to secure loopback address, edit the Controller Manager pod specification file /etc/origin/master/master-config.yaml on the master node(s) and ensure the correct value for the bind-address parameter. For example:

kubernetesMasterConfig:
  controllerArguments:
    bind-address:
      - '192.168.1.101'

Warning:  The associated value must be reachable by the rest of the cluster, and by CLI/web clients. If blank all interfaces will be used (0.0.0.0 for IPv4 and ``::`` for IPv6).
Rationale:

The Controller Manager API service (which runs on a port specified by the secure-port argument) is used for health and metrics information and is available without authentication or encryption. As such it should only be bound to a localhost interface, to minimize the cluster's attack surface.

Severity:  low

References:  1.3.7

Enable terminated-pod-gc-threshold for the Controller Manager   [ref]rule

To ensure the garbage collector is activated upon pod termination, edit the Controller Manager pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the terminated-pod-gc-threshold to true. For example:

kubernetesMasterConfig:
  controllerArguments:
    terminated-pod-gc-threshold:
      - true

Rationale:

Garbage collection is important to ensure sufficient resource availability and avoiding degraded performance and availability. In the worst case, the system might crash or just be unusable for a long period of time. The default setting for garbage collection is 12,500 terminated pods which might be to high for your system to sustain. Based on your system resources and tests, choose an appropriate threshold value to activate garbage collection.

Severity:  low

References:  1.3.1

Ensure that the RotateKubeletServerCertificate argument is set   [ref]rule

To enforce kublet server certificate rotation on the Controller Manager, edit the Controller Manager pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the controllerArguments parameter to include RotateKubeletServerCertificate=true. For example:

kubernetesMasterConfig:
  controllerArguments:
    feature-gates:
      - RotateKubeletServerCertificate=true

Rationale:

RotateKubeletServerCertificate causes the kubelet to both request a serving certificate after bootstrapping its client credentials and rotate the certificate as its existing credentials expire. This automated periodic rotation ensures that there are no downtimes due to expired certificates and thus addressing the availability in the C/I/A security triad. NOTE: This recommendation only applies if you let kubelets get their certificates from the API Server. In case your certificates come from an outside Certificate Authority/tool (e.g. Vault) then you need to take care of rotation yourself.

Severity:  medium

References:  1.3.6

OpenShift - Kubernetes - Scheduler Settings   [ref]group

Contains evaluations for kube-scheduler configuration settings.

contains 1 rule

Disable Scheduler Profiling   [ref]rule

Profiling should be disabled if not needed. To disable profiling, edit the Scheduler pod specification file /etc/origin/master/master-config.yaml file on the master node and set the below parameter:

kubernetesMasterConfig:
  schedulerArguments:
    profiling:
    - false

Rationale:

Profiling allows for the identification of specific performance bottlenecks. It generates a significant amount of program data that could potentially be exploited to uncover system and program details. If you are not experiencing any bottlenecks and do not need the profiler for troubleshooting purposes, it is recommended to turn it off to reduce the potential attack surface.

Severity:  low

References:  1.2.1

Permissions   [ref]group

Traditional security relies heavily on file and directory permissions to prevent unauthorized users from reading or modifying files to which they should not have access.

contains 39 rules

Verify Permissions on Important Files and Directories   [ref]group

Permissions for many files on a system must be set restrictively to ensure sensitive information is properly protected. This section discusses important permission restrictions which can be verified to ensure that no harmful discrepancies have arisen.

contains 39 rules

Verify User Who Owns The OpenShift Node Configuration File   [ref]rule

To properly set the owner of /etc/origin/node/node-config.yaml, run the command:

$ sudo chown root /etc/origin/node/node-config.yaml 

Rationale:

The /etc/origin/node/node-config.yaml file contains information about the configuration of the OpenShift node that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.2

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/node/node-config.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/node-config.yaml
  stat:
    path: /etc/origin/node/node-config.yaml
  register: file_exists

- name: Ensure owner 0 on /etc/origin/node/node-config.yaml
  file:
    path: /etc/origin/node/node-config.yaml
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_node_config
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Group Who Owns The OpenShift Container Network Interface Files   [ref]rule

To properly set the group owner of /etc/cni/net.d/*, run the command:

$ sudo chgrp root /etc/cni/net.d/*

Rationale:

CNI (Container Network Interface) files consist of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins. Allowing writeable access to the files could allow an attacker to modify the networking configuration potentially adding a rouge network connection.

Severity:  medium

References:  1.4.10

The OpenShift Configuration Directory Must Have Mode 0700   [ref]rule

To properly set the permissions of /etc/origin/, run the command:

$ sudo chmod 0700 /etc/origin/

Rationale:

If users can modify the OpenShift configurations, the OpenShift cluster can become inoperable or compromised

Severity:  medium

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0700 /etc/origin
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0700 on /etc/origin
  file:
    path: /etc/origin
    mode: 0700
  tags:
    - file_permissions_etc_origin
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Group Who Owns The OpenShift Master Kubeconfig File   [ref]rule

To properly set the group owner of /etc/origin/master/openshift-master.kubeconfig, run the command:

$ sudo chgrp root /etc/origin/master/openshift-master.kubeconfig

Rationale:

The /etc/origin/master/openshift-master.kubeconfig file contains information about the master configuration of the OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.18

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/master/openshift-master.kubeconfig
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/openshift-master.kubeconfig
  stat:
    path: /etc/origin/master/openshift-master.kubeconfig
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/master/openshift-master.kubeconfig
  file:
    path: /etc/origin/master/openshift-master.kubeconfig
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_master_openshift_kubeconfig
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns The OpenShift etcd Specification File   [ref]rule

To properly set the owner of /etc/origin/node/pods/etcd.yaml, run the command:

$ sudo chown root /etc/origin/node/pods/etcd.yaml 

Rationale:

The /etc/origin/node/pods/etcd.yaml file contains information about the configuration of the OpenShift etcd Server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.8

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/node/pods/etcd.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/pods/etcd.yaml
  stat:
    path: /etc/origin/node/pods/etcd.yaml
  register: file_exists

- name: Ensure owner 0 on /etc/origin/node/pods/etcd.yaml
  file:
    path: /etc/origin/node/pods/etcd.yaml
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_master_etcd
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Group Who Owns The OpenShift Admin Kubeconfig File   [ref]rule

To properly set the group owner of /etc/origin/master/admin.kubeconfig, run the command:

$ sudo chgrp root /etc/origin/master/admin.kubeconfig

Rationale:

The /etc/origin/master/admin.kubeconfig file contains information about the administrative configuration of the OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.14

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/master/admin.kubeconfig
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/admin.kubeconfig
  stat:
    path: /etc/origin/master/admin.kubeconfig
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/master/admin.kubeconfig
  file:
    path: /etc/origin/master/admin.kubeconfig
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_master_admin_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift Node Service File   [ref]rule

To properly set the permissions of /etc/systemd/system/atomic-openshift-node.service, run the command:

$ sudo chmod 0644 /etc/systemd/system/atomic-openshift-node.service

Rationale:

If the /etc/systemd/system/atomic-openshift-node.service file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the service configuration of the OpenShift node service that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.3

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0644 /etc/systemd/system/atomic-openshift-node.service
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0644 on /etc/systemd/system/atomic-openshift-node.service
  file:
    path: /etc/systemd/system/atomic-openshift-node.service
    mode: 0644
  tags:
    - file_permissions_openshift_node_service
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Group Who Owns The OpenShift Configuration Directory   [ref]rule

To properly set the group owner of /etc/origin/, run the command:

$ sudo chgrp root /etc/origin/

Rationale:

If users can modify the OpenShift configurations, the OpenShift cluster can become inoperable or compromised

Severity:  medium

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin
  stat:
    path: /etc/origin
  register: file_exists

- name: Ensure group owner 0 on /etc/origin
  file:
    path: /etc/origin
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_etc_origin
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift Container Network Interface Files   [ref]rule

To properly set the permissions of /etc/cni/net.d/*, run the command:

$ sudo chmod 0644 /etc/cni/net.d/*

Rationale:

CNI (Container Network Interface) files consist of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins. Allowing writeable access to the files could allow an attacker to modify the networking configuration potentially adding a rouge network connection.

Severity:  medium

References:  1.4.9

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure
find /etc/cni/net.d -regex '^/etc/cni/net.d/.*$' -exec chmod 0644 {} \;
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Find /etc/cni/net.d file(s)
  find:
    paths: "/etc/cni/net.d"
    patterns: "^.*$"
  register: files_found
  tags:
    - file_permissions_master_cni_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

- name: Set permissions for /etc/cni/net.d file(s)
  file:
    path: "{{ item.path }}"
    mode: 0644
  with_items:
    - "{{ files_found.files }}"
  tags:
    - file_permissions_master_cni_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Group Who Owns The OpenShift Node Configuration File   [ref]rule

To properly set the group owner of /etc/origin/node/node-config.yaml, run the command:

$ sudo chgrp root /etc/origin/node/node-config.yaml

Rationale:

The /etc/origin/node/node-config.yaml file contains information about the configuration of the OpenShift node that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.2

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/node/node-config.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/node-config.yaml
  stat:
    path: /etc/origin/node/node-config.yaml
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/node/node-config.yaml
  file:
    path: /etc/origin/node/node-config.yaml
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_node_config
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Group Who Owns OpenShift Node Certificate File   [ref]rule

To properly set the group owner of /etc/origin/node/client-ca.crt, run the command:

$ sudo chgrp root /etc/origin/node/client-ca.crt

Rationale:

The /etc/origin/node/client-ca.crt file contains the certificate authority certificate for an OpenShift node that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.8

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/node/client-ca.crt
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/client-ca.crt
  stat:
    path: /etc/origin/node/client-ca.crt
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/node/client-ca.crt
  file:
    path: /etc/origin/node/client-ca.crt
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_openshift_node_client_crt
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns The OpenShift Admin Kubeconfig File   [ref]rule

To properly set the owner of /etc/origin/master/admin.kubeconfig, run the command:

$ sudo chown root /etc/origin/master/admin.kubeconfig 

Rationale:

The /etc/origin/master/admin.kubeconfig file contains information about the administrative configuration of the OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.14

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/master/admin.kubeconfig
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/admin.kubeconfig
  stat:
    path: /etc/origin/master/admin.kubeconfig
  register: file_exists

- name: Ensure owner 0 on /etc/origin/master/admin.kubeconfig
  file:
    path: /etc/origin/master/admin.kubeconfig
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_master_admin_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift Controller Manager Specification File   [ref]rule

To properly set the permissions of /etc/origin/node/pods/controller.yaml, run the command:

$ sudo chmod 0600 /etc/origin/node/pods/controller.yaml

Rationale:

If the /etc/origin/node/pods/controller.yaml file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the configuration of an OpenShift Controller Manager server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.3

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/node/pods/controller.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/node/pods/controller.yaml
  file:
    path: /etc/origin/node/pods/controller.yaml
    mode: 0600
  tags:
    - file_permissions_master_controller_manager
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Permissions on the OpenShift Master Kubeconfig File   [ref]rule

To properly set the permissions of /etc/origin/master/openshift-master.kubeconfig, run the command:

$ sudo chmod 0600 /etc/origin/master/openshift-master.kubeconfig

Rationale:

If the /etc/origin/master/openshift-master.kubeconfig file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the master configuration of an OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.17

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/master/openshift-master.kubeconfig
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/master/openshift-master.kubeconfig
  file:
    path: /etc/origin/master/openshift-master.kubeconfig
    mode: 0600
  tags:
    - file_permissions_master_openshift_kubeconfig
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify User Who Owns The OpenShift Container Network Interface Files   [ref]rule

To properly set the owner of /etc/cni/net.d/*, run the command:

$ sudo chown root /etc/cni/net.d/* 

Rationale:

CNI (Container Network Interface) files consist of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins. Allowing writeable access to the files could allow an attacker to modify the networking configuration potentially adding a rouge network connection.

Severity:  medium

References:  1.4.10

Verify Group Who Owns The OpenShift Scheduler Configuration File   [ref]rule

To properly set the group owner of /etc/origin/master/scheduler.json, run the command:

$ sudo chgrp root /etc/origin/master/scheduler.json

Rationale:

The /etc/origin/master/scheduler.json file contains information about the configuration of the OpenShift scheduler that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.16

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/master/scheduler.json
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/scheduler.json
  stat:
    path: /etc/origin/master/scheduler.json
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/master/scheduler.json
  file:
    path: /etc/origin/master/scheduler.json
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_master_scheduler_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

The OpenShift etcd Data Directory Must Have Mode 0700   [ref]rule

To properly set the permissions of /var/lib/etcd, run the command:

$ sudo chmod 0700 /var/lib/etcd

Rationale:

The /var/lib/etcd directory contains highly-avaliable distributed key/value data storage across an OpenShift cluster. Allowing access to users to this directory could compromise OpenShift data and the cluster.

Severity:  medium

References:  1.4.11

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0700 /var/lib/etcd
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0700 on /var/lib/etcd
  file:
    path: /var/lib/etcd
    mode: 0700
  tags:
    - file_permissions_var_lib_etcd
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify User Who Owns The OpenShift API Specification File   [ref]rule

To properly set the owner of /etc/origin/node/pods/apiserver.yaml, run the command:

$ sudo chown root /etc/origin/node/pods/apiserver.yaml 

Rationale:

The /etc/origin/node/pods/apiserver.yaml file contains information about the configuration of the OpenShift API Server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.2

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/node/pods/apiserver.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/pods/apiserver.yaml
  stat:
    path: /etc/origin/node/pods/apiserver.yaml
  register: file_exists

- name: Ensure owner 0 on /etc/origin/node/pods/apiserver.yaml
  file:
    path: /etc/origin/node/pods/apiserver.yaml
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_master_api_server
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Group Who Owns The OpenShift Master Configuration File   [ref]rule

To properly set the group owner of /etc/origin/master/master-config.yaml, run the command:

$ sudo chgrp root /etc/origin/master/master-config.yaml

Rationale:

The /etc/origin/master/master-config.yaml file contains information about the master configuration of the OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.18

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/master/master-config.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/master-config.yaml
  stat:
    path: /etc/origin/master/master-config.yaml
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/master/master-config.yaml
  file:
    path: /etc/origin/master/master-config.yaml
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_master_openshift_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns OpenShift Node Certificate File   [ref]rule

To properly set the owner of /etc/origin/node/client-ca.crt, run the command:

$ sudo chown root /etc/origin/node/client-ca.crt 

Rationale:

The /etc/origin/node/client-ca.crt file contains the certificate authority certificate for an OpenShift node that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.8

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/node/client-ca.crt
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/client-ca.crt
  stat:
    path: /etc/origin/node/client-ca.crt
  register: file_exists

- name: Ensure owner 0 on /etc/origin/node/client-ca.crt
  file:
    path: /etc/origin/node/client-ca.crt
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_openshift_node_client_crt
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift Scheduler Configuration File   [ref]rule

To properly set the permissions of /etc/origin/master/scheduler.json, run the command:

$ sudo chmod 0600 /etc/origin/master/scheduler.json

Rationale:

If the /etc/origin/master/scheduler.json file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the configuration of an OpenShift scheduler that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.15

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/master/scheduler.json
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/master/scheduler.json
  file:
    path: /etc/origin/master/scheduler.json
    mode: 0600
  tags:
    - file_permissions_master_scheduler_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Group Who Owns The OpenShift etcd Data Directory   [ref]rule

To properly set the group owner of /var/lib/etcd, run the command:

$ sudo chgrp root /var/lib/etcd

Rationale:

The /var/lib/etcd directory contains highly-avaliable distributed key/value data storage across an OpenShift cluster. Allowing access to users to this directory could compromise OpenShift data and the cluster.

Severity:  medium

References:  1.4.12

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /var/lib/etcd
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /var/lib/etcd
  stat:
    path: /var/lib/etcd
  register: file_exists

- name: Ensure group owner 0 on /var/lib/etcd
  file:
    path: /var/lib/etcd
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_var_lib_etcd
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift Master Configuration File   [ref]rule

To properly set the permissions of /etc/origin/master/master-config.yaml, run the command:

$ sudo chmod 0600 /etc/origin/master/master-config.yaml

Rationale:

If the /etc/origin/master/master-config.yaml file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the master configuration of an OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.17

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/master/master-config.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/master/master-config.yaml
  file:
    path: /etc/origin/master/master-config.yaml
    mode: 0600
  tags:
    - file_permissions_master_openshift_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify User Who Owns The OpenShift Controller Manager Specification File   [ref]rule

To properly set the owner of /etc/origin/node/pods/controller.yaml, run the command:

$ sudo chown root /etc/origin/node/pods/controller.yaml 

Rationale:

The /etc/origin/node/pods/controller.yaml file contains information about the configuration of the OpenShift Controller Manager Server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.4

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/node/pods/controller.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/pods/controller.yaml
  stat:
    path: /etc/origin/node/pods/controller.yaml
  register: file_exists

- name: Ensure owner 0 on /etc/origin/node/pods/controller.yaml
  file:
    path: /etc/origin/node/pods/controller.yaml
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_master_controller_manager
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Group Who Owns The OpenShift etcd Specification File   [ref]rule

To properly set the group owner of /etc/origin/node/pods/etcd.yaml, run the command:

$ sudo chgrp root /etc/origin/node/pods/etcd.yaml

Rationale:

The /etc/origin/node/pods/apiserver.yaml file contains information about the configuration of the OpenShift etcd Server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.8

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/node/pods/etcd.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/pods/etcd.yaml
  stat:
    path: /etc/origin/node/pods/etcd.yaml
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/node/pods/etcd.yaml
  file:
    path: /etc/origin/node/pods/etcd.yaml
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_master_etcd
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns The OpenShift Scheduler Configuration File   [ref]rule

To properly set the owner of /etc/origin/master/scheduler.json, run the command:

$ sudo chown root /etc/origin/master/scheduler.json 

Rationale:

The /etc/origin/master/scheduler.json file contains information about the configuration of the OpenShift scheduler that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.16

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/master/scheduler.json
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/scheduler.json
  stat:
    path: /etc/origin/master/scheduler.json
  register: file_exists

- name: Ensure owner 0 on /etc/origin/master/scheduler.json
  file:
    path: /etc/origin/master/scheduler.json
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_master_scheduler_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns The OpenShift Master Configuration File   [ref]rule

To properly set the owner of /etc/origin/master/master-config.yaml, run the command:

$ sudo chown root /etc/origin/master/master-config.yaml 

Rationale:

The /etc/origin/master/master-config.yaml file contains information about the master configuration of the OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.18

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/master/master-config.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/master-config.yaml
  stat:
    path: /etc/origin/master/master-config.yaml
  register: file_exists

- name: Ensure owner 0 on /etc/origin/master/master-config.yaml
  file:
    path: /etc/origin/master/master-config.yaml
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_master_openshift_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns The OpenShift etcd Data Directory   [ref]rule

To properly set the owner of /var/lib/etcd, run the command:

$ sudo chown root /var/lib/etcd 

Rationale:

The /var/lib/etcd directory contains highly-avaliable distributed key/value data storage across an OpenShift cluster. Allowing access to users to this directory could compromise OpenShift data and the cluster.

Severity:  medium

References:  1.4.12

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /var/lib/etcd
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /var/lib/etcd
  stat:
    path: /var/lib/etcd
  register: file_exists

- name: Ensure owner 0 on /var/lib/etcd
  file:
    path: /var/lib/etcd
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_var_lib_etcd
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns The OpenShift Configuration Directory   [ref]rule

To properly set the owner of /etc/origin/, run the command:

$ sudo chown root /etc/origin/ 

Rationale:

If users can modify the OpenShift configurations, the OpenShift cluster can become inoperable or compromised

Severity:  medium

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin
  stat:
    path: /etc/origin
  register: file_exists

- name: Ensure owner 0 on /etc/origin
  file:
    path: /etc/origin
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_etc_origin
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift etcd Specification File   [ref]rule

To properly set the permissions of /etc/origin/node/pods/etcd.yaml, run the command:

$ sudo chmod 0600 /etc/origin/node/pods/etcd.yaml

Rationale:

If the /etc/origin/node/pods/etcd.yaml file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the configuration of an OpenShift etcd server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.7

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/node/pods/etcd.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/node/pods/etcd.yaml
  file:
    path: /etc/origin/node/pods/etcd.yaml
    mode: 0600
  tags:
    - file_permissions_master_etcd
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Group Who Owns The OpenShift Node Service File   [ref]rule

To properly set the group owner of /etc/systemd/system/atomic-openshift-node.service, run the command:

$ sudo chgrp root /etc/systemd/system/atomic-openshift-node.service

Rationale:

The /etc/systemd/system/atomic-openshift-node.service file contains information about the configuration of the OpenShift node service that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.4

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/systemd/system/atomic-openshift-node.service
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/systemd/system/atomic-openshift-node.service
  stat:
    path: /etc/systemd/system/atomic-openshift-node.service
  register: file_exists

- name: Ensure group owner 0 on /etc/systemd/system/atomic-openshift-node.service
  file:
    path: /etc/systemd/system/atomic-openshift-node.service
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_openshift_node_service
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify User Who Owns The OpenShift Master Kubeconfig File   [ref]rule

To properly set the owner of /etc/origin/master/openshift-master.kubeconfig, run the command:

$ sudo chown root /etc/origin/master/openshift-master.kubeconfig 

Rationale:

The /etc/origin/master/openshift-master.kubeconfig file contains information about the master configuration of the OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.18

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/origin/master/openshift-master.kubeconfig
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/master/openshift-master.kubeconfig
  stat:
    path: /etc/origin/master/openshift-master.kubeconfig
  register: file_exists

- name: Ensure owner 0 on /etc/origin/master/openshift-master.kubeconfig
  file:
    path: /etc/origin/master/openshift-master.kubeconfig
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_master_openshift_kubeconfig
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift Node Configuration File   [ref]rule

To properly set the permissions of /etc/origin/node/node-config.yaml, run the command:

$ sudo chmod 0600 /etc/origin/node/node-config.yaml

Rationale:

If the /etc/origin/node/node-config.yaml file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the configuration of an OpenShift node that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.1

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/node/node-config.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/node/node-config.yaml
  file:
    path: /etc/origin/node/node-config.yaml
    mode: 0600
  tags:
    - file_permissions_node_config
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Group Who Owns The OpenShift API Specification File   [ref]rule

To properly set the group owner of /etc/origin/node/pods/apiserver.yaml, run the command:

$ sudo chgrp root /etc/origin/node/pods/apiserver.yaml

Rationale:

The /etc/origin/node/pods/apiserver.yaml file contains information about the configuration of the OpenShift API Server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.2

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/node/pods/apiserver.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/pods/apiserver.yaml
  stat:
    path: /etc/origin/node/pods/apiserver.yaml
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/node/pods/apiserver.yaml
  file:
    path: /etc/origin/node/pods/apiserver.yaml
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_master_api_server
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Group Who Owns The OpenShift Controller Manager Specification File   [ref]rule

To properly set the group owner of /etc/origin/node/pods/controller.yaml, run the command:

$ sudo chgrp root /etc/origin/node/pods/controller.yaml

Rationale:

The /etc/origin/node/pods/controller.yaml file contains information about the configuration of the OpenShift Controller Manager Server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.4

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chgrp 0 /etc/origin/node/pods/controller.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/origin/node/pods/controller.yaml
  stat:
    path: /etc/origin/node/pods/controller.yaml
  register: file_exists

- name: Ensure group owner 0 on /etc/origin/node/pods/controller.yaml
  file:
    path: /etc/origin/node/pods/controller.yaml
    group: 0
  when: file_exists.stat.exists and True
  tags:
    - file_groupowner_master_controller_manager
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on OpenShift Node Certificate File   [ref]rule

To properly set the permissions of /etc/origin/node/client-ca.crt, run the command:

$ sudo chmod 0644 /etc/origin/node/client-ca.crt

Rationale:

If the /etc/origin/node/client-ca.crt file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the certificate authority certificate for an OpenShift node that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/node/client-ca.crt
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/node/client-ca.crt
  file:
    path: /etc/origin/node/client-ca.crt
    mode: 0600
  tags:
    - file_permissions_openshift_node_client_crt
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify User Who Owns The OpenShift Node Service File   [ref]rule

To properly set the owner of /etc/systemd/system/atomic-openshift-node.service, run the command:

$ sudo chown root /etc/systemd/system/atomic-openshift-node.service 

Rationale:

The /etc/systemd/system/atomic-openshift-node.service file contains information about the configuration of the OpenShift node service that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  2.2.4

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chown 0 /etc/systemd/system/atomic-openshift-node.service
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Test for existence /etc/systemd/system/atomic-openshift-node.service
  stat:
    path: /etc/systemd/system/atomic-openshift-node.service
  register: file_exists

- name: Ensure owner 0 on /etc/systemd/system/atomic-openshift-node.service
  file:
    path: /etc/systemd/system/atomic-openshift-node.service
    owner: 0
  when: file_exists.stat.exists and True
  tags:
    - file_owner_openshift_node_service
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption

Verify Permissions on the OpenShift Admin Kubeconfig File   [ref]rule

To properly set the permissions of /etc/origin/master/admin.kubeconfig, run the command:

$ sudo chmod 0600 /etc/origin/master/admin.kubeconfig

Rationale:

If the /etc/origin/master/admin.kubeconfig file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the administration configuration of the OpenShift cluster that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.13

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/master/admin.kubeconfig
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/master/admin.kubeconfig
  file:
    path: /etc/origin/master/admin.kubeconfig
    mode: 0600
  tags:
    - file_permissions_master_admin_conf
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

Verify Permissions on the OpenShift API Specification File   [ref]rule

To properly set the permissions of /etc/origin/node/pods/apiserver.yaml, run the command:

$ sudo chmod 0600 /etc/origin/node/pods/apiserver.yaml

Rationale:

If the /etc/origin/node/pods/apiserver.yaml file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the configuration of an OpenShift API server that is configured on the system. Protection of this file is critical for OpenShift security.

Severity:  medium

References:  1.4.1

Remediation Shell script:   (show)

Complexity:low
Disruption:low
Strategy:configure

chmod 0600 /etc/origin/node/pods/apiserver.yaml
Remediation Ansible snippet:   (show)

Complexity:low
Disruption:low
Strategy:configure
- name: Ensure permission 0600 on /etc/origin/node/pods/apiserver.yaml
  file:
    path: /etc/origin/node/pods/apiserver.yaml
    mode: 0600
  tags:
    - file_permissions_master_api_server
    - medium_severity
    - configure_strategy
    - low_complexity
    - low_disruption
  

OpenShift API Server   [ref]group

This section contains recommendations for kube-apiserver configuration.

contains 39 rules

Configure the kubelet Certificate Authority for the API Server   [ref]rule

To ensure OpenShift verifies kubelet certificates before establishing connections, follow the OpenShift documentation and setup the TLS connection between the API Server and kubelets. Then, verify that kubeletClientInfo has the ca configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

kubeletClientInfo:
  ca: ca-bundle.crt
  certFile: master.kubelet-client.crt
  keyFile: master.kubelet-client.key

Rationale:

Connections from the API Server to the kubelet are used for fetching logs for pods, attaching (through kubectl) to running pods, and using the kubelet port-forwarding functionality. These connections terminate at the kubelet HTTPS endpoint. By default, teh API Server does not verify the kubelet serving certificate, which makes the connection subject to man-in-the-middle attacks, and unsafe to run over untrusted and/or public networks.

Severity:  high

References:  1.1.31

Configure the Certificate Key for the API Server   [ref]rule

To ensure the API Server utilizes its own TLS certificates, the keyFile must be configured. To, verify that servingInfo has the keyFile configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

servingInfo:
  clientCA: ca.crt
  certFile: master.server.crt
  keyFile: master.server.key

Rationale:

API Server communication contains sensitive parameters that should remain encrypted in transit. Configure the API Server to serve only HTTPS traffic.

Severity:  medium

References:  1.1.38

Configure the Client Certificate Authority for the API Server   [ref]rule

Certificates must be provided to fully setup TLS client certificate authentication. To ensure the API Server utilizes its own TLS certificates, the clientCA must be configured. Verify that servingInfo has the clientCA configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

servingInfo:
  clientCA: ca.crt
  certFile: master.server.crt
  keyFile: master.server.key

Rationale:

API Server communication contains sensitive parameters that should remain encrypted in transit. Configure the API Server to serve only HTTPS traffic. If -clientCA is set, any request presenting a client certificate signed by one of the authorities in the client-ca-file is authenticated with an identity corresponding to the CommonName of the client certificate.

Severity:  medium

References:  1.1.39

Configure the Audit Log Path   [ref]rule

To enable auditing on the OpenShift API Server, the audit log path must be set. Edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the audit-log-path to a suitable path and file where you would like audit logs to be written. For example:

auditConfig:
  auditFilePath: "/var/log/audit-ocp.log"
  enabled: true
  maximumFileRetentionDays: 30
  maximumFileSizeMegabytes: 10
  maximumRetainedFiles: 10

Rationale:

Auditing of the API Server is not enabled by default. Auditing the API Server provides a security-relevant chronological set of records documenting the sequence of activities that have affected the system by users, administrators, or other system components.

Severity:  high

References:  1.1.22

Use Strong Cryptographic Ciphers on the API Server   [ref]rule

To ensure that the API Server is configured to only use strong cryptographic ciphers, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node and set the parameter below:

servingInfo:
  cipherSuites:
  - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
  - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
  - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  - TLS_RSA_WITH_AES_256_GCM_SHA384
  - TLS_RSA_WITH_AES_128_GCM_SHA256

Warning:  Once configured, API Server clients that cannot support modern cryptographic ciphers will not be able to make connections to the API server.
Rationale:

TLS ciphers have had a number of known vulnerabilities and weaknesses, which can reduce the protection provided. By default OpenShift supports a number of TLS ciphersuites including some that have security concerns, weakening the protection provided.

Severity:  medium

References:  1.1.40

Enable the EventRateLimit Admission Control Plugin   [ref]rule

To limit the rate at which the API Server accepts requests, follow the OpenShift documentation and set the desired limits in a configuration file. Then, edit the API Server pod specification file /etc/origin/master/master-config.yaml and set the admissionConfig to include DenyEscalatingExec:

admissionConfig:
  pluginConfig:
    EventRateLimit:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false

Rationale:

Using EventRateLimit admission control enforces a limit on the number of events that the API Server will accept in a given time slice. In a large multi-tenant cluster, there might be a small percentage of misbehaving tenants which could have a significant impact on the performance of the cluster overall. It is recommended to limit the rate of events that the API Server will accept.

Severity:  medium

References:  1.1.46

Disable use of AlwaysAllow for the API Server Authorization Mode   [ref]rule

The OpenShift API server should not allow anonymous API requests. To ensure that the API server requires authorization for API requests, validate that AlwaysAllow is not configured for authorization-mode in /etc/origin/master/master-config.yaml:

kubernetesMasterConfig:
  apiServerArguments:
    authorization-mode:
    - AlwaysAllow

Rationale:

The AlwaysAllow authorization mode allows all requests including anonymous requests. This would grant any authenticated entity full cluster access.

Severity:  medium

References:  1.1.42

Configure the Audit Log Maxage   [ref]rule

To configure audit log retention, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the maximumFileRetentionDays parameter to 30 or as appropriate number of days:

auditConfig:
  auditFilePath: "/var/log/audit-ocp.log"
  enabled: true
  maximumFileRetentionDays: 30
  maximumFileSizeMegabytes: 10
  maximumRetainedFiles: 10

Rationale:

Retaining audit logs for a specified period of time allows OpenShift Operators to retroactively review and correlate events, such as for investigative purposes.

Severity:  medium

References:  1.1.23

Enable the DenyEscalatingExec Admission Control Plugin   [ref]rule

By default, DenyEscalatingExec is not enabled, which allows privileged pods to execute exec and attach commands. To disable this capability, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the admissionConfig to include DenyEscalatingExec:

admissionConfig:
  pluginConfig:
    DenyEscalatingExec:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false

Rationale:

Setting admission control policy to include DenyEscalatingExec denies exec and attach commands to pods that run with escalated privileges that allow host access. This includes pods that run as privileged, have access to the host IPC namespace, and have access to the host PID namespace.

Severity:  high

References:  1.1.15

Enable the ServiceAccount Admission Control Plugin   [ref]rule

To ensure ServiceAccount objects must be created and granted before pod creation is allowed, follow the documentation and create ServiceAccount objects as per your environment. Then, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) set the admissionConfig to include ServiceAccount:

admissionConfig:
  pluginConfig:
    ServiceAccount:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false

Rationale:

When a pod is created, if a service account is not specified, the pod is automatically assigned the default service account in the same namespace. OpenShift operators should create unique service accounts and let the API Server manage its security tokens.

Severity:  medium

References:  1.1.37

Disable the AlwaysAdmit Admission Control Plugin   [ref]rule

To ensure OpenShift only responses to requests explicitly allowed by the admissions control plugin, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and ensure the admissionConfig is not configured to include AlwaysAdmit.

Rationale:

Enabling the admission control plugin AlwaysAdmin allows all requests and does not provide any filtering.

Severity:  medium

References:  1.1.10

Disable Token-based Authentication   [ref]rule

To ensure OpenShift does not accept token-based authentication, follow the OpenShift documentation and configure alternate mechanisms for authentication. Then, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and remove the token-auth-file setting.

kubernetesMasterConfig:
  apiServerArguments:
    token-auth-file:
    - /path/to/file

Rationale:

The token-based authentication utilizes static tokens to authenticate requests to the API Server. The tokens are stored in clear-text in a file on the API Server, and cannot be revoked or rotated without restarting the API Server.

Severity:  high

References:  1.1.30

Disable Anonymous Authentication to the API Server   [ref]rule

By default, anonymous access to the OpenShift API is enabled. This configuration check ensures that anonymous requests to the OpenShift API server are disabled. Edit the API server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the below parameter:

apiServerArguments:
  anonymous-auth:
  - 'false'

Rationale:

When enabled, requests that are not rejected by other configured authentication methods are treated as anonymous requests. These requests are then served by the API server. OpenShift Operators should rely on authentication to authorize access and disallow anonymous requests.

Severity:  medium

References:  1.1.1

Disable Profiling on the API server   [ref]rule

To disable profiling, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set profiling to false:

kubernetesMasterConfig:
  schedulerArguments:
    profiling:
    - false

Rationale:

Profiling allows for the identification of specific performance bottlenecks. It generates a significant amount of program data that could potentially be exploited to uncover system and program details. If the profiler is not needed for troubleshooting purposes, it is recommended to turn off for reduction of potential attack surface.

Severity:  low

References:  1.1.8

Configure the etcd Certificate Authority for the API Server   [ref]rule

To ensure etcd is configured to make use of TLS encryption for client connections, follow the OpenShift documentation and setup the TLS connection between the API Server and etcd. Then, verify that etcdClientInfo has the ca configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

etcdClientInfo:
  ca: master.etcd-ca.crt
  certFile: master.etcd-client.crt
  keyFile: master.etcd-client.key

Rationale:

etcd is a highly-available key-value store used by OpenShift deployments for persistent storage of all REST API objects. These objects are sensitive in nature and should be protected by client authentication. This requires the API Server to identify itself to the etcd server using a SSL Certificate Authority file.

Severity:  medium

References:  1.1.41

Enable Advanced Auditing for the API Server   [ref]rule

To ensure advanced auditing is not disabled, edit the API server pod specification file /etc/origin/master/master-config.yaml and set the parameters below:

kubernetesMasterConfig:
  apiServerArguments:
    feature-gates:
    - AdvancedAuditing=true

Rationale:

AdvancedAuditing enables a much more general API auditing pipeline, which includes support for pluggable output backends and an audit policy specifying how different requests should be audited. Additionally, this enables auditing of failed authentication, authorization, and login attempts which could prove crucial for protecting your production clusters. It is recommended not to disable advanced auditing.

Severity:  medium

References:  1.1.47

Configure the Maximum Retained Audit Logs   [ref]rule

To configure how many rotations of audit logs are retained, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the maximumRetainedFiles parameter to 10 or to an organizationally appropriate value:

auditConfig:
  auditFilePath: "/var/log/audit-ocp.log"
  enabled: true
  maximumFileRetentionDays: 30
  maximumFileSizeMegabytes: 10
  maximumRetainedFiles: 10

Rationale:

OpenShift automatically rotates the log files. Retaining old log files ensures OpenShift Operators will have sufficient log data available for carrying out any investigation or correlation. For example, if the audit log size is set to 100 MB and the number of retained log files is set to 10, OpenShift Operators would have approximately 1 GB of log data to use during analysis.

Severity:  low

References:  1.1.25

Configure Maximum Audit Log Size   [ref]rule

To rotate audit logs upon reaching a maximum size, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the maximumFileSizeMegabytes parameter to an appropriate size in MB. For example, to set it to 100 MB:

auditConfig:
  auditFilePath: "/var/log/audit-ocp.log"
  enabled: true
  maximumFileRetentionDays: 30
  maximumFileSizeMegabytes: 100
  maximumRetainedFiles: 10

Rationale:

OpenShift automatically rotates log files. Retaining old log files ensures that OpenShift Operators have sufficient log data available for carrying out any investigation or correlation. If you have set file size of 100 MB and the number of old log files to keep as 10, there would be approximately 1 GB of log data available for use in analysis.

Severity:  medium

References:  1.1.28

Enable the NodeRestriction Admission Control Plugin   [ref]rule

To limit the Node and Pod objects that a kubelet could modify, follow the OpenShift documentation and configure NodeRestriction plugin on kubelets. Then, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set set the admissionConfig to include NodeRestriction:

admissionConfig:
  pluginConfig:
    NodeRestriction:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false

Rationale:

Using the NodeRestriction plugin ensures that the kubelet is restricted to the Node and Pod objects that it could modify as defined. Such kubelets will only be allowed to modify their own Node API object, and only modify Pod API objects that are bound to their node.

Severity:  medium

References:  1.1.43

Enable the SecurityContextDeny Admission Control Plugin   [ref]rule

Instead of using a customized SecurityContext for pods, a Pod Security Policy (PSP) should be used. PSP is a cluster-level resource that controls the actions that a pod can perform and what resource the pod may access. The SecurityContextDeny admission control policy enables PSP. To configure OpenShift to use PSP, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the admissionConfig to include SecurityContextDeny:

admissionConfig:
  pluginConfig:
    SecurityContextDeny:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false

Rationale:

Setting admission control policy to SecurityContextDeny denies the pod level SecurityContext customization. Any attempts to customize the SecurityContext that are not explicitly defined in the Pod Security Policy (PSP) are blocked. This ensures that all pods adhere to the PSP defined by your organization and you have a uniform pod level security posture.

Severity:  medium

References:  1.1.17

Enable the PodSecurityPolicy Admission Control Plugin   [ref]rule

To reject pods that do not match Pod Security Policies, follow the OpenShift documentation and create Pod Security Policy objects as per your environment. Then, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the admissionConfig to include PodSecurityPolicy:

admissionConfig:
  pluginConfig:
    PodSecurityPolicy:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false
Once configured, the API Server service will need to be restarted.

Warning:  When the PodSecurityPolicy admission plugin is in use, there needs to be at least one PodSecurityPolicy in place for ANY pods to be admitted.
Rationale:

A Pod Security Policy is a cluster-level resource that controls the actions which a pod can perform and what the pod may access. The PodSecurityPolicy objects define a set of conditions that a pod must run with in order to be accepted into the system. Pod Security Policies are comprised of settings and strategies that control the security features a pod has access to and hence this must be used to control pod access permissions.

Severity:  medium

References:  1.1.34

Disable basic-auth-file for the API Server   [ref]rule

Basic Authentication should not be used. Follow the OpenShift documentation and configure alternate mechanisms for authentication. Then, edit API server pod specification file /etc/origin/master/master-config.yaml on the master node and remove the basic-auth-file parameter.

kubernetesMasterConfig:
  apiServerArguments:
    basic-auth-file:
    - /path/to/any/file
Alternate authentication mechanisms such as tokens and certificates will need to be used. Username and password for basic authentication will be disabled.

Rationale:

Basic authentication uses plaintext credentials for authentication. Currently the basic authentication credentials last indefinitely, and the password cannot be changed without restarting the API Server. The Basic Authentication is currently supported for convenience and is not intended for production workloads.

Severity:  medium

References:  1.1.2

Configure the kubelet Certificate Key for the API Server   [ref]rule

To enable certificate based kubelet authentication, follow the OpenShift documentation and setup the TLS connection between the API Server and kubelets. Then, verify that kubeletClientInfo has the keyFile configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

kubeletClientInfo:
  ca: ca-bundle.crt
  certFile: master.kubelet-client.crt
  keyFile: master.kubelet-client.key

Rationale:

By default the API Server does not authenticate itself to the kubelet's HTTPS endpoints. Requests from the API Server are treated anonymously. Configuring certificate-based kubelet authentication ensures that the API Server authenticates itself to kubelets when submitting requests.

Severity:  high

References:  1.1.32

Configure the etcd Certificate Key for the API Server   [ref]rule

To ensure etcd is configured to make use of TLS encryption for client communications, follow the OpenShift documentation and setup the TLS connection between the API Server and etcd. Then, verify that etcdClientInfo has the keyFile configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

etcdClientInfo:
  ca: master.etcd-ca.crt
  certFile: master.etcd-client.crt
  keyFile: master.etcd-client.key

Rationale:

etcd is a highly-available key-value store used by OpenShift deployments for persistent storage of all REST API objects. These objects are sensitive in nature and should be protected by client authentication. This requires the API Server to identify itself to the etcd server using a client certificate and key.

Severity:  medium

References:  1.1.36

Disable Insecure Tokens   [ref]rule

Insecure tokens should be forbidden. Edit the API server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and remove any instance of the insecure-allow-any-token parameter.

Rationale:

Accepting insecure tokens would allow any token without performing actual authentication. User information is parsed from the token and connections are allowed.

Severity:  medium

References:  1.1.3

Configure the Certificate for the API Server   [ref]rule

To ensure the API Server utilizes its own TLS certificates, the certFile must be configured. Verify that servingInfo has the certFile configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

servingInfo:
  clientCA: ca.crt
  certFile: master.server.crt
  keyFile: master.server.key

Rationale:

API Server communication contains sensitive parameters that should remain encrypted in transit. Configure the API Server to serve only HTTPS traffic.

Severity:  medium

References:  1.1.38

Enable the AlwaysPullImages Admission Control Plugin   [ref]rule

To ensure credentials are required to pull images, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the admissionConfig to include AlwaysPullImages:

admissionConfig:
  pluginConfig:
    AlwaysPullImages:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false

Rationale:

Setting admission control policy to include AlwaysPullImages forces every new pod to pull the required images during every build. In a multi-tenant cluster users can be assured that private images can only be used by those who have the credentials to pull them. Without this admission control policy, once an image has been pulled to a node, any pod from any user can use it simply by knowing the image's name (without any authorization check against the image access control lists). When this plugin is enabled, images are always pulled prior to starting containers and forces authorization.

Severity:  high

References:  1.1.14

Configure the kubelet Certificate File for the API Server   [ref]rule

To enable certificate based kubelet authentication, follow the OpenShift documentation and setup the TLS connection between the API Server and kubelets. Then, verify that kubeletClientInfo has the certFile configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

kubeletClientInfo:
  ca: ca-bundle.crt
  certFile: master.kubelet-client.crt
  keyFile: master.kubelet-client.key

Rationale:

By default the API Server does not authenticate itself to the kublet's HTTPS endpoints. Requests from the API Server are treated anonymously. Configuring certificate-based kubelet authentication ensures that the API Server authenticates itself to kubelets when submitting requests.

Severity:  high

References:  1.1.32

Configure the API Server Request Timeout   [ref]rule

All components that use the API should connect via the secured port, authenticate themselves, and be authorized to use the API. To ensure such a configuration, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the request-timeout to 300:

kubernetesMasterConfig:
  apiServerArguments:
    request-timeout:
    - 300

Rationale:

Setting global request timout allows extending the API Server request timeout limit to a duration appropriate to the user's connection speed. By default, it is set to 60 seconds which might be problematic on slower connections making cluster resources inaccessible once the data volume for requests exceeds what can be transmitted in 60 seconds. But, setting this timeout limit to be too large can exhaust the API Server resources making it prone to Denial-of-Service attack. It is recommended to set this limit as appropriate and change the default limit of 60 seconds only if needed.

Severity:  medium

References:  1.1.48

Enable kubelet HTTPS connections to the API Server   [ref]rule

HTTPS should be used for connections between the API Server and Kubelets. Edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and remove the kubelet-https parameter. This will ensure communications are encrypted using TLS (the default setting).

kubernetesMasterConfig:
  apiServerArguments:
    kubelet-https:
    - 'false'

Rationale:

Connections from the API Server to Kubelets could potentially carry sensitive data such as secrets and keys. It is important to use in-transit encryption for any communication between the API Server and the Kubelets.

Severity:  medium

References:  1.1.4

Configure the etcd Certificate for the API Server   [ref]rule

To ensure etcd is configured to make use of TLS encryption for client communications, follow the OpenShift documentation and setup the TLS connection between the API Server and etcd. Then, verify that etcdClientInfo has the certFile configured in the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) to something similar to:

etcdClientInfo:
  ca: master.etcd-ca.crt
  certFile: master.etcd-client.crt
  keyFile: master.etcd-client.key

Rationale:

etcd is a highly-available key-value store used by OpenShift deployments for persistent storage of all REST API objects. These objects are sensitive in nature and should be protected by client authentication. This requires the API Server to identify itself to the etcd server using a client certificate and key.

Severity:  medium

References:  1.1.36

Configure the Encryption Provider   [ref]rule

To encrypt the etcd key-value store, follow the OpenShift documentation and configure a EncryptionConfig file. Then, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set experimental-encryption-provider-config to the path of that file:

kubernetesMasterConfig:
  apiServerArguments:
    experimental-encryption-provider-config:
    - /etc/origin/master/encryption-config.yaml

Rationale:

etcd is a highly available key-value store used by OpenShift deployments for persistent storage of all REST API objects. These objects are sensitive in nature and should be encrypted at rest to avoid any disclosures.

Severity:  medium

References:  1.1.44

Disable Insecure Port Access   [ref]rule

All components that use the API should connect via the secured port, authenticate themselves, and be authorized to use the API. To ensure such a configuration, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the insecure-port to 0:

kubernetesMasterConfig:
  apiServerArguments:
    insecure-port:
    - 0

Rationale:

Configuring the API Server on an insecure port would allow unauthenticated and unencrypted access to your master node(s). It is assumed firewall rules will be configured to ensure this port is not reachable from outside the cluster, however as a defense in depth measure, OpenShift should not be configured to use insecure ports.

Severity:  medium

References:  1.1.6

Enable the NamespaceLifecyle Admission Control Plugin   [ref]rule

To enable NamespaceLifecycle, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and set the admissionConfig to include NamespaceLifecyle:

admissionConfig:
  pluginConfig:
    NamespaceLifecyle:
      configuration:
      kind: DefaultAdmissionConfig
      apiVersion: v1
      disable: false

Rationale:

Setting admission control policy to NamespaceLifecycle ensures that objects cannot be created in non-existent namespaces, and that namespaces undergoing termination are not used for creating new objects. This is recommended to enforce the integrity of the namespace termination process and also for the availability of new objects.

Severity:  medium

References:  1.1.19

Configure the Encryption Provider Cipher   [ref]rule

To configure OpenShift to use the aescbc encryption provider, follow the OpenShift documentation and configure a EncryptionConfig file /etc/origin/master/encryption-config.yaml. In this file, choose aescbc as the encryption provider:

kind: EncryptionConfig
apiVersion: v1
resources:
  - resources:
    - secrets
    providers:
    - aescbc:
        keys:
        - name: key1
          secret: 32-byte base64-encoded secret

Rationale:

aescbc is currently the strongest encryption provider, it should be preferred over other providers.

Severity:  medium

References:  1.1.45

Enable the Secure Port for the API Server   [ref]rule

To ensure traffic is served over HTTPS, edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and either remove the secure-port or set it to a different (non-zero) desired port.

kubernetesMasterConfig:
  apiServerArguments:
    secure-port:
    - 8443

Rationale:

The secure port is used to serve HTTPS with authentication and authorization. If secure-port is disabled, as indicated with a value of 0, HTTPS traffic will not be served and all traffic will be unencrypted.

Severity:  medium

References:  1.1.7

Disable Use of the Insecure Bind Address   [ref]rule

OpenShift should not bind to non-loopback insecure addresses. Edit the API Server pod specification file /etc/origin/master/master-config.yaml on the master node(s) and remove the insecure-bind-address parameter.

kubernetesMasterConfig:
  apiServerArguments:
    insecure-bind-address:
    - 127.0.0.1

Rationale:

If the API Server is bound to an insecure address the installation would be susceptible to unauthented and unencrypted access to the master node(s). The API Server does not perform authentication checking for insecure binds and the traffic is generally not encrypted.

Severity:  medium

References:  1.1.5

Red Hat and Red Hat Enterprise Linux are either registered trademarks or trademarks of Red Hat, Inc. in the United States and other countries. All other names are registered trademarks or trademarks of their respective companies.