For the complete documentation index, see llms.txt. This page is also available as Markdown.

Deploy Device Protection with Puppet

Use a Puppet class to install Device Protection on the Linux nodes your Puppet agent already manages. The class below picks the right package per platform, installs it with your user group token, and keeps the service running on every run.

Read Deploying on Linux first for the token, the package list, and the reboot behaviour that applies to every method.

Module layout

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

Set up the class

1

Store the token in Hiera eyaml

Encrypt the token for the group of nodes that maps to your Aikido user group:

eyaml encrypt -l 'aikido_device_protection::token' -s '<your-token>'

Paste the output into the matching Hiera layer:

data/groups/developers.yaml
---
aikido_device_protection::token: >
  ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEw...]

The class parameter is typed Sensitive, and Puppet wraps values coming from Hiera automatically, so nothing else is needed.

2

Add the class

modules/aikido_device_protection/manifests/init.pp
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'],
  }
}

The download uses curl, which minimal images sometimes leave out. If yours does, install it alongside this class.

3

Classify your nodes

Declare the class where you classify nodes, through roles and profiles, the Puppet Enterprise console, or site.pp:

include aikido_device_protection

The next agent run installs the agent. Classify one group first, then widen.

Why a script and not an exec environment

The package reads AIKIDO_TOKEN while it installs, so the token has to be in the environment of the process that runs apt-get or dnf. Passing it through environment => ["AIKIDO_TOKEN=..."] on the exec works, but Puppet does not treat that attribute as sensitive: the token then shows up in agent logs and in reports sent to the primary server.

Writing it into a root-only script whose content is wrapped in Sensitive() avoids that. Puppet redacts sensitive content from logs, reports, and --noop diffs.

Keep runs idempotent

unless => $installed_check guards the download and the install, so nodes that already run the agent do nothing. The token is only needed on first install, and upgrades keep the device's registration.

On the Debian family the check is dpkg-query, not dpkg -s. dpkg -s also succeeds for a package that was removed but not purged, so a node where someone ran apt remove aikido-endpoint-protection would look installed to Puppet and never be brought back. That check is a pipeline, and exec does not use a shell by default, which is what provider => shell is there for.

Handle the reboot

Installing sets the Aikido CA environment variables system-wide, and running shells only pick them up after a new login shell or a reboot. Puppet has no built-in reboot resource, so either ask users to log out and back in, or handle the reboot with your existing maintenance tooling. If you already use puppetlabs-reboot, notify it from the install exec.

Verify the rollout

On a node that has run:

The device then appears in your device list with an Active status.

Troubleshooting

Problem
Fix

The package installs but the device never appears in the dashboard

AIKIDO_TOKEN was not set for the install command. Configuration management tools do not forward your local environment to the host, so set the variable on the task itself, then install the package again

apt or dnf looks for the package in your repositories instead of installing the file

Pass a path, not a name: apt install ./EndpointProtection-amd64.deb. The leading ./ is what makes the package manager treat it as a local file

The install fails on a Red Hat-family host

Match the build to the major version: use the el9 package on version 9 and the el10 package on version 10

The service is not running

Run systemctl status aikido-endpoint-protection, then sudo aikido-doctor diagnostics to send us the details

Node.js or uv still reject the Aikido certificate

Installing sets NODE_EXTRA_CA_CERTS and UV_SYSTEM_CERTS system-wide, and running shells do not pick them up. Open a new login shell or reboot the device

The token shows up in run output or logs

Use your tool's redaction: no_log in Ansible, sensitive true in Chef, Sensitive() in Puppet

Several machines share one entry in the device list

They booted with the same /etc/machine-id. Device identity on Linux follows that file, so clear it in the image you clone from and let systemd write a fresh one on first boot

No tray icon appears

Expected on GNOME outside Ubuntu, and cosmetic. See Tray Icon Support on Linux

Last updated

Was this helpful?