# BuildkiteでのDevice Protection

BuildkiteのジョブはLinux上で実行されるため、Device Protectionは他のLinuxマシンと同じ方法でインストールします。Buildkite固有なのはインストール先です。存続し続けるエージェントホストに一度だけインストールするか、ビルドごとに破棄されるエージェントでは各ジョブ内でインストールします。

トークンとパッケージについては、まず[Install Device Protection for Linux](https://help.aikidogov.us/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/install-device-protection-for-linux)を、以下のジョブレベルのスニペットで使用するコンテナインストールについては[Device Protection in Containers](https://help.aikidogov.us/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/device-protection-in-containers)をお読みください。

## 存続し続けるエージェント

他のビルドサーバーと同様にホストにエージェントをインストールすれば、パイプラインを一切変更せずに、そのエージェントが実行するすべてのジョブが検査されます。Ansible、cloud-init、または独自にビルドしたイメージを使ってエージェント群に展開するには、[Deploying on Linux](https://help.aikidogov.us/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux)を使用してください。

## ビルドごとに破棄されるエージェント

エフェメラルエージェント、コンテナ化されたエージェント、Buildkiteホステッドエージェントには準備するホストがないため、ジョブ内でエージェントをインストールし、パッケージのインストールより前に起動します:

{% code title=".buildkite/pipeline.yml" overflow="wrap" %}
```yaml
agents:
  queue: linux-small

steps:
  - label: ":shield: install dependencies"
    command: |
      export AIKIDO_TOKEN=$$(buildkite-agent secret get AIKIDO_TOKEN)

      curl -fsSLO https://github.com/AikidoSec/safechain-internals/releases/latest/download/EndpointProtection-amd64.deb
      AIKIDO_CONTAINER=1 AIKIDO_CI_CD=1 apt-get install -y --no-install-recommends ./EndpointProtection-amd64.deb

      aikido-endpoint-protection-start --wait-for-healthy
      for f in /etc/profile.d/aikido-*.sh; do . "$$f"; done

      npm ci
```
{% endcode %}

* **インストール前にトークンをエクスポートしてください。** パッケージはインストール中に`AIKIDO_TOKEN`を読み取ります。
* **インストール自体は標準のコンテナインストールです。** モード変数、起動コマンド、sourceによる読み込みについては、arm64およびRed Hat系エージェントで使用するパッケージとあわせて[Device Protection in Containers](https://help.aikidogov.us/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/device-protection-in-containers)で説明しています。

インストールにはroot権限が必要ですが、Dockerベースのエージェントはすでにroot権限を持っています。ジョブが`buildkite-agent`ユーザーとして実行される場合は、インストールの前に`sudo`を付けてください。

{% hint style="info" %}
`buildkite-agent secret get`にはエージェント3.106.0以降が必要です。このバージョンでは、`$$`エスケープを省略してBuildkiteに変数を設定させることもできます:

```yaml
steps:
  - command: .buildkite/install-deps.sh
    secrets:
      AIKIDO_TOKEN: aikido_token
```
{% endhint %}

### パイプラインを編集せずにすべてのジョブで実行する

このブロックを入れ忘れたステップでは、パッケージが検査されずにインストールされます。代わりに、リポジトリの`.buildkite/hooks/pre-command`またはエージェントのhooksディレクトリにある`pre-command`フックに移動してください:

{% code title=".buildkite/hooks/pre-command" overflow="wrap" %}
```bash
#!/bin/bash

export AIKIDO_TOKEN="$(buildkite-agent secret get AIKIDO_TOKEN)"

if ! command -v aikidoctl >/dev/null 2>&1; then
  curl -fsSLO https://github.com/AikidoSec/safechain-internals/releases/latest/download/EndpointProtection-amd64.deb
  AIKIDO_CONTAINER=1 AIKIDO_CI_CD=1 apt-get install -y --no-install-recommends ./EndpointProtection-amd64.deb
  rm -f EndpointProtection-amd64.deb
fi

aikido-endpoint-protection-start --wait-for-healthy

for f in /etc/profile.d/aikido-*.sh; do
  [ -e "$f" ] && . "$f"
done
```
{% endcode %}

フックはパイプラインYAMLではなくディスク上のスクリプトなので、ここでは`$$`ではなく`$`と記述します。Buildkiteはフックをsourceで読み込むため、フックがエクスポートした内容はコマンドに引き継がれます。

## コンテナ内で実行されるジョブ

ステップをDockerまたはDocker Composeプラグイン経由で実行する場合は、ステップではなくイメージにエージェントをインストールしてください。[Device Protection in Containers](https://help.aikidogov.us/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/device-protection-in-containers)を参照してください。

{% code title=".buildkite/pipeline.yml" overflow="wrap" %}
```yaml
steps:
  - label: ":shield: install dependencies"
    command: |
      for f in /etc/profile.d/aikido-*.sh; do . "$$f"; done
      npm ci
    plugins:
      - docker#v5.14.0:
          image: "ghcr.io/your-org/my-app:latest"
          environment:
            - AIKIDO_TOKEN
```
{% endcode %}

プラグインはイメージの`ENTRYPOINT`を維持するため、エージェントは自動的に起動します。プラグインの`entrypoint`または`command`オプションを設定するとそのエントリポイントは失われるため、コマンドの最初で`aikido-endpoint-protection-start --wait-for-healthy`を実行してください。Kubernetesスタックはコンテナのコマンドを置き換えるため、同様の対応が必要です。

## 動作確認

Aikidoがブロックするパッケージをダウンロードするステップを追加します:

{% code title=".buildkite/pipeline.yml" overflow="wrap" %}
```yaml
steps:
  - label: ":shield: verify Device Protection"
    command: |
      aikidoctl version
      curl -sS -o /dev/null -w "%{http_code}\n" --max-time 15 https://registry.npmjs.org/safe-chain-test/-/safe-chain-test-0.0.1-security.tgz
```
{% endcode %}

エージェントがすでに実行されているステップで実行してください。`curl`は`403`を出力し(エージェントがマルウェアテストパッケージを拒否したことを示します)、エージェントが[デバイス一覧](https://app.aikido.dev/endpoint-protection/devices)に表示されます。その他の確認方法については、[How to test if Device Protection is working](https://help.aikidogov.us/docs/docs-ja/aikido-device-protection/miscellaneous-aikido-endpoint/how-to-test-device-protection)を参照してください。

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

| 問題                                                            | 解決策                                                                                                                                                                                       |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| トークンが空で、エージェントが登録されない                  | `$`がエスケープされていなかったため、Buildkiteがアップロード時に`$(buildkite-agent secret get ...)`を解決しました。パイプラインYAMLでは`$$`を、フックスクリプトでは単一の`$`を使用してください                            |
| `buildkite-agent: command not found`、またはシークレットを読み取れない | エージェントが3.106.0より古い、シークレットが別のクラスターにある、またはジョブがエージェントバイナリのないコンテナで実行されています。Dockerプラグインで`mount-buildkite-agent`を有効にしてください        |
| ジョブ内のダウンロードがまったく検査されない                        | プラグインの`entrypoint`または`command`オプションがイメージのエントリポイントを置き換えたため、エージェントが起動しませんでした。コマンドの最初で`aikido-endpoint-protection-start --wait-for-healthy`を実行してください |

`npm`や`uv`からの証明書エラーなど、Buildkite固有でない問題については、[Device Protection in Containers](https://help.aikidogov.us/docs/docs-ja/aikido-device-protection/deploying-aikido-endpoint/device-protection-mdm-guides/linux/device-protection-in-containers#troubleshooting)のトラブルシューティング表を参照してください。
