# Puppet で Device Protection をデプロイする

Puppet クラスを使用して、Puppet エージェントがすでに管理している Linux ノードに Device Protection をインストールします。以下のクラスは、プラットフォームごとに適切なパッケージを選択し、ユーザーグループトークンを使用してインストールし、実行のたびにサービスが稼働し続けるようにします。

まず [Install Device Protection for Linux](https://help.aikido.dev/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/install-device-protection-for-linux) を読み、すべての方法で使用するトークン、パッケージ、インストールオプションを確認してください。残りの内容（トークンの取り扱い、再起動、繰り返し実行、デバイス ID）は [Linux Rollout Reference](https://help.aikido.dev/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/linux-rollout-reference) で説明しています。

## モジュール構成

```
modules/aikido_device_protection/
└── manifests/init.pp
data/
└── groups/developers.yaml
```

## クラスをセットアップする

{% stepper %}
{% step %}
**トークンを Hiera eyaml に保存する**

Aikido のユーザーグループに対応するノードグループ用にトークンを暗号化します。

{% code overflow="wrap" %}
```bash
eyaml encrypt -l 'aikido_device_protection::token' -s '<your-token>'
```
{% endcode %}

出力を該当する Hiera レイヤーに貼り付けます。

{% code title="data/groups/developers.yaml" %}
```yaml
---
aikido_device_protection::token: >
  ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEw...]
```
{% endcode %}

クラスパラメーターは `Sensitive` 型で定義されており、Puppet は Hiera から渡される値を自動的にラップするため、ほかに必要な作業はありません。
{% endstep %}

{% step %}
**クラスを追加する**

{% code title="modules/aikido_device_protection/manifests/init.pp" %}
```puppet
class aikido_device_protection (
  Sensitive[String[1]] $token,
  String[1] $release_url = 'https://github.com/AikidoSec/safechain-internals/releases/latest/download',
) {
  $arch = $facts['os']['architecture'] ? {
    /^(aarch64|arm64)$/ => 'arm64',
    default             => 'amd64',
  }

  case $facts['os']['family'] {
    'Debian': {
      $package_file    = "EndpointProtection-${arch}.deb"
      $install_command = 'apt-get install -y'
      $installed_check = "dpkg-query -W -f='\${db:Status-Status}' aikido-endpoint-protection 2>/dev/null | grep -qx installed"
    }
    'RedHat': {
      $package_file    = "EndpointProtection-${arch}.el${facts['os']['release']['major']}.rpm"
      $install_command = 'dnf install -y'
      $installed_check = 'rpm -q aikido-endpoint-protection'
    }
    default: {
      fail("Aikido Device Protection does not support ${facts['os']['family']}")
    }
  }

  $package_path = "/var/cache/aikido/${package_file}"

  file { '/var/cache/aikido':
    ensure => directory,
    owner  => 'root',
    group  => 'root',
    mode   => '0700',
  }

  exec { 'download aikido-endpoint-protection':
    command  => "curl -fsSLo ${package_path} ${release_url}/${package_file}",
    provider => shell,
    path     => ['/usr/bin', '/bin'],
    creates  => $package_path,
    unless   => $installed_check,
    require  => File['/var/cache/aikido'],
  }

  $install_script = @("SCRIPT")
    #!/bin/sh
    set -e
    export AIKIDO_TOKEN='${$token.unwrap}'
    exec ${install_command} ${package_path}
    | SCRIPT

  file { '/usr/local/sbin/aikido-install':
    ensure  => file,
    owner   => 'root',
    group   => 'root',
    mode    => '0700',
    content => Sensitive($install_script),
  }

  exec { 'install aikido-endpoint-protection':
    command  => '/usr/local/sbin/aikido-install',
    provider => shell,
    path     => ['/usr/bin', '/bin', '/usr/sbin', '/sbin'],
    unless   => $installed_check,
    require  => [
      Exec['download aikido-endpoint-protection'],
      File['/usr/local/sbin/aikido-install'],
    ],
  }

  service { 'aikido-endpoint-protection':
    ensure  => running,
    enable  => true,
    require => Exec['install aikido-endpoint-protection'],
  }
}
```
{% endcode %}

このクラスについて、知っておくべき点が 4 つあります。

* パッケージには [環境変数に `AIKIDO_TOKEN`](https://help.aikido.dev/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/linux-rollout-reference#how-the-token-reaches-the-package) が必要で、Puppet は `exec` の `environment` 属性を秘匿化しないため、インストールは `Sensitive()` でラップされた root 専用スクリプトから実行されます。
* [`unless => $installed_check`](https://help.aikido.dev/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/linux-rollout-reference#make-repeat-runs-cheap) がダウンロードとインストールをガードするため、すでにエージェントが稼働しているノードでは何も実行されません。
* Debian のチェックはパイプラインであり、`exec` はデフォルトではシェルを使用しないため、`provider => shell` を指定しています。
* ダウンロードには `curl` を使用しますが、最小構成のイメージには含まれていないことがあります。その場合は、このクラスと併せてインストールしてください。

{% hint style="warning" %}
トークンは root のみがアクセスできる 2 か所のディスク上に保存されます。1 つはガードがなくインストール後も残る `/usr/local/sbin/aikido-install`、もう 1 つはエージェントがリソースを適用するために必要とする `/opt/puppetlabs/puppet/cache` 配下のキャッシュされたカタログです。どちらも機密情報として扱い、レポートへのアクセスを制限してください。

ノードグループへのインストールが完了したら、`file` リソースを `ensure => absent` に切り替えると、すべてのノードからスクリプトが削除されます。そのグループに次の新しいノードが参加する前に、元に戻してください。
{% endhint %}
{% endstep %}

{% step %}
**ノードを分類する**

ロールとプロファイル、Puppet Enterprise コンソール、または `site.pp` など、ノードを分類する場所でクラスを宣言します。

```puppet
include aikido_device_protection
```

次回のエージェント実行時にエージェントがインストールされます。まず 1 つのグループを分類してから、対象を広げてください。

Puppet には組み込みの再起動リソースがないため、保護はユーザーがログアウトして再度ログインした時点で有効になります。無人のノードを再起動させたい場合は、インストール用の `exec` から [puppetlabs-reboot](https://forge.puppet.com/modules/puppetlabs/reboot) に通知します。[When protection becomes active](https://help.aikido.dev/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/linux-rollout-reference#when-protection-becomes-active) を参照してください。
{% endstep %}
{% endstepper %}

## ロールアウトを確認する

実行済みのノードで次を実行します。

{% code overflow="wrap" %}
```bash
systemctl is-active aikido-endpoint-protection
aikidoctl version
```
{% endcode %}

その後、デバイスが [デバイス一覧](https://app.aikido.dev/endpoint-protection/devices) に **Active** ステータスで表示されます。

## トラブルシューティング


| 問題                                                                                  | 対処法                                                                                                                                                                                                                                             |
| ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| パッケージはインストールされるが、デバイスがダッシュボードに表示されない                       | インストールコマンドに `AIKIDO_TOKEN` が設定されていませんでした。構成管理ツールはローカル環境をホストに転送しないため、タスク自体に変数を設定してから、パッケージを再度インストールしてください                                    |
| `apt` または `dnf` がファイルをインストールせず、リポジトリ内でパッケージを探してしまう | 名前ではなくパスを指定してください: `apt install ./EndpointProtection-amd64.deb`。先頭の `./` によって、パッケージマネージャーはそれをローカルファイルとして扱います                                                                                              |
| Red Hat 系のホストでインストールが失敗する                                               | ビルドをメジャーバージョンに合わせてください。バージョン 9 では `el9` パッケージを、バージョン 10 では `el10` パッケージを使用します                                                                                                                                   |
| サービスが実行されていない                                                               | `systemctl status aikido-endpoint-protection` を実行し、次に `sudo aikidoctl diagnostics` を実行して詳細を送信してください                                                                                                                                 |
| Node.js または uv が依然として Aikido 証明書を拒否する                                        | インストール時に `NODE_EXTRA_CA_CERTS` と `UV_SYSTEM_CERTS` がシステム全体に設定されますが、実行中のシェルにはこれらが反映されません。新しいログインシェルを開くか、デバイスを再起動してください                                                                                    |
| トークンが実行出力やログに表示される                                                 | ツールのマスキング機能を使用してください: Ansible では `no_log`、Chef では `sensitive true`、Puppet では `Sensitive()`                                                                                                                                               |
| 複数のマシンがデバイス一覧で 1 つのエントリを共有している                                      | それらのマシンは同じ `/etc/machine-id` で起動しています。Linux のデバイス ID はこのファイルに基づくため、クローン元のイメージでこのファイルをクリアし、初回起動時に systemd に新しいものを書き込ませてください                                                                |
| トレイアイコンが表示されない                                                                     | Ubuntu 以外の GNOME では想定どおりの動作であり、見た目上の問題にすぎません。[Tray Icon Support on Linux](https://help.aikido.dev/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/install-device-protection-for-linux/tray-icon-support-on-linux) を参照してください |
