Deploy ggshield at scale with a service account token
What is a service account token?
A Service account is a special type of API key intended to represent a non-human user that needs to authenticate and be authorized for scenarios such as secrets scanning in CI pipelines or batch processing open incidents.
Prerequisites
To create a service account token, follow the instructions in the service accounts documentation.
End-to-end overview
At a high level, a fleet-wide deployment comes down to five steps:
- Create a dedicated GitGuardian service account token (SAT) with the
nhi:send-inventoryscope. - Deploy
ggshieldto endpoints via your MDM or config management tool, keeping it continuously enforced and updated. - Install and enable the
machine_scanplugin — treat it as its own compliance item. - Store the SAT in a secure secret store (MDM secret variable or a dedicated secret manager). Never embed it in scripts, config files, or CLI arguments.
- Configure a daily scheduled job that injects the SAT at runtime as
GITGUARDIAN_API_KEY(andGITGUARDIAN_INSTANCEif needed) and runsggshield machine inventory.
Step 1 - Create the service account token
Create a dedicated SAT from a GitGuardian Account Admin account.
Required scopes:
nhi:send-inventory
honeytokens:check
These scopes are required so endpoints can send machine inventory data to GitGuardian without triggering HoneyTokens from your account.
- Use a dedicated SAT for endpoint secret protection.
- Do not use Personal Access Tokens.
- Do not run
ggshield auth loginon endpoints. - Do not hardcode the SAT in public scripts, packages, or documentation.
Step 2 - Install and manage ggshield with MDM
At scale, do not treat installation as a one-time script. Treat ggshield as an MDM-managed component that is continuously checked.
Recommended MDM flow
| MDM action | What it should do |
|---|---|
| Audit/check | Verify ggshield is installed, the binary is trusted according to your policy, and the version is the approved/current version. |
| Install | Download, verify and install the approved version, then verify the binary again. |
| Update | When the audit detects an outdated version, remediation installs the approved newer version. |
Typical binary paths
| Platform | Typical path |
|---|---|
| macOS | /usr/local/bin/ggshield |
| Linux | /usr/bin/ggshield |
Validate the installation with:
ggshield --version
Implementation notes
- On macOS, validate the package and installed binary signature according to your policy.
- On Linux, validate package checksums/signatures according to your policy.
- For large fleets, use an internal package cache or MDM-hosted package instead of having every endpoint download independently.
- You can track either the latest available version or an internally approved pinned version.
Step 3 - Install, manage, and update the machine scan plugin with MDM
Machine scanning must be installed and enabled before running ggshield machine inventory.
At scale, manage the machine scan plugin as its own MDM compliance item. This lets you install, verify, update, and repair drift independently from the daily inventory scan.
MDM audit model
| MDM action | What it should check or do |
|---|---|
| Audit/check | Confirm ggshield exists. Confirm machine_scan is enabled for the user context that will run the scan. Optionally confirm the plugin version is the approved/current version. |
| Install | Get the approved plugin package for the endpoint architecture, verify it, install it, enable machine_scan, then verify with ggshield plugin list. |
| Update | If the plugin is missing or outdated, rerun installation. |
| User-context repair | Because plugin configuration is user-scoped, install/enable it for the active or target scan user, not only for root/admin. |
Generic commands used by the MDM:
export GITGUARDIAN_API_KEY="<SAT_FROM_SECRET_STORE>"
export GITGUARDIAN_INSTANCE="<GITGUARDIAN_INSTANCE_URL>"
ggshield plugin install machine_scan
ggshield plugin enable machine_scan
ggshield plugin list
User-scoped installation
Plugin configuration is user-scoped. The MDM job normally runs as root/admin, but the inventory scan is often run as the logged-in user. The remediation should therefore install and enable machine scanning in the same user context used for the scan.
macOS pattern:
export GITGUARDIAN_API_KEY="<SAT_FROM_SECRET_STORE>"
export GITGUARDIAN_INSTANCE="<GITGUARDIAN_INSTANCE_URL>"
GGSHIELD_BIN="/usr/local/bin/ggshield"
loggedInUser=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && !/loginwindow/ {print $3}')
# Management/root context.
"$GGSHIELD_BIN" plugin install machine_scan
"$GGSHIELD_BIN" plugin enable machine_scan
# Scan user context.
if [ -n "$loggedInUser" ] && [ "$loggedInUser" != "root" ]; then
sudo -i -u "$loggedInUser" -- "$GGSHIELD_BIN" plugin install machine_scan
sudo -i -u "$loggedInUser" -- "$GGSHIELD_BIN" plugin enable machine_scan
sudo -i -u "$loggedInUser" -- "$GGSHIELD_BIN" plugin list
fi
Linux pattern:
export GITGUARDIAN_API_KEY="<SAT_FROM_SECRET_STORE>"
export GITGUARDIAN_INSTANCE="<GITGUARDIAN_INSTANCE_URL>"
GGSHIELD_BIN="/usr/bin/ggshield"
TARGET_USER="<target-user>"
"$GGSHIELD_BIN" plugin install machine_scan
"$GGSHIELD_BIN" plugin enable machine_scan
sudo -i -u "$TARGET_USER" -- "$GGSHIELD_BIN" plugin install machine_scan
sudo -i -u "$TARGET_USER" -- "$GGSHIELD_BIN" plugin enable machine_scan
sudo -i -u "$TARGET_USER" -- "$GGSHIELD_BIN" plugin list
Implementation notes
- If the plugin package is copied to a temporary path, make sure the target user can read it.
- If no user is logged in, install/enable for the management context and let the next MDM run repair the user context when a user is available.
- Keep the plugin installation job separate from the inventory scan job where possible.
- For updates, let the MDM audit fail when the plugin is missing or outdated, then remediate by installing the approved package again.
Step 4 - Run the inventory scan securely
At scan time, ggshield needs the SAT as GITGUARDIAN_API_KEY.
Simple form:
export GITGUARDIAN_API_KEY="<SAT_FROM_SECRET_STORE>"
export GITGUARDIAN_INSTANCE="<GITGUARDIAN_INSTANCE_URL>"
ggshield machine inventory
For managed endpoints, avoid exposing the SAT in command-line arguments, logs, or files.
Disable shell tracing (set -x) in any script that handles the SAT.
Step 5 - Configure MDM jobs and the scheduled task
Use the MDM to manage three separate concerns:
| MDM job | Purpose | Needs SAT? | Suggested recurrence |
|---|---|---|---|
Install/enforce ggshield | Install, verify, and update the ggshield binary. | No | MDM compliance/enforcement schedule. |
| Install/enforce machine scan plugin | Install, verify, enable, and update machine_scan for the scan user. | Yes | MDM compliance/enforcement schedule. |
| Inventory scan | Run ggshield machine inventory. | Yes | Once per day. |
Inventory scan job settings
| Setting | Recommendation |
|---|---|
| Script purpose | Run ggshield machine inventory |
| Frequency | Once per day |
| Run as | Root/admin for the management script |
| Scan user | Active user for workstations, unless another context is required |
| Secret input | SAT injected as a secret variable, for example GGSHIELD_SAT |
| First rollout | 10-20 monitored machines |
| Large fleets | Split devices into groups/schedules so scans do not all start at the same time |
| Success criteria | Command exits successfully and the machine appears in the GiGuardian's Endpoints dashboard with an updated latest scan |
| Logs | Success/failure, endpoint identifier, date, and scan duration if available |
Why separate jobs
- MDM compliance can repair missing/outdated components automatically.
- Updating the binary or plugin does not require changing the scan schedule.
Optional local schedules
If MDM scheduling is not available or sufficient, local schedulers can be used. Validate this approach in your environment before broad rollout.
| Platform | Local scheduler | Guidance |
|---|---|---|
| macOS | launchd LaunchDaemon | Run a local scan script daily. Do not put the SAT in the plist. |
| Linux | systemd timer | Run a local scan script daily. Use protected local credential storage only if MDM secret injection is not available. |
| Legacy fallback | cron | Use only when MDM or native schedulers are not available. |
Recurrence recommendation
Recommended default: once per day per endpoint.
- It gives GitGuardian enough endpoint inventory freshness.
- It should be almost transparent for most users after the first scan, thanks to caching.
- Less frequent scans may not send enough data and can reduce visibility over secrets exposure.
- More frequent scans are possible for specific use cases, but more than once per day is not recommended as the default policy for performance and fleet/API load reasons.
Deployment runbook
Use this checklist to track your rollout from initial setup to full fleet coverage.
| Phase | Action | Done when |
|---|---|---|
| 1. Create access | Create a dedicated GitGuardian service account token (SAT). | SAT exists with scope nhi:send-inventory and honeytokens:check. |
| 2. Install ggshield | Deploy the ggshield package through MDM, RMM, or config management. | Endpoint can run ggshield --version. |
| 3. Enable machine scanning | Install and enable the machine scan plugin. | ggshield plugin list shows machine_scan for the scan user. |
| 4. Configure auth | Store the SAT in the MDM/RMM secret store or another controlled secret mechanism. | The scan job receives the SAT as GITGUARDIAN_API_KEY at runtime. |
| 5. Schedule scans | Configure a daily scheduled task. | ggshield machine inventory runs without user interaction. |
| 6. Validate first group | Deploy to 10-20 monitored machines. | Machines appear in the GitGuardian's Endpoints dashboard with acceptable scan performance; see Validate and roll out. |
| 7. Scale rollout | Expand by percentage-based waves. | Success/error rates stay acceptable at each wave. |
After deployment
When scheduled scans succeed, findings are available in the Endpoints Protection meanu of your GitGuardian dashboard:
- Machines — fleet KPIs and a filterable table of endpoints with latest scan time and severity summary
- Endpoint detail — per-machine discovered secrets, scan history, and optional AI agent inventory
Use Validate and roll out for the dashboard checklist before expanding beyond your pilot group. For what each view shows, see Core concepts.