KeyGuardRail customer-side metadata collector Runs on your Linux/macOS host with Node.js 22.13 or later. Download /downloads/keyguardrail-vault-collector.mjs from your KeyGuardRail installation. Review and pin the downloaded file's SHA-256 checksum through your own change process. No npm installation or central provider credential storage is needed. Supported sources: - HashiCorp Vault Community/Enterprise KV v2 metadata on explicit paths. - 1Password Business Events API v2 item changes, US/EU/Canada. - Bitwarden cloud Public API Secrets Manager events, US/EU. Requires an eligible Password Manager Teams/Enterprise organization with Public API access; a standalone Secrets Manager subscription alone does not establish eligibility. These sources report observations. They NEVER update rotation dates or expiration, even when an inventory mapping enables the active-version rotation policy. Vault snapshots describe current metadata, not a reconstructed history. 1Password server-update can include Favorites, archive, delete, restore and moves; it is only labeled an observed change. Bitwarden 2101/2102/2103/2104 map to created, changed, disabled and deleted; access events and Password Manager items are ignored. Setup 1. In Integrations, create the matching collector connection and enter its exact source identity. Generate a credential with events:write, status:read and reconcile:write. Set an expiry compatible with your credential rotation process. 2. On a dedicated customer host/account, store the KeyGuardRail credential and source reporting credential in separate files, owned by the collector user, mode 0600. Provision their contents through your existing credential manager; do not put tokens in command arguments, URLs, config JSON or shell history. 3. Create a mode-0600 config JSON, using one example below. All paths must be absolute. Replace the destination with Connection details, without /events. Create a dedicated state directory with mode 0700. Parent directories must be trusted and writable only by authorized administrators/the collector user. 4. Run: node /opt/kgr-collector/keyguardrail-vault-collector.mjs \ /etc/kgr-collector/config.json /var/lib/kgr-collector/production 5. Inspect reconciliation status and Recent events in KeyGuardRail. Add explicit mappings using the resource IDs shown on those observations. Enable automatic processing only for mappings you have reviewed. A successful empty poll verifies a source check; delivery remains unverified until an event is accepted. 6. Schedule the command every five minutes, using the same user and state directory. Monitor its JSON output, exit status and KeyGuardRail's last successful check. Example systemd service (provision the user and protected directories first): [Unit] Description=KeyGuardRail metadata collection After=network-online.target Wants=network-online.target [Service] Type=oneshot User=kgr-collector Group=kgr-collector UMask=0077 ExecStart=/usr/bin/node /opt/kgr-collector/keyguardrail-vault-collector.mjs /etc/kgr-collector/config.json /var/lib/kgr-collector/production TimeoutStartSec=150 NoNewPrivileges=true ProtectSystem=strict ProtectHome=true PrivateTmp=true ReadWritePaths=/var/lib/kgr-collector Example timer: [Unit] Description=Check vault metadata every five minutes [Timer] OnBootSec=2min OnUnitActiveSec=5min RandomizedDelaySec=30 Persistent=true [Install] WantedBy=timers.target Exit 0: complete or waiting for a saved retry time. Exit 2: partial, pagination continues on the next run. Exit 1: fixed error code; investigate and retry. A timer must run again after partial/failure. No long-running daemon is required. HashiCorp Vault Create a token with only read on the EXACT metadata paths; no list/data/subkeys permissions are needed. For example, this policy observes one existing KV v2 path: path "secret/metadata/production/database" { capabilities = ["read"] } Use a short-lived token provisioned/renewed by Vault Agent or your existing auth workflow; this collector does not authenticate, renew tokens or read secret values. Do not use a root token. /v1/sys/health must expose the expected cluster_id. Obtain that identifier through your administrator and enter it in both KeyGuardRail and the config. The collector rejects redacted/mismatched identity or a sealed vault. Namespace is an exact relative namespace path, without a trailing slash, or empty for root. Enterprise namespace authentication and policies remain your responsibility. { "provider": "hashicorp", "destination": "https://keyguardrail.com/api/v1/integrations/ORGANIZATION_UUID/INTEGRATION_UUID", "destinationTokenFile": "/etc/kgr-collector/keyguardrail-token", "sourceTokenFile": "/etc/kgr-collector/vault-token", "source": { "url": "https://vault.example.com", "clusterId": "85f10224-27d4-11fd-ec8a-6549d71779f2", "namespace": "", "mount": "secret", "paths": ["production/database"] } } Use HTTPS, including private Vault installations; use NODE_EXTRA_CA_CERTS for an approved private CA. Never disable TLS verification. Redirects are rejected. Paths use ASCII letters/digits/_/- with dots permitted after the first segment; empty, dot-only and parent segments are rejected. At most 1000 explicit paths. The collector checks five paths per page, up to ten pages per run by default. A first snapshot, version change or availability change emits an observation; unchanged snapshots are suppressed. Deleted/destroyed current versions are unavailable. Scheduled deletion in the future is not treated as already deleted. A missing metadata path (404) fails the check, rather than inventing a deletion. Fix permissions or intentionally adjust the allowlist and initialize new state. Mapping format (namespace/mount encoded with encodeURIComponent; ~ means root): vault://CLUSTER_ID/namespaces/~/mounts/secret/secrets/production/database This is KV v2 only. KV v1, dynamic database leases, PKI engines, Enterprise WebSocket subscriptions, target rotation verification and complete deletion of metadata are not inferred by this collector. 1Password Business An owner/admin creates an Events Reporting integration with Item Usage reporting only, and an expiring Events API token. Do not use a Connect/service-account token that can read item contents. GET /api/v2/auth/introspect provides account_uuid and authorizations; find the vault UUID in the admin interface or a reporting event. The collector verifies account identity and the itemusages feature on every run. { "provider": "onepassword", "destination": "https://keyguardrail.com/api/v1/integrations/ORGANIZATION_UUID/INTEGRATION_UUID", "destinationTokenFile": "/etc/kgr-collector/keyguardrail-token", "sourceTokenFile": "/etc/kgr-collector/onepassword-events-token", "source": { "region": "us", "accountId": "aaaaaaaaaaaaaaaaaaaaaaaaaa", "vaultId": "vvvvvvvvvvvvvvvvvvvvvvvvvv" } } Regions: us, eu, ca. Item change reporting requires supported clients (8.4.0+). Only server-create/server-update for the selected vault are forwarded. The API returns account-wide reporting metadata; unrelated items, actor, location and client details are discarded before any local state or delivery is written. The persistent response cursor captures late-synced client events; it is reused across runs instead of resetting to a timestamp. Initial retrieval starts 24 hours ago unless startTime is supplied. Historical events cannot reconstruct current contents or prove all items exist. A quiet stream has no automatic inventory scan. Provider limits include 600 requests/minute and 30,000/hour; this collector uses at most ten source pages per run. Business plan/reporting availability is required. Mapping: onepassword://ACCOUNT_UUID/vaults/VAULT_UUID/items/ITEM_UUID All 26-character IDs are canonicalized to lowercase. A move between vaults may require a new explicit mapping; names are never used for automatic matching. Bitwarden Secrets Manager Use the organization's Public API key, obtained by an authorized organization administrator. Store only its client_secret in sourceTokenFile; client_id is constructed as organization.ORGANIZATION_UUID. The collector requests a short-lived OAuth token with scope api.organization, retained only in memory, then GETs /public/events. It never invokes a Secrets Manager value-reading SDK or endpoint. Important provider permission limit: the Public API organization key has broad organization-management authority; Bitwarden does not offer a read-only events scope for this key. Keep it on a tightly controlled host, rotate it, and only use this option if that provider access model is acceptable. KeyGuardRail never gets this key. The collector itself only mints an access token and reads events. { "provider": "bitwarden", "destination": "https://keyguardrail.com/api/v1/integrations/ORGANIZATION_UUID/INTEGRATION_UUID", "destinationTokenFile": "/etc/kgr-collector/keyguardrail-token", "sourceTokenFile": "/etc/kgr-collector/bitwarden-client-secret", "source": { "region": "eu", "organizationId": "f2089d45-2cc0-4a8d-a479-83237a180f50" } } Regions: us, eu. Self-hosted/custom endpoints are not included in this release. The API must return secretId for Secrets Manager events. A relevant event without it stops the check; itemId is not a substitute. Dates and continuation tokens are preserved across fixed-window pagination. Once every page is durably delivered, the watermark advances. Later checks overlap by 24 hours (overlapHours: 1..168) and end two minutes behind the local clock. Events arriving later than the overlap may be missed; increase the window and perform independent periodic review. The API exposes no event UUID. KeyGuardRail deduplicates the organization/type/ secretId/exact date tuple, preserving fractional timestamp precision. Two genuinely identical tuples cannot be distinguished; this is not an exactly-once audit export. No current inventory scan, rotation completion or expiry evidence is claimed. Mapping: bitwarden://ORGANIZATION_UUID/secrets/SECRET_UUID Checkpoints, retries and recovery State contains only source identity hashes, opaque cursors, metadata fingerprints, watermarks and a sanitized delivery outbox. It contains no provider or KeyGuardRail credentials. Keep it private and backed up; it is still sensitive operational metadata. Source bodies and personal reporting fields are never retained. Pending batches are written atomically and fsynced before delivery; source checkpoints advance only after all batches are accepted. A lost acknowledgment replays the same IDs and fields. KeyGuardRail accepts duplicates without a second mutation. 202 means durable receipt, not processing success; check review/unmatched/conflict and failed outcomes separately in the application. The state is bound to the exact source identity, endpoint, allowlist and destination. Changing credentials/files is safe without resetting it. Changing source identity, allowlist, destination or overlapHours requires a deliberate new state directory. Drain the old outbox first and plan the new startTime to avoid an unreviewed gap. Do not share one state directory across integrations or hosts. An exclusive .lock prevents overlap. After an abrupt process/host crash, verify that no collector process still uses this state, then remove only that stale .lock before restarting. Normal exits remove it. Do not automatically steal locks based on elapsed time. No automatic cursor reset or silent skipping occurs. For checkpoint_invalid, restore a known checkpoint or investigate the provider cursor before reinitializing. For source_unauthorized, fix/rotate the local source token. For delivery_failed, check KeyGuardRail availability, scopes, source configuration, event age and limits. A 429 honors Retry-After (up to 24 hours); other failures use exponential backoff with jitter, capped near one hour. Failed outboxes survive retries. Provider error bodies and exception strings are never written to output or reported upstream. Optional config fields: maxPages (1..10, default 10), maxRunSeconds (10..120, default 60), startTime (RFC3339, at most 89 days ago, used only when state is first created), overlapHours (Bitwarden 1..168, default 24). The initial startTime must precede Bitwarden's two-minute lag. Omit startTime for normal scheduled operation; an existing checkpoint always takes precedence over startTime. Requests time out after ten seconds and responses are capped at 1 MiB. Large source pages fail without checkpoint advancement; narrow the initial time window or contact the provider if its page cannot fit. Each delivery contains at most 20 events. KeyGuardRail limits payloads to 64 KiB, requests to 120/integration/minute and new events to 10,000/integration/day. Shared egress also has an IP rate limit. Reconciliation reports complete only after a full scan/page window and durable acceptance. Partial/failed attempts are visible and do not refresh the successful reconciliation timestamp. If delivery itself is unavailable, even the failure report may not arrive: monitor the local scheduler and stale-connection status. All hosts need synchronized clocks. Review token expirations before they lapse. Official references https://developer.hashicorp.com/vault/api-docs/secret/kv/kv-v2 https://developer.hashicorp.com/vault/api-docs/system/health https://www.1password.dev/events-api/reference https://www.1password.dev/events-api/item-usage-actions https://www.1password.dev/events-api/pagination https://support.1password.com/events-reporting-elastic/ https://bitwarden.com/help/public-api/ https://bitwarden.com/help/event-logs/ https://github.com/bitwarden/server/blob/main/src/Api/Dirt/Public/Models/EventResponseModel.cs https://github.com/bitwarden/server/blob/main/src/Api/Dirt/Public/Controllers/EventsController.cs