# Macでのリモートアクション用スクリプトの作成

{% hint style="info" %}
この記事で説明されている操作の実行に助けが必要な場合は、Nexthink認定パートナーにお問い合わせください。
{% endhint %}

このページでは、Mac上でNexthinkのリモートアクションスクリプトを準備するプロセスの詳細を説明します。 スクリプトは、Unix系の多くのオペレーティングシステムでサポートされているコマンドラインシェルおよびスクリプティング言語であるBashで書かれた後、セキュリティーのために証明書で署名されます。 Bashスクリプトは、タスクの自動化や構成管理に適しており、リモートアクションを従業員のデバイスで実行することができます。

{% hint style="warning" %}
macOSデバイスでMobile Accountsが有効になっている場合、リモートアクションは現在サポートされていません。 このモードでは、アクションが成功したように見えることがありますが、実際には変更が適用されません。
{% endhint %}

リモートアクションの主な使用ケースは、デバイスからのオンデマンドデータ収集、自己修復タスク、および設定の変更を含みます。

この記事は、読者がBashスクリプティングに精通していることを前提としています。

詳細については、[Remote Actionsグループのコミュニティ](https://community.nexthink.com/s/group/0F92p000000kI80CAE)のドキュメントを参照してください。

{% hint style="info" %}
詳しくは、Nexthink Securityの\[Remote Actionsのセキュリティに関するベストプラクティス]\(<https://docs.nexthink.com/security/security-best-practices/remote-actions-security-best-practices)を参照してください。>
{% endhint %}

## スクリプトの作成

### 一般的なスクリプトと入力変数

デジタル署名されたスクリプトのカスタマイズが必要な場合に、汎用スクリプトは便利です。 署名済みスクリプトを変更するとその署名は無効になりますが、汎用スクリプトはパラメーターでカスタマイズでき、署名を保持します。

スクリプトの冒頭でパラメータを宣言し、Bashの位置パラメータとして次のように2つの特別なコメントの間に挿入します：

```
# NXT_PARAMETERS_BEGIN
Parameter1=$1
Parameter2=$2
Parameter3=$3
# NXT_PARAMETERS_END
```

リモートアクションの構成中にスクリプトをアップロードするとき、システムはBashスクリプト内の特別なNexthinkコメントの間にあるパラメーターを取得します。 それらをスクリプトテキストの下にある**パラメーター**セクションに一覧表示します。 各パラメータ名の右側に表示されたテキスト入力ボックスに、実際の値を提供してください。

{% hint style="info" %}
実際の値は常にテキストとしてスクリプトに渡されます。 スクリプトが**string**以外の型でパラメータを宣言している場合は、スクリプトが期待する型に変換できる値を提供してください。
{% endhint %}

### アウトプット変数の作成

スクリプトを実行すると、オンデマンドデータとして保存したいアウトプットが生成されることがあります。 Nexthinkは、Collectorと同時に従業員デバイスにインストールされるBashスクリプト（`nxt_ra_script_output.sh`）を提供しています。 このスクリプトには、結果をデータレイヤーに書き込むための関数が含まれています。

リモートアクションのアウトプットにNexthinkスクリプトの関数を使用するには、Bashスクリプトの最初に以下のヘッダーを追加してください。

```
#!/bin/bash
. "${NEXTHINK}"/bash/nxt_ra_script_output.sh
```

すべての書き込み方法は、アウトプット名と書き込む値の2つの引数を受け入れます。 例えば、ディレクトリ内のファイル数をデータレイヤーに返したい場合、スクリプト内の変数`nfiles`にその数が含まれます。 `nfiles`の値を`FileNumber`というアウトプット名でデータレイヤーに書き込むには、符号なし整数の書き込み関数を呼び出してください。

```
nxt_write_output_uint32 'FileNumber' $nfiles
```

リモートアクションエディタは、スクリプト内のアウトプットの書き込み呼び出しを認識し、アウトプット変数をアウトプットセクションに一覧表示します。 アウトプットのラベルを設定して、調査やメトリクスでどのように参照するかを示してください。

各`write`メソッドの終了はアウトプットの種類を示します。 Bashは、緩やかに型付けされた言語であるため、アウトプットの種類は文脈によって解釈されます。 利用可能なメソッドの一覧は次のとおりです。

| nxt 書き込み方法                       | 制約                                                            |
| -------------------------------- | ------------------------------------------------------------- |
| nxt\_write\_output\_string       | 0 - 1024 バイト（これ以上の場合、出力が切り捨てられます）                             |
| nxt\_write\_output\_bool         | true / false                                                  |
| nxt\_write\_output\_uint32       | <ul><li>最小値: 0</li><li>最大値: 4 294 967 295</li></ul>           |
| nxt\_write\_output\_float        | <ul><li>最小値: -3.4E+38</li><li>最大値: 3.4E+38</li></ul>          |
| nxt\_write\_output\_size         | <ul><li>最小値: 0</li><li>最大値: 3.4E+38</li></ul>                 |
| nxt\_write\_output\_ratio        |                                                               |
| nxt\_write\_output\_bitrate      |                                                               |
| nxt\_write\_output\_duration     | <ul><li>最小値: 0ミリ秒</li><li>最大値: 49日</li><li>ミリ秒単位の精度</li></ul> |
| nxt\_write\_output\_date\_time   | YYYY年MM月DD日 HH時MM分SS秒                                         |
| nxt\_write\_output\_string\_list | 0 - 1024 バイト（これ以上の場合、出力が切り捨てられます）                             |

### **出力フィールドの定義**

スクリプトを開発する際は次のことを必ず行ってください:

* **すべての出力フィールドの名前を事前に定義する:** これにより、スクリプトが実行中に出力テーブルの正しいフィールドにデータを入力することが保証されます。 事前にフィールド名が定義されていない場合、未知の出力スキーマによりスクリプトが失敗する可能性があります。
  * 出力フィールドの名前は常に`string`形式であるべきです。
  * 例: `nxt_write_output_string 'output_field_name' "$output_value"`
* **出力フィールドの数を定義する:** スクリプトは常に固定数の出力フィールドを指定する必要があります。 固定スキーマにより、予測可能な結果と互換性が保証されます。
  * 動的フィールドを避ける。 動的な出力構造は、プラットフォームにおける不整合や潜在的な処理エラーを引き起こします。
  * スクリプトを実行するとき、出力フィールドを定義するためにループを使用しないでください。

### キャンペーンの実装

従業員が独自に問題を解決できるよう、リモートアクションとキャンペーンを組み合わせましょう。 キャンペーンを使用して、従業員に問題の検出を通知し、その解決に向けて誘導します。

デバイスとやり取りしている従業員のデスクトップにキャンペーンを表示するには:

* キャンペーンは**リモートアクション**トリガーを持ち、公開されなければなりません。
* リモートアクションのスクリプトは以下のいずれかで実行できます。
  * 特別な権限を必要としないアクションの場合、従業員のコンテクストで。
  * 管理者特権を必要とするアクションの場合、ローカルシステムアカウントのコンテクストで。

### **キャンペーン識別子の取得**

リモートアクションからキャンペーンを実行するメソッドでは、引数としてキャンペーン識別子を渡す必要があります。 キャンペーンNQL ID（推奨）とキャンペーンUID（クラシックオプション）の両方を使用できます。

```
NQL IDを識別子としてサポートするには、Collectorバージョン23.5以上が必要です。
```

リモートアクションにキャンペーン識別子を渡すには、必要なキャンペーンごとにリモートアクションのスクリプトでパラメータを宣言します。 リモートアクションを編集するときに、実際の値としてNQL ID（またはUID）を使用します。

キャンペーンの NQL ID または UID の取得方法について詳しくは、[Triggering a campaign](https://github.com/nexthink/documentation.online-product-documentation/blob/develop/ja_docs/user-guide/campaigns/working-with-campaigns/triggering-campaigns/README.md) のドキュメントを参照してください。

### **リモートアクションのスクリプトからキャンペーンを実行する**

{% hint style="info" %}
エラーログは`/Library/Logs/nxtcod.log`で確認できます。 これは、ファイル構造によって異なる場合があります。
{% endhint %}

次の関数はリモートアクションのスクリプト機能を拡張します。

```
nxt_run_campaign( id )
```

この関数は、引数として渡されたNQL ID（推奨）またはUIDに一致するキャンペーンを実行し、解答を内部に保存します。

* キャンペーンのステータスを受信した場合、関数は0を返します。
* その他のケースでは関数は1を返し、エラーはログに記録されます。

この関数を呼び出すと、従業員がキャンペーンを完了するか、却下するまでリモートアクションの実行が一時停止されます。

```
nxt_run_campaign_with_timeout( id timeout)
```

この関数は、引数として渡されたNQL ID（推奨）またはUIDとタイムアウト（秒単位: 0 < T < 1 週間）に一致するキャンペーンを実行し、解答を内部に保存します。

* キャンペーンのステータスを受信した場合、関数は0を返します。
* その他のケースでは関数は1を返し、エラーはログに記録されます。

この関数を呼び出すと、従業員がキャンペーンを完了するか却下するか、タイムアウト前にキャンペーンを完了できなかった場合までリモートアクションの実行が一時停止されます。

```
nxt_run_standalone_campaign( id )
```

この関数は、引数として渡されたNQL ID（推奨）またはUIDに一致するキャンペーンを実行し、解答を内部に保存します。

* キャンペーンのステータスを受信した場合、関数は0を返します。
* その他のケースでは関数は1を返し、エラーはログに記録されます。

この関数を実行すると、キャンペーンの開始がトリガーされ、従業員の回答を待たずにリモートアクションの実行が続行されます。

```
nxt_get_campaign_status( res_var )
```

関数：

* `res_var` にキャンペーンのステータスが無事に保存された場合は0を返します。
* その場合は1を返します。

その後、キャンペーンのステータスを文字列として抽出し、指定された変数 `res_var` に保存します。 関数が`0`の結果を返すと、`res_var`には以下のいずれかの値が入ります:

* **完全**: 従業員がキャンペーンの質問に完全に回答しました。
* **タイムアウト**: ユーザーが回答を終える前にキャンペーンがタイムアウトしました。
* **延期**: 従業員がキャンペーンへの参加に同意しました。
* **拒否**: 従業員がキャンペーンへの参加を拒否しました。
* **接続失敗**: スクリプトがキャンペーン通知を制御するCollectorコンポーネントに接続できませんでした。
* **通知失敗**: スクリプトがキャンペーンを正常に表示できなかった理由は次のいずれかです。
  * 存在しないキャンペーン、または未公開のキャンペーンのため、プラットフォームからキャンペーン定義を取得できませんでした。
  * 別のキャンペーンが既に従業員に表示されています。
  * Collectorの集中保護または「邪魔しないで」ルールのために急を要しないキャンペーンを表示できません。 詳細については、[キャンペーンの受信率の制限](https://docs.nexthink.com/platform/ja/user-guide/campaigns/managing-campaigns/creating-campaigns/limiting-the-reception-rate-of-campaigns)のドキュメントを参照してください。
* 最後のキャンペーンが失敗した場合は空白になります。

```
nxt_get_response_answer( res_var question_key)
```

質問ラベルを文字列パラメータのクエリ\_keyとして使用して、最後のキャンペーンに問い合わせます。 関数は回答を文字列として抽出し、指定された変数 `res_var` に保存します。

* `res_var` にキャンペーンの回答が正常に保存された場合は0を返します。
* それ以外の場合は1を返します。

### スクリプトのエンコード

リモートアクション用Bashスクリプトを書くには:

* スクリプトを含むファイルをBOMなしのUTF-8でエンコードします。
* コードの各行は、UNIXシステムの通常の文字 `LF` で終了します。

エンコードを正しく行い、エラーや機能しないスクリプトを避けてください。

***

## コード例

<details>

<summary>キャンペーンの呼び出し</summary>

この例では、リモートアクションがキャンペーンIDによって基本的なキャンペーンを呼び出し、成功した場合はステータスメッセージを、失敗した場合はエラーメッセージを出力します。

```bash
if nxt_run_campaign "#my_campaign_nql_id"; then
    nxt_get_campaign_status status
    if [[ status == "fully" ]]; then
        echo "キャンペーンが成功しました"
    else
        echo "ステータスは $status です"
    fi
else
    echo "キャンペーンが失敗しました"
fi
```

</details>

<details>

<summary>回答へのアクセス</summary>

この例では、リモートアクションがキャンペーンの回答データを要求し、配列として出力します。 各回答は対応する番号付きオプションで表されます。 Bashは0を最低オプションとして使用し、Zshは1を使用します。

```bash
nxt_get_campaign_status status
echo "応答ステータスは $status です"
nxt_get_response_answer answersArray key1
echo ${answersArray[1]}
```

</details>

<details>

<summary>タイムアウト付きキャンペーンの実行</summary>

この例では、リモートアクションが指定された時間後にタイムアウトして終了するキャンペーンを実行するように設定されています。秒単位で入力されます。

```bash
# タイムアウトは秒単位です（100秒または00:01:40）

if nxt_run_campaign_with_timeout "#my_campaign_nql_id" 100; then
    nxt_get_campaign_status status
    if [[ status == "fully" ]]; then
        echo "キャンペーンが成功しました"
    else
        echo "ステータスは $status です"
    fi
else
    echo "キャンペーンが失敗しました"
fi
```

</details>

<details>

<summary>非ブロッキングキャンペーンの実行</summary>

この例では、リモートアクションはユーザー入力を必要とせず、キャンペーンをトリガーした後も実行を続けます。 ユーザーはいつでもキャンペーンを閉じることができます。 これは主に、データを取得するのではなく、ユーザーに情報を提供するために使用されます。

詳しくは[魅力的なキャンペーンの実施](https://docs.nexthink.com/platform/ja/user-guide/remote-actions/managing-remote-actions/broken-reference)のドキュメントを参照してください。

```bash
if nxt_run_standalone_campaign "#my_campaign_nql_id"; then
    nxt_get_campaign_status status
    if [[ status == "fully" ]]; then
        echo "キャンペーンが成功しました"
    else
        echo "ステータスは $status です"
    fi
else
    echo "キャンペーンが失敗しました"
fi
```

</details>

***

## スクリプトの署名

{% hint style="info" %}
セキュリティ上の理由から、NexthinkはmacOS上でのリモートアクションのBashスクリプトを`codesign`ツールでデジタル署名する必要があります。 Appleは署名をファイルの拡張属性に保存します。 署名済みスクリプトを`tar.gz`ファイルとしてパッケージ化し、拡張属性を保持してください。 Nexthink web インターフェースは、macOSを対象としたリモートアクションのスクリプトをインポートする際、`tar.gz`拡張子のファイルのみを受け付けます。

Nexthinkは、本番環境でのすべてのスクリプトの署名を推奨しています。 署名のないスクリプトはテスト環境でのみ使用するべきです。
{% endhint %}

<details>

<summary>オプション1: システム証明書ストアに依存する</summary>

**署名証明書の作成**

{% hint style="warning" %}
MacOS Sequoia (バージョン15)から、Appleによる変更により、署名証明書自体をすべてのデバイスで信頼されたものとして展開する代わりに、署名証明書のルート認証局 (CA) を展開する必要があります。 オペレーティングシステムに事前インストールされた公開ルートCAは機能しません。
{% endhint %}

リモートアクションが実行されるすべてのデバイスに以下のオプションのいずれかを展開できます。

* リモートアクション専用の自己署名ルートCA
* 社内のルートCA

以下は、自己署名ルートCAを作成し、それを使用してリモートアクションの署名用コード署名証明書を生成する方法の例です：

1. Macデバイスでキー チェーンアクセスを起動します。
2. Keychain Access > 証明書アシスタント > **証明書局を作成...** に移動します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-74ab0f25cd95c11344bbde5fbd73817e03f87c7e%2Fimage%20(212).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

3. 証明書局の名前をEnterします。
4. **ユーザー証明書**で**コード署名**を選択します。
5. 管理目的の連絡先として使用するメールアドレスをEnterします。
6. **Create** をクリックして証明書を生成します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-c1a3c18c67f750b3f8f2789e893fce3b09072724%2Fimage%20(211).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

以下は、コード署名証明書自体を作成する方法の例です。

1. MacデバイスでKeychain Accessを起動します。
2. キー チェーンアクセス > 証明書アシスタント > **証明書を作成…** に移動します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-4d6c1478ab6b0a12b56c6c3d36aee0af5ac95e2f%2Fimage%20(208).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

3. 証明書名を入力してください。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-ef09cd196e7565bb30629ef211fb8d5dd079d0a6%2Fimage%20(223)%20(1).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

4. この証明書の発行者としてルートCAを選択します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-8399ecddc1b9a933df07c1798b504b3f51d9408a%2Fimage%20(216).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

5. 証明書を生成し、以下のように確認を得るために、**作成**をクリックします。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-7ca8d83d0439c7ea4a5412184d53a966b1e0c702%2Fimage%20(217).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

証明書が作成されると、Keychain Accessアプリケーションに表示されます。 証明書を右クリックし、情報を取得をクリックします。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-7ca8d83d0439c7ea4a5412184d53a966b1e0c702%2Fimage%20(218).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

下までスクロールしてSHA-1をコピーアンドペーストします。 リモートアクションスクリプトを署名するために、値からスペースを削除します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-abca3a911b648407e3e090bc7f2abd62fec91b7e%2FScreenshot%202025-01-24%20at%2014.05.10%20(1).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

署名スクリプトにコード署名証明書を使用します：

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-817c17d6399f08d03076f1d9034d63193603eb3c%2Fimage%20(20)%20(2).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

以下のようにコマンドを実行して、以前のスクリプト署名手順が成功したかどうかを確認します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-b420bbcbd3ceacd0c78830003a2e4a6a42df6725%2Fimage%20(21)%20(2).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

**パッケージ化**

.tarアーカイブと.gzip圧縮を用いてリモートアクションスクリプトをパッケージ化してください。 ".tar.gz"拡張子は必須です。

```
tar -czvf ./<スクリプト名>.tar.gz ./<スクリプト名>.sh
```

スクリプトファイルが署名されている場合、tarユーティリティはその拡張属性もパックします。 この方法で、システムはコード署名とスクリプトファイルを転送できます。

**制限事項**

* 一つのアーカイブには一つのスクリプトしか入れられません。
* スクリプトファイルはルートパッケージフォルダに配置する必要があります。`./myscript/myscript.sh` パスは正しくありません。
* スクリプトは.sh拡張子を持っていなければなりません。
* スクリプトファイル名はUTF-8エンコードである必要があります。これはmacOSでデフォルト設定です。

**例**

`test.sh` スクリプトのパッケージ化の例:

```
tar -czvf ./example_ra_script.tar.gz ./example_ra_script.sh
```

生成された `example_ra_script.tar.gz` はリモートアクションスクリプトファイルです。

{% hint style="info" %}
Nexthinkは署名とパッケージ化のプロセスを簡素化するために、このスクリプトを使用することを推奨しています。
{% endhint %}

```
#!/bin/bash
#
# script_signing.sh
# 
# Copyright (C) 2023 by Nexthink S.A., Switzerland. Any usage, copy or partial copy of
# this code without the explicit agreement of Nexthink S.A. is prohibited and will be
# pursued to the full extend of the law.
#
# The arguments for the script:
# - input script filename
# - output archive filename
# - Certificate owner
# - Prefix
#
 
 
# Error handling
set -euo pipefail
trap "echo unrecoverable error !" ERR
 
 
# Check codesign
if [[ ! -x /usr/bin/codesign ]]
then
    echo "Error: this script requires that codesign is installed"
    exit 2
fi
 
# Check tar
if [[ ! -x /usr/bin/tar ]]
then
    echo "Error: this script requires that tar is installed"
    exit 2
fi
 
 
# Check arguments
if [[ $# -lt 4 ]]
then
    echo "Usage: script_signing.sh inputScriptFilename outputArchiveFilename CertificateOwner prefix"
    echo "Example: ./script_signing.sh script.sh script.tar.gz \"John Doe\" com.john.remote-action.macos."
    exit 1
fi
 
/usr/bin/codesign -s "$3" --timestamp --prefix="$4" --force "$1"
/usr/bin/tar czf "$2" "$1"
```

**ルートCAが生成されたマシンで署名済みスクリプトをテストする**

Root CAが作成された同じマシンで署名されたスクリプトをテストするとき、以下のステップを実行する必要があります。

**ルートCAをシステムキーチェーンにコピーし、信頼済みとしてマークする**

Appleはデフォルトで生成されたRoot CAを\*\*「ログイン」**キーチェーンに配置します。 しかし、適切な機能を保証するためには、それを**「システム」\*\*キーチェーンにインストールする必要があります。

証明書をシステムキーチェーンにコピーするには、次のステップを実行します。

1. **キーチェーンアクセス**を開きます。
2. ルートCA証明書を右クリックして、**エクスポート**を選択してエクスポートします。\
   ポップアップウィンドウで、**証明書 (.cer)** ファイル形式を選択します。<br>

   <figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-e7ffd5bdb22efef75a35ccba1c70b6eb520ce7f8%2Fimage%20(220).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>
3. **ターミナル**アプリケーションを開きます。
4. Root CAをシステムキーチェーンにインポートするために、次のコマンドを実行します:\
   `sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain Certificate.cer`
5. インポート後、証明書が**システム**キーチェーンに表示されることを確認します:
   * **キーチェーンアクセス**に戻ります。
   * 左サイドバーで**システム**セクションを選択します。
   * 右上の検索バーを使用して証明書を見つけます。
   * 結果テーブルで、**キーチェーン**列が**システム**を表示していることを確認します。
6. Root CA証明書を右クリックし、**情報を見る**を選択して信頼済みにマークします。
   * **信頼**セクションで、ルートCAを信頼済みとしてマークするように設定を調整します。<br>

     <figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-0ba7e0205dc2ff5cc3da6807597587300b365a24%2Fimage%20(223).png?alt=media" alt=""><figcaption></figcaption></figure>

**署名証明書のルートCAをエンドポイントに展開する**

{% hint style="info" %}
macOS Sequoiaバージョン15では、Windowsのようにすべてのデバイスに署名証明書を信頼済みとして導入するのではなく、署名証明書のRoot CAを導入する必要があります。

Collector Cloud 24.10.2.10およびCollector on-prem 24.10.30.26は、署名された証明書に代わる展開されたRoot CAに基づくリモートアクションスクリプト信頼ソース検証をサポートしています。
{% endhint %}

Root CAは、以下に示すように、主にJAMFを使用して構成プロファイルを作成することで導入することができます。

**ルートCAで作成された証明書のエクスポート**

1. ポップアップウィンドウで\_証明書(.cer)\_ファイル形式を選択します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-e7ffd5bdb22efef75a35ccba1c70b6eb520ce7f8%2Fimage%20(220).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-d78c1e595e93096bf319c73dbfa01f2438af2d46%2Fimage%20(221).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

2. 上記の構成プロファイルを使用してすべてのエンドポイントに展開します。 ルートCAは自動的に信頼としてマークされます。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-4e94894aa4ab9214490a900989a6463e5dd54959%2Fimage%20(222).png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-0ba7e0205dc2ff5cc3da6807597587300b365a24%2Fimage%20(223).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

**証明書がエンドポイントに正しくインポートされたことを確認する**

署名済みのリモートアクションスクリプトをendpointにコピーして解凍してください。

```
tar -xzvf example_ra_script.tar.gz
```

あなたの署名を確認してください。

```
codesign -vvvv -R="anchor trusted" example_ra_script.sh
```

署名証明書のRoot CAが適切にインポートされた場合、次の出力が表示されます:

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-43f3bd35069b437963326a5863d0743a6942f42f%2FScreenshot%202025-02-10%20at%2009.19.33.png?alt=media" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>オプション2: 証明書ピニングに依存する</summary>

{% hint style="info" %}
Collector バージョン2025.9.1.xから、macOSのCollectorは、実行可能なスクリプトを制御する追加の実行ポリシーをサポートします。 このセクションでは、詳細を説明します。
{% endhint %}

**新しい実行ポリシー**

macOSでは、2つの新しい実行ポリシーが導入されています:

* **signed\_pinned**
* **signed\_pinned\_or\_nexthink**

さらに、新しいインストーラオプション`cert_fingerprints`が追加されました。

**`cert_fingerprints`インストーラーオプション**

`cert_fingerprints` オプションは、スクリプトの署名ハッシュリストを定義することを可能にします（各ハッシュは1つの `,` で区切られ、その周りにスペースはありません）。 スクリプト署名サムプリントは、署名の**リーフ証明書**のサムプリントでなければなりません。

署名されたスクリプトファイルのリーフ証明書の指紋を抽出するには、以下のスクリプトを使用します:

```
#!/bin/bash
#
# extract_signature_leaf_certificate_thumbprint.sh
#
# 著作権 (C) 2025 by Nexthink S.A., スイス。Nexthink S.A.の明示的な同意なしに、このコードを使用、コピー、または部分的にコピーすることは禁止されており、法の最大限の範囲で追求されます。
#
# スクリプトの引数:
# - 入力スクリプトファイル名
#

set -euo pipefail

if [ $# -lt 1 ]; then
  echo "Usage: $0 <path-to-signed-binary>" >&2
  exit 1
fi

sigpath="$1"

tmpdir=$(mktemp -d) || { echo "テンポラリディレクトリの作成に失敗" >&2; exit 1; }

(
  cd "$tmpdir" || exit 1
  codesign -d --extract-certificates "$sigpath" >/dev/null

  leaf=$(ls codesign0* 2>/dev/null | head -n 1)
  if [ -n "$leaf" ] && [ -f "$leaf" ]; then
    openssl x509 -in "$leaf" -inform DER -noout -fingerprint -sha256
  else
    echo "リーフ証明書が見つかりません" >&2
    exit 2
  fi
)

rm -rf "$tmpdir"
```

{% hint style="danger" %}
`cert_fingerprints` オプションは、新しい実行ポリシー（`signed_pinned` と `signed_pinned_or_nexthink`）を使用する場合にのみ適用されます。 これは他の実行ポリシーに影響を与えません。
{% endhint %}

**ポリシーの動作**

**signed\_pinned**

* アンシグネードスクリプトは許可されていません。 実行中に失敗し、Collectorが関連するステータスを報告します。
* Nexthink LibraryのRAスクリプト: `cert_fingerprints`が署名のリーフ証明書のサムプリントを含んでいる場合にのみ実行が許可されます。 そうでなければ、実行はブロックされ、ステータスが報告されます。
* 他のスクリプト: `cert_fingerprints`が署名のリーフ証明書のサムプリントを含んでいる場合にのみ実行が許可されます。 そうでなければ、実行はブロックされ、ステータスが報告されます。

**signed\_pinned\_or\_nexthink**

* アンシグネードスクリプトは**許可されていません**。 実行中に失敗し、Collectorが関連するステータスを報告します。
* Nexthink LibraryのRAスクリプト：実行は常に許可されます（ポリシーによってブロックされません）。
* 他のスクリプト：`cert_fingerprints`が署名のリーフ証明書のサムプリントを含んでいる場合のみ実行が許可されます。 そうでなければ、実行はブロックされ、ステータスが報告されます。

**実行ポリシーの概要表**

| ポリシー                              | アンシグネードスクリプト | Nexthink LibraryのRAスクリプト                        | 他の署名付きスクリプト                                     | cert\_fingerprintsの影響 |
| --------------------------------- | ------------ | ----------------------------------------------- | ----------------------------------------------- | --------------------- |
| signed\_trusted（既存）               | ブロックされました    | ブロックされました                                       | 信頼された証明書によって署名された場合は許可                          | 効果なし                  |
| signed\_trusted\_or\_nexthink（既存） | ブロックされました    | 常に許可されます                                        | 信頼された証明書によって署名された場合は許可                          | 効果なし                  |
| signed\_pinned                    | ブロックされました    | サムプリントが許可リスト内にある場合に許可されます（`cert_fingerprints`内） | サムプリントが許可リスト内にある場合に許可されます（`cert_fingerprints`内） | 必要                    |
| signed\_pinned\_or\_nexthink      | ブロックされました    | 常に許可されます                                        | サムプリントが許可リスト内にある場合に許可されます（`cert_fingerprints`内） | 必要                    |

**証明書ピニング用のコード署名証明書の作成**

証明書ピニングでは、あらゆる種類のコード署名証明書がサポートされています:

* Appleの開発者サイトで作成されたコード署名証明書
* Appleの証明書アシスタントを使用して作成されたコード署名証明書
* プライベートルートCAでのコード署名証明書
* パブリックルートCAでのコード署名証明書
* その他の種類の証明書でも

プライベートルートCAでコード署名証明書を使用したい場合は、具体的な手順を[上記](#option-1-relying-on-the-system-certificate-store)で確認できます。

**署名済みリモートアクションスクリプトのパッケージ化、既知の制限**

コード署名証明書が作成されたら、Keychain Accessアプリケーションで開くためにダブルクリックしてください。 証明書を右クリックし、「情報を取得」をクリックします。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-7ca8d83d0439c7ea4a5412184d53a966b1e0c702%2Fimage%20(218).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

一番下までスクロールし、そこからSHA-1をコピー＆ペーストします。 リモートアクションスクリプトの署名に使用するために、その値からスペースを削除します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-abca3a911b648407e3e090bc7f2abd62fec91b7e%2FScreenshot%202025-01-24%20at%2014.05.10%20(1).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

コード署名証明書を使用してスクリプトに署名します:

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-817c17d6399f08d03076f1d9034d63193603eb3c%2Fimage%20(20)%20(2).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

次のコマンドを実行して、前のスクリプト署名手順が成功したことを確認します。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-b420bbcbd3ceacd0c78830003a2e4a6a42df6725%2Fimage%20(21)%20(2).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

**パッケージ**

リモートアクションスクリプトを.tarアーカイブと.gzip圧縮でパッケージ化します。 拡張子「.tar.gz」は必須です。

```
tar -czvf ./<your script name>.tar.gz ./<your script name>.sh
```

スクリプトファイルが署名されている場合、tarユーティリティはその拡張属性もパックします。 この方法で、システムはコード署名とスクリプトファイルを転送できます。

**制限事項**

* 1つのアーカイブには1つのスクリプトのみを入れることができます。
* スクリプトファイルはルートパッケージフォルダに配置する必要があります; `./myscript/myscript.sh` のパスは正しくありません。
* スクリプトには.sh拡張子が必要です。
* スクリプトファイル名はUTF-8エンコードされている必要があります。この形式はmacOSでデフォルトとなっています。

**例**

`test.sh` スクリプトのパッケージ化の例：

```
tar -czvf ./example_ra_script.tar.gz ./example_ra_script.sh
```

生成された `example_ra_script.tar.gz` はリモートアクションスクリプトファイルです。

{% 提示スタイル="情報" %}

Nexthinkは、このスクリプトを使用して署名およびパッケージ化プロセスを簡素化することをお勧めします。

```
#!/bin/bash
#
# script_signing.sh
# 
# 著作権 2023 Nexthink S.A., スイス。Nexthink S.A. の明確な同意なしにこのコードの使用、コピーまたは部分コピーは禁じられており、法律の最大限に従って追求されます。
#
# スクリプトの引数:
# - 入力スクリプトファイル名
# - 出力アーカイブファイル名
# - 証明書所有者
# - プレフィックス
#
 
 
# エラーハンドリング
set -euo pipefail
trap "回復不能なエラーです！" ERR
 
 
# コードサインの確認
if [[ ! -x /usr/bin/codesign ]]
then
    echo "エラー: このスクリプトにはcodesign がインストールされている必要があります"
    exit 2
fi
 
# tar の確認
if [[ ! -x /usr/bin/tar ]]
then
    echo "エラー: このスクリプトにはtarがインストールされている必要があります"
    exit 2
fi
 
 
# 引数の確認
if [[ $# -lt 4 ]]
then
    echo "使用法: script_signing.sh inputScriptFilename outputArchiveFilename CertificateOwner prefix"
    echo "例: ./script_signing.sh script.sh script.tar.gz \"John Doe\" com.john.remote-action.macos."
    exit 1
fi
 
/usr/bin/codesign -s "$3" --timestamp --prefix="$4" --force "$1"
/usr/bin/tar czf "$2" "$1"
```

**署名証明書のルートCAをエンドポイントに展開する**

証明書は、証明書ピンニングでエンドポイントに展開する必要はありません。 上記の説明に従って、すべてのエンドポイントに `cert_fingerprints` コレクターインストーラオプションを設定してください。

</details>

***

## スクリプトの保守

### 比較と検証

リモートアクションスクリプトを展開する前に、Nexthinkが準備した他のスクリプトと比較することができます。 このステップはオプションですが、初めてスクリプトを準備する場合は推奨されます。

1. Nexthink Libraryで、**コンテンツ**を選択してください。
2. **リモートアクション**でフィルタリングします。
3. **リモートアクション**管理ページに移動してください。
4. Nexthink Library から直接インストールされたリモートアクションスクリプトの中で、ターゲットオペレーティングシステムに一致するものを選択してください。
5. スクリプトをエクスポートし、その構文を自分のスクリプトと比較してください。

### スクリプトの終了とタイムアウト

リモートアクションスクリプトからサブプロセスを開始し、リモートアクションスクリプトが終了またはタイムアウトすると、Collectorはサブプロセスを自動的に終了します。 リモートアクションが終了した後もサブプロセスを実行し続けるには、&文字を使用してスクリプトがサブプロセスをデタッチすることを確認してください。例:

```
some_script.sh -arg1 -arg2 &
```

#### Zshコマンドインタープリタ

Collectorバージョン6.27.2以降では、Zsh Unixシェル用に書かれたスクリプトを実行できます。 シェルスクリプトの一番最初に以下の行を追加する必要があります:

```
#!/bin/zsh
```

これはシバンと呼ばれる文字列です([シバンとは](https://en.wikipedia.org/wiki/Shebang_/\(Unix/\))（外部リンク）)。

システムがMac上でリモートアクションを実行すると、Collectorはコードの最初の行をチェックし、指定されたインタープリタを使用して残りの指示を実行します。 シバンのないスクリプトは、Bashコマンドインタープリタを使って実行されます。

{% hint style="info" %}
Nexthinkは常にシェルスクリプトにシバンを使用し、標準インタープリタに従うことを推奨しています。
{% endhint %}

<details>

<summary>アーカイブ済み - 証明書の生成、署名、展開、確認（旧アプローチ<strong>、macOS Sequoiaおよびそれ以降には非対応</strong>）</summary>

**Root CAなしの証明書生成アプローチ**

この証明書生成アプローチは、すべてのデバイスで引き続き機能しますが、デバイス上で信頼済みとしてマークするためにユーザーの操作が必要です。

* MacデバイスでKeychain Accessを起動します。
* Keychain Access > 証明書アシスタント > **証明書を作成...** に進みます。

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-e418da8393e0720e43c81f62dbddfabcded75768%2FUntitled.png?alt=media" alt="" data-size="original">

1. 証明書の名前を入力します。

* **証明書の種類**として**コード署名**を選択してください。
* テスト目的の場合、**デフォルトを上書きさせてください**をチェックなしのままにすることができます。<br>

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-e69de29bb2d1d6434b8b29ae775ad8c2e48c5391%2FUntitled-1%20(5).png?alt=media" alt="" data-size="original">

* **作成**および**完了**をクリックしてください。 システムが証明書を生成しました。

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-683cd69ba7f35c6e1b50afcf5c3b2fb5c7e70b05%2FUntitled-1%20(1).png?alt=media" alt="" data-size="original">

**署名**

標準macOSコードサインユーティリティを使用してリモートアクションスクリプトに署名します。

```
codesign -s <あなたの証明書のアイデンティティ> --timestamp --prefix=<コード署名識別子のプレフィックス> --force <スクリプトファイル名>
```

パラメータ:

```
-s <あなたの証明書のアイデンティティ>
```

コード署名証明書のアイデンティティはキーチェーン内にあります。 通常、これは証明書主題の共通名または証明書のハッシュです。 詳細については、[codesignマニュアルページ](https://ss64.com/mac/codesign.html)を参照してください。

```
--timestamp
```

署名の信頼できるタイムスタンプ。

```
--prefix
```

コード署名識別子へのプレフィックス。 企業のアイデンティティを識別子に付加し、識別子をユニークにするのに役立ちます。 コード署名識別子生成規則については、UNIXの[codesignマニュアルページ](https://www.unix.com/man-page/osx/1/codesign/)を参照してください。

```
--force
```

既存のコード署名を上書きすることを強制します。

**例**

*example\_ra\_script.sh* リモートアクションスクリプトのテスト証明書の例:

```
codesign -s "RAスクリプトコード署名証明書" --timestamp --prefix=com.my-organisation.remote-action.macos. --force example_ra_script.sh
```

スクリプトファイルの署名は、ファイルに関連付けられたファイルシステムの拡張属性で生成されます。 コードサインの詳細を取得し署名を検証するためにcodesignユーティリティを使用してください。

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-e418da8393e0720e43c81f62dbddfabcded75768%2FUntitled%20(1).png?alt=media" alt="" data-size="original">

**エンドポイントへの署名証明書の配置**

この展開アプローチは動作を続けますが、ユーザーの操作が必要になります。

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-ba18bb82386f520a47e0f751814fce18e1f1137b%2FUntitled%20(2).png?alt=media" alt="" data-size="original">

ポップアップウィンドウで公開証明書用に *証明書 (.cer)* ファイル形式を選択します。

**証明書をendpointのキーチェーンにインポートする**

* 署名済みの証明書をSystemキーチェーンにインポートして、*Trusted Publisher* 実行ポリシーを使用してリモートアクションスクリプトを使用します。
* .cerファイルをダブルクリックし、**キーチェーン**のドロップダウンメニューで**システム**オプションを選択します。

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-fe5fc3d908671e7054702d0952718c9d3f8cf0fa%2FUntitled-1%20(2).png?alt=media" alt="" data-size="original">

* 証明書をインポートするためにルートパスワードを入力してください。

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-20761f69de42332a3eddab166f762c44e8f04b08%2FUntitled%20(3).png?alt=media" alt="" data-size="original">

これらの作業を自動化するために、[セキュリティユーティリティ](https://ss64.com/mac/security-cert.html)（外部リンク）または自動化フレームワークを使用してください。

**証明書が正しくendpointにインポートされたか確認する**

* 署名済みのリモートアクションスクリプトをエンドポイントにコピーして展開します。

```
tar -xzvf example_ra_script.tar.gz
```

* 署名を確認します。

```
codesign -vvvv -R="証明書リーフは信頼されている" example_ra_script.sh
```

署名が正しくインポートされている場合、次の出力が表示される必要があります:

<img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-06a3ab5d7ec64340d1b9e96377f6a0ae7a20c608%2FUntitled-1%20(3).png?alt=media" alt="" data-size="original">

</details>
