日本語

Terraform で Device Protection を展開する

Terraform はマシンを作成するツールであり、既存のマシン上でソフトウェアの状態を収束させ続けるものではありません。そのため、ここでの Terraform の役割は、作成するすべての Linux インスタンスが Device Protection をインストール済みの状態で起動するようにすることです。

まず Install Device Protection for Linux を読み、すべての方法で共通して使用するトークン、パッケージ、インストールオプションを確認してください。トークンの取り扱い、再起動、繰り返し実行、デバイス ID などその他の事項は Linux Rollout Reference で説明しています。

これは Aikido Terraform provider とは別物です。このプロバイダーは、リポジトリの有効化や AutoFix 設定など、Aikido ワークスペースの構成を管理するものです。マシンへのエージェントのインストールとは関係ありません。

新しいインスタンスにインストールする

cloud-init ドキュメントを user_data として渡します。ドキュメントを独立したファイルにしておくと、読みやすさが保たれ、Terraform 以外でも再利用できます。ドキュメント自体とそのオプションについては cloud-init を参照してください。

main.tf
variable "aikido_token" {
  type      = string
  sensitive = true
}

resource "aws_instance" "workstation" {
  ami           = var.workstation_ami
  instance_type = "m7i.large"

  user_data = templatefile("${path.module}/aikido-user-data.yaml.tftpl", {
    package      = "EndpointProtection-amd64.deb"
    aikido_token = var.aikido_token
  })

  tags = {
    Name = "workstation"
  }
}
aikido-user-data.yaml.tftpl
#cloud-config
runcmd:
  - curl -fsSLo /tmp/${package} https://github.com/AikidoSec/safechain-internals/releases/latest/download/${package}
  - AIKIDO_TOKEN=${aikido_token} apt-get install -y /tmp/${package}
  - rm -f /tmp/${package}

cloud-init の runcmd は初回起動時にのみ実行されるため、user_data を変更しても、すでに稼働中のインスタンスには何も再インストールされません。変更が反映されるのは、変更後に作成されたインスタンスのみです。

トークンを state とメタデータに残さない

Terraform が user_data にレンダリングした内容はすべて state に保存されます。また、user_data はマシン上で実行されているあらゆるプロセスからインスタンスメタデータサービス経由で読み取れます。トークンの代わりにシークレットの名前を渡し、ブートスクリプトに値を取得させてください。

main.tf
  user_data = templatefile("${path.module}/aikido-user-data.yaml.tftpl", {
    package         = "EndpointProtection-amd64.deb"
    token_parameter = "/aikido/device-protection-token"
  })

インスタンスプロファイルにそのパラメータへの読み取り権限を付与し、aikido-user-data.yaml.tftpl で boot-time lookup を使用します。その際、ハードコードされたパラメータ名とパッケージファイルの代わりに ${token_parameter} と ${package} を使います。これにより aikido_token 変数は完全に不要になり、機密情報が Terraform の state に入ることはなくなります。

Terraform で管理済みのインスタンスにインストールする

作成時に一度だけプッシュする場合は、remote-exec プロビジョナーを使用します。

resource "aws_instance" "workstation" {
  # ...

  connection {
    type        = "ssh"
    host        = self.public_ip
    user        = "ubuntu"
    private_key = file(var.ssh_private_key)
  }

  provisioner "remote-exec" {
    inline = [
      "curl -fsSLo /tmp/EndpointProtection-amd64.deb https://github.com/AikidoSec/safechain-internals/releases/latest/download/EndpointProtection-amd64.deb",
      "sudo AIKIDO_TOKEN=${var.aikido_token} apt-get install -y /tmp/EndpointProtection-amd64.deb",
      "rm -f /tmp/EndpointProtection-amd64.deb",
    ]
  }
}

プロビジョナーには実際的な制約があり、そのため HashiCorp はこれを最後の手段と位置づけています。

  • 作成時に一度だけ実行されます。二度と実行されないため、ドリフトが修正されることはありません。
  • プロビジョナーが失敗するとリソースは tainted としてマークされ、次回の apply でインスタンスが破棄・再作成されます。
  • Terraform を実行する場所(CI を含む)から SSH で到達可能である必要があります。

既存のフリートには、Ansible、Chef、または Puppet を使用してください。AWS では、稼働中のインスタンスを操作するために設計された SSM Run Command and State Manager も Terraform より適しています。

ロールアウトを確認する

新しいインスタンス上で次を実行します。

cloud-init status --wait
systemctl is-active aikido-endpoint-protection
aikidoctl version

その後、デバイスが デバイス一覧 に 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 を参照してください