mSCPとJamf Pro APIによるmacOSセキュリティ設定の手動IaC化の試行

この記事は、Mercari Advent Calendar 2024 の16日目の記事です。

メルカリでは多くの従業員の業務端末にMacbookを用いています。Security チームがmacOSのセキュリティ設定に関わる一連の作業品質・効率改善のため、設定内容の手動IaC化(Infrastructure as Code)を検討・試行した際の技術や課題に関わる所見について紹介します。

概要

この記事では、macOSのセキュリティ設定に関わる一部の作業を自動化し、作業効率を改善するための取り組みについてご紹介します。具体的には、macOS Security Compliance Project (以降mSCP)とJamf Proという2つのツールを組み合わせることで、macOSのセキュリティ設定をコード化しGitHub上で管理する手法となります。これは、将来的なGitOps化の前段階の位置づけです。

mSCPは、さまざまなコンプライアンスガイドラインに基づいたセキュリティ設定のベースラインを自動生成するツールです。一方、Jamf Proは、MDM(モバイルデバイス管理)ツールとして、macOS端末を一元的に管理します。これら2つのツールを連携させることで、以下のメリットが得られます。

  • 設定情報をコード化しバージョン管理することで、設定変更のトレーサビリティを確保し、監査性を高めます。
  • 設定変更作業の自動化により、人的ミスを減らし、複数環境への展開を容易にします。
  • GitHubのpull request機能を活用し、変更要求ごとにコードレビューと承認プロセスを設けることで、誤った設定変更のリスクを低減します。

また、Jamf APIを用いてmSCPの設定内容を含めたJamf Proの構成をコード化する方法とその考慮点についても触れています。これにより、よりシームレスなプロセス自動化を実現することができます。

本記事では、mSCPとJamf Proを組み合わせたmacOSセキュリティ設定の自動化の実例を交えながら、そのメリットや課題、今後の展望について説明しています。macOSのセキュリティ設定の管理に課題を抱えているセキュリティエンジニアやシステム管理者の参考となれば幸いです。

セキュリティ設定のライフサイクル

macOSのセキュリティ設定は利用者端末への配布までさまざまな検討・作業が必要となります。まず、セキュリティ設定配布に関わる作業例について下表に紹介します。

表1:セキュリティ設定のフェージング例

No フェーズ 内容
1 設計 設定内容や配布スコープの定義。設定配布の目的・背景や配布に伴う利用者側への影響の試算
2 実装 設計に基づきセキュリティ設定のためのMDM管理ツール上の手順書等を作成
3 テスト 実装した設定値が有効かを検証機で検証
4 配布 実装した設定を本番の端末環境へ配布
5 監視運用 配布された設定が適切に適用されるかどうかをMDM管理ツール側及び端末側の双方で確認

そして、一連の作業は一過性のものでは無く、OSのバージョン・アップやOS開発元の仕様変更、業務・セキュリティ要件等に伴い、設定の見直しが一定頻度で発生するサイクリックな作業となります。
フェーズ毎の作業の重みは変更内容により変わりますが、作業品質を保ちながら各フェーズを全て手動で実施・管理していくことは人的な工数が多くかかる見込のため、一部自動化を試行し始めました。

macOS Security Compliance Project (mSCP) とは

表題の前の助走的な位置づけとして、mSCPの内容について紹介します。mSCPはmacOSのセキュリティ設定を自動作成するためのCLI(Command Line Interface)ツールであり、各種のコンプライアンスガイドライン(※1)に基づいたベースライン(プリセット)を作成可能です。GitHub上でオープンソースとして開発・配布されており、主には下記の機能を提供しています。

※1: NIST 800-53、800-171、DiSA-STIG、CIS Benchmarks, CMMC, CNSSI等

  1. YAML形式のテキストファイル編集によるベースラインや設定値のカスタマイズ
  2. セキュリティ設定用の構成プロファイルやスクリプトの作成。尚、スクリプトには構成プロファイル含む全対象設定のチェック機能(除外設定管理)も含まれる。
  3. 設定内容に関わるドキュメント生成(adoc, html, json, pdf, xls形式に対応)
title: "タイトル"
description: "概要"
authors: "作成者・チーム名等"
parent_values: "cis_lvl1"
profile:
  - section: "auditing"
    rules:
      - audit_acls_files_configure
      - audit_acls_folders_configure
      - audit_auditd_enabled
<中略>
  - section: "macos"
    rules:
<中略>
  - section: "passwordpolicy"
    rules:
<中略>
  - section: "systemsettings"
    rules:
<後略>

2024年時点でmSCPでは約200項目のセキュリティ設定を構成プロファイルとスクリプトで適用可能です。mSCPを活用することにより、例えば、上表No.1, 2の設計・実装フェーズにおいては以下の様に変更可能です:

  1. mSCPで設定可能な全項目に関わるドキュメント生成(例:Microsoft Excelブック形式)
  2. 設計のベースとなるコンプライアンスガイドラインの内容をスプレッドシート化
  3. No.1, 2で作成したシートを1つのシートに統合
  4. 統合シートで必要に応じて「現状の設定値」や「変更予定の設定値」「変更理由やその影響」列を追加し変更予定内容を関係者内で評価
  5. 確定した設定値でシートをフィルターしRuleID(mSCPにおける設定項目の識別名)をYAMLファイルへコピー&ペースト
  6. mSCPコマンドにより構成プロファイル・スクリプトの作成

この統合シートの利点としては、設定内容に付随する背景・外部のガイドラインとの差異を一元的に管理し、仮にmSCPにおける設定内容が更新されてもRuleIDやCCE(NISTのCommon Configuration Enumeration)等の識別子で再マッピングが比較的容易に可能なことです。もちろん、設定内容の説明先やその背景に応じてより要約・抽象化する必要はありますが、そのベースの資料としてはこちらのシート一つで収められます。

また、上記リストNo.6「mSCPコマンドにより構成プロファイル・スクリプトの作成」においてもmSCPがGitHubでバージョン管理されているため、GitHub Actions workflowへ組み込み、設定の自動作成を行う場合、mSCPの特定のコミットバージョンを指定して作成することが可能です。
以下はworkflow YAMLファイルの作成例となります。

<前略>
jobs:
  build:
    runs-on: example-env # <適切なrunner環境名を指定>
    steps:
      - name: Checkout this repository
        uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4

      - name: Checkout mSCP repository
        uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
        with:
          repository: usnistgov/macos_security
          ref: '6b4330120592baf7f5a696764e67f2fbd0eaaa3a' # tested version
          path: 'macos_security'

      - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
        with:
          python-version: '3.11'
      - name: Install pip
        run: python -m ensurepip --upgrade

      - name: Install Ruby and Bundler
        run: |
          sudo apt-get update
          sudo apt-get install -y ruby-full
          sudo gem install bundler

      - name: Install dependencies for mSCP
        run: |
          cd macos_security
          pip install -r requirements.txt
          bundle install --binstubs --path mscp_gems
          ls -la

      - name: Copy mSCP configuration files to cloned macos_security repository
        run: |
          cp -r ./macos/mSCP/baselines ./macos_security/build/
          cp -r ./macos/mSCP/custom/rules/* ./macos_security/custom/rules/
          cp ./macos/mSCP/logo_corporate.png ./macos_security/scripts/logo_corporate.png

      - name: Generate mSCP guidelines
        run: |
          cd macos_security
          ./scripts/generate_guidance.py -p build/baselines/sample_baseline.yaml -l logo_corporate.png -s -x
<後略(作成したファイルの保管やrunner環境によっては自動テスト実行を必要に応じて追加)>

また、上表No.3のテストフェーズにおける検証環境への設定配布に際しては、これまでMDM管理ツールなどのWeb UIベースでの手動設定から、mSCPで生成された設定ファイルのアップロードによって一部の設定項目を代替し、さらにチェックスクリプトを用いることで手動・目視での確認項目を削減することができます。

mSCPとJamf Proを組み合わせる利点

メルカリではMDM管理ツールとしてJamf Proを利用していますが、mSCPと組み合わせることで上表No.5 監視運用フェーズにおける利点についても紹介します。Jamf Proには管理対象のコンピュータ情報(名前、モデル名、シリアル番 等)について管理者側で新たな属性を追加できる、「拡張属性」機能があります。この拡張属性にはスクリプトの実行結果を設定できるため、mSCPのチェックスクリプトの実行結果を抽出・整形し下図の様に属性値としてJamf Pro上に登録することが可能です(※3)。
※3:https://github.com/jordanburnette/mSCP_EAs

下図は対象端末の属性情報一覧の一例ですが、「Baseline – Failed Count」項目は構成プロファイルや設定スクリプトで適用できなかった設定項目数を記載しています。

mSCP_EA_Sample

図1:mSCPの適用結果を抽出する拡張属性(引用元:https://raw.githubusercontent.com/jordanburnette/mSCP_EAs/refs/heads/main/mSCP_EA_Sample.png

Jamf Pro上ではスマートコンピュータグループの設定にて、拡張属性の値を対象端末を絞り込む検索クライテリアとして設定可能であり、例えば下図の2段目の式で「Baseline – Failed Count」> 0の端末の抽出が可能です。

mscp_non_compliant_jamf_smart_computer_group

図2:スマートコンピュータグループのクライテリア設定画面

端末側で設定が適用されない状態は、さまざまな要因が考えられますが、ここでは単純に、端末利用者が一時的にローカル管理者権限を借用の上、システム設定を変更し、変更後の戻し忘れと仮定しましょう。仮に対象の設定がmSCPスクリプトで設定可能であれば、Jamf Pro上のポリシーのスコープ設定にて上記のスマート・コンピュータグループを設定し、適当な「トリガー」や「実行頻度」を設定することで、自動で設定の再適用が可能です。

mSCPを利用する上での考慮点

mSCPを利用する利点がある一方で、mSCPが作成する各種の設定ファイルを適切に管理する必要があります。下記は約100項目のmSCP Ruleを設定したカスタムベースラインYAMLをもとに作成した設定ファイル一覧です。

build/sample_baseline
├── sample_baseline_compliance.sh
<中略>
├── mobileconfigs
│   ├── preferences
│   │   ├── com.apple.MCX.plist
│   │   ├── com.apple.Safari.plist
│   │   ├── com.apple.SoftwareUpdate.plist
│   │   ├── com.apple.SubmitDiagInfo.plist
│   │   ├── com.apple.Terminal.plist
│   │   ├── com.apple.applicationaccess.plist
│   │   ├── com.apple.controlcenter.plist
│   │   ├── com.apple.loginwindow.plist
│   │   ├── com.apple.mDNSResponder.plist
│   │   ├── com.apple.mobiledevice.passwordpolicy.plist
│   │   ├── com.apple.preferences.sharing.SharingPrefsExtension.plist
│   │   ├── com.apple.screensaver.plist
│   │   ├── com.apple.security.firewall.plist
│   │   ├── com.apple.systempolicy.control.plist
│   │   └── com.apple.timed.plist
│   └── unsigned
│       ├── com.apple.MCX.mobileconfig
│       ├── com.apple.ManagedClient.preferences.mobileconfig
│       ├── com.apple.Safari.mobileconfig
│       ├── com.apple.SoftwareUpdate.mobileconfig
│       ├── com.apple.SubmitDiagInfo.mobileconfig
│       ├── com.apple.Terminal.mobileconfig
│       ├── com.apple.applicationaccess.mobileconfig
│       ├── com.apple.controlcenter.mobileconfig
│       ├── com.apple.loginwindow.mobileconfig
│       ├── com.apple.mDNSResponder.mobileconfig
│       ├── com.apple.mobiledevice.passwordpolicy.mobileconfig
│       ├── com.apple.preferences.sharing.SharingPrefsExtension.mobileconfig
│       ├── com.apple.screensaver.mobileconfig
│       ├── com.apple.security.firewall.mobileconfig
│       └── com.apple.systempolicy.control.mobileconfig
└── preferences
    └── org.sample_baseline.audit.plist

構成プロファイル経由で設定する内容はmobileconfigsサブディレクトリ配下にありますが、.plist、 .mobileconfigファイルは各々14、15ファイルに及びます。基本的にはplistかmobileconfigのどちら一方のファイル群を配布することで所定の設定が適用されますが、mSCPのバージョンや適用対象端末のOSバージョンの組み合わせによっては、mobileconfigかplistファイルの一方でのみ有効な設定があることを確認しています。
mSCPはApple社やJamf社の公式サイトで紹介されているツールではありますが(※4)、位置づけとしてはサードパーティツールであり、本番適用に際しては事前にmSCPを利用者側で検証する必要があります。

※4

このことは、上表No.3 テストフェーズにおける実機検証において、検証パターンの増加に伴うJamf Proへのファイルアップロード回数の増加を意味します。その回数も適用するベースラインの数、適用対象テナント数、試行回数の乗算となり、加えて各ファイルのスコープ設定の調整を踏まえるとWeb UI上での操作数は相応の規模となり、操作数に比例しオペレーションリスクを増加させる要因にもなります。

Jamf APIを用いた構成のコード化

前述のようなリスクや手動での操作を低減し一連の配布作業・管理を効率化するためにJamf APIを用いてmSCP設定内容を含めたJamf Pro構成のコード化(YAML形式のテキストファイル)を試行しました。こちらの手法についてはJNUC 2021(※5)で紹介されたセッションを参考にしています。
※5: https://www.jamf.com/blog/github-as-the-source-of-truth-for-configuration-in-jamf-pro/

Jamf社はClassic APIとJamf Pro APIの2種類のAPIを提供しておりmSCPに関連するコンポーネントを取得・更新するためのAPI概要は以下のとおりです。

表2:mSCPに関わる各Jamf ProコンポーネントのAPI種別

No コンポーネント名 API種別 データ形式
1 カテゴリー Jamf Pro JSON
2 コンピュータグループ Classic XML
3 拡張属性 Jamf Pro JSON
4 macOS構成プロファイル Classic XML
5 ポリシー Classic XML
6 スクリプト Jamf Pro JSON

そして、2024年時点では公式が提供するTerraform providerやAPIラッパーライブラリーが存在しないことから、実装の投資対効果を踏まえて上記のコンポーネントの管理に特化したAPIラッパーや関連するサービスロジックを実装しました。以下はそのプログラムディレクトリ構造例です。

.
<前略>
├── cmd
│   └── main.go
├── go.mod
├── go.sum
├── internal
│   ├── api
│   │   ├── category.go
│   │   ├── client.go
│   │   ├── computer_group.go
│   │   ├── configuration_profile.go
│   │   ├── extension_attribute.go
│   │   ├── policy.go
│   │   └── script.go
<中略>
│   ├── service
│   │   ├── category.go
│   │   ├── computer_group.go
│   │   ├── configuration_profile.go
│   │   ├── extension_attribute.go
│   │   ├── factory.go
│   │   ├── policy.go
│   │   ├── script.go
│   │   └── service.go
│   └── util
│       ├── compare.go
│       └── file.go
<後略>

また、上記のプログラムの構成としては下表のとおりです。

表3:各フォルダ配下のプログラム処理概要

No フォルダ名 処理概要
1 cmd プログラムのエントリーポイントであり、コマンドライン引数やクレデンシャル情報の処理や後述のserviceの生成・実行等
2 service ビジネスロジックの実装箇所。後述のapi、util内の関数等を用いてJamf Proコンポーネントのコード化や、コードとの差分確認、及びJamf Pro側へ適用等
3 api Jamf Classic / Pro API双方に対応したAPIラッパー。Jamf Pro上の構成情報を取得、更新等
4 util 各種コンポーネント横断で利用する処理を共通化した関数群
・YAMLファイル化した構成定義とJamf Pro上の構成の差分確認を行う
・YAMLファイルの読み込みや書き出し処理

こちらのプログラムを用い、先ほどWeb UIで設定したスマート・コンピュータグループをYAMLファイルへエクスポートすると以下の様になります。(一部の値を掲載用に変更しています)

id: 999
name: mSCP - sample_baseline - NonCompliant
is_smart: true
site:
  id: -1
  name: NONE
criteria:
  size: 2
  criterion:
  - name: Computer Group
    and_or: and
    search_type: member of
    value: xxxxx_group
  - name: mSCP - Failed Results Count
    priority: 1
    and_or: and
    search_type: more than
    value: "0"

上記の様な単純なクライテリア設定であればWebUIと作業工数はあまり変わらないですが、クライテリア条件の増加やグルーピングの修正等が発生する場合は、YAMLテキストファイル上で修正しAPI経由で更新する手法が効率的です。

Jamf ProにおけるWeb UI設定内容をAPI経由で取り扱う際の考慮点

コード化に伴い、設定作業者はWeb UIに代わり、YAMLファイルの編集に注力することが可能ですが、Jamf ProはWeb UI経由での設定した内容については、UIには現れない部分であるものの、API経由で設定を管理する際の考慮点があり、下表に検証・試行の中で確認した主な例を紹介します。

表4:API経由でJamf Proコンポーネントを管理する際の考慮点

No 考慮点 詳細
1 改行コードの取り扱い Web UIで設定した内容をAPI経由で取得する場合、改行コードが\r\n となる要素があります。(例:拡張属性やスクリプトのscriptContents等)
2 構成プロファイルにおけるペイロードの要素 mSCPにおいてWeb UI経由で初回アップロードした場合は一部の要素が追加・編集されます(例: PayloadRemovalDisallowed、PayloadIdentifier、PayloadUUID等)

これらの内容はJamf ProーYAMLファイル間の差分確認や、mSCP設定内容をAPI経由で更新する際に特に考慮する必要があります。

macOSセキュリティ設定のIaC化による利点の考察

弊社の試行に際しては上記の様なWeb UI側との差分の考慮などを踏まえて、GitHub Actions workflowを用いた全コンポーネントの完全なIaC化やGitOps化は現時点では行っておらず、一部手動で構成管理・適用を行う手法を採っています。但し、仮にIaC化を進めて行くと以下の様な利点があります。

表5:IaC化による主な利点の考察

No IaC化のポイント 考えられる主な利点
1 構成情報のコード化とAPI経由での構成適用 • Web UIベースでの設定手順書の作成が不要となり、設定作業者はYAMLファイルの編集で設定が可能となる。
• YAMLファイルのコメント記法を活用することで構成内容の補足説明を追記できる。
• Jamf Pro テナントをまたいだ構成の移行が容易になる。(例:検証テナント→本番テナント)
2 GitHub上で構成情報のバージョン管理とWorkflowによる自動化 • Jamf Pro標準の履歴機能より詳細な変更差分を残すことができ、定期的なバックアップ取得や、YAMLファイル内容とJamf Pro上の設定内容を比較処理を行うことで、意図せぬ変更の検知する運用を自動化できる。
• 変更の背景起因をPull Request(以降PRと表記)上に残すことができる。
• Branch protection rulesやCODEOWNERSファイルの設定を組み合わせることで、簡易的なワークフロー(起票〜レビュー・承認)を作成できる。
• Jamf Proの編集権限がないユーザにおいても、リポジトリへのwrite権限があれば設定変更のPR起票ができる 、Jamf Pro上の編集権限者を必要最小限に絞ることが可能。

os_security_configs_mgmt_diagram

まとめ

macOSのセキュリティ設定についてmSCPを活用した設定手法や多数の設定ファイルを管理する上で設定ファイルのコード化や、IaC化による利点などについて紹介しました。セキュリティ設定のライフサイクルを踏まえて、これらの要素を掛け合わせることで、プロセス全体の最適化に関わる考察を得られるよう努めました。
ここで記載された内容については全ての組織や環境に画一的に通じる方法では無く、またこの技術への投資における損益分岐点とその時期は組織ごとに異なります。実装寄りの記述も多数含む記載となりましたが、予め実装内容の解像度を上げることで、投資判断や技術負債化の予防の一助となれば幸いです。
メルカリのSecurity Teamでは、Jamf Proに限らずGoogle WorkspaceやOkta等の他のサービスのIaC化の実装へ投資し、設定自動化及び管理高度化を図っています。

Security Teamにおける採用情報についてはMercari Careerをご覧ください。

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加