Skip to content

Latest commit

 

History

History
439 lines (326 loc) · 10.6 KB

File metadata and controls

439 lines (326 loc) · 10.6 KB

Deployment Guide

Step-by-step guide for deploying E8CR Squad against a real Microsoft 365 tenant.


Prerequisites

  • Python 3.10+ installed
  • Access to an Azure AD tenant with Global Administrator or Application Administrator role
  • Microsoft 365 licensing (E3/E5 for Intune, E5 or MDE P2 for Defender Vulnerability Management)
  • A Linux server, macOS host, or Docker-capable host for running the bots

Azure AD App Registration

Each bot needs its own app registration for least-privilege isolation. Repeat this process for each bot (VM+PM, Identity, AppControl, Backup).

Step 1: Create the App Registration

  1. Go to Azure Portal > Azure Active Directory > App registrations
  2. Click New registration
  3. Configure:
    • Name: E8CR-VMPM (or E8CR-Identity, E8CR-AppControl, E8CR-Backup)
    • Supported account types: "Accounts in this organizational directory only"
    • Redirect URI: Leave blank (not needed for client credentials flow)
  4. Click Register
  5. Note the Application (client) ID and Directory (tenant) ID from the overview page

Step 2: Create a Client Secret

  1. In the app registration, go to Certificates & secrets
  2. Click New client secret
  3. Description: E8CR production (or similar)
  4. Expiry: 6 months (set a calendar reminder to rotate)
  5. Click Add
  6. Copy the secret value immediately — it will not be shown again

Step 3: Grant API Permissions

  1. Go to API permissions > Add a permission > Microsoft Graph > Application permissions
  2. Add the permissions for the specific bot (see table below)
  3. Click Grant admin consent for [your tenant]

Permissions by Bot

VM+PM Bot:

  • DeviceManagementManagedDevices.Read.All
  • DeviceManagementConfiguration.Read.All
  • WindowsUpdates.Read.All
  • If using MDVM: Vulnerability.Read.All, Software.Read.All, Machine.Read.All

Identity Bot:

  • User.Read.All
  • Directory.Read.All
  • Policy.Read.All
  • AuditLog.Read.All
  • RoleManagement.Read.All
  • UserAuthenticationMethod.Read.All

AppControl Bot:

  • DeviceManagementConfiguration.Read.All
  • DeviceManagementManagedDevices.Read.All

Backup Bot:

  • DeviceManagementManagedDevices.Read.All

Step 4: Verify Authentication

export AZURE_TENANT_ID="your-tenant-id"
export AZURE_CLIENT_ID="your-client-id"
export AZURE_CLIENT_SECRET="your-client-secret"

python3 shared/graph_auth.py --check

You should see confirmation that the token was acquired and the organisation query succeeded.


Single Bot Quickstart (30 Minutes)

Get the VM+PM bot running against a real tenant.

1. Clone and Set Up

git clone https://github.com/RADobson/e8cr-squad.git
cd e8cr-squad

2. Configure Credentials

export AZURE_TENANT_ID="your-tenant-id"
export AZURE_CLIENT_ID="vmpm-client-id"
export AZURE_CLIENT_SECRET="vmpm-client-secret"
export E8CR_SIGNING_KEY="$(python3 -c 'import secrets; print(secrets.token_hex(32))')"

3. Test Authentication

python3 shared/graph_auth.py --check

4. Run a Live Assessment

# Audit mode (read-only, safe)
python3 run_all.py --bots vmpm --output ./vmpm-assessment

5. Review Output

open ./vmpm-assessment/e8cr-assessment.html
# Or on Linux:
# xdg-open ./vmpm-assessment/e8cr-assessment.html

6. Verify Evidence

python3 scripts/verify_evidence.py ./vmpm-assessment/vmpm/evidence-pack/manifest.json

Full Squad Deployment

Directory Structure

sudo mkdir -p /opt/e8cr/{vmpm,identity,appcontrol,backup}
sudo chown -R $(whoami) /opt/e8cr

Environment Files

Create a .env file for each bot with its own credentials:

# /opt/e8cr/vmpm/.env
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=vmpm-client-id
AZURE_CLIENT_SECRET=vmpm-client-secret
E8CR_SIGNING_KEY=your-signing-key
E8CR_ENABLE_CHANGES=false
# /opt/e8cr/identity/.env
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=identity-client-id
AZURE_CLIENT_SECRET=identity-client-secret
E8CR_SIGNING_KEY=your-signing-key
E8CR_ENABLE_CHANGES=false

Repeat for appcontrol and backup. Secure the files:

chmod 600 /opt/e8cr/*/.env

Docker Deployment

Quick Demo

# Run unified assessment with synthetic data
docker compose --profile unified up unified
# Output is in the unified-output volume

Production (Individual Bots)

  1. Create a .env file in the repo root:
AZURE_TENANT_ID=your-tenant-id
VMPM_CLIENT_ID=vmpm-client-id
VMPM_CLIENT_SECRET=vmpm-client-secret
IDENTITY_CLIENT_ID=identity-client-id
IDENTITY_CLIENT_SECRET=identity-client-secret
APPCONTROL_CLIENT_ID=appcontrol-client-id
APPCONTROL_CLIENT_SECRET=appcontrol-client-secret
BACKUP_CLIENT_ID=backup-client-id
BACKUP_CLIENT_SECRET=backup-client-secret
E8CR_SIGNING_KEY=your-signing-key
  1. Remove the --demo flag from docker-compose.yml command entries (or override):
# Run all 4 bots against the real tenant
docker compose up vmpm identity appcontrol backup
  1. Access output:
# Copy evidence from volumes
docker compose cp vmpm:/output ./vmpm-evidence
docker compose cp identity:/output ./identity-evidence

Scheduled Runs with Docker

Use cron to trigger Docker runs on a schedule:

# Daily assessment at 2am
0 2 * * * cd /opt/e8cr/e8cr-squad && docker compose up --abort-on-container-exit vmpm identity appcontrol backup >> /var/log/e8cr/daily.log 2>&1

Systemd Service Files (Linux)

For bare-metal Linux deployment, create systemd services and timers for each bot.

Service Unit (VM+PM example)

Create /etc/systemd/system/e8cr-vmpm.service:

[Unit]
Description=E8CR VM+PM Bot Assessment
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=e8cr
Group=e8cr
WorkingDirectory=/opt/e8cr/e8cr-squad
EnvironmentFile=/opt/e8cr/vmpm/.env
ExecStart=/usr/bin/python3 run_all.py --bots vmpm --output /opt/e8cr/vmpm/output
StandardOutput=journal
StandardError=journal
TimeoutStartSec=600

Timer Unit

Create /etc/systemd/system/e8cr-vmpm.timer:

[Unit]
Description=E8CR VM+PM Bot Daily Timer

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target

Enable and Start

sudo systemctl daemon-reload
sudo systemctl enable --now e8cr-vmpm.timer

Repeat for Other Bots

Create matching service and timer files for e8cr-identity, e8cr-appcontrol, and e8cr-backup, staggering the timer schedules:

Bot Schedule
VM+PM 02:00
Identity 02:15
AppControl 02:30
Backup 02:45

Check Status

systemctl list-timers 'e8cr-*'
journalctl -u e8cr-vmpm --since today

macOS launchd

For Mac mini deployment (useful for small MSP environments).

LaunchDaemon Plist (VM+PM example)

Create ~/Library/LaunchAgents/com.e8cr.vmpm.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.e8cr.vmpm</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>
        <string>/opt/e8cr/e8cr-squad/run_all.py</string>
        <string>--bots</string>
        <string>vmpm</string>
        <string>--output</string>
        <string>/opt/e8cr/vmpm/output</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict>
        <key>AZURE_TENANT_ID</key>
        <string>your-tenant-id</string>
        <key>AZURE_CLIENT_ID</key>
        <string>vmpm-client-id</string>
        <key>AZURE_CLIENT_SECRET</key>
        <string>vmpm-client-secret</string>
        <key>E8CR_SIGNING_KEY</key>
        <string>your-signing-key</string>
        <key>E8CR_ENABLE_CHANGES</key>
        <string>false</string>
    </dict>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>2</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/opt/e8cr/vmpm/output/launchd.log</string>
    <key>StandardErrorPath</key>
    <string>/opt/e8cr/vmpm/output/launchd.err</string>
</dict>
</plist>

Load the Agent

launchctl load ~/Library/LaunchAgents/com.e8cr.vmpm.plist

For the multi-instance OpenClaw deployment on macOS, see examples/openclaw-multi-instance/README.md.


Monitoring and Alerting

Health Checks

After each bot run, verify:

  1. Exit code: Non-zero means the bot encountered an error
  2. Report file exists: Check that the expected HTML report was generated
  3. Evidence files exist: Verify all files listed in bot.contract.yaml evidence_files are present
  4. Evidence integrity: Run scripts/verify_evidence.py on the manifest

Example health check script:

#!/bin/bash
BOT=$1
OUTPUT_DIR="/opt/e8cr/$BOT/output"

# Check report exists
if [ ! -f "$OUTPUT_DIR"/*-report.html ]; then
    echo "ALERT: $BOT report missing"
    exit 1
fi

# Verify evidence integrity
python3 /opt/e8cr/e8cr-squad/scripts/verify_evidence.py \
    "$OUTPUT_DIR/manifest.json"
if [ $? -ne 0 ]; then
    echo "ALERT: $BOT evidence integrity check failed"
    exit 1
fi

echo "OK: $BOT healthy"

Failure Notifications

Integrate with your existing alerting:

  • Systemd: Use OnFailure= in the service unit to trigger a notification script
  • Docker: Check container exit codes in your cron wrapper
  • Email: Pipe health check output to sendmail or a webhook
  • Webhook: POST to Slack, Teams, or PagerDuty on failure

Systemd Failure Notification Example

Create /etc/systemd/system/e8cr-notify-failure@.service:

[Unit]
Description=E8CR Failure Notification for %i

[Service]
Type=oneshot
ExecStart=/opt/e8cr/scripts/notify-failure.sh %i

Add to each bot service:

[Unit]
OnFailure=e8cr-notify-failure@%n.service

Security Checklist

Before going to production, verify:

  • Each bot has its own Azure AD app registration
  • Permissions are read-only (no .ReadWrite scopes)
  • Admin consent is granted for all permissions
  • E8CR_ENABLE_CHANGES=false is set
  • Credentials are in environment variables, not in code
  • .env files have chmod 600
  • E8CR_SIGNING_KEY is set for evidence signing
  • Network egress is restricted to required endpoints only
  • No inbound ports are open to the bot hosts
  • Logs are being collected and retained
  • A credential rotation schedule is in place

See SECURITY.md for the full security hardening guide.