CIS コンプライアンスの構成とチェック

このドキュメントでは、CIS ベンチマークの概要、ベンチマークと Container-Optimized OS(COS)の関係、インスタンスのコンプライアンス ステータスの監査方法、障害発生時のトラブルシューティング方法について説明します。

概要

Center for Internet Security(CIS)では、さまざまなプラットフォームでのおすすめのセキュリティに関するベンチマークを公開しています。Container-Optimized OS CIS Benchmark は、Container-Optimized OS を使用して強固なセキュリティ体制をサポートするインスタンスを構成するための一連の推奨事項です。 COS x86 イメージと ARM イメージはどちらも CIS に準拠しています。

ベンチマークへのアクセス

Container-Optimized OS CIS ベンチマークは CIS ウェブサイトで入手できます。

セキュリティの推奨事項レベル

CIS は、次のような Container-Optimized OS の推奨レベルを定義しています。

レベル 1

このレベルの推奨事項は、大半の環境に適用できることを意味しています。 このレベルには、次のような推奨事項が含まれます。

  • アドレス空間配置のランダム化が有効になっている
  • 実行可能バイナリの実行に /tmp は使用できない
  • パケット リダイレクト送信が無効になっている

レベル 2

このレベルの推奨事項は、レベル 1 の推奨事項を拡張し、より厳密なセキュリティ環境を実現します。レベル 2 の推奨事項は、アプリケーションの変更が必要となる可能性があるため、必ずしもすべてのケースに適用できるわけではありません。推奨事項は、適用する前に環境ごとにレベル 2 で評価する必要があります。このレベルには、次のような推奨事項が含まれます。

  • 開放しているポートすべてにファイアウォール ルールが存在する
  • ICMP のリダイレクトとルーター アドバタイズは受け入れられません
  • デフォルトのユーザーシェル タイムアウトが 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 のコンプライアンスを 1 回だけチェックします。定期的なコンプライアンス チェックを構成するには、CIS コンプライアンス ステータスの定期的なチェックをご覧ください。

CIS レベル 2 のコンプライアンスを構成し、ステータスを確認する

cis-level2 サービスを使用すると、CIS レベル 2 に準拠するようにインスタンスを構成し、レベル 1 とレベル 2 の両方に対するコンプライアンス ステータスを確認できます。systemd サービスは、以下を除き、すべての CIS レベル 2 の推奨事項をサポートします。

  • 4.1.1.2 Logging が実行されていることを確認する(ID: logging-service-running)

    この推奨事項はデフォルトで無効になっていますが、/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 への準拠を 1 回だけチェックします。定期的なコンプライアンス チェックを構成するには、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 を定期的に実行します。デフォルトの間隔は 1 日 1 回です。

Scanner サービスを構成する

cis-compliance-scanner.service は、/etc/cis-scanner/env_vars で定義された環境変数に基づいて、CIS コンプライアンスのステータスを確認します。デフォルトでは、このサービスは CIS レベル 1 のコンプライアンスを確認します。

CIS レベル 2 への準拠を確認するには、/etc/cis-scanner/env_varsLEVEL 環境変数を 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 は 1 日に 1 回 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

この例では、スキャナ期間を 1 時間に 1 回に設定します。

変更を適用するには、systemd ユニットを再読み込みします。

systemctl daemon-reload

特定の CIS コンプライアンス チェックを無効にする

CIS レベル 1 とレベル 2 の推奨事項は、ほとんどの環境に適用できるようになっています。ただし、特定の環境には推奨事項が該当しない場合があります。特定の推奨事項を無効にするには、/etc/cis-scanner/env_varsEXTRA_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 ポリシーを使用して、インスタンスのコンプライアンス チェック プロセスを自動化できます。次の例は、各ツールのユースケースを示しています。

  • 例 1: 1 日に 1 回、CIS レベル 1 への準拠を確認する。
  • 例 2: 1 時間に 1 回、CIS レベル 1 への準拠を確認する。
  • 例 3: 1 日に 1 回、CIS レベル 2 への準拠を確認する。
  • 例 4: 特定の CIS コンプライアンス チェックを無効にする。

cloud-init の使用

以下の例を試す前に、cloud-config 形式での cloud-init の使用の説明に沿って、cloud-init を使用して COS インスタンスを構成する方法を確認してください。

例 1

次の構成例では、CIS レベル 1 の定期的なスキャンをデフォルトの周期である 1 日に 1 回開始します。

#cloud-config

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

例 2

次の例では、CIS レベル 1 の定期的なスキャンを 1 時間に 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 の定期的なスキャンをデフォルトの周期である 1 日 1 回構成しています。

#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

次の例では、スキャナが 1 日に 1 回実行されるように構成し、特定の 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

OS ポリシーの使用

OS ポリシーを使用して、CIS ベンチマーク スキャンを構成できます。始める前に、OS ポリシー(次の内容を含む)について理解しておいてください。

さらに、次のデプロイ例では instanceFilter オプションと rollout オプションを追加する必要があります。

例 1

次の構成例では、CIS レベル 1 の定期的なスキャンをデフォルトの周期である 1 日に 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 の定期的なスキャンを 1 時間に 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 の定期的なスキャンをデフォルトの周期である 1 日 1 回構成しています。

# 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

次の例では、スキャナが 1 日に 1 回実行されるように構成し、特定の 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 を調べます。