Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,29 @@ Invoke-WebRequest -Uri "https://github.com/AikidoSec/safechain-internals/release
msiexec /i SafeChainUltimate.msi /qn /norestart AIKIDO_TOKEN=YOUR_TOKEN
```

## MDM Installs

### CA Certificates

When deploying via an MDM solution (e.g. Jamf, Mosyle, Kandji), the CA certificate can be pushed by the MDM rather than installed interactively by the agent.

Create the flag file before running the `.pkg` installer:

```bash
touch /tmp/aikido_endpoint_mdm_ca_install.txt
```

When this flag is present, after the `.pkg` install completes the daemon will:
1. Start the proxy.
2. Download the CA certificate to the run directory (path below) — this is the file your MDM configuration profile should deploy as a trusted root CA.
3. Poll every minute for up to 20 minutes until the MDM has installed the certificate into the system trust store.
4. Only once the certificate is trusted: apply system proxy settings and begin sending heartbeats.

**CA certificate path (reference this in your MDM configuration profile):**

- **macOS:** `/Library/Application Support/AikidoSecurity/SafeChainUltimate/run/safechain-proxy-ca-crt.pem`
- **Windows:** `%ProgramData%\AikidoSecurity\SafeChainUltimate\run\safechain-proxy-ca-crt.pem`

## Uninstall

### macOS
Expand Down
33 changes: 33 additions & 0 deletions internal/proxy/proxy_ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (
"log"
"os"
"path/filepath"
"time"

"github.com/AikidoSec/safechain-internals/internal/platform"
"github.com/AikidoSec/safechain-internals/internal/utils"
)

const mdmCAInstallFlagPath = "/tmp/aikido_endpoint_mdm_ca_install.txt"

func GetProxyCAInstalledMarker() string {
return filepath.Join(platform.GetRunDir(), ".proxy_ca_installed")
}
Expand Down Expand Up @@ -61,6 +64,12 @@ func InstallProxyCA(ctx context.Context) error {
if err := DownloadCACertFromProxy(); err != nil {
return err
}

if _, err := os.Stat(mdmCAInstallFlagPath); err == nil {
log.Println("MDM CA install flag detected, polling for MDM-managed CA cert installation...")
return waitForMDMCAInstall(ctx)
}

if err := platform.InstallProxyCA(ctx, GetCaCertPath()); err != nil {
return fmt.Errorf("failed to install ca cert: %v", err)
}
Expand All @@ -72,6 +81,30 @@ func InstallProxyCA(ctx context.Context) error {
return nil
}

func waitForMDMCAInstall(ctx context.Context) error {
const maxAttempts = 20

for i := range maxAttempts {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(time.Minute):
}

if err := platform.IsProxyCAInstalled(ctx); err == nil {
log.Println("MDM-managed CA cert detected, creating installed marker...")
if err := CreateProxyCAInstalledMarker(); err != nil {
return fmt.Errorf("failed to create proxy CA installed marker: %v", err)
}
log.Println("CA cert installed by MDM successfully")
return nil
}
log.Printf("CA cert not yet installed by MDM, still waiting... (%d/%d)", i+1, maxAttempts)
}

return fmt.Errorf("CA cert was not installed by MDM within %d minutes", maxAttempts)
}

func UninstallProxyCA(ctx context.Context) error {
if err := platform.UninstallProxyCA(ctx); err != nil {
return fmt.Errorf("failed to uninstall ca cert: %v", err)
Expand Down
22 changes: 22 additions & 0 deletions packaging/macos/scripts/postinstall
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ chown -R root:wheel "$RUN_DIR"
AIKIDO_TOKEN=""
CONFIG_FILE="$RUN_DIR/config.json"
TOKEN_STAGING_FILE="/tmp/aikido_endpoint_token.txt"
MDM_CA_FLAG="/tmp/aikido_endpoint_mdm_ca_install.txt"
CA_CERT_PATH="$RUN_DIR/safechain-proxy-ca-crt.pem"

# 1) Explicit token via staging file always wins (fresh install or re-provisioning)
if [ -f "$TOKEN_STAGING_FILE" ]; then
Expand Down Expand Up @@ -86,6 +88,26 @@ else
echo "Warning: LaunchDaemon plist not found at $LAUNCHDAEMON_PLIST"
fi

# If MDM CA install flag is present, wait for the daemon to download the CA cert
# before exiting so the MDM solution can immediately install it from the known path.
# This is best-effort (120s); use the mdm-install-ca-cert.sh script on the MDM side
# for a reliable install with a longer timeout.
if [ -f "$MDM_CA_FLAG" ]; then
echo "MDM CA install flag detected, waiting for CA cert to be downloaded..."
echo " Expected path: $CA_CERT_PATH"
MAX_WAIT=120
WAITED=0
while [ ! -f "$CA_CERT_PATH" ] && [ "$WAITED" -lt "$MAX_WAIT" ]; do
sleep 5
WAITED=$((WAITED + 5))
done
if [ -f "$CA_CERT_PATH" ]; then
echo "CA cert is ready at: $CA_CERT_PATH"
else
echo "Warning: CA cert not yet downloaded after ${MAX_WAIT}s — the MDM install script will keep polling."
fi
fi

echo "Post-installation completed"
echo ""
echo "SafeChain Ultimate has been installed successfully!"
Expand Down
Loading