配置和检查 CIS 合规性

本文档介绍了什么是 CIS 基准,该基准与 Container-Optimized OS (COS) 的关系,如何审核实例中的合规性状态,以及如何在失败时进行问题排查。

概览

互联网安全中心 (CIS) 发布了针对各种平台的最佳安全建议的基准。Container-Optimized OS CIS 基准是一组建议,用于配置使用 Container-Optimized OS 的实例,以支持可靠的安全状况。COS x86 和 ARM 映像均符合 CIS 标准。

访问基准

您可以通过 CIS 网站获取 Container-Optimized OS CIS 基准:

安全建议级别

CIS 为 Container-Optimized OS 定义了以下建议级别。

1 级

此级别的建议适用于大多数环境。此级别包括如下建议:

  • 已启用地址空间布局随机化
  • /tmp 不能用于运行可执行二进制文件
  • 数据包重定向发送功能已停用

2 级

此级别的建议扩展了第 1 级建议,从而打造了更严格的安全环境。2 级建议不一定适用于所有情况,因为可能需要更改应用。您应该先评估 2 级针对您环境的建议,然后再采纳。此级别包括如下建议:

  • 所有开放端口都存在防火墙规则
  • 不接受 ICMP 重定向和路由器通告
  • 默认用户 shell 超时不超过 900 秒

Container-Optimized OS 如何符合 CIS 基准

Milestone 97 开始,Container-Optimized OS 映像默认符合 CIS 级别 1 要求,并提供一个选项来遵从 CIS 级别 2。我们还提供了一个扫描器,可用于根据 CIS 建议级别审核您的实例。

定义推荐的 CIS 配置位于 /usr/share/google/security/cis-compliance/cis_config.textproto 中。CIS 扫描器使用配置来检查实例的合规性状态。CIS 级合规性扫描程序每次运行的结果都会写入 /var/lib/google/cis_scanner_scan_result.textproto。每次运行 CIS 扫描器时,此文件都会被覆盖。如果 CIS 级别 1 或 2 级扫描失败,cis_scanner_scan_result.textproto 文件将包含所有失败检查的列表。

检查实例合规性状态

Container-Optimized OS 映像提供以下 systemd 服务,用于合规性检查和配置:

  • cis-level1.service:默认处于启用状态,并且会在启动时启动。当服务启动时,它会检查实例是否符合 CIS 级别 1。
  • cis-level2.service:默认处于停用状态。借助此服务,您可以将实例配置为符合 CIS 级别 2,并针对级别 1 和级别 2 检查合规性状态。

以下部分介绍了如何检查实例的合规性状态以及如何自动执行审核流程。

查看 CIS 1 级合规状态

如需查看您的实例是否符合 CIS 1 级要求,请检查 cis-level1.service 的状态:

systemctl status cis-level1

输出类似于以下内容:

Reading scan config from /usr/share/google/security/cis-compliance/cis_config.textproto
Running scan of 62 benchmarks
Scan status: SUCCEEDED
Found 0 non-compliant benchmarks
Writing scan results to /var/lib/google/cis_scanner_scan_result.textproto

如果发现任何不合规的检查,请参阅 CIS 合规性等级 1/2 级检查失败

cis-level1.service 仅在实例启动时检查一次 CIS 级别 1 合规性。如需配置定期合规性检查,请参阅定期检查 CIS 合规性状态

配置 CIS 2 级合规性并检查状态

您可以使用 cis-level2 服务将实例配置为符合 CIS 级别 2 要求,并针对级别 1 和级别 2 检查合规性状态。systemd 服务支持所有 CIS 2 级建议,但下列建议除外

  • 4.1.1.2 确保 Logging 正在运行(ID:logging-service-running)

    此建议默认处于停用状态,但可以重新启用,只需从拒绝列表中的 ID(可在 /etc/cis-scanner/env_vars 文件中找到)中删除相应 ID 即可。此检查仅存在于里程碑 109 及更高版本中。在早期里程碑中,自行启用 Logging 可让您遵循此建议。如果您撤消停用操作,则运行 cis-level2 服务会运行启动 fluent-bit 日志记录的脚本。如果您不想使用我们的默认日志记录或希望使用自己的日志记录,请让 logging-service-running 保持停用状态。

对于以下建议,cis-level2 服务会配置实例,但不验证合规性状态:

  • 105 及更低版本:

    • 3.3.1.1 确保 IPv6 默认拒绝防火墙政策
    • 3.3.1.2 确保已配置 IPv6 环回流量
    • 3.3.1.3 确保已配置 IPv6 出站和已建立的连接
    • 3.3.1.4 确保所有开放端口都存在 IPv6 防火墙规则
    • 3.3.2.1 确保默认的拒绝防火墙政策
    • 3.3.2.2 确保已配置环回流量
    • 3.3.2.3 确保已配置出站和已建立的连接
  • 109 及更高版本:

    • 3.3.1.4 确保所有开放端口都存在 IPv6 防火墙规则

cis-level2 服务默认处于停用状态。如需启动服务,请运行以下命令:

systemctl start cis-level2.service

如需查看您的实例是否配置成功以及是否符合 CIS 2 级建议,请检查 cis-level2.service 的状态:

systemctl status cis-level2

输出类似于以下内容:

Reading scan config from /usr/share/google/security/cis-compliance/cis_config.textproto
Running scan of 112 benchmarks
Scan status: SUCCEEDED
Found 0 non-compliant benchmarks
Writing scan results to /var/lib/google/cis_scanner_scan_result.textproto

如果实例配置失败,或发现任何不合规的检查,请参阅问题排查

cis-level2 服务会配置实例并仅检查一次 CIS 级别 2 合规性。如需配置定期合规性检查,请参阅定期检查 CIS 合规性状态

定期检查 CIS 合规状态

Container-Optimized OS 映像包含以下服务,用于定期检查 CIS 合规性:

  • cis-compliance-scanner.service:根据 /etc/cis-scanner/env_vars 中定义的环境变量检查合规性状态。默认情况下,此服务会检查 CIS 级别 1 合规性并被停用。
  • cis-compliance-scanner.timer:定期运行 cis-compliance-scanner.service。默认周期为每天一次。

配置扫描器服务

cis-compliance-scanner.service 负责根据在 /etc/cis-scanner/env_vars 中定义的环境变量检查 CIS 合规性的状态。默认情况下,此服务会检查 CIS 级别 1 合规性。

如需检查 CIS 级别 2 的合规性,请将 /etc/cis-scanner/env_vars 中的 LEVEL 环境变量设置为 2/etc/cis-scanner/env_vars 文件类似于以下内容:

# cis-compliance-scanner.service environment variables
# The config file defines which checks to perform by cis_scanner
CONFIG="/usr/share/google/security/cis-compliance/cis_config.textproto"
# Where to store the result of the scan
RESULT="/var/lib/google/cis_scanner_scan_result.textproto"
# Upto which level to scan. It can be 1 or 2
LEVEL="2"
# Extra options that can be passed to cis_scanner
# For valid options, see output of `cis_scanner -h`
EXTRA_OPTIONS=""

配置计时器

如需设置定期合规性扫描,请启动 cis-compliance-scanner.timer 单元:

systemctl start cis-compliance-scanner.timer

默认情况下,cis-compliance-scanner.timer 每天启动一次 cis-compliance-scanner.service。如需更改扫描周期,请替换 cis-compliance-scanner.timer 单元的 OnUnitActiveSec 字段:

sudo mkdir /etc/systemd/system/cis-compliance-scanner.timer.d
sudo tee /etc/systemd/system/cis-compliance-scanner.timer.d/override.conf <<EOF
[Unit]
Description=Run CIS Scanner once an hour
[Timer]
OnUnitActiveSec=1h
EOF

本示例将扫描程序周期设置为每小时一次。

如需应用更改,请重新加载 systemd 单元:

systemctl daemon-reload

选择停用特定的 CIS 合规性检查

CIS 1 级和 2 级建议适用于大多数环境。但是,某些建议可能不适用于您的特定环境。如需选择停用特定建议,请在 /etc/cis-scanner/env_vars 中使用 EXTRA_OPTIONS 环境变量。

以下示例 env_vars 文件停用了 etc-passwd-permissions 建议:

# cis-compliance-scanner.service environment variables
# The config file defines which checks to perform by cis_scanner
CONFIG="/usr/share/google/security/cis-compliance/cis_config.textproto"
# Where to store the result of the scan
RESULT="/var/lib/google/cis_scanner_scan_result.textproto"
# Upto which level to scan. It can be 1 or 2
LEVEL="1"
# Extra options that can be passed to cis_scanner
# For valid options:`cis_scanner -h`
EXTRA_OPTIONS="--benchmark-opt-out-ids=etc-passwd-permissions"

自动启用和检查 CIS 合规性状态

您可以使用 cloud-init 或 OS Policy 自动执行实例合规性检查流程。以下示例展示了每种工具的一些使用场景:

  • 示例 1:每天检查一次 CIS 1 级合规性。
  • 示例 2:每小时检查一次 CIS 级别 1 合规性。
  • 示例 3:每天检查一次 CIS 级别 2 合规性。
  • 示例 4:选择退出特定的 CIS 合规性检查。

使用 cloud-init

在尝试以下示例之前,请确保您已按照以 Cloud config 格式使用 cloud-init 中的说明熟悉如何使用 cloud-init 配置 COS 实例。

示例 1

以下示例配置开始定期进行 CIS 级别 1 扫描,默认周期为每天一次。

#cloud-config

runcmd:
# Check the compliance status of the instance once a day.
- systemctl start cis-compliance-scanner.timer

示例 2

以下示例配置每小时一次的 CIS 级别 1 定期扫描。

#cloud-config

# Override cis-compliance-scanner.timer with 1 hour frequency.
write_files:

- path: /etc/systemd/system/cis-compliance-scanner.timer.d/override.conf
  permissions: 0600
  owner: root
  content: |
    [Unit]
    Description=Run CIS Scanner once an hour

    [Timer]
    OnUnitActiveSec=1h

runcmd:
# Reload systemd units.
- systemctl daemon-reload
# Check the compliance status of the instance once an hour.
- systemctl start cis-compliance-scanner.timer

示例 3

以下示例将 CIS 级别 2 定期扫描配置为每天一次的默认周期。

#cloud-config

runcmd:
# Configure the instance for CIS level 2.
- systemctl start cis-level2.service
# Change the scan level to CIS Level 2.
- sed -i 's/^LEVEL=.*$/LEVEL="2"/' /etc/cis-scanner/env_vars
# Check the compliance status of the instance once a day.
- systemctl start cis-compliance-scanner.timer

示例 4

以下示例将扫描程序配置为每天运行一次,并选择停用特定的 CIS 建议。

#cloud-config

runcmd:
# Opt-out of the etc-passwd-permissions check.
- sed -i 's/^EXTRA.*$/EXTRA_OPTIONS="--benchmark-opt-out-ids=etc-passwd-permissions"/' /etc/cis-scanner/env_vars
# Check the compliance of the instance once a day.
- systemctl start cis-compliance-scanner.timer

使用操作系统政策

您可以使用操作系统政策配置 CIS 基准扫描。在开始之前,请确保您熟悉操作系统政策,包括以下内容:

此外,您必须在以下示例中添加 instanceFilterrollout 选项进行部署。

示例 1

以下示例配置开始定期进行 CIS 级别 1 扫描,默认周期为每天一次。

# An OS policy to check CIS level 1 compliance once a day.
osPolicies:
- id: ensure-cis-level1-compliance-once-a-day-policy
  mode: ENFORCEMENT
  resourceGroups:
  - resources:
      id: ensure-cis-level1-compliance-once-a-day
      exec:
        validate:
          interpreter: SHELL
          # If cis-compliance-scanner.service is active, return an exit code
          # 100 to indicate that the instance is in compliant state.
          # Otherwise, return an exit code of 101 to run `enforce` step.
          script: |-
            is_active=$(systemctl is-active cis-compliance-scanner.timer)
            result=$(systemctl show -p Result --value cis-compliance-scanner.service)

            if [ "$is_active" == "active" ] && [ "$result" == "success" ]; then
              exit 100;
            else
              exit 101;
            fi
        enforce:
          interpreter: SHELL
          # COS 97 images are by-default CIS Level 1 compliant and there is no
          # additional configuration needed. However, if certain changes
          # cause non-compliance because of the workload on the instance, this
          # section can be used to automate to make fixes. For example, the
          # workload might generate a file that does not comply with the
          # recommended file permissions.
          # Return an exit code of 100 to indicate that the desired changes
          # successfully applied.
          script: |-
            # optional <your code>
            # Check the compliance of the instance once a day.
            systemctl start cis-compliance-scanner.timer && exit 100

示例 2

以下示例配置每小时一次的 CIS 级别 1 定期扫描。

# An OS policy to check CIS level 1 compliance once an hour.
osPolicies:
- id: ensure-cis-level1-compliance-once-an-hour-policy
  mode: ENFORCEMENT
  resourceGroups:
  - resources:
      id: ensure-cis-level1-compliance-once-an-hour
      exec:
        validate:
          interpreter: SHELL
          # If cis-compliance-scanner.service is active, return an exit code
          # 100 to indicate that the instance is in compliant state.
          # Otherwise, return an exit code of 101 to run `enforce` step.
          script: |-
            is_active=$(systemctl is-active cis-compliance-scanner.timer)
            result=$(systemctl show -p Result --value cis-compliance-scanner.service)

            if [ "$is_active" == "active" ] && [ "$result" == "success" ]; then
              exit 100;
            else
              exit 101;
            fi
        enforce:
          interpreter: SHELL
          # Return an exit code of 100 to indicate that the desired changes
          # were successfully applied.
          script: |-
            # Overwrite "OnUnitActiveSec" field of the
            # cis-compliance-scanner.timer to trigger
            # cis-compliance-scanner.service once an hour
            # instead of once a day.
            mkdir /etc/systemd/system/cis-compliance-scanner.timer.d
            tee /etc/systemd/system/cis-compliance-scanner.timer.d/override.conf <<EOF
            [Unit]
            Description=Run CIS Scanner once an hour

            [Timer]
            OnUnitActiveSec=1h
            EOF
            # Reload systemd units.
            systemctl daemon-reload
            # Check the compliance of the instance once an hour.
            systemctl start cis-compliance-scanner.timer && exit 100

示例 3

以下示例将 CIS 级别 2 定期扫描配置为每天一次的默认周期。

# An OS policy to check CIS level 2 compliance once a day.
osPolicies:
- id: ensure-cis-level2-compliance-once-a-day-policy
  mode: ENFORCEMENT
  resourceGroups:
  - resources:
      id: ensure-cis-level2-compliance-once-a-day
      exec:
        validate:
          interpreter: SHELL
          # If cis-compliance-scanner.service is active, return an exit code
          # 100 to indicate that the instance is in compliant state.
          # Otherwise, return an exit code of 101 to run `enforce` step.
          script: |-
            is_active=$(systemctl is-active cis-compliance-scanner.timer)
            result=$(systemctl show -p Result --value cis-compliance-scanner.service)

            if [ "$is_active" == "active" ] && [ "$result" == "success" ]; then
              exit 100;
            else
              exit 101;
            fi
        enforce:
          interpreter: SHELL
          # Return an exit code of 100 to indicate that the desired changes
          # were successfully applied.
          script: |-
            # Configure the instance for CIS level 2.
            systemctl start cis-level2.service
            # Change the scan level to 2.
            sed -i 's/^LEVEL=.*$/LEVEL="2"/' /etc/cis-scanner/env_vars
            # Check the compliance of the instance once a day.
            systemctl start cis-compliance-scanner.timer && exit 100

示例 4

以下示例将扫描程序配置为每天运行一次,并选择停用特定的 CIS 建议。

# An OS policy to opt-out of CIS check and check compliance status once a day.
osPolicies:
- id: exclude-cis-check-and-check-compliance-once-a-day-policy
  mode: ENFORCEMENT
  resourceGroups:
  - resources:
      id: exclude-cis-check-and-check-compliance-once-a-day
      exec:
        validate:
          interpreter: SHELL
          # If cis-compliance-scanner.service is active, return an exit code
          # 100 to indicate that the instance is in compliant state.
          # Otherwise, return an exit code of 101 to run `enforce` step.
          script: |-
            is_active=$(systemctl is-active cis-compliance-scanner.timer)
            result=$(systemctl show -p Result --value cis-compliance-scanner.service)

            if [ "$is_active" == "active" ] && [ "$result" == "success" ]; then
              exit 100;
            else
              exit 101;
            fi
        enforce:
          interpreter: SHELL
          # Return an exit code of 100 to indicate that the desired changes
          # were successfully applied.
          script: |-
            # Opt-out of the etc-passwd-permissions check.
            sed -i 's/^EXTRA.*$/EXTRA_OPTIONS="--benchmark-opt-out-ids=etc-passwd-permissions"/' /etc/cis-scanner/env_vars &&
            # Check the compliance of the instance once a day.
            systemctl start cis-compliance-scanner.timer
            # Ensure cis-compliance-scanner completes before exiting
            PID=$(systemctl show --property MainPID --value cis-compliance-scanner.service) &&
            timeout 5m bash -c -- 'while [ -e /proc/'$PID' ]; do echo "CIS Scanner with PID:'$PID' is still running"; sleep 1; done' &&
            exit 100

问题排查

本部分介绍如何解决与 CIS 基准扫描相关的问题。

无法将实例配置为符合 CIS 级别 2 建议

cis-level2 服务会先将实例配置为符合 CIS 级别 2 建议,然后检查其是否符合 CIS 级别 1 和级别 2。如果实例配置失败,cis-level2 服务会退出,并显示以下错误消息:

Job for cis-level2.service failed because the control process exited with error code.
See "systemctl status cis-level2.service" and "journalctl -xeu cis-level2.service" for details.

日志日志会提及未能应用于实例并导致 cis-level2 systemd 服务失败的建议。

CIS 合规性级别 1 或级别 2 检查失败

每次运行 CIS 级别合规性的扫描结果写入 /var/lib/google/cis_scanner_scan_result.textproto。如果 CIS 级别 1 或 2 级扫描失败,textproto 文件将包含所有失败检查的列表,如以下示例所示:

cat /var/lib/google/cis_scanner_scan_result.textproto

# Output
start_time: {
  seconds: 1648241700
  nanos: 763152171
}
end_time: {
  seconds: 1648241700
  nanos: 812992527
}
scanner_version: "1.1.4.3"
benchmark_version: "1.0.0"
status: {
  status: SUCCEEDED
}
non_compliant_benchmarks: {
  id: "etc-passwd-permissions"
  compliance_occurrence: {
    non_compliant_files: {
      path: "/etc/passwd"
      reason: "File permission is 0664, expected the following bits to be set: 0444 and the following bits to be clear: 0133"
    }
  }
}
compliant_benchmarks:  {
  id:  "etc-passwd-permissions"
  compliance_occurrence:  {}
}

如需减少失败的检查数量,请使用 CIS 基准,然后按照 Remediation 部分中的步骤检查失败的检查,以确保实例符合政策要求。如需查找哪项建议对应于 CIS 基准中的失败检查,请在位于 /usr/share/google/security/cis-compliance/cis_config.textproto 的 CIS 扫描器配置文件中查找 non_compliant_benchmark's ID。