# GitGuardian Documentation > GitGuardian is a code security platform that detects and remediates secrets (API keys, passwords, certificates) leaked in source code across the entire Software Development Lifecycle. Complete GitGuardian documentation in a single document, optimized for LLM consumption. ## API Reference The [**API Reference Documentation**](https://api.gitguardian.com/docs) contains useful information for developers about the GitGuardian API. > Note that if you are using a GitGuardian self-hosted instance, the base url of the API routes will be `https://dashboard.gitguardian.mycorp.local/exposed/` instead of `https://api.gitguardian.com/`. For example, the scan route will be: `https://dashboard.gitguardian.mycorp.local/exposed/v1/scan` Examples are provided in all supported programming languages (e.g. Python and Go). --- ## Authentication The GitGuardian API uses API keys to authenticate requests. ## Creating your API key There are 2 different types of API keys: - **[Service accounts](./service-accounts.md):** a special type of token 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. - **[Personal access tokens](./personal-access-tokens.md):** a token intended for the use of the GitGuardian API and command-line application ggshield by individual developers on their local workstations (e.g. pre-commit or pre-push git hooks). You need to [create an account](https://dashboard.gitguardian.com/auth/signup) in order to get an API key. Your API key must be kept private and should neither be embedded directly in the code nor versioned in Git. (Please do not push GitGuardian's API keys to public GitHub repositories ^^). As in the example below, use the [`/health` endpoint](https://api.gitguardian.com/docs#tag/Status/operation/health_check) to check the validity of your API key. ## Authentication scheme The GitGuardian API uses `Authorization` header authentication for its requests. The `Authorization` header value must be prefixed with `Token`. Example request using `curl`: ```shell curl -H "Authorization: Token ${TOKEN}" \ https://api.gitguardian.com/v1/health ``` ## Scopes {#scopes} **Scopes are tied to an API key and control the access to resources and scan capability**. ### Dashboard data management scopes - `incidents` - `incidents:share`: grant view, edit and share permissions on the incidents of your GitGuardian workspace. - `incidents:write`: grant view and edit permissions on the incidents of your GitGuardian workspace. - `incidents:read`: grant view only permission on the incidents of your GitGuardian workspace. - `sources` - `sources:write`: grant view and edit permissions on the sources (code repositories only) of your GitGuardian workspace. - `sources:read`: grant view only permission on the sources (code repositories only) of your GitGuardian workspace. - `honeytokens` - `honeytokens:write`: grant view and edit permissions on the honeytokens of your GitGuardian workspace. Available under specific conditions: the honeytoken product must be enabled for the workspace, and for personal access token the role must be minimum "manager". - `honeytokens:read`: grant view only permission on the honeytokens of your GitGuardian workspace. Available under specific conditions: the honeytoken product must be enabled for the workspace, and for personal access token the role must be minimum "manager". - `honeytokens:check`: grant permission to check whether a detected secret is a honeytoken, without exposing honeytoken details. Used by ggshield during scans so honeytokens are recognized instead of being treated as live secrets or accidentally triggered. Unlike the read/write honeytoken scopes, it does not require a Manager role. - `members` - `members:write`: grant view and edit permissions on the members of your GitGuardian workspace. - `members:read`: grant view permission on the members of your GitGuardian workspace. - `teams` - `teams:write`: grant view and edit permissions on the teams of your GitGuardian workspace. - `teams:read`: grant view permission on the teams of your GitGuardian workspace. - `api_tokens` - `api_tokens:write`: grant view and edit permissions on the api tokens (personal access tokens and service accounts) of your GitGuardian workspace. - `api_tokens:read`: grant view permission on the api tokens (personal access tokens and service accounts) of your GitGuardian workspace. - `audit_logs:read`: grant view permission on the audit logs of your GitGuardian workspace. If you are using personal access tokens, it is only available to Managers. - `ip_allowlist` - `ip_allowlist:write`: grant view and edit permissions on the IP allowlist of your GitGuardian workspace. - `ip_allowlist:read`: grant view only permission on the IP allowlist of your GitGuardian workspace. - `custom_tags` - `custom_tags:write`: grant view and edit permissions on the custom tags of your GitGuardian workspace. - `custom_tags:read`: grant view only permission on the custom tags of your GitGuardian workspace. - `secrets` - `secrets:write`: grant view and edit permissions on NHI secrets of your GitGuardian workspace. - `secrets:read`: grant view only permission on NHI secrets of your GitGuardian workspace. - `nhi` - `nhi:send-inventory`: grant permission to send NHI inventory data to GitGuardian. - `nhi:write-vault`: grant permission to receive write instructions from GitGuardian for secret synchronization. - `nhi:ownership:write`: grant view and edit permissions on NHI ownership. - `nhi:ownership:read`: grant view only permission on NHI ownership. - `public-perimeter:read`: grant view permission on the public monitoring perimeter of your GitGuardian workspace. - `endpoints:send`: grant permission to upload [Endpoint Protection](/endpoint-protection/home) scan results, machine metadata, and findings to your GitGuardian workspace. Used by `ggshield machine submit` and `ggshield machine report`. Detection runs on the endpoint, so this scope does not grant scanning. - `ai-discover:send`: grant permission to upload the inventory of AI agents and MCP servers found on an endpoint. Used by `ggshield ai discover`. Available on the Business and Enterprise plans. ### Scan capability scope - `scan`: grant permissions to scan any text content for secrets with GitGuardian secrets detection engine. Required to use [ggshield](../ggshield-docs/getting-started). - `scan:create-incidents`: grant permissions to scan content and create incidents from custom sources. Includes `scan` scope. > You can even test this capability directly in the [Secrets detection playground section in your dashboard](https://dashboard.gitguardian.com/api/secrets-detection-playground): ![API Secrets detection playground](/img/api/secrets_detection_playground.png) --- ## Introduction The GitGuardian API gives you full creative control to **manage your dashboard** data and also to **use GitGuardian secrets detection engine**, whether through ggshield or in a custom way. All API calls need to be authenticated. ### Use cases - Export your incidents to build custom reports. - Manage your incidents programmatically. - Perform your users and teams management programmatically. - Plug GitGuardian easily into your existing services. - Build your own integration for secrets detection. - You want to use ggshield to shift left. ### Considerations - The GitGuardian API is versioned. - All requests to the GitGuardian API must be authenticated. - The GitGuardian API enforces rate limits on all requests. ### Limitations - Only secret incidents are available through the API. [Start to use the API by creating your API key ->](./authentication.md) --- ## Pagination Cursor-based pagination is the method used to navigate through the large datasets offered by the GitGuardian API. This method allows you to retrieve items in chunks (pages) by using cursors, which are pointers to a specific item in a dataset. The cursor indicates the position in the dataset, making it easier to navigate back and forth between pages. ## How cursor-based pagination works - **Initial Request**: When you make the first request to an endpoint, you receive the first set of results - **Subsequent Requests**: Use the response's [`link`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link) header to request the next set of results. `link: ; rel="next"` - **No more data**: If there's no more data to retrieve, the response will have no `link` header. ## Examples ### Python ```python BASE_URL = "https://api.gitguardian.com/v1" API_KEY = os.environ['GITGUARDIAN_API_TOKEN'] HEADERS = {"Authorization": f"Token {API_KEY}"} endpoint_url = f"{BASE_URL}/members?per_page=10" all_members = [] while True: response = requests.get(endpoint_url, headers=HEADERS) assert response.status_code == 200, response.json() all_members += response.json() if "next" not in response.links: # final page was reached break endpoint_url = response.links["next"]["url"] ``` ### Bash/cURL ```bash #!/bin/bash URL="https://api.gitguardian.com/v1/members?per_page=10" # Check if jq is installed if ! command -v jq &> /dev/null; then echo "jq could not be found, please install it to parse JSON." exit 1 fi MEMBERS="[]" while [ "${URL}" ]; do RESP=$(curl -i -Ss -H "Authorization: Token $API_KEY" "${URL}") # Check for curl error if [ $? -ne 0 ]; then echo "Error: Failed to retrieve data from ${URL}" exit 1 fi # Extract HTTP status code HTTP_STATUS=$(echo "$RESP" | grep HTTP | awk '{print $2}') if [ "$HTTP_STATUS" != "200" ]; then echo "Error: Received HTTP status $HTTP_STATUS" exit 1 fi # Retrieve the body of the response and parse it with jq BODY=$(echo "$RESP" | sed -n '/^\r$/,$p' | sed '1d' | jq '.') # Append to members list MEMBERS=$(echo "${MEMBERS}" | jq ". + ${BODY}") # Retrieve the next url from the response's headers URL=$(echo "$RESP" | grep -i '^link:' | sed -n -E 's/^link:.*<(.*)>; rel="next".*/\1/p') done # Output the members list formatted with jq echo "${MEMBERS}" | jq '.' ``` --- ## Personal access tokens ## Prelude **Personal access tokens are used to authenticate calls to the GitGuardian API**. They are intended to be used by developers on their local workstations to scan for secrets with the help of [ggshield](../ggshield-docs/getting-started.md) (in [pre-commit](../ggshield-docs/integrations/git-hooks/pre-commit.md) or [pre-push](../ggshield-docs/integrations/git-hooks/pre-push.md) git hooks). ## Creating a personal access token 1. Go to the [Personal access tokens page](https://dashboard.gitguardian.com/api/personal-access-tokens) in the API section of your workspace. Click on `Create token` 2. Name your key according to its use-case (for example `-`) 3. Set an expiry date for your token (in 1 week, 1 month, 3 months, 6 months, 1 year, or never). If you set an expiry date, you will receive an email to notify you 5 days before expiration. 4. Click on `Create token` Make sure you copy the token, it will no longer be visible to you in the future. ![Personal access tokens modal](/img/api/personal_access_tokens_modal.png) ## Additional thoughts - A user provisioning a personal access token with any data scope will allow them to **only retrieve resources following what they have access to via the UI**. - Each user is allowed 5 personal access tokens in total. - A personal access token is tied to the user who created it. If the user is deleted, their personal access tokens are also deleted. This is especially useful for deprovisioning purposes in a large organization. - If you are a member of more than one workspace, you will need to specify which workspace your personal access token is attached to. ## Managing personal access tokens In the Business plan, workspace Managers can administrate the personal access tokens issued for their GitGuardian workspace. They can view, filter, and revoke personal access tokens of all workspace members directly from the table. ![Personal access tokens table](/img/api/personal_access_tokens_table.png) --- ## Service accounts ## Prelude 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. > Please note that service accounts are **only available for workspaces under our Business plan**. ## Creating a service account > **Only workspace Managers** are allowed to manage service accounts. 1. Go to the [Service accounts page](https://dashboard.gitguardian.com/api/service-accounts) in the API section of your workspace. Click on `Create service account`. 2. Name your service account according to its use-case (for example `-`) 3. Set an expiry date for your token (in 1 week, 1 month, 3 months, 6 months, 1 year, or never). If an expiry date is set, all the Managers of the workspace will receive an email notification 5 days before expiration. 4. Choose one or several scopes for your service account. 5. Click on `Create service account` Make sure you copy the service account, it will no longer be visible to you in the future. ![Service accounts modal](/img/api/service_accounts_modal.png) The service accounts of your workspace are visible and can be managed [here](https://dashboard.gitguardian.com/api/service-accounts) by workspace Managers of workspaces under our Business plan. ![Service accounts table](/img/api/service_accounts_table.png) ## Revoking a service account A service account token can be revoked from the [Service accounts page](https://dashboard.gitguardian.com/api/service-accounts) by a workspace Manager, or through the Public API by another token holding the [`api_tokens:write`](/api-docs/authentication#scopes) scope. A service account token **cannot revoke itself**. Since a service account token can be shared across several deployments, letting it self-revoke would break every deployment using it. Attempting to do so (for example via `ggshield auth logout`) is refused with a `403` error. --- ## Usage and quotas ## Usage The **GitGuardian API and its scan capability** can be used to scan simple content quickly, or even to write complex integrations for non-publicly available services. Most of GitGuardian's Open Source projects use the **GitGuardian API** as their backbone. [ggshield](../ggshield-docs/getting-started.md) and [py-gitguardian](https://github.com/GitGuardian/py-gitguardian) are two examples. ## What the scan API stores The GitGuardian scan API does not keep scanned documents as incidents in your workspace. On GitGuardian SaaS, each secret detection from that API is logged, including detections that ggshield later ignores. We also store metadata for quota usage and access logs. ## Quotas API quotas are only consumed by API calls related to the [`scan` scope](./authentication#scopes): - the [`/scan` endpoint](https://api.gitguardian.com/docs#operation/content_scan) ingests only one document (piece of text) and consumes 1 quota. - the [/multiscan endpoint](https://api.gitguardian.com/docs#operation/multiple_scan) ingests several documents at a time (20 max) and consumes 1 quota. If a commit contains 40 different documents to scan, scanning this commit will require 2 quotas. Quota usage is based on requests, not on the size of the content you scan. **The quota is set on a rolling month**, not on a calendar month. This means that if 200 API calls are made on the last day of the month, you will need to wait 30 days before 200 new calls are credited back to your account. This quota is applied at the workspace level, not at the individual API key level. Consequently, exceeding the quota with one API key will restrict all other API keys in the same workspace from making further API calls. The quota depends on your plan but you can always contact us to increase it (see [GitGuardian Pricing](https://www.gitguardian.com/pricing) for more details): | | Free plan | Business plan | Enterprise plan | | --------- | :----------------- | :------------------ | :-------------- | | **Quota** | 10,000 calls/month | 100,000 calls/month | Unlimited | Workspace Managers can track usage of their quota in the [Quota section](https://dashboard.gitguardian.com/api/quota) of their workspace: ![API usage](/img/api/quota.png) ## Rate limiting The GitGuardian API implements rate limiting to manage the number of requests made to the API. This helps prevent abuse, ensures fair usage, and maintains the performance and availability of the API. The GitGuardian API implements rate limiting at the API key level, ensuring that each key is allocated a predetermined maximum number of requests within a designated timeframe. If the limit is exceeded, the GitGuardian API will return error with status code 429 and the requests will not be processed. The rate limiting varies based on the type of API key (personal access token or service account) and the plan of your workspace: | | Free plan | Business plan | Enterprise plan | | ------------------------- | :------------------------------------------------------------- | :------------------- | :-------------------- | | **Personal access token** | 50 requests/minute | 200 requests/minute | 2000 requests/minute | | **Service account** | N/AService accounts are not available under the Free plan | 1000 requests/minute | 10000 requests/minute | > By default, API rate limiting is not applied to GitGuardian self-hosted instances. --- ## AI agents and MCP inventory The AI agents and MCP inventory gives security teams visibility into the AI tooling actually running on developer endpoints: which AI agents are installed (Claude Code, Cursor, Codex, and others), which MCP servers they are configured to use, and what data and tools those servers can access. This matters because AI tooling spreads faster than any approval process. Developers add AI agents and MCP servers on their own machines, each one a new path for credentials to move. GitGuardian found 24,008 unique secrets in public MCP configuration files in 2025 (State of Secrets Sprawl 2026). You cannot investigate what you cannot see. ## Use cases - **Shadow AI discovery**: detect AI agents and MCP servers that were never approved. The inventory shows what is installed across the fleet, including personal subscriptions, and not just what developers declared. - **Incident scoping**: after a compromise, investigate what AI tooling was on the machine, which MCP servers were configured, and what they could reach. - **Grounding your AI usage policy**: write policy from observed behavior rather than assumptions. The AI Agents inventory tells you which tools your organization actually uses before you decide what to allow. ## How it works `ggshield ai discover` inventories AI tooling locally on the endpoint by parsing the configuration files of supported AI agents. Like [machine scans](/endpoint-protection/core-concepts#how-scanning-works), it runs on a schedule rather than as a continuous agent, but it is its own job and is scheduled separately from the scan. The inventory also reports whether [AI Hooks](/endpoint-protection/ai-hooks) are installed for each AI agent it finds, which gives you fleet-wide hook coverage without inspecting individual machines. Add `--history` to also backfill MCP tool calls rebuilt from agent transcripts, with the tool input and the working directory each call ran in. This covers the period before the hooks were installed, which is usually the period an investigation cares about. See the [`ggshield ai discover` reference](/ggshield-docs/reference/ai/discover) for the full option list. ## Deploy the inventory Deploy the inventory as a scheduled MDM job, alongside the rest of Endpoint Protection. After the developer logs in, `ggshield ai discover` uses their token. Uploading needs the `ai-discover:send` scope, included in the default login and available on Business and Enterprise plans. For the job pattern, follow [Step 7 of the service account token guide](/endpoint-protection/deploy/deploy-ggshield-with-sat#step-7---collect-the-ai-and-mcp-inventory). ## What is collected, and what is not - **Collected**: configuration metadata about installed AI agents and configured MCP servers, whether [AI Hooks](/endpoint-protection/ai-hooks) are installed for each AI agent, and the AI agent's subscription email, which is what tells a company subscription from a personal one. - **Not collected**: your files. Parsing happens on the endpoint, and configuration files and transcripts stay there. Any secret detected along the way is reported as a hashed fingerprint, never as a plaintext value. The one exception is the experimental `--activity` flag, which ships raw agent activity records to GitGuardian, where the content is scanned and secrets are stripped before storage. Leave it off if you want parsing to stay entirely local. For everything that leaves an endpoint across the AI layer, including what AI Hooks report at runtime, see [what the AI layer sends](/endpoint-protection/data-handling-and-privacy#what-the-ai-layer-sends). ## Scope of the inventory The inventory observes and reports. It does not block AI agents or MCP servers, does not change any configuration on the endpoint, and takes no action on what it detects. Use it to see and investigate. Prevention on the endpoint comes from [AI Hooks](/endpoint-protection/ai-hooks), which block secrets in AI tool interactions. --- ## Prevent leaks with AI Hooks AI Hooks make `ggshield` part of the AI coding tools your developers already use. When a prompt or a tool call contains a secret, `ggshield` blocks the action before it reaches the model and tells the developer or the agent what to remove. When a secret only appears in a tool's output, which a shell command or an MCP response can produce unpredictably, the action has already run, so `ggshield` raises a desktop notification. ## Why AI Hooks matter on developer endpoints Endpoint scanning inventories the credentials already sitting on a machine. AI Hooks stop new ones from leaving it. Developers using AI coding tools leak secrets at roughly twice the baseline rate. An agent asked to debug a failing deployment reads the `.env` file or `~/.aws/credentials` and passes the contents to a model provider. There is no commit, no push, and no pull request, so none of the checkpoints that protect your repositories and CI ever fire. Hooks act at the moment of the interaction, which gives you a few things: - **Prevention rather than cleanup.** The secret is caught before it reaches a third party, so there is no rotation to schedule and no model provider to ask about retention. - **A fix the developer can act on.** Every block names the detected secret and what to remove, so the developer or the agent can correct the content and retry immediately. - **No extra agent to deploy.** Hooks reuse the `ggshield` binary you already install for scanning. They run only when the AI tool calls them, so there is no resident process on the machine. ## What hooks scan `ggshield` registers on three stages of an AI interaction: - **Prompt submission**: the prompt is scanned before it reaches the model, and blocked if it contains a secret. - **Pre-tool use**: file reads, shell commands, and MCP calls are scanned before the agent runs them, and blocked if they contain a secret. - **Post-tool use**: if a tool output contains a secret, the developer gets a desktop notification. Detection uses the same engine as every other `ggshield` scan, covering 600+ types of secrets. Supported tools are Claude Code, Cursor, Codex, Copilot CLI, VS Code, and Mistral Vibe. For per-tool setup, what the blocking message looks like to a developer, and how to handle false positives, see [Secret scanning for AI coding tools](/ggshield-docs/integrations/ai-coding-tools/secret-scanning-for-ai-coding-tools). ## What a hook sends Detection happens on GitGuardian's side, so the content of the interaction is scanned by the API, the same way `ggshield` scans a commit or a push. Hooks also report each MCP tool call, with the tool and server name and the arguments the agent passed. That is what fills your MCP activity view and what carries the allow or deny decision back to the tool. Machine scans work the other way around and keep detection on the endpoint. For the full breakdown of both, see [Data handling & privacy](/endpoint-protection/data-handling-and-privacy#what-the-ai-layer-sends). ## Deploy AI Hooks across your fleet Hooks protect a machine only once they are configured on it, and asking each developer to opt in leaves gaps exactly where you need coverage. Push them through your MDM instead, alongside the rest of Endpoint Protection. Scanning needs a token every time a hook fires, and because hooks run in the developer's own session rather than in your MDM job, that token has to be the developer's. Inject an admin service account token at runtime to install the hooks, then log the developer in so the hook scans under their membership: see [Step 4](/endpoint-protection/deploy/deploy-ggshield-with-sat#step-4---set-up-hooks-and-honeytokens) and [Step 5](/endpoint-protection/deploy/deploy-ggshield-with-sat#step-5---log-the-developer-in). To set up a single machine, run one command as the logged-in user: ```bash ggshield machine setup ``` `machine setup` configures the hook for every AI coding assistant it detects, and skips the ones that are not installed. It also installs the git pre-commit and pre-push hooks and plants a honeytoken, so add `--no-git-hooks` or `--no-honeytokens` if you want AI Hooks alone. To pick or exclude specific assistants, use `--agent` or `--exclude-agent` with any of `claude-code`, `codex`, `copilot`, `cursor`, `vibe`, and `vscode`. Hooks require `ggshield` 1.49.0 or later, 1.51.0 or later for Codex, and 1.54.0 or later for Mistral Vibe. `machine setup` requires 1.53.0 or later. On earlier versions, install one assistant at a time with `ggshield install -t -m global`, which still works but is deprecated. ## Verify that hooks are active On a sample machine, as the logged-in user, run: ```bash ggshield machine doctor ``` `machine doctor` is read-only and reports, for every assistant it finds on the machine, whether the hook is installed. It also checks that the token reaches GitGuardian and carries the scopes your protections need, and it exits non-zero if any check fails, so you can run it as an MDM audit script. Each failed check prints its own fix. Both halves of that check matter. Because hooks fail open, a machine with hooks installed but no working credentials looks the same to a developer as a machine with nothing to block, apart from the warning that the content was not scanned. To confirm end to end, paste a test credential into a prompt and check that the tool displays the `ggshield` blocking message. ## Roll back Disabling the MDM setup job stops new machines from receiving hooks, but leaves the configurations already on disk in place. To remove them, delete the `ggshield` entries from the tool's hook configuration: | Tool | Hook configuration | |---|---| | Claude Code | `~/.claude/settings.json` | | Cursor | `~/.cursor/hooks.json` | | Codex | `~/.codex/hooks.json` | | Copilot CLI and VS Code | `~/.copilot/hooks/hooks.json` | | Mistral Vibe | `~/.vibe/hooks.toml` | --- ## Commands Endpoint Protection is driven by the commands under `ggshield machine`. Scanning is handled by three of them. | Command | What it does | Sends data to GitGuardian | |---|---|---| | `ggshield machine scan` | Scans the machine and stores the results locally. | No | | `ggshield machine report` | Scans the machine, then sends the results. | Yes | | `ggshield machine submit` | Sends the results of the latest local scan, without scanning again. | Yes | `ggshield machine dashboard` opens the local dashboard to browse the findings of the latest scan on the machine itself. ## Set up and check a machine Two more commands, available from `ggshield` 1.53.0, manage the protections that live on the machine rather than the scan itself. | Command | What it does | |---|---| | `ggshield machine setup` | Configures the AI Hook for every detected AI coding assistant, installs the git pre-commit and pre-push hooks, and plants a honeytoken. Idempotent, so it doubles as a repair job. | | `ggshield machine doctor` | Reports whether those protections are in place and whether the token carries the scopes they need. Read-only, and exits non-zero if any check fails. | Drop any part of the setup with `--no-ai-hooks`, `--no-git-hooks`, or `--no-honeytokens`, and narrow which assistants get the hook with `--agent` or `--exclude-agent`. Run `machine setup` as root, or pass `--system`, to install the git hooks machine-wide for every user. Because `machine doctor` exits non-zero on failure, it works directly as an MDM audit script. See [Roll out and verify](/endpoint-protection/deploy/deploy-ggshield-with-sat#step-8---roll-out-and-verify). ## Which scan command should I use? - **Fleet deployment (MDM, scheduled job, CI):** `ggshield machine report`. One fire-and-forget invocation that scans fresh and uploads the result. This is the command to put in your daily job. - **Evaluating on your own machine:** `ggshield machine scan --dashboard` to scan and review locally, then `ggshield machine submit` when you want the results in GitGuardian. - **Local only, nothing uploaded:** `ggshield machine scan`. Results stay in the local results database and never leave the machine. `submit` sends the *latest completed* scan and takes no scan options: the scope and mode were decided when `machine scan` ran. The upload timestamp is the scan time, not the send time, so re-sending an old scan does not make the endpoint look freshly scanned. :::note A scan run with `sudo` stores its results in the system database. Run `submit` with `sudo` too, so both commands use the same database. ::: ## `ggshield machine inventory` is deprecated `ggshield machine inventory` still works as an alias of `report` (scan, then send) so existing jobs keep running, and it prints a deprecation notice. Update your MDM scripts and scheduled jobs to `ggshield machine report`. ## Examples ```bash # Scan and send in one step (MDM / automation) ggshield machine report # Scan locally, review in the local dashboard, send later ggshield machine scan --dashboard ggshield machine submit # Build the payload locally without sending anything ggshield machine report --no-upload -o inventory.json # Self-hosted instance ggshield machine --instance https://gitguardian.example.com report ``` Sending requires GitGuardian credentials: the token stored by `ggshield auth login`, or an API key in the `GITGUARDIAN_API_KEY` environment variable. See [Deploy at scale with a service account token](/endpoint-protection/deploy/deploy-ggshield-with-sat) for unattended deployments. --- ## Configuration reference ## Excluding paths from scans You can exclude specific files or directories from being scanned by ggshield using a global configuration file. This is useful for ignoring test fixtures, generated files, or other paths that are known to be safe. ggshield looks for a `.gitguardian.yaml` configuration file in two locations, evaluated in order: 1. **Global config** in the user's home directory: - `~/.gitguardian.yaml` on Linux or macOS - `%USERPROFILE%\.gitguardian.yaml` on Windows 2. **Local config** at `./.gitguardian.yaml` in the directory being scanned. Both files follow the same format as the [ggshield configuration file](/ggshield-docs/configuration#configuration-files). Settings from the local config take precedence over the global one. Use the `ignored_paths` key under `secret` to specify glob patterns for paths to exclude: ```yaml secret: ignored_paths: - 'LICENSE' # exact file at the root - '*.log' # all .log files in the root directory - 'doc/*' # all files directly inside doc/ - 'tests/**/*' # all files anywhere inside tests/ - '**/*.generated.ts' # all .generated.ts files in any directory - '**/README.md' # all README.md files in any directory ``` ## Scheduling scans across timezones Scan scheduling is configured at deployment time. There are two approaches: - **MDM-native scheduling:** configure the execution frequency directly in your MDM for the custom script (e.g. Jamf's policy execution frequency). - **OS-level scheduling:** deploy a scheduled task via the MDM and let the OS scheduler handle recurrence: a `launchd` agent on macOS, a Task Scheduler job on Windows, or a `systemd` timer or `cron` entry on Linux. A wall-clock trigger such as "18:00 daily" fires at 6 pm in each device's local timezone automatically. ## Machine identifier GitGuardian uses a source identifier to represent each machine in your inventory. It has the format `/` and is used to deduplicate results across successive scans from the same machine. The ggshield CLI and the machine_scan plugin derive it identically, so all activity from one machine maps to a single inventory entry. **Hostname** is obtained via: - `gethostname()` syscall on Linux and macOS - The `COMPUTERNAME` environment variable on Windows **System ID** is a platform-specific unique identifier, re-derived at every scan: - **macOS:** the `IOPlatformUUID` from `ioreg -rd1 -c IOPlatformExpertDevice` - **Linux:** the first non-empty value from `/etc/machine-id`, `/sys/class/dmi/id/product_uuid`, or `/var/lib/dbus/machine-id` - **Windows:** the SMBIOS UUID, normalized to its lowercase canonical form. It is read with `wmic csproduct get uuid`, or through PowerShell on systems where `wmic` is not available. Placeholder firmware UUIDs (all zeros, all `F`s, or known BIOS vendor placeholders) are not accepted as identity. Machines whose firmware reports one, typically cloned VM images or boards with an unconfigured BIOS, use the fallback below instead of colliding on a single inventory entry. **Fallback:** if no platform-specific ID can be determined, a random UUID v4 is generated and cached at `~/.ggshield/machine_id` so it persists across scans. A warning is logged in this case: if that file is deleted, a new ID is generated and the machine may appear as a duplicate in your inventory. The file is writable only by its owner. A cache file that other users can write to, that belongs to an unrelated account, or that is a symbolic link is ignored and replaced with a fresh one. --- ## Core concepts ## What is Endpoint Protection? GitGuardian **Developer Endpoint Protection** extends secrets security to developer workstations. Credentials accumulate in shell history, config files, IDE caches, browser stores, and the files and caches that AI coding agents create on the local filesystem, all places outside the reach of repository scanners and CI checks. Endpoint Protection discovers those credentials on the machine where they live, and plants decoy credentials there to catch anyone trying to steal them. ## Why it matters As a security or platform lead, you typically already scan repos and CI. Endpoint Protection answers questions those layers cannot: - What credentials are sitting on developer laptops right now? - Which machines were scanned recently, and which were never scanned? - Is someone stealing credentials off a laptop at this moment? - After a compromise, what was on a given machine, ranked by severity? ## What it does **Machine scan**: recursively discovers plaintext credentials across the local filesystem, including config files, dotfiles, logs, IDE caches, and browser data. Findings are reported to the GitGuardian inventory, where each one is scored by severity and access scope, and can then be forwarded to your SOC, SIEM, or SOAR. **Honeytoken protection**: plants a decoy AWS credential on each machine, in the location credential harvesters read first. The decoy grants no access, so any use of it is unauthorized by definition and raises an alert naming the compromised machine. This adds intrusion detection on top of the inventory that scanning builds. See [Protect endpoints with Honeytokens](/endpoint-protection/honeytoken-protection). **AI Hooks**: guardrails registered in Claude Code, Cursor, Codex, Copilot CLI, VS Code, and Mistral Vibe that scan prompts and tool calls, block any that contain secrets, and tell the developer or the agent what to fix. See [Prevent leaks with AI Hooks](/endpoint-protection/ai-hooks). **AI agents and MCP inventory**: visibility into which AI agents and MCP servers run on each endpoint, what data and tools they can access, and how they are used. See [AI agents and MCP inventory](/endpoint-protection/agent-and-mcp-inventory). Each capability is deployed independently, and you can [monitor coverage](/endpoint-protection/dashboard) for each one separately. ## How scanning works `ggshield` runs the scan locally on the endpoint. Results are uploaded to your GitGuardian dashboard (SaaS or self-hosted) for centralized visibility. **What is sent to GitGuardian:** The secret hash, not the secret value. GitGuardian stores metadata and context around the finding, not the credential itself. Machine inventory metadata (machine identifier, hostname, local account names) is also sent so findings are attributed to the right machine and user (see [Data handling & privacy](./data-handling-and-privacy.md)). Source documents from the filesystem are never transmitted to GitGuardian's servers. **Validity checks:** For active secrets (AWS keys, GitHub tokens, etc.), `ggshield` calls the provider's API directly from the endpoint to verify validity and retrieve metadata such as scopes and owner. This call goes from the endpoint to the third-party provider, not through GitGuardian's servers. **Scan cache:** Scan results are cached locally on the endpoint: for each scanned file, the cache keeps finding metadata, secret hashes, and redacted values, never the plaintext secrets themselves. On the next scan, files that haven't changed (same size and modification time) are skipped and their cached results are reused, making recurring scans much faster than the first one. ## Platform support | Platform | Architecture | Status | |----------|-------------|--------| | macOS (workstations) | arm64 (M1/M2/M3/M4), x86_64 | ✅ Fully supported | | Linux (workstations) | arm64, x86_64 | ✅ Fully supported | | Windows (workstations) | x86_64 | ✅ Fully supported | | Linux servers (RHEL, Debian, Ubuntu) | arm64, x86_64 | 🚧 Beta | | Windows Server (2022 & 2025) | x86_64 | 🚧 Beta | On Windows, antimalware real-time scanning and Exploit Protection settings can slow scans considerably. See [Tune scan performance on Windows](/endpoint-protection/windows-scan-performance). --- ## Monitor coverage The **Endpoints** dashboard answers the question a security team actually has about a fleet: how much of it is covered, and which machines are not. Open it from **Endpoint protection > Endpoints** in your GitGuardian dashboard. ![The Endpoints dashboard, with coverage KPIs above a table of machines](/img/endpoint-protection/endpoints-coverage-dashboard.png) ## Coverage comes from your deployment, not from a setting here There is no switch in GitGuardian that turns scanning or honeytoken protection on for a machine. Coverage is a result of which jobs you deploy through your MDM, and this dashboard reports that result. That distinction matters when you are closing a gap. An endpoint missing from the fleet has no `ggshield` installed. An endpoint that is never scanned has no inventory job running. An endpoint marked as unprotected has no plant job running. In every case the fix happens in your MDM, and the dashboard is how you confirm it worked. See [Deploy Endpoint Protection](/endpoint-protection/deploy/deployment-options). The two capabilities are independent. A machine can be scanned without being planted, or planted without being scanned, so read the two columns separately rather than assuming one implies the other. ## Read the coverage KPIs The cards across the top summarize the fleet: - **Endpoints scan**: the share of endpoints that ran a scan recently. This is your scanning coverage, and it drops when scheduled jobs stop firing rather than when machines get riskier. - **Endpoints with critical findings**: the share of endpoints carrying at least one critical finding, with a trend against the previous period. This is the one card that measures risk rather than coverage. - **Honeytoken protection**: the share of endpoints with a honeytoken planted, alongside a count of unprotected endpoints and a link that filters the table down to them. - **AI hooks coverage**: the share of endpoints running AI agents that have guardrails in place. ## Work through the endpoints table Each row is one machine. The columns tell you what is known about it and how recently: | Column | What it tells you | |--------|-------------------| | Endpoint | The machine identifier and its owner. | | Latest endpoint scan | When the machine last reported. An `Inactive` marker means it has stopped reporting altogether, which is a deployment problem rather than a security finding. | | Scan secrets | Findings on that machine, broken down by severity. | | Honeytoken protection | `Protected` when a honeytoken is planted, `Unprotected` when none is. | | AI agents | Whether the AI agents on the machine have guardrails, and how many are covered. | Use the tabs and the filter bar to turn the fleet view into a work queue: - **All** for the whole perimeter. - **Compromised** for machines that need investigation now. - **Unprotected** for machines with no honeytoken planted, which is the list you work to raise honeytoken coverage. ## Investigate a single machine Selecting a machine opens its detail page, which carries the same split between capabilities: **Local scanning** for its latest scan, severity counts, and scanner version, and **Honeytoken protection** for its latest sync and planted honeytokens. Tabs give you discovered secrets, scan history, AI agents, and honeytokens. For what the honeytoken card and tab show, and how to act on them, see [Protect endpoints with Honeytokens](/endpoint-protection/honeytoken-protection). For what to do about the secrets a scan surfaces, see [Remediate findings](/endpoint-protection/remediate-findings). ## Where to go next - [Remediate findings](/endpoint-protection/remediate-findings) for acting on the secrets discovered on a machine. - [Validate and roll out](/endpoint-protection/deploy/validate-and-roll-out) for the checks to run on a pilot group before you expand. - [What is scanned](/endpoint-protection/what-is-scanned) for the sources behind the findings in the table. - [Data handling and privacy](/endpoint-protection/data-handling-and-privacy) for what leaves the machine. --- ## Data handling & privacy Endpoint Protection detects secrets in two ways, and each one handles your data differently. A **machine scan** walks the disk of a company machine on a schedule. Detection runs on the endpoint, and **file contents are never transmitted** to GitGuardian's servers. A full disk holds far more than the credentials we look for, so none of that content needs to leave the machine. [AI Hooks](./ai-hooks.md) work like every other `ggshield` scan: the GitGuardian API scans the content, exactly as it does when `ggshield` scans a commit or a push. That is what lets a hook block a secret before it reaches a model. Those calls do not create incidents. On GitGuardian SaaS, each detection is [logged](/api-docs/usage-and-quotas#what-the-scan-api-stores), including matches that ggshield later ignores. ## What a machine scan sends The only data sent during a machine scan is: - **Hashed fingerprints** of detected secrets (see below) - **Metadata** such as file path, timestamp, and scan context - **Machine and user inventory metadata**: the [machine identifier](./configuration-reference.md#machine-identifier), hostname, operating system and hardware characteristics, and the username and display name of local accounts. Outbound calls made during a scan include: - **Provider validity checks** (e.g., AWS, GitHub): these go directly from the endpoint to the provider to verify whether a secret is valid and retrieve metadata such as scopes or owner. These calls do not go through GitGuardian's servers. ## How secrets are hashed A machine scan never sends plaintext secrets to GitGuardian. Instead, it hashes them on the endpoint using GitGuardian's **HasMySecretLeaked (HMSL) protocol**. The hashing scheme uses a 256-bit **Scrypt** hash, which is intentionally slow and memory-hard to make brute-forcing impractical at scale. Like any one-way hash, it is not reversible. The main residual risk is offline guessing against very weak secrets, which the slow hash design mitigates. ## Scan scope and personal files Scan scope is policy-configurable. See [Configuration reference](./configuration-reference.md) for details. A few important points: - Endpoint Protection is a **corporate control deployed on company-issued machines** via MDM. - A machine scan sends only credential hashes and metadata, not file contents. - System directories and personal files outside the configured scope can be excluded entirely. ## What the AI layer sends | Data | When it is sent | What it is for | |---|---|---| | The content being scanned: a prompt, or the file read, shell command, or MCP call an agent is about to run | On every interaction, once AI Hooks are installed | Detecting the secret so the hook can block the action before the content reaches a model | | MCP tool call records: the tool and server name, the agent and model, the working directory, and the tool input | On every MCP tool call, once AI Hooks are installed | Reporting MCP activity in your dashboard, and returning the allow or deny decision to the AI tool | | Configuration metadata about installed agents and configured MCP servers, whether AI Hooks are installed for each agent, and the assistant subscription email | On every `ggshield ai discover` run | Reporting which AI tooling runs across your fleet, your hook coverage per machine, and whether a developer signed in with a company or a personal subscription | | MCP tool call records rebuilt from agent transcripts | Only when you add `--history` to `ggshield ai discover` | Backfilling MCP activity from before the hooks were installed, so an investigation can cover that period too | The assistant subscription email is read locally from the configuration of Claude Code, Codex, and Cursor. It can be a personal address, which is what makes the company versus personal subscription distinction possible in the first place. The inventory parses configuration files and transcripts on the endpoint. It uploads the records described above, not the files themselves. ## Where your data is stored Findings, machine metadata, and the inventory records above are stored in your GitGuardian workspace. MCP tool call records are retained, because they are what your MCP activity view is built from. Secret scans do not create incidents. On SaaS they still produce detection logs, as described in [What the scan API stores](/api-docs/usage-and-quotas#what-the-scan-api-stores). See [Data retention](/platform/security-data-privacy/data-retention) for how long GitGuardian keeps workspace data, and the [Trust Center](https://trust.gitguardian.com/) for our security and compliance documentation. If you need to share data protection and privacy details with internal audiences, reach out to your GitGuardian contact to request a dedicated document. --- ## Deploy ggshield at scale with a service account token Use this page to deploy Developer Endpoint Protection on managed endpoints: machine scanning, honeytoken protection, AI Hooks, and an inventory of the AI agents and MCP servers in use. The same pattern works with **Jamf Pro, Iru (formerly Kandji), Intune, Workspace ONE, Mosyle, Addigy, Canonical Landscape**, or configuration management tools such as **Ansible, Puppet, Chef, and Salt**. We recommend storing no GitGuardian token on the endpoint. Inject an **admin service account token** at runtime, only for the jobs your MDM runs: install `ggshield`, install the machine scanning plugin, plant the honeytoken, and running the scans. AI and git hooks are the exception. They fire in the developer's own session, not in your MDM job, so that machine needs a developer login. Log the developer in and the AI inventory is attributed to them too. ## Deployment model Deploy each capability as its own MDM job so you can audit, repair, or roll it back independently. The capabilities are optional and independent of each other, so you can scan a machine without planting a honeytoken, or install AI Hooks without scanning. Yet, we strongly recommend enabling all of them. | Job | What it does | GitGuardian token | Good MDM fit | |---|---|---|---| | Install or update `ggshield` | Deploy the CLI binary | Not needed | package deployment or remediation script | | Install or update `machine_scan` | Add the Machine Scan plugin for the scan user | Admin SAT, injected at runtime | audit/remediation script | | Machine setup | Run `ggshield machine setup` to configure AI Hooks, git hooks, and the honeytoken | Admin SAT, injected at runtime | scheduled script, daily | | Developer login | `ggshield auth logout --no-revoke`, then `ggshield auth login` as the logged-in user | Developer personal token | remediation script, once per machine | | Inventory scan | Run `ggshield machine report` | Admin SAT, injected at runtime, or the developer token | scheduled script, once per day | | AI and MCP inventory | Run `ggshield ai discover` | Developer token | scheduled script | In MDM terms, an **audit** script checks whether a machine is compliant, and a **remediation** script installs or repairs what is missing. Do not persist the admin SAT with `ggshield auth login --method token`. That overwrites the developer's login, so every later `ggshield` command on that machine reports as the shared account, and an admin token sits on disk. ## Step 1 - Create the admin token Create one dedicated [Service Account](/api-docs/service-accounts) token for the MDM jobs. Add only the scopes those jobs need: | Scope | Why it is needed | |---|---| | `scan` | Install the `machine_scan` plugin by name, which downloads it from the GitGuardian catalog | | `endpoints:send` | Upload scan results, when the MDM job runs `ggshield machine report` itself | | `honeytokens:write` | Plant honeytokens on the machine. Only needed for honeytoken protection | | `honeytokens:check` | Recognize your own honeytokens during a scan and avoid reporting it as a regular secret. Only needed for machine scans | Store the token in your MDM secret store or secret manager and inject it at runtime. ## Step 2 - Install and manage ggshield Use the deployment method your fleet already trusts: - **Jamf Pro / Iru (formerly Kandji) / Mosyle / Addigy**: deploy the signed macOS package or run an install remediation script. - **Intune**: deploy the Windows installer or run the PowerShell installer. For macOS/Linux, use shell scripts or remediations. - **Workspace ONE / RMM tools**: use a managed package or script assignment. - **Landscape / Ansible / Puppet / Chef / Salt**: install the `.deb`/`.rpm` or run the official installer, then enforce the version. For script-based macOS/Linux deployments, install only the binary first, and set `GGSHIELD_BIN_DIR` to a directory already on everyone's `PATH`: ```bash curl -sSfL https://raw.githubusercontent.com/GitGuardian/ggshield/main/scripts/install/install.sh | \ GGSHIELD_BIN_DIR=/usr/local/bin bash -s -- --install-only ``` Audit with `ggshield --version`, which must report **1.53.0 or later** for the commands on this page. For large fleets, prefer an internal package cache or MDM-hosted package so every machine does not download from the internet at the same time. The examples below reuse this `loggedInUser` lookup. On Linux, or on a server with a dedicated scan user, use that user instead. ```bash loggedInUser=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && !/loginwindow/ {print $3}') ``` ## Step 3 - Install Machine Scan for the scan user Machine scan plugin must be installed and enabled before running `ggshield machine report`. Install it for the user that will run the scan. Run the job as root instead and the plugin is installed machine-wide so every user can load it, which is the better fit when several people share a host. If your MDM can stage a signed or internal plugin package, install that package and the job needs no token: ```bash sudo -i -u "$loggedInUser" -- ggshield plugin install /path/to/machine-scan-plugin.whl ``` If you install by name, `ggshield plugin install machine_scan` contacts the GitGuardian plugin catalog. Pipe the admin SAT into `GITGUARDIAN_API_KEY` through stdin so it stays out of command lines and shell history. Disable shell tracing (`set -x`) in scripts that handle it. :::tip The token still lives in the process environment, where `ps -E` on macOS and `/proc//environ` as root on Linux can read it. Configure your MDM to redact secret environment variables and captured stdin from its own logs. ::: ```bash # Your MDM injects the admin SAT as GGSHIELD_SAT. printf '%s\n' "$GGSHIELD_SAT" | sudo -i -u "$loggedInUser" -- /bin/zsh -c \ 'IFS= read -r GITGUARDIAN_API_KEY && export GITGUARDIAN_API_KEY && exec ggshield plugin install machine_scan < /dev/null' sudo -i -u "$loggedInUser" -- ggshield plugin list ``` For Linux, use `/bin/bash` and your target user. `auth login` and later `ggshield` commands default to US SaaS. For EU or self-hosted instances, pass `GITGUARDIAN_INSTANCE` into the inner shell. The instance URL is not a secret: ```bash export GITGUARDIAN_INSTANCE=https://dashboard.eu1.gitguardian.com # or your self-hosted instance URL printf '%s\n' "$GGSHIELD_SAT" | sudo -i -u "$loggedInUser" -- \ env GITGUARDIAN_INSTANCE="$GITGUARDIAN_INSTANCE" /bin/zsh -c \ 'IFS= read -r GITGUARDIAN_API_KEY && export GITGUARDIAN_API_KEY && exec ggshield plugin install machine_scan < /dev/null' ``` Use that same `env GITGUARDIAN_INSTANCE=...` prefix on every later admin job. Audit success when `ggshield plugin list` shows `machine_scan` for the scan user. ## Step 4 - Set up hooks and honeytokens `ggshield machine setup` configures the 3 endpoint protections in one idempotent run. Drop any of them with `--no-ai-hooks`, `--no-git-hooks`, or `--no-honeytokens`. Run it as the logged-in user, and inject the admin SAT the same way as in [Step 3](#step-3---install-machine-scan-for-the-scan-user): ```bash printf '%s\n' "$GGSHIELD_SAT" | sudo -i -u "$loggedInUser" -- /bin/zsh -c \ 'IFS= read -r GITGUARDIAN_API_KEY && export GITGUARDIAN_API_KEY && exec ggshield machine setup < /dev/null' ``` Schedule this job daily. It adds missing protections and leaves ones already in place: - Writes hooks for AI agents that are not yet protected, and git hooks when they are not yet enforced. - Reconciles honeytoken protection against GitGuardian on every run: it rewrites a deleted honeytoken and removes one you revoked in the dashboard. That is why planting stays an MDM job with `honeytokens:write`. To pick specific assistants, use `--agent`. To skip some, use `--exclude-agent`. Both accept `claude-code`, `codex`, `copilot`, `cursor`, `vibe`, and `vscode`. ### Honeytoken Planting writes a decoy AWS profile in `~/.aws`. The process user decides whose home that is: - As the logged-in user: that account only, which is enough on a one-person laptop. - As root: every user home it finds (`/Users`, `/home`, and similar), so every account on a shared host gets a decoy. On a shared host, run the honeytoken part as root and inject the SAT through stdin: ```bash printf '%s\n' "$GGSHIELD_SAT" | sudo /bin/sh -c \ 'IFS= read -r GITGUARDIAN_API_KEY && export GITGUARDIAN_API_KEY && exec ggshield machine setup --no-ai-hooks --no-git-hooks < /dev/null' ``` Preview targets without writing anything: `ggshield honeytoken plant --list-targets`. See [Protect endpoints with Honeytokens](/endpoint-protection/honeytoken-protection). ### AI Hooks Hooks are written in the **current user's** AI agent config (`~/.claude`, `~/.cursor`, and the other [supported tools](/endpoint-protection/ai-hooks)). `machine setup` configures every AI agent it detects for that account. The hook later runs in the developer's session. It reads that user's credential store, which is why [Step 5](#step-5---log-the-developer-in) logs them in as themselves. If they are not logged in, the hook fails open: it does not block, and the tool shows a warning that the content was not scanned. On a shared host, keep AI Hooks in the logged-in user job and skip them in the root job (`--no-ai-hooks`). See [Prevent leaks with AI Hooks](/endpoint-protection/ai-hooks). ### Git hooks Installs global `pre-commit` and `pre-push` hooks. Scope follows the process user: - Root, or `--system`: git's **system** `core.hooksPath`, covering every user on the machine. - Not root, no `--system`: git's **global** `core.hooksPath` for the current user. A `core.hooksPath` that points somewhere else (Husky, lefthook) takes precedence, and the `ggshield` hook never fires there. A global install is the exception: when a global `core.hooksPath` already exists, `ggshield` writes its hook inside that directory instead of being shadowed by it. `ggshield machine doctor` reports this per repository, and it resolves the effective path from the current directory. Run your MDM audit script inside a repository, otherwise the check means nothing. On a shared host, install system hooks as root and skip git hooks in the user job, so you do not set a user-global `core.hooksPath` that shadows system for that account. System git hooks do not need a token: ```bash sudo ggshield machine setup --system --no-ai-hooks --no-honeytokens ``` ## Step 5 - Log the developer in After the admin jobs, log the developer in so AI Hooks, git hooks, and the AI inventory run under their membership. `ggshield auth login` requests `scan`, `honeytokens:check`, `endpoints:send`, and `ai-discover:send` automatically. `auth login` keeps an existing token if one is already stored, so log out first. Use `--no-revoke` so logout only clears the stored token. ```bash sudo -i -u "$loggedInUser" -- ggshield auth logout --no-revoke sudo -i -u "$loggedInUser" -- ggshield auth login ``` The login command opens a browser in the developer's session and provisions a personal token. For EU or self-hosted instances, pass `--instance` on both commands: ```bash sudo -i -u "$loggedInUser" -- ggshield auth logout --no-revoke --instance https://dashboard.eu1.gitguardian.com sudo -i -u "$loggedInUser" -- ggshield auth login --instance https://dashboard.eu1.gitguardian.com ``` US SaaS needs no `--instance` flag. ## Step 6 - Run the daily inventory scan Schedule one MDM job per day that runs `ggshield machine report`. It scans and sends in one step, see [Commands](/endpoint-protection/commands). Inject the admin SAT for this job, the same way as in [Step 3](#step-3---install-machine-scan-for-the-scan-user). The scan does not depend on the developer login, which is simpler across a fleet: ```bash printf '%s\n' "$GGSHIELD_SAT" | sudo -i -u "$loggedInUser" -- /bin/zsh -c \ 'IFS= read -r GITGUARDIAN_API_KEY && export GITGUARDIAN_API_KEY && exec ggshield machine report < /dev/null' ``` This job needs `endpoints:send` only. Detection runs locally, and the plugin checks that scope before it uploads. `scan` is for downloading the plugin from the catalog, not for scanning the machine. If you want each scan attributed to the developer instead, drop the injection and run it as the logged-in user after [Step 5](#step-5---log-the-developer-in), which uses their token: ```bash sudo -i -u "$loggedInUser" -- ggshield machine report ``` For EU or self-hosted instances, pass the instance through `env`, the same way as in [Step 3](#step-3---install-machine-scan-for-the-scan-user). Login does not store it for later commands. If your MDM cannot run scheduled scripts reliably, you can use `launchd` or a `systemd` timer as a fallback. ## Step 7 - Collect the AI and MCP inventory `ggshield ai discover` parses the configuration files of supported AI assistants and reports which agents and MCP servers are present on the machine. This is its own job, separate from the machine scan, so schedule it separately. Run it as the logged-in user after [Step 5](#step-5---log-the-developer-in), so it uses their token and the inventory is attributed to them. AI tooling changes less often than scan results, so a daily or weekly pass is enough. ```bash sudo -i -u "$loggedInUser" -- ggshield ai discover ``` For EU or self-hosted instances, pass the instance through `env`, the same way as in [Step 3](#step-3---install-machine-scan-for-the-scan-user). For what the inventory collects and how security teams use it, see [AI agents and MCP inventory](/endpoint-protection/agent-and-mcp-inventory). ## Step 8 - Roll out and verify Start with **10 to 20 monitored machines**, then expand in waves. On a sample machine, run the readiness check as the logged-in user, from inside a git repository so the git hooks check resolves the effective `core.hooksPath`: ```bash sudo -i -u "$loggedInUser" -- /bin/zsh -c 'cd /path/to/a/repo && exec ggshield machine doctor' ``` `machine doctor` is read-only and exits non-zero when any check fails, so you can use it directly as an MDM audit script and gate the next wave on it. Every failed check prints its own fix. After [Step 5](#step-5---log-the-developer-in), it should report that the developer token reaches GitGuardian with the scopes the protections need. Then trigger the MDM inventory job once. Go to **Endpoint protection → Endpoints** in GitGuardian and confirm the machine appears with a recent scan, and reports as `Protected` if you deployed honeytoken protection. See [Monitor coverage](/endpoint-protection/dashboard). To roll back, disable the scheduled jobs first, especially `machine setup`. Then clear what is already on disk. `ggshield auth logout` as the logged-in user removes their personal token. Revoke the admin SAT in your workspace to cover the whole fleet at once. For the pilot checklist, the wave sizes, and what to monitor at each gate, see [Validate and roll out](validate-and-roll-out). --- ## Deploy with Intune Each `ggshield` release ships two Windows packages. Both work with Intune, so choose based on your existing deployment workflow. | Package | Format | Intune deployment method | |---------|--------|--------------------------| | `ggshield--x86_64-pc-windows-msvc.msi` | MSI installer | Deploy as a **Line-of-business app** (`.msi` is natively supported). Intune handles install, repair, and removal. | | `ggshield--x86_64-pc-windows-msvc.zip` | ZIP archive | Extract and deploy the binary using your existing script-based deployment workflow. | The MSI is the simpler option for most environments. Use the ZIP if you need more control over the installation path or want to manage the binary directly without a Windows installer. Deploy the Microsoft Defender exclusion for the scanner process together with the package, otherwise Microsoft Defender real-time protection inspects every file the scanner opens and scans take much longer: see [Tune scan performance on Windows](/endpoint-protection/windows-scan-performance). --- ## Deploy with Iru (Kandji) GitGuardian maintains ready-to-use scripts for Iru deployments in the [ggshield-mdm-deploy](https://github.com/GitGuardian/ggshield-mdm-deploy) GitHub repository. Use these as the source of truth rather than writing scripts from scratch. Relevant scripts in the repository: | Script | Purpose | |--------|---------| | `shared/ggshield_install.sh` | Shared install script (single source of truth). | | `kandji/ggshield_audit.sh` | Audit script run by Iru to check whether `ggshield` is installed and up to date. | | `kandji/ggshield_remediation.sh` | Symlink to the shared install script, run by Iru when the audit fails. | --- ## Deploy with Jamf GitGuardian maintains ready-to-use scripts for Jamf deployments in the [ggshield-mdm-deploy](https://github.com/GitGuardian/ggshield-mdm-deploy) GitHub repository. Use these as the source of truth rather than writing scripts from scratch. Relevant scripts in the repository: | Script | Purpose | |--------|---------| | `shared/ggshield_install.sh` | Shared install script (single source of truth, symlinked by Jamf scripts). | | `jamf/ggshield_install.sh` | Symlink to the shared install script for use as a Jamf policy script. | | `jamf/jamf_ea_ggshield_version.sh` | Extension Attribute script for reporting the installed `ggshield` version in Jamf. | --- ## Deploy Endpoint Protection GitGuardian Endpoint Protection requires the deployment of `ggshield` onto each machine, which then delivers 4 independent capabilities: - **Scheduled scanning**, which discovers the credentials already sitting on the machine. - **Honeytoken protection**, which plants a decoy credential so that any attempt to steal it raises an alert. See [Protect endpoints with Honeytokens](/endpoint-protection/honeytoken-protection). - **AI Hooks**, which block secrets in prompts and tool calls before they reach an AI model. See [Prevent leaks with AI Hooks](/endpoint-protection/ai-hooks). - **AI agents and MCP inventory**, which reports the AI tooling running on each machine. See [AI agents and MCP inventory](/endpoint-protection/agent-and-mcp-inventory). You can deploy each one on its own, and GitGuardian reports their coverage separately. Most teams roll out scanning first and add the others once the fleet is reporting reliably. The outcome you validate in GitGuardian is **visibility**: fleet coverage and discovered secrets in **Endpoint protection > Endpoints**. Plan for both the MDM rollout and how your team will [monitor coverage](/endpoint-protection/dashboard) after the first scans complete. To try Endpoint Protection on a **single machine** first, use the [install script](/endpoint-protection/getting-started) to set up `ggshield` and the `machine_scan` plugin in one command. For a fleet rollout, choose one of the approaches below. The recommended and currently validated approach is an **MDM scheduled script**. The table below summarizes all supported deployment approaches. | Option | Best fit | Guidance | |--------|----------|----------| | MDM scheduled script | Managed macOS or Linux endpoints | Recommended starting point, and the approach validated in the current implementation. | | MDM install + local schedule | Endpoints that need to scan even when MDM does not trigger jobs reliably | Use `launchd` on macOS or `systemd` on Linux. Validate in your environment before broad rollout. | | Config management | Server or mixed fleets | Tools like Ansible, Puppet, Chef, or Salt can install `ggshield` and create the recurring job. | Regardless of the approach, the core setup steps are the same: [deploy ggshield at scale with a service account token](deploy-ggshield-with-sat). --- ## Validate and roll out ## Validate on 10 to 20 machines Before broad rollout, deploy to **10 to 20 closely monitored machines** and confirm all of the following: - `ggshield` installs successfully, and `ggshield --version` reports **1.53.0 or later**. - The binary is on every user's `PATH`. With the install script, `GGSHIELD_BIN_DIR=/usr/local/bin` keeps it reachable from an MDM job that runs as root and from `sudo -i`. - `ggshield plugin list` shows `machine_scan` for the scan user. - Admin jobs inject the SAT through stdin, so it stays out of command lines and shell history. Your MDM redacts secret environment variables and captured stdin from its logs. - `ggshield machine setup` exits successfully and is idempotent: a second run adds nothing that is already in place. - `ggshield auth logout --no-revoke`, then `ggshield auth login`, ran as the logged-in user. Login opens a browser in their session. For EU or self-hosted instances, both commands used `--instance`. - Recurring `ggshield machine setup` still injects the admin SAT through stdin. - `ggshield machine report` exits successfully, whether you inject the SAT for that job or run it as the logged-in user after login. - `ggshield machine doctor` exits zero when run from inside a git repository, which is what it needs to resolve the effective `core.hooksPath`. Use it as the MDM audit script that gates the next wave. Every failed check prints its own fix. - Scan duration is acceptable, and users do not report noticeable performance issues. If you are deploying honeytoken protection, also confirm: - `ggshield honeytoken plant --list-targets` resolves the expected target on a test machine. - After `machine setup`, the honeytoken is present and the developer's existing AWS profiles are untouched. If you are deploying AI Hooks, also confirm: - `machine doctor` reports the hook installed for every AI coding assistant it finds on the machine. - The developer is logged in. On a sample machine, pasting a test credential into a prompt shows the `ggshield` blocking message. If they are not logged in, the hook fails open and only shows a warning. If you are collecting the AI and MCP inventory, also confirm: - `ggshield ai discover` exits successfully. Only continue to percentage-based rollout after this first group is healthy. ### Confirm visibility in the Endpoints dashboard In your GitGuardian dashboard, open **Endpoint protection > Endpoints** and verify the pilot machines appear as expected: - The machines table lists each pilot endpoint with a **latest endpoint scan** time, not **Never scanned**. - Fleet coverage KPIs reflect the pilot group, so the **Endpoints scan** percentage rises after scans run. - Opening a machine shows **Local scanning** with severity counts and a **ggshield** scanner version on the latest scan. - The **Discovered secrets** table loads for machines where the scan found credentials. An empty table is acceptable on a clean test machine. - If you deployed honeytoken protection, the pilot machines show as `Protected`, and the **Honeytoken protection** card on a machine reports a recent latest sync. - If you deployed AI Hooks, the **AI hooks coverage** card reflects the pilot group, and the **AI agents** column shows which agents have guardrails. - If you deployed the AI and MCP inventory, the **AI Agents** tab on a machine lists the agents and MCP servers `ai discover` found, including whether each agent's subscription is personal or company. For the CLI and MDM checks above, see [Deploy ggshield at scale with a service account token](deploy-ggshield-with-sat). For how to read each view, see [Monitor coverage](/endpoint-protection/dashboard). ## Roll out at scale Here is the suggested rollout path: ``` 10-20 monitored machines → 1% → 10% → 25% → 50% → 100% | | | | | +-------------+-----+------+-------+-- pause / rollback gates ``` We recommend the following approaches for a successful scaled rollout: - Split waves by region, timezone, business unit, OS, or device type. - Spread first scans across hours or days, not minutes. - On Windows, deploy the [Microsoft Defender exclusion for the scanner process](/endpoint-protection/windows-scan-performance) with the package, so pilot scan durations are representative. - Use package caching or internal distribution for very large fleets. - Monitor errors and endpoint impact before each increase. Gate the next wave on `ggshield machine doctor` returning zero on a sample of the current wave. ### Roll back Disable the scheduled jobs first, especially `machine setup`. That job reconciles honeytokens against GitGuardian on every run, so a cleanup pass is undone the next day if setup is still enabled. Then clear what is already on disk: - Honeytokens: `ggshield honeytoken plant --remove-only`. - AI Hooks: delete the `ggshield` entries from the tool's hook configuration, listed in [Prevent leaks with AI Hooks](/endpoint-protection/ai-hooks#roll-back). `ggshield auth logout --no-revoke` as the logged-in user removes their personal token. Revoke the admin SAT in your workspace to cover the whole fleet at once. --- ## Getting started :::info This is the single-machine path: it uses an interactive browser login and needs no service account token. To roll out across a fleet, manage installation and credentials through your MDM with a service account token instead (see [Deploy at scale with a service account token](/endpoint-protection/deploy/deploy-ggshield-with-sat)). ::: ## Prerequisites - A GitGuardian business account with Endpoint Protection enabled. ## Step 1: Install ggshield and enable machine scanning ```sh curl -sSfL \ https://raw.githubusercontent.com/GitGuardian/ggshield/main/scripts/install/install.sh | bash -s -- --plugin machine_scan ``` ```powershell & ([scriptblock]::Create((irm https://raw.githubusercontent.com/GitGuardian/ggshield/main/scripts/install/install.ps1))) ` -Plugin machine_scan ``` :::note By default the script targets the US workspace. For the EU workspace or a self-hosted instance, export your instance URL **before running the command**. It then applies to the install and to every command below (same shell): ```sh export GITGUARDIAN_INSTANCE=https://dashboard.eu1.gitguardian.com # or your self-hosted instance URL ``` ::: ## Step 2: Run your first scan ```bash ggshield machine scan --dashboard ``` ## Step 3: Send your results to GitGuardian ```bash ggshield machine submit ``` `submit` sends the scan you just ran. To scan and send in one step, the shape you want for a scheduled job, use `ggshield machine report`. See [Commands](/endpoint-protection/commands). Your machine then shows up under **Endpoint protection → Endpoints** in the GitGuardian dashboard. See [Core concepts](/endpoint-protection/core-concepts) for what each view shows. ## Step 4: Turn on the endpoint protections The scan tells you which credentials are already on the machine. This step stops new ones from leaking and catches anything that comes looking for them. The install script authenticated you with the default scopes (`scan`, `honeytokens:check`, `endpoints:send`, and `ai-discover:send`). That covers the scan, AI Hooks, and git hooks. Planting a honeytoken also needs `honeytokens:write`, so log in again with that extra scope before setup: ```bash ggshield auth logout ggshield auth login --scopes honeytokens:write ggshield machine setup ``` `honeytokens:write` requires a workspace Manager role. If your account does not have it, the login fails and you can either ask a Manager to plant the honeytoken, or skip it with `--no-honeytokens` below. Across a fleet, planting stays an admin job: see [Deploy at scale with a service account token](/endpoint-protection/deploy/deploy-ggshield-with-sat#step-1---create-the-admin-token). One idempotent run configures all three protections: - **AI Hooks** for every AI coding agent it finds, so secrets are blocked before they reach a model. - **Git hooks**, pre-commit and pre-push, in your global git configuration. - **A honeytoken**, a decoy AWS credential profile that alerts GitGuardian if anything reads it. If you skip the honeytoken, keep the install-script token and run `ggshield machine setup --no-honeytokens`. Drop AI Hooks or git hooks the same way with `--no-ai-hooks` or `--no-git-hooks`. Requires `ggshield` 1.53.0 or later. ## Verify your setup Confirm the install and the plugin at any time: ```bash ggshield --version ggshield plugin list # machine_scan should be listed and enabled ``` For the protections from Step 4, run the read-only check: ```bash ggshield machine doctor ``` It reports, for each AI agent it finds, whether the hook is installed, whether the git hooks are in place, and whether your token reaches GitGuardian with the scopes those protections need. Requires `ggshield` 1.53.0 or later. ## Notes The script installs the standalone build per user (no admin or sudo required), and each downloaded release artifact is checksum-verified against the digest GitHub publishes for that release. That verification covers the binaries, not the installer script itself, which is fetched from `main`. For stricter supply-chain control, pin the script to a reviewed commit or serve it from an internal/MDM-hosted package (see [Deploy at scale with a service account token](/endpoint-protection/deploy/deploy-ggshield-with-sat)). ## Remove ggshield To uninstall later, follow [Uninstall](https://github.com/GitGuardian/ggshield/blob/main/scripts/install/README.md#uninstall) in the install scripts' README. ## Next steps - Deploy across a fleet: [Deploy at scale with a service account token](/endpoint-protection/deploy/deploy-ggshield-with-sat) - What gets scanned: [What is scanned](/endpoint-protection/what-is-scanned) - Block secrets in AI coding tools: [Prevent leaks with AI Hooks](/endpoint-protection/ai-hooks) - Catch credential harvesting: [Protect endpoints with Honeytokens](/endpoint-protection/honeytoken-protection) - Manage the plugin: [ggshield plugin commands](/ggshield-docs/reference/plugin/install) --- ## Protect endpoints with Honeytokens Honeytoken protection places a decoy AWS credential on each developer machine. The credential grants no access to anything, so nobody has a legitimate reason to use it. The moment someone does, GitGuardian raises an alert that tells you which machine was compromised. ## Why plant honeytokens on developer machines Endpoint scanning inventories the credentials that are already on a machine. Honeytoken protection adds intrusion detection to that same deployment, so you also learn the moment someone tries to steal them. Credential harvesters are programs that search a machine for saved credentials and send them to an attacker. They reach developer machines through malicious packages, trojanized tools, and rogue browser extensions. Their behavior is predictable: read the well-known credential locations (.env, .gitconfig, .npmrc, etc.), and exfiltrate whatever is there. Planting a decoy in exactly those locations means the attacker's first move is what gives them away. This gives you a few things that are hard to get from any other detection layer: - **A signal with no ambiguity.** The decoy has no legitimate use, so any use of it is unauthorized by definition. There is no baseline to learn, no tuning, and no signature list to keep current. - **A last line of defense.** If malware has already slipped past your EDR and other endpoint controls, using the decoy still exposes it. - **A named machine to investigate.** The event carries the IP address, user agent, and timestamp, and the honeytoken resolves to a specific endpoint and its owner, which is where an investigation actually starts. - **Coverage you can measure.** The dashboard reports the share of your fleet that is protected and lists the endpoints that are not, so this is a program you can drive to completion rather than a best effort. See [Monitor coverage](/endpoint-protection/dashboard). - **No extra agent to deploy.** Planting reuses the `ggshield` binary you already install for scanning and writes a file rather than running a resident process, so there is nothing new to certify and no ongoing cost on the machine. For developers, planting is unobtrusive. It only ever touches its own profile and leaves every other AWS profile on the machine untouched. ## How planting works The `ggshield honeytoken plant` command reconciles the machine against GitGuardian on every run. It asks GitGuardian what the desired state is for this endpoint, then applies it to disk: - For an active honeytoken, it writes or refreshes the decoy AWS credential profile. - For a honeytoken you revoked in GitGuardian, it removes that profile from the machine. - Any other profile in the file is preserved. `ggshield` never revokes a honeytoken by itself. It applies the desired state and reports back where the honeytoken landed. Revoking stays a deliberate action you take in GitGuardian, which means a cleanup on one machine can never disable a tripwire you still rely on. Because the command reconciles rather than appends, running it repeatedly is safe. A machine that has already been planted stays as it is. :::note Planting requires the `honeytokens:write` scope on the token that `ggshield` uses. This is not the same as `honeytokens:check`, which exists so that endpoint scanning does not trigger your own honeytokens when it encounters them. A fleet doing both needs both scopes. ::: ## Deploy honeytoken protection Honeytoken protection is deployed the same way as scanning, through your MDM, and the two are independent. An endpoint can be scanned without being planted, and the dashboard reports each separately. The simplest path is `ggshield machine setup`, which plants the honeytoken as part of one idempotent run that also configures the AI Hooks and the git hooks. Schedule that single job and the honeytoken is reconciled on every pass. If you want the honeytoken on its own, run `ggshield honeytoken plant` directly, either inside the job that already runs your daily inventory scan or as its own job on a lower frequency, since the desired state changes far less often than scan results. For the token setup, the MDM job patterns, and the scheduling detail, follow [Deploy ggshield at scale with a service account token](/endpoint-protection/deploy/deploy-ggshield-with-sat#step-4---set-up-hooks-and-honeytokens). To plant on a single machine: ```bash export GITGUARDIAN_API_KEY="" export GITGUARDIAN_INSTANCE="" ggshield honeytoken plant ``` To see which targets would be written without contacting GitGuardian or touching the disk, use a dry run first: ```bash ggshield honeytoken plant --list-targets ``` For the full option list, including how to override the profile name and target a specific user, see the [ggshield honeytoken plant reference](/ggshield-docs/reference/honeytoken/plant). ## Verify that a machine is protected Open the endpoint in **Endpoint protection > Endpoints** and check the **Honeytoken protection** card, which shows the latest sync, how many honeytokens are deployed, and how long the machine has been protected. The **Honeytokens** tab lists each one with its placement method, status, and when it was planted and last synced. ![Honeytoken protection on an endpoint detail page, showing the latest sync and the planted honeytoken](/img/endpoint-protection/endpoint-honeytoken-detail.png) A machine that shows no recent sync is a machine whose plant job is not running. Because the command reconciles on every run, a stale sync also means a honeytoken you revoked may still be sitting on that disk. ## Audit your endpoint honeytokens at scale To review every honeytoken planted across the fleet, go to **Honeytoken > Honeytokens** and filter on `Source type is Endpoints`. ![The honeytoken list filtered on endpoint sources](/img/endpoint-protection/honeytokens-filtered-by-endpoints.png) Opening one shows where it lives. The **Sources** card resolves the honeytoken to a machine and its owner, names the on-disk profile it was written to, and marks it as `Planted`. ![A honeytoken detail page showing the machine it was planted on and the credential profile it was written to](/img/endpoint-protection/honeytoken-planted-source.png) For everything else you can do from this view, such as tagging and filtering, see [Manage your population of honeytokens](/honeytoken/manage). ## Remove a honeytoken from a machine Removal is a two-step process, by design: 1. Revoke the honeytoken in GitGuardian, which is what stops it from being a live tripwire. See [Respond to a triggered honeytoken](/honeytoken/respond). 2. Let the next plant run remove it from disk. To run a cleanup pass that only applies removals and writes nothing new, use `ggshield honeytoken plant --remove-only`. This is also the rollback path. Disabling the plant job stops new placements, and a `--remove-only` pass clears what is already there. ## When a honeytoken is triggered A triggered honeytoken on an endpoint means someone used a credential that only exists on that machine as a decoy. Treat the machine as compromised and investigate from there. Honeytoken alerting and response work the same way regardless of where the honeytoken was planted: - [Configure your alerts](/honeytoken/configure-alerts) to route events to email, Slack, Microsoft Teams, or a webhook. - [Understand honeytoken events and trigger mechanism](/honeytoken/understand-events) for what each event tells you. - [Respond to a triggered honeytoken](/honeytoken/respond) for the reset and revoke workflow. --- ## Remediate findings A machine scan surfaces findings of different kinds, and each kind calls for a different action: - **Overprivileged secrets**: such as secrets with admin permissions. Remove them from the machine and store them in a vault or password manager. - **Leaked secrets**: secrets that ended up in shell history or log files. Redact them and [prevent future leaks](#prevent-future-leaks). - **Secrets you actively use**: secrets your daily work relies on, typically stored in env files. Move them to a vault to keep using them safely. ## Remove overprivileged secrets Admin-level secrets shouldn't sit on a workstation, but not every finding deserves an incident. Review the findings in the GitGuardian dashboard and create incidents for the ones that call for action: 1. In the GitGuardian dashboard, go to the **Endpoint protection > Secrets** page. ![Secrets page under Endpoint protection in the sidebar](/img/endpoint-protection/secrets-page.webp) 2. Optionally, select the **Highly privileged & Valid** filter to narrow the list down to the secrets with admin permissions. ![Highly privileged & Valid filter tab](/img/endpoint-protection/filter-highly-privileged-valid.webp) 3. Review the findings. A finding warrants an incident when the secret is valid and carries more permissions than work on the endpoint requires: admin scopes, organization-wide access, or write access to production systems. 4. For each finding that needs action, click **Create incident** and assign the incident to the relevant member. Bulk actions let you create several incidents at once. ![Create incident button](/img/endpoint-protection/create-incident.webp) 5. Follow the [incident remediation workflow](/internal-monitoring/remediate/remediation-overview) to revoke the secret and remove it from the machine. ### Prevent overprivileged secrets - **Use fine-grained or lower-permission tokens.** Most services offer permission granularity: create tokens with only the permissions you need. - **Keep admin tokens in a vault.** Most daily tasks don't require admin permissions. Store admin tokens in a vault and use them only when really needed. ## Redact secrets in shell history and log files Secrets that leaked into shell history or log files serve no purpose there. The redact action rewrites the file in place: only the secret itself is replaced with `[REDACTED]`, the rest of the line and the file stay untouched. Your history and logs remain readable, minus the credentials. To use a different placeholder, set the `remediation.scrub_redact_string` option in the **Configuration** page of the local dashboard. :::warning Redaction cannot be undone. ::: 1. Open the local dashboard: ```bash ggshield machine dashboard ``` 2. Go to the **Findings** page. ![Findings page in the local dashboard](/img/endpoint-protection/local-dashboard-findings.webp) 3. Select the **Auto-fixable** filter to show findings where at least one occurrence can be scrubbed automatically. ![Auto-fixable filter with its tooltip](/img/endpoint-protection/filter-auto-fixable.webp) 4. Select all results with the main checkbox. Use **Select all x matching** if the results span multiple pages. ![Selection bar with the Select all matching option](/img/endpoint-protection/select-all-findings.webp) 5. Click **Redact selected**. ### Prevent future leaks **Block AI agents from reading secrets.** AI coding agents can read secrets from any file they have access to, and anything they read ends up in plain text in their logs, session transcripts, and shell history. Install the [ggshield AI hooks](/ggshield-docs/integrations/ai-coding-tools/secret-scanning-for-ai-coding-tools) to stop them from accessing files that contain secrets. **Keep secrets out of shell history.** Use a variable instead of a plaintext secret in your commands: ```bash psql "postgresql://admin:${DB_PASSWORD}@db.example.com:5432/mydb" ``` ## Move the secrets you use to a vault Some secrets are needed for daily work. They usually live in `.env`, `.bashrc`, and similar files. Using them is legitimate, but they belong in a vault or secrets manager. GitGuardian doesn't offer an official solution to relocate them yet. In the meantime, move them to your vault manually. --- ## What is scanned ggshield machine scan operates in three modes that control coverage depth: - **Quick mode:** focuses on credential-dense paths (shell history, config files, dotfiles). Fastest, lowest overhead. - **Standard mode:** full filesystem traversal plus supplemental sources such as environment variables and the temporary directory. The default for `ggshield machine report`. - **Full mode:** same as standard but also includes build artifacts and dependency directories that are skipped by default. ## Files The engine performs a full filesystem traversal, covering any file that may contain a secret: - Shell history files (`.zsh_history`, `.bash_history`, etc.) - Configuration files (`.env`, `.gitconfig`, `.npmrc`, SSH configs, credential files) - Cloud credential stores (for example `~/.aws`, GCP, or Azure CLI caches) - AI coding agent caches and histories (Cursor, Claude Code, Copilot, MCP configs, etc.) - Temporary directories and browser storage - Structured data files (CSV, SQL, XLSX, PDF, SQLite) - Archives (`.zip`, `.jar`, `.war`, `.ear`) and compressed files (`.gz`, `.bz2`, `.xz`, `.zst`) - Any file matching patterns associated with secrets (API keys, tokens, certificates, private keys) Security teams can define exclusion lists to exclude specific directories or file types from the scan scope. :::note Machine scan focuses on credential accumulation across the full filesystem and does not limit itself to Git repositories. ::: ## Non-file sources Machine scan also scans local sources that are not ordinary files. These are included by default in standard and full modes: | Source | What is scanned | Opt-out | |---|---|---| | Environment variables | Current process environment values. | `--no-scan-env` | | Windows registry | User-readable registry credential locations on Windows. | `--no-scan-registry` | | Temporary directory | `$TMPDIR`, `/tmp`, and platform temp roots. On macOS, only the per-user temp root. | `--no-scan-temp` | Quick mode focuses on credential paths and may not include every supplemental source depending on the command wrapper. ## Built-in directory exclusions In standard mode, ggshield automatically skips directories that are typically large, generated, binary-heavy, or unlikely to contain user secrets: | Category | Examples | |---|---| | Dependency and build output | `node_modules`, `.venv`, `venv`, `target`, `dist`, `build`, `.next`, `.nuxt`, `Pods`, `DerivedData` | | Caches and package caches | `.cache`, `__pycache__`, `.npm/_cacache`, `.cargo/registry`, `.m2/repository`, `.gradle/caches`, `.pnpm-store` | | Version control internals | `.git`, `.svn`, `.hg` | | Media and user libraries | `Movies`, `Music`, `Pictures`, `Photos Library.photoslibrary` | | Virtual machines and runtimes | OrbStack, Parallels, VirtualBox VMs, `.colima`, `.lima`, `.multipass`, `.vagrant.d` | | Browser and app caches | Chrome/Edge cache and service worker caches, Firefox crash reports, Slack logs | | Scanner state | `.ggshield`, `.gitguardian` | To include build and dependency directories, use `--thorough` with the plugin or `--full` on the native CLI. For persistent overrides, use `scan.extra_skip_dirs` and `scan.include_dirs` in your configuration file. ## Areas skipped by default Some areas are deliberately excluded unless you opt in, for privacy, performance, or safety reasons: | Area | Why skipped | Opt in | |---|---|---| | macOS TCC-protected directories | Desktop, Documents, Downloads, Mail, Messages, Safari, and similar paths trigger macOS privacy prompts. | `--include-protected` | | Remote and network filesystems | NFS, SMB, SSHFS, and cloud drives can be slow, shared, or trigger cloud downloads. | Native CLI: `--include-remote-fs`; config: `scan.skip_remote_fs: false` | | Kernel pseudo filesystems | `procfs`, `sysfs`, `cgroupfs`, `debugfs` entries can misreport size and stream unbounded data. | `--include-pseudo-fs` | | Other users' home directories | Requires elevated privileges and changes the privacy boundary. | `--scan-all-users`; add `--include-root` for root homes | | Public repository checkouts | Open-source clones often create noise unrelated to local machine risk. | `scan.skip_public_repositories: false` | --- ## Tune scan performance on Windows Microsoft Defender real-time protection, or a third-party EDR, inspects every file the scanner opens. On a workstation with hundreds of thousands of files, a first scan can take hours, with **Antimalware Service Executable** using more CPU than the scan itself. The fix is one process exclusion for `ggshield-py.exe`, the process that runs the scan (`ggshield.exe` is only a launcher). ## Exclude the scanner process from Microsoft Defender Add a process exclusion for `ggshield-py.exe` with the path that matches your install method. The wildcards cover the user name and the versioned directory the install script creates. | Install method | Process exclusion | | -------------------------------- | -------------------------------------------------------------- | | Install script or ZIP (per user) | `C:\Users\*\AppData\Local\Programs\ggshield\*\ggshield-py.exe` | | MSI (per machine) | `C:\Program Files\GitGuardian\ggshield\ggshield-py.exe` | Write per-user paths with `C:\Users\*`: Microsoft Defender resolves `%LOCALAPPDATA%` and `%USERPROFILE%` to the system account's profile, not the user's. :::warning Microsoft Defender no longer scans the files this process opens, so keep the exclusion to `ggshield-py.exe` and do not add path exclusions for the user profile. Behavioural detections in Microsoft Defender for Endpoint still apply. ::: ### Deploy the exclusion ```powershell # Run as administrator. Keep the line for your install method. Add-MpPreference -ExclusionProcess 'C:\Users\*\AppData\Local\Programs\ggshield\*\ggshield-py.exe' Add-MpPreference -ExclusionProcess 'C:\Program Files\GitGuardian\ggshield\ggshield-py.exe' ``` If Intune or Configuration Manager also manages Defender exclusions, their policy overwrites local changes at the next startup. Open **Endpoint security > Antivirus > Create policy**, select platform **Windows** and profile **Microsoft Defender Antivirus exclusions**, add the path under **Excluded processes**, then assign the profile to the device group that receives `ggshield`. For another MDM, set the Policy CSP `./Device/Vendor/MSFT/Policy/Config/Defender/ExcludedProcesses` to the same path. Open **Computer Configuration > Administrative Templates > Windows Components > Microsoft Defender Antivirus > Exclusions > Process Exclusions**, enable the setting, and add one entry with the path as the value name and `0` as the value. Check the result with `Get-MpPreference | Select-Object -ExpandProperty ExclusionProcess`, then time a scan with `Measure-Command { ggshield machine report }`. ## Exempt the scanner from Arbitrary code guard If an Exploit Protection policy applies Arbitrary code guard (ACG) to `ggshield-py.exe`, the scanner cannot use its regex JIT compiler and scans take several times longer, without any warning. ACG is off by default. Check, then exempt the process: ```powershell Get-ProcessMitigation -Name ggshield-py.exe # DynamicCode Enable: ON means ACG applies Set-ProcessMitigation -Name ggshield-py.exe -Disable DynamicCode ``` To deploy the exemption fleet-wide, export it with `Get-ProcessMitigation -RegistryConfigFilePath ggshield-exploit-protection.xml` and upload the file in Intune under **Endpoint security > Attack surface reduction > Exploit Protection**, or distribute it through Group Policy. See [Customize exploit protection](https://learn.microsoft.com/en-us/defender-endpoint/customize-exploit-protection). ## Other antivirus and application control - **Third-party EDR** (CrowdStrike Falcon, SentinelOne, Cortex XDR, Carbon Black): apply the same process exclusion for `ggshield-py.exe` with the vendor's equivalent feature. When one of these is the primary antivirus, Microsoft Defender runs in passive mode, so configure the EDR instead. - **AppLocker, App Control for Business, code integrity guard**: `ggshield.exe`, `ggshield-py.exe`, and the MSI are signed by GitGuardian, but the support files in the `_internal` folder and the scanner plugin are not. Allow the install directory and `C:\Users\*\AppData\Local\GitGuardian\ggshield` by path, and do not enable code integrity guard for `ggshield-py.exe`. `ggshield machine doctor` fails when the scanner cannot load. ## If scans are still slow Record what Microsoft Defender scans during a run with its performance analyzer, as administrator: ```powershell New-MpPerformanceRecording -RecordTo "$env:TEMP\ggshield-defender.etl" # Run ggshield machine report as the scan user, then press Enter here. Get-MpPerformanceReport -Path "$env:TEMP\ggshield-defender.etl" -TopProcesses 10 -TopFiles 10 ``` If `ggshield-py.exe` still leads the process list, the exclusion is not applied. Review the file paths in the report before sharing it with GitGuardian support. See [Performance analyzer for Microsoft Defender Antivirus](https://learn.microsoft.com/en-us/defender-endpoint/tune-performance-defender-antivirus). --- ## Authentication(Ggmcp-docs) :::warning[Beta] The GitGuardian MCP Server is currently in **beta**. Features and behavior may change as we iterate based on user feedback. ::: The server authenticates with your GitGuardian workspace using one of: | Method | When to use | |--------|-------------| | **OAuth** *(default)* | IDE usage — opens browser to log in, stores token locally | | **Personal Access Token** | CI/CD or non-interactive environments | | **Authorization header** | HTTP/SSE server deployments | See [Authentication](https://github.com/GitGuardian/gg-mcp#authentication) for configuration details. --- ## Installation :::warning[Beta] The GitGuardian MCP Server is currently in **beta**. Features and behavior may change as we iterate based on user feedback. ::: ## Prerequisites - A [GitGuardian](https://www.gitguardian.com/) account - [uv](https://docs.astral.sh/uv/getting-started/installation/) installed ## Install in Cursor Click the one-click install button from the [GitHub README](https://github.com/GitGuardian/gg-mcp#installation-with-cursor), or add manually to `~/.cursor/mcp.json`: ```json { "mcpServers": { "GitGuardianDeveloper": { "command": "uvx", "args": [ "--from", "git+https://github.com/GitGuardian/gg-mcp.git", "developer-mcp-server" ] } } } ``` ## Other IDEs For **Claude Desktop**, **Windsurf**, and **Zed** installation instructions, see the [GitHub README](https://github.com/GitGuardian/gg-mcp#installation). ## Instance configuration The server defaults to GitGuardian SaaS (US). For other instances, set the `GITGUARDIAN_URL` environment variable: | Instance | URL | |----------|-----| | SaaS US *(default)* | `https://dashboard.gitguardian.com` | | SaaS EU | `https://dashboard.eu1.gitguardian.com` | | Self-hosted | Your instance URL (e.g., `https://dashboard.gitguardian.mycorp.local`). See [Configure for self-hosted](./self-hosted-configuration) | See [Configuration](https://github.com/GitGuardian/ggmcp#configuration-reference) for all environment variables. --- ## Overview # GitGuardian MCP Server :::warning[Beta] The GitGuardian MCP Server is currently in **beta**. Features and behavior may change as we iterate based on user feedback. ::: The GitGuardian MCP Server brings secrets security directly into your AI coding assistant. Scan for leaked credentials, manage security incidents, and deploy honeytokens — all without leaving your IDE. > For full documentation, source code, and installation guides, see the [GitHub repository](https://github.com/GitGuardian/gg-mcp). ## What is MCP? The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is an open standard that lets AI assistants interact with external tools and data sources. The GitGuardian MCP server exposes security capabilities as tools your AI agent can call on your behalf. ## Server profile The GitGuardian MCP Server is available as a **Developer** profile *(beta)*, designed for developers working in IDEs. It provides primarily read-focused tools for scanning, incident review, and guided remediation, with limited write capabilities such as honeytoken generation. A **SecOps** profile tailored for security teams is being planned, with additional capabilities such as incident management, secret revocation, and automated code fixes. --- ## Security :::warning[Beta] The GitGuardian MCP Server is currently in **beta**. Features and behavior may change as we iterate based on user feedback. ::: Most tools operate with **read-only permissions** by design, limiting the agent's capabilities to safe, non-destructive operations such as scanning, listing incidents, and browsing detectors. A few tools — such as honeytoken generation — perform write operations but remain scoped to low-risk actions. Secret values are never sent to the AI model — scanning is performed server-side via the GitGuardian API. --- ## Configure for self-hosted # Configure the GitGuardian Remote MCP server in self-hosted :::warning[Beta] The GitGuardian MCP Server is currently in **beta**. Features and behavior may change as we iterate based on user feedback. ::: The GitGuardian self-hosted Helm chart ships the Remote MCP server as an opt-in component. It runs in your own cluster, next to your instance, so no traffic and no secret ever leaves your network. Requirements: - GitGuardian self-hosted **2026.7.0** or later. - With the `aws_alb` ingress controller, AWS Load Balancer Controller 2.14 or later (for Helm-based installation). ## Enable the MCP server Add the following to your Helm values file: ```yaml mcpServer: enabled: true ``` Then run `helm upgrade` with the version currently installed, to avoid an unwanted upgrade of your instance. Use `helm ls` to find the release name and that version: ```bash helm upgrade -n oci://registry.replicated.com/gitguardian/gitguardian --version -f local-values.yaml ``` Once the pod is running, the MCP server is served under the `/mcp-server` path of your application host, on the same ingress and the same TLS certificate as your dashboard. The OAuth proxy is enabled by default, so your developers log in against your own domain and no token has to be distributed. ## Connect an MCP client Point clients at the `/mcp` endpoint of the MCP server. For Cursor, edit `~/.cursor/mcp.json`: ```json { "mcpServers": { "GitGuardian": { "type": "http", "url": "https://dashboard.gitguardian.mycorp.local/mcp-server/mcp" } } } ``` Replace the host with your own instance URL. Claude Desktop, Windsurf, and Zed take the same `type: http` block in their own configuration file. See [Installation](./installation) for the file locations. The client opens a browser tab to your dashboard the first time it connects. The tools it then exposes depend on the permissions of the account that logs in, so a developer and a manager do not get the same set. See the [tools reference](./tools-reference). ## Tune the deployment The most useful keys, on top of `mcpServer.enabled`: | Key | Purpose | Default | |-----|---------|---------| | `mcpServer.replicas` | Fixed number of replicas | `1` | | `mcpServer.autoscaling.hpa.enabled` | Scale with the Kubernetes HPA | `false` | | `mcpServer.autoscaling.metrics.targetLatency` | Target latency in milliseconds driving autoscaling | `1000` | | `mcpServer.resources` | CPU and memory requests and limits | `250m` / `1Gi` requested | | `mcpServer.ingress.enabled` | Expose the server through the application ingress | `true` | | `mcpServer.mcpOAuthProxyEnabled` | Let clients run OAuth against your dashboard | `true` | | `mcpServer.extraEnv` | Extra environment variables passed to the server | `[]` | The full list is in the [Helm values reference](../self-hosting/management/infrastructure-management/helm-values). For the environment variables you can inject through `mcpServer.extraEnv`, see the [configuration reference](https://github.com/GitGuardian/ggmcp#configuration-reference) of the MCP server repository. In an airgapped environment, mirror `ghcr.io/gitguardian/mcp-server` to your private registry along with the other GitGuardian images. See [Airgap installation](../self-hosting/installation/airgap-installation-existing-cluster-helm). ## Troubleshoot **The client cannot reach the server.** Check that `mcpServer.ingress.enabled` is `true` and that your ingress controller routes the `/mcp-server` path. On AWS ALB, confirm the Load Balancer Controller is 2.14 or later. **The OAuth flow fails or redirects to the wrong host.** The MCP server derives its public URL from your application host. Make sure clients use the same host as your dashboard, not an internal service address. **Some tools are missing.** The exposed tools follow the permissions of the account that logged in. Check the role and the team perimeters of that member. ## What's next - [Tools reference](./tools-reference): the tools the server exposes. - [Security](./security): the permission model and secret redaction. --- ## Tools reference :::warning[Beta] The GitGuardian MCP Server is currently in **beta**. Features and behavior may change as we iterate based on user feedback. ::: The following tools are available in the Developer profile *(beta)*: | Tool | Description | |------|-------------| | **Scan secrets** | Detect leaked credentials in code before commit | | **List incidents** | View security incidents filtered by severity, status, detector, and more | | **Get incident** | Retrieve detailed incident information with occurrences | | **List repo occurrences** | Locate secrets with exact file paths and line numbers | | **Remediate incidents** | Get step-by-step remediation instructions for detected secrets | | **Find current source** | Auto-detect the current repository's GitGuardian source ID | | **List sources** | Browse repositories and integrations monitored by GitGuardian | | **List detectors** | Explore 600+ available secret detectors | | **Generate honeytoken** | Create AWS honeytokens with placement recommendations | | **List honeytokens** | View existing honeytokens | | **List users / Get member** | Look up workspace members | ## What's next A **SecOps** profile for security teams is being planned. It will extend the Developer tools with additional capabilities such as incident assignment, status management, custom tags, secret revocation, and automated code fix requests. --- ## Deploy and configure ggscout ## Quick Start The fastest way to test ggscout is to run it locally using the pre-built binary or Python package: ### Option 1: Download the Binary (Recommended for Testing) ```bash # Download for Linux x86_64 (GNU libc) wget https://ggscout-repository.gitguardian.com/ggscout/latest/x86_64-unknown-linux-gnu/ggscout chmod +x ggscout # Verify installation ./ggscout --help ``` ### Option 2: Use Python Package ```bash # Using uvx (no installation required) uvx ggscout --help # Or install with uv uv tool install ggscout ggscout --help ``` ### Test with a Simple Configuration Create a minimal `ggscout.toml` file to test connectivity: ```toml [gitguardian] api_token = "${GITGUARDIAN_API_KEY}" endpoint = "https://api.gitguardian.com/v1" ``` Set your API key and test the connection: ```bash export GITGUARDIAN_API_KEY="your-service-account-token" ./ggscout ping ggscout.toml ``` If successful, you're ready to configure your first integration! Continue reading for production deployment options. --- ## Overview ggscout can be executed on-demand as a Command Line Interface (CLI) for testing and development, or deployed in your infrastructure as an autonomous service for production use: - **CLI binary**: Best for local testing, development, and manual operations - **Docker Image**: Suitable for scheduled jobs on a single host using cron - **Kubernetes/Helm**: Recommended for production deployments with automated scheduling and monitoring :::success ggscout is compatible with self-hosted GitGuardian instances! The Self-Hosted deployment comes with a ready-to-use Helm chart that you can use to deploy ggscout alongside your GitGuardian instance. Check out the dedicated **[Self-hosted section](./self-hosted-configuration)**. ::: :::tip Using ggscout with GitGuardian SaaS behind a private network? If your Kubernetes cluster doesn't have direct access to the GitGuardian SaaS platform, you can use [GitGuardian Bridge](../platform/deployment-model/ggbridge) to establish a secure tunnel between your private network and GitGuardian SaaS. See the **[ggbridge + ggscout example](https://github.com/GitGuardian/ggbridge/tree/main/examples/ggscout)** for detailed setup instructions. ::: GitGuardian Scout (ggscout) is a command-line tool that acts as an outpost in your infrastructure perimeter to collect and synchronize data with your GitGuardian platform. It does not store or transfer any sensitive information: sensitive information is always hashed using the [HasMySecretLeaked](https://www.gitguardian.com/hasmysecretleaked) algorithm. :::warning Detector classification requires ggscout 0.32.0 or later From **0.32.0**, ggscout classifies collected values with the Secrets Detection Engine before hashing. If you already run ggscout, upgrade to **0.32.0 or later** so the [NHI inventory](/nhi-governance/discover-your-nhis) can show detector, detector type, secret family, category, and provider. Download the latest binary, or pin the Docker image and Helm chart to `0.32.0` or `latest`. See [Classify secrets with the Secrets Detection Engine](/ggscout-docs/what-is-ggscout#classify-secrets-with-the-secrets-detection-engine). ::: ggscout supports various integrations with secrets managers, CI/CD systems, and other infrastructure components. ### Available Commands ggscout provides several commands to manage your integrations: #### GGScout Commands - **`fetch-and-send`** - Combined operation that fetches data and immediately sends it to GitGuardian platform - **`fetch`** - Run fetchers defined in a configuration file to collect data from your sources, and persist the collected inventory to file storage. This does NOT transfer any data to GitGuardian. - **`send`** - Send previously collected inventory to your GitGuardian platform instance - **`sync-secrets`** - Retrieve secrets from GitGuardian platform and write them to configured destinations - **`ping`** - Test connectivity and send source information to GitGuardian platform ## Generic Integration Flow All ggscout integrations follow a consistent pattern for the `fetch` and `fetch-and-send` commands: ### 1. GitGuardian Authentication First, if you intend to use any command other than `fetch`, you need to set up authentication to your GitGuardian platform: #### GitGuardian Service Account ggscout requires specific access rights to communicate with the GitGuardian Platform. Create a [service account](https://dashboard.gitguardian.com/workspace/0/settings/api/service-accounts) and select the relevant scopes: ![Scout SAT](/img/ggscout/scout-sat.png) - `nhi:send-inventory` allows ggscout to send the collected data to GitGuardian - `nhi:write-vault` allows ggscout to receive write instructions from GitGuardian. See the **[Secret synchronization](./sync-secrets)** section to learn more. #### Configuration example ```yaml [gitguardian] api_token = "${GITGUARDIAN_API_KEY}" endpoint = "${GITGUARDIAN_API_URL}" ``` And set these variables in your environment, for instance in a `.env` file: ```bash GITGUARDIAN_API_KEY="your-api-key" GITGUARDIAN_API_URL="https://api.gitguardian.com/v1" ``` ### 2. Configuration Create a TOML configuration file defining your sources and GitGuardian platform connection: ```toml # Source configuration [sources.my-source] type = "source_type" # Source-specific parameters param1 = "value1" param2 = "value2" # GitGuardian platform configuration (required for `fetch-and-send` or `send` commands) [gitguardian] api_token = "${GITGUARDIAN_API_KEY}" endpoint = "${GITGUARDIAN_API_URL}" ``` See [Configure integrations](./configure-integrations) for more general details on how integrations work. ### 3. Integration Authentication Set up authentication for your specific integrations using environment variables or direct configuration: ```bash # Additional source-specific environment variables export HASHICORP_VAULT_TOKEN="your-vault-token" export AWS_PROFILE="your-aws-profile" # ... other integration-specific variables ``` Note that depending on the integration, there may be other authentication methods available that don't require long-lived secrets, such as: - Kubernetes service account tokens - IAM roles and OIDC for cloud providers - Certificate-based authentication - OAuth flows with short-lived tokens Check the relevant page in the **[Integrations](./integrations)** section for more details. ### 4. Execution For a first manual usage, you would typically run the following commands: - `ping` - `fetch` - `send` In production, you would configure a recurrent cronjob to run the `ping` and `fetch-and-send` commands. See the deployment section below for details. ### 5. Monitoring Review the GitGuardian platform to see collected data and manage incidents. #### Exit codes `ggscout` returns a process exit code you can rely on for monitoring (cron, ECS/Fargate, Kubernetes): | Exit code | Meaning | |-----------|---------| | `0` | The command completed. For `fetch-and-send`, the inventory was successfully sent to GitGuardian. | | non-zero | A blocking error stopped the command. | A command exits **non-zero** on blocking errors such as: - an invalid or unreadable configuration file; - no source could be initialized (for example, authentication fails for every source); - **every** source failed to fetch, so no data could be collected; - the upload to GitGuardian failed (`fetch-and-send` and `send`). Errors affecting **individual secrets, paths, or mounts are non-blocking**: they are logged and the run continues with the rest of the data, then sends what it could collect. For example, a token that lacks permission on one path produces: ``` ERROR ... step="list keys": task errored error=Failed to list mount keys for mount kv2 kv_app ... ``` This does **not** fail the command — `fetch-and-send` still uploads the other secrets and exits `0`. :::caution Because partial failures are non-blocking, the exit code alone does not tell you whether ggscout collected **fewer** secrets than expected. A token that loses access to an entire mount can still exit `0` with a smaller (or empty) inventory. For complete monitoring, also watch: - log lines containing `task errored` or `100% failure rate`, and - the collected item count (`Fetched a total of N items`) or the inventory size on the GitGuardian platform. ::: ## Deployment Once you have configured ggscout, you can deploy it using various methods depending on your infrastructure needs. ### Docker For production deployments on a single host or when you need scheduled execution without Kubernetes, use the Docker image with a cron job. GitGuardian provides a public docker image on GitHub Container Registry: `ghcr.io/gitguardian/ggscout/chainguard`. The following examples use the `latest` tag, but you can pin to a specific version for production use. Consult the **[list of available releases](https://github.com/orgs/GitGuardian/packages/container/package/ggscout%2Fchainguard)** to choose a version. #### Why Chainguard? The ggscout Docker image is built using [Chainguard](https://www.chainguard.dev/)'s distroless base images for maximum security: - **Zero CVEs**: Chainguard images are continuously rebuilt from source in secure environments, eliminating known vulnerabilities - **Minimal attack surface**: Contains only the ggscout binary and essential runtime libraries - no shell, package managers, or debugging tools - **Secure by design**: Runs as nonroot user (UID 65532) and follows distroless principles **What's inside the image:** 1. **Base layer**: `cgr.dev/chainguard/glibc-dynamic:latest` - minimal runtime libraries 2. **Application layer**: ggscout binary (written in Rust) at `/usr/bin/ggscout` 3. **Configuration layer**: Nonroot user and secure entrypoint **What's NOT included** (for security): - No shell (`/bin/sh`, `/bin/bash`) - No package managers (`apt`, `yum`, `apk`) - No debugging utilities or text editors - No system utilities beyond essential runtime libraries This approach significantly reduces the container's attack surface and eliminates entire classes of vulnerabilities. You can manually execute the image using the following commands: ```bash # Ping command docker run --rm -ti -v ${PWD}:/tmp --env-file .env ghcr.io/gitguardian/ggscout/chainguard:latest ping /tmp/config.toml ``` ```bash # Fetch and send command docker run --rm -ti -v ${PWD}:/tmp --env-file /path/to/config/dir/.env ghcr.io/gitguardian/ggscout/chainguard:latest fetch-and-send /tmp/config.toml ``` :::warning Use a crontab to configure a recurring job The Docker image embeds the CLI. Configure a crontab to configure a recurring job with the commands you need to launch. ::: Below is an example of the execution with crontab. ```bash # Ping command (every minute) * * * * * docker run --rm -ti -v /path/to/config/dir:/tmp --env-file /path/to/config/dir/.env ghcr.io/gitguardian/ggscout/chainguard:latest ping /tmp/config.toml ``` ```bash # Fetch and send command (every 5 minutes) */5 * * * * docker run --rm -ti -v /path/to/config/dir:/tmp --env-file /path/to/config/dir/.env ghcr.io/gitguardian/ggscout/chainguard:latest fetch-and-send /tmp/config.toml ``` Replace the `/path/to/config/dir` where you have configured your config file and your `.env` file. Example `.env`: ```bash GITGUARDIAN_API_KEY=my_gitguardian_api_key GITLAB_TOKEN=my_gitlab_token HASHICORP_VAULT_TOKEN=my_vault_token ``` ### Helm You can deploy ggscout on a Kubernetes cluster using ggscout Helm chart. :::tip This is the preferred deployment model if you run ggscout as an autonomous collector periodically. ::: Deployment instructions are available on our public **[GitHub repository](https://github.com/GitGuardian/ggscout-helm-charts).** The Helm values allows you to define ggscout configuration in YAML. [Examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples) are provided as templates in the repository. ### OpenShift Deployment ggscout supports deployment on OpenShift platforms. When deploying on OpenShift, you need to disable the default security context in the Helm chart configuration. Add the following configuration to your Helm `values.yaml`: ```yaml securityContext: # Enable security Context in deployments. # Set to false when deploying on OpenShift enabled: false ``` This configuration is necessary because OpenShift has its own security context constraints that conflict with the default Kubernetes security context settings. :::info All other configuration options for sources, authentication, and scheduling remain the same when deploying on OpenShift. ::: --- ## Configure integrations ggscout integrates with various secrets managers, CI/CD systems, and infrastructure components to collect and monitor secrets. This page covers how to configure and use integrations for secret discovery and monitoring. ## Integration Modes Sources can be configured with different operational modes: - **`read`** - Only collect data from the source (default) - **`write`** - Only write data to the source - **`read/write`** - Both collect data and write to the source ```toml [sources.my-source] type = "source_type" mode = "read/write" # Supports both operations ``` ## Configuration File ggscout configuration file uses the TOML format to describe: - How ggscout will communicate with GitGuardian platform - How to access the different secrets managers to collect secrets **Configuration example:** ```yaml [gitguardian] # SaaS US endpoint = "https://api.gitguardian.com/v1" # SaaS EU # endpoint = "https://api.eu1.gitguardian.com/v1" # Self-hosted # endpoint = "https://my-gg-instance.com/exposed/v1" api_token = "${GITGUARDIAN_API_KEY}" [sources.my-hashicorp-vault] # This lets ggscout know what source to contact type = "hashicorpvault" # And this lets ggscout know how to contact it vault_address = "${HASHICORP_VAULT_ADDRESS}" auth.auth_mode = "token" auth.token = "${HASHICORP_VAULT_TOKEN}" # Many vaults support secret versioning. Set this to false if you only # want to collect the latest version of the vault secrets fetch_all_versions = true # Allow ggscout instance to read from and write to that vault mode = "read/write" # "read" and "write" are other possible values # Will help assess policy breaches and their severity env = "staging" # Optional: specify the owner of this source owner = "devops-team@example.com" # Configure another vault to collect here # [sources.my-other-vault] # type = "gcpsecretmanager" ``` The config file supports reading environment variables (`"${GITGUARDIAN_API_KEY}"`) instead of raw values. You can set these variables in a `.env` file: ```bash GITGUARDIAN_API_KEY= HASHICORP_VAULT_ADDRESS= HASHICORP_VAULT_TOKEN= ``` Please refer to **[Secrets Managers](./integrations/secret-managers)** section to properly configure the collection of secrets. ## Supported Integration Types ggscout supports multiple integration types across different categories. The table below shows all available integrations and their capabilities: | Integration Type | Integration Name | Type Identifier | Write Support | |------------------|------------------|-----------------|---------------| | **Secrets Managers** | HashiCorp Vault | `hashicorpvault` | ✅ Yes | | | AWS Secrets Manager | `awssecretsmanager` | ✅ Yes | | | CyberArk Secrets Manager SaaS | `cyberarksaas` | ✅ Yes | | | CyberArk Secrets Manager Self-Hosted | `cyberarkselfhosted` | ✅ Yes | | | Akeyless | `akeyless` | ✅ Yes | | | Delinea Secret Server | `delineasecretserver` | ✅ Yes | | | Azure Key Vault | `azurekeyvault` | ❌ No | | | Google Secret Manager | `gcpsecretmanager` | ❌ No | | **CI/CD Systems** | GitLab CI | `gitlabci` | ❌ No | | **Infrastructure** | Kubernetes | `k8s` | ❌ No | :::info Integrations that don't support writing can still be used for secret discovery and monitoring with the `fetch-and-send` command. Only integrations with write support can be used with the `sync-secrets` command. Refer to the **[Secret synchronization](./sync-secrets)** section for more details on `sync-secrets`. ::: ## Common Configuration Parameters All secrets manager integrations support the following common parameters in addition to their specific configuration: ### Environment Categorization - **`env`**: Environment label for categorizing secrets (e.g., "production", "staging", "development"). This helps organize and filter secrets by their intended environment. ### Source Ownership - **`owner`**: Owner of this source (an email, usually of an employee or a team). This field is optional and helps identify who is responsible for managing the source. ### Resource Filtering - **`[[sources..include]]`**: Table of resource_id patterns to include. Only secrets matching these patterns will be collected. - **`[[sources..exclude]]`**: Table of resource_id patterns to exclude. Secrets matching these patterns will be ignored. Each `include` or `exclude` table must have a `resource_ids` array. You can specify multiple `include` or `exclude` tables for different sets of patterns. Patterns support wildcards (*) only at the end for prefix matching. For exact matches, specify the complete name without wildcards. ### Example Configuration ```toml [sources.my-vault] type = "hashicorpvault" vault_address = "${HASHICORP_VAULT_ADDRESS}" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" [[sources.my-vault.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.my-vault.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] auth.auth_mode = "token" auth.token = "${HASHICORP_VAULT_TOKEN}" ``` In this example: - **Prefix patterns**: `"app/*"` and `"database/*"` match all secrets starting with those prefixes - **Exact matches**: `"api-key"` matches only the exact secret with that name --- ## Integrations # ggscout Integrations ggscout can integrate with various types of sources in your infrastructure to discover, monitor, and manage secrets. Each integration type serves different purposes and has specific capabilities. See [Configure integrations](./configure-integrations) for general information on how integration configuration is handled. ## Integration Types ### Secrets Managers Secrets managers are dedicated services for storing and managing sensitive information like passwords, API keys, and certificates. ggscout can both read from and write to most secrets managers, making them ideal for secret discovery and remediation workflows. **Supported Secrets Managers:** - **[HashiCorp Vault](./integrations/secret-managers/hashicorp-vault)** - Enterprise-grade secret management with multiple authentication methods - **[AWS Secrets Manager](./integrations/secret-managers/aws-secrets-manager)** - AWS native secret management service - **[Azure Key Vault](./integrations/secret-managers/azure-key-vault)** - Microsoft Azure's secret management solution - **[Google Secret Manager](./integrations/secret-managers/google-secret-manager)** - Google Cloud's secret management service - **[CyberArk Secrets Manager SaaS](./integrations/secret-managers/cyberark-secrets-manager-saas)** - Enterprise security platform for secrets management (cloud) - **[CyberArk Secrets Manager Self-Hosted](./integrations/secret-managers/cyberark-secrets-manager-self-hosted)** - Enterprise security platform for secrets management (on-premises) - **[Akeyless](./integrations/secret-managers/akeyless)** - Cloud-native secrets management platform - **[Delinea Secret Server](./integrations/secret-managers/delinea-secret-server)** - Privileged access management and secrets vault [**Learn more about Secrets Managers integrations →**](./integrations/secret-managers) ### CI/CD Systems Continuous Integration and Continuous Deployment platforms often contain secrets in environment variables, pipeline configurations, and deployment scripts. ggscout can monitor these systems to identify exposed secrets. **Supported CI/CD Systems:** - **[GitLab CI](./integrations/gitlab-ci)** - GitLab's integrated CI/CD platform with comprehensive secret scanning *More CI/CD integrations coming soon!* ### Infrastructure Sources ggscout can also integrate with infrastructure components where secrets might be stored or configured. **Supported Infrastructure Sources:** - **[Kubernetes](./integrations/infrastructure/kubernetes)** - Native Kubernetes resources including Secrets, ConfigMaps, Deployments, and Service Accounts *More infrastructure integrations coming soon!* ## Integration Capabilities | Integration Type | Read Support | Write Support | Primary Use Case | |------------------|--------------|---------------|------------------| | **Secrets Managers** | ✅ Yes | ✅ Most | Secret discovery and remediation | | **CI/CD Systems** | ✅ Yes | ❌ No | Secret discovery and monitoring | | **Infrastructure** | ✅ Yes | ❌ No | Secret discovery and monitoring | ## Getting Started 1. **Choose your integrations**: Select the sources where your secrets might be stored 2. **Configure authentication**: Set up proper credentials and permissions 3. **Deploy ggscout**: Use our [configuration guide](./configure-ggscout) to deploy ggscout 4. **Monitor and remediate**: Use the GitGuardian platform to review discovered secrets ## Need Help? - **Configuration guidance**: Check our [integration configuration guide](./configure-integrations) - **Secret remediation**: Learn about [secret synchronization](./sync-secrets) - **Best practices**: Review our [deployment recommendations](./configure-ggscout#deployment) Each integration has specific setup requirements and capabilities. Click on the links above to access detailed configuration instructions for your chosen integrations. --- ## GitHub Actions Integration GitGuardian Scout (`ggscout`) can inventory secrets stored in GitHub Actions — at the organization, repository, and environment level — enabling you to discover and monitor Non-Human Identities across your GitHub CI/CD infrastructure. ## Overview Unlike other ggscout integrations, the GitHub Actions fetcher runs **inside a GitHub Actions workflow**. It reads secrets directly from the runner environment, requiring zero credentials for basic operation. For full visibility, we recommend configuring an API token to enrich each secret with metadata such as scope, ownership, and timestamps. The integration supports both **github.com** and **GitHub Enterprise Server** (GHES) instances. Key capabilities: - **Inventory all GitHub Actions secrets** available to a workflow (org, repo, and environment-level) - **Enrich with metadata** (scope, visibility, environment, owner, timestamps) when an API token is provided ## Prerequisites Before configuring the GitHub Actions integration, ensure you have: 1. **A GitHub repository** with GitHub Actions enabled (github.com or GHES) 2. **GitGuardian API token** with NHI permissions 3. **(Recommended)** A GitHub API token for metadata enrichment — see [Metadata Enrichment](#metadata-enrichment) ## Workflow Setup ggscout is embedded as a step in a GitHub Actions workflow. Secrets are relatively static and do not change on every commit, so we recommend running it on a **nightly schedule** to avoid unnecessary workflow minutes. ### Deployment Scope GitHub Actions secrets exist at three levels: **organization**, **repository**, and **environment**. A single ggscout workflow can see all secrets available to its job, but repo-level and environment-level secrets are only visible from within that specific repository's workflow. To get full coverage: 1. **Deploy on at least one repository** — this captures all organization-level secrets shared across the org. 2. **Deploy on each repository with secrets of interest** — repo-level and environment-level secrets are only accessible from within the repository where they are defined. ### Workflow Examples Create a dedicated workflow file (e.g., `.github/workflows/ggscout-nhi.yml`). #### Option A: Docker Image (Recommended) ```yaml name: NHI Inventory with ggscout on: schedule: - cron: '0 2 * * *' # Run nightly at 2:00 AM UTC workflow_dispatch: # Allow manual runs jobs: inventory: runs-on: ubuntu-latest container: image: ghcr.io/gitguardian/ggscout/chainguard-bash:latest steps: - name: Create ggscout config run: | cat > /tmp/config.toml << 'EOF' [sources.github-actions] type = "githubactions" env = "production" [gitguardian] api_token = "${GITGUARDIAN_API_KEY}" endpoint = "https://api.gitguardian.com/v1" EOF - name: Collect secrets with ggscout env: GGSCOUT_GITHUB_ACTION_SECRETS: ${{ toJSON(secrets) }} GGSCOUT_GITHUB_ACTION_CONTEXT: ${{ toJSON(github) }} GGSCOUT_GITHUB_API_TOKEN: ${{ secrets.GGSCOUT_API_TOKEN }} GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} run: ggscout fetch-and-send /tmp/config.toml ``` #### Option B: Binary Download If you prefer not to use Docker: ```yaml name: NHI Inventory with ggscout on: schedule: - cron: '0 2 * * *' # Run nightly at 2:00 AM UTC workflow_dispatch: # Allow manual runs jobs: inventory: runs-on: ubuntu-latest steps: - name: Download ggscout run: | wget https://ggscout-repository.gitguardian.com/ggscout/latest/x86_64-unknown-linux-gnu/ggscout chmod +x ggscout - name: Create ggscout config run: | cat > /tmp/config.toml << 'EOF' [sources.github-actions] type = "githubactions" env = "production" [gitguardian] api_token = "${GITGUARDIAN_API_KEY}" endpoint = "https://api.gitguardian.com/v1" EOF - name: Collect secrets with ggscout env: GGSCOUT_GITHUB_ACTION_SECRETS: ${{ toJSON(secrets) }} GGSCOUT_GITHUB_ACTION_CONTEXT: ${{ toJSON(github) }} GGSCOUT_GITHUB_API_TOKEN: ${{ secrets.GGSCOUT_API_TOKEN }} GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} run: ./ggscout fetch-and-send /tmp/config.toml ``` ### Environment Variables The workflow must inject the following environment variables on the ggscout step. These variables are how ggscout discovers which secrets exist and where they come from — without them, ggscout has no visibility into your GitHub Actions environment. | Variable | Description | Required | |----------|-------------|----------| | `GGSCOUT_GITHUB_ACTION_SECRETS` | `${{ toJSON(secrets) }}` — JSON object of all secrets available to the job. This is ggscout's primary input for discovering secrets. | Yes | | `GGSCOUT_GITHUB_ACTION_CONTEXT` | `${{ toJSON(github) }}` — GitHub context providing source identity (server URL, repository owner, repository name). | Yes | | `GGSCOUT_GITHUB_API_TOKEN` | GitHub API token for metadata enrichment (see [Metadata Enrichment](#metadata-enrichment)). | No (recommended) | | `GITGUARDIAN_API_KEY` | GitGuardian API token with NHI permissions. | Yes | ## Configuration The ggscout TOML configuration for GitHub Actions is minimal — the source identity (hostname, org, repo) is derived automatically from the GitHub runner context. In the workflow examples above, the configuration is created inline during the workflow run. Alternatively, you can commit a `config.toml` file to your repository and reference it directly (using `actions/checkout` to make it available): ```toml [sources.github-actions] type = "githubactions" env = "production" # Optional: Environment label owner = "devops-team@example.com" # Optional: Owner of this source token = "${GGSCOUT_GITHUB_API_TOKEN}" # Optional: GitHub API token for metadata enrichment [gitguardian] api_token = "${GITGUARDIAN_API_KEY}" endpoint = "https://api.gitguardian.com/v1" ``` ### Configuration Parameters | Parameter | Description | Required | Example | |-----------|-------------|----------|---------| | `type` | Must be `"githubactions"` | Yes | `"githubactions"` | | `env` | Environment label for categorizing secrets | No | `"production"` | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | `"devops-team@example.com"` | | `token` | GitHub API token (fallback if `GGSCOUT_GITHUB_API_TOKEN` env var is not set) | No | `"ghp_xxxx"` | ## Metadata Enrichment By default, ggscout inventories secret names and values from the runner environment. When a GitHub API token is provided (via `GGSCOUT_GITHUB_API_TOKEN` or the `token` config field), ggscout also calls the GitHub REST API to enrich each secret with additional metadata: - **`created_at`** and **`updated_at`** timestamps - **`scope`** tag — `"org"`, `"repo"`, or `"env"`, indicating where the secret is defined - **`visibility`** tag — for org-level secrets: `"all"`, `"private"`, or `"selected"` - **`environment`** tag — for environment-level secrets: the environment name (e.g., `"production"`) - **`owner_email`** tag — from the GitHub user profile of the repository/org owner ### Required Token Permissions | Token Type | Permissions | Scope | |------------|-------------|-------| | **Fine-grained PAT** | Repository: **Secrets: Read** + **Environments: Read**. Organization: **Secrets: Read** | Repo + environment + org secrets | | **Classic PAT** | `repo` + `admin:org` | Repo + environment + org secrets | | **GitHub App** | `secrets:read` + `environments:read` + `organization_secrets:read` | Repo + environment + org secrets | Missing scopes result in `403 Forbidden` warnings in logs. The fetcher continues without the corresponding metadata (graceful degradation). ### Rate Limit Considerations When metadata enrichment is enabled, ggscout makes approximately 5–10 API calls per run (listing org, repo, and environment-level secrets, plus owner info). The rate limits depend on the token type: | Token Type | Rate Limit | |------------|------------| | **GITHUB_TOKEN** | 1,000 req/hr per repository (15,000 for Enterprise Cloud) | | **Personal Access Token** | 5,000 req/hr shared across all uses (15,000 for Enterprise Cloud) | | **GitHub App** | 5,000–15,000 req/hr depending on installation size | **Important:** PAT rate limits are **shared across all uses by that user**. If multiple repositories run ggscout with the same PAT concurrently, the combined API calls can exhaust the quota. **Recommendation:** Use a **GitHub App token** or a **dedicated service account PAT** rather than a personal PAT. Personal PATs share their rate limit quota with all other API activity by that user, which can lead to unexpected throttling. A GitHub App token provides a dedicated rate limit pool per installation and avoids long-lived credentials. ## GitHub Enterprise Server The integration automatically supports GHES instances. The hostname and API URL are derived from the `github` context provided by the runner — no additional configuration is needed. The `server_url` field from the GitHub context is parsed to determine the hostname (e.g., `github.example.com` instead of `github.com`), and `api_url` is used for REST API calls when metadata enrichment is enabled. ## Data Collected The GitHub Actions integration collects the following data: - **All user-defined secrets** available to the workflow job at runtime, including org-level, repo-level, and environment-level secrets - **Secret metadata** (when API token is provided): timestamps, scope, visibility, environment, and owner **Excluded:** `GITHUB_TOKEN` — this is an ephemeral token automatically generated by GitHub for every workflow run. It expires when the job ends or after 24 hours and is not a user-managed NHI. **Note on environment secret shadowing:** GitHub Actions environments (e.g., `production`, `staging`) can define secrets that override repo or org secrets with the same name. The `secrets` context presents all scopes as a flat object, so the origin is not visible from within the workflow. When metadata enrichment is enabled, ggscout queries all environments and applies environment > repo > org precedence to correctly attribute the `scope` and `environment` tags. ## Troubleshooting ### No Metadata Appearing - Verify that `GGSCOUT_GITHUB_API_TOKEN` is set (or `token` is configured in the TOML file) - Check that the token has the required permissions (see [Required Token Permissions](#required-token-permissions)) - Look for `403 Forbidden` warnings in the workflow logs — this indicates missing scopes ### Empty Inventory - Ensure `GGSCOUT_GITHUB_ACTION_SECRETS` is set to `${{ toJSON(secrets) }}` in the workflow step - Ensure `GGSCOUT_GITHUB_ACTION_CONTEXT` is set to `${{ toJSON(github) }}` - Verify that the repository has GitHub Actions secrets configured ### Debug Mode Enable verbose logging to troubleshoot issues: ```yaml - name: Collect secrets with ggscout (debug) env: GGSCOUT_GITHUB_ACTION_SECRETS: ${{ toJSON(secrets) }} GGSCOUT_GITHUB_ACTION_CONTEXT: ${{ toJSON(github) }} RUST_LOG: debug run: ggscout fetch /tmp/config.toml --verbose -o inventory.json - name: View inventory.json run: cat inventory.json | python3 -m json.tool ``` --- ## GitLab Integration GitGuardian Scout (`ggscout`) can be configured to collect secrets and CI/CD variables from GitLab instances, enabling you to inventory and monitor secrets stored in your GitLab environment. ## Overview The GitLab integration allows ggscout to: - **Collect CI/CD variables** from GitLab projects - **Inventory secrets** stored in GitLab CI/CD variable settings ## Prerequisites Before configuring the GitLab integration, ensure you have: 1. **GitLab instance access** (GitLab.com or self-hosted GitLab) 2. **Personal Access Token** or **Project/Group Access Token** with appropriate permissions 3. **GitGuardian API token** with NHI permissions 4. **ggscout deployed** in your environment (Docker, Kubernetes, or local installation) ## Configuration ### 1. GitLab Access Token Create a GitLab access token with the `read_api scope. **For Personal Access Tokens:** 1. Go to GitLab → User Settings → Access Tokens 2. Create a new token with required scopes 3. Note the token value securely **For Project Access Tokens:** 1. Go to Project → Settings → Access Tokens 2. Create a token with `Developer` or higher role 3. Select required scopes ### 2. Basic Configuration Add the GitLab source to your ggscout configuration file: ```toml [sources.gitlab] type = "gitlabci" token = "${GITLAB_CI_TOKEN}" # GitLab access token url = "https://gitlab.com/" # Your GitLab instance URL env = "production" # Optional: Environment label owner = "devops-team@example.com" # Optional: Owner of this source [gitguardian] api_token = "${GITGUARDIAN_API_KEY}" endpoint = "https://api.gitguardian.com/v1" ``` ### 3. Environment Variables Set the required environment variables: ```bash # GitLab access token GITLAB_CI_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx" # GitGuardian API token GITGUARDIAN_API_KEY="your-gitguardian-api-key" ``` ## Advanced Configuration ### Self-Hosted GitLab For self-hosted GitLab instances: ```toml [sources.gitlab-selfhosted] type = "gitlabci" token = "${GITLAB_CI_TOKEN}" url = "https://gitlab.example.com/" # Your GitLab instance URL ``` ### Multiple GitLab Instances You can configure multiple GitLab sources: ```toml [sources.gitlab-saas] type = "gitlabci" token = "${GITLAB_SAAS_TOKEN}" # Token for GitLab.com url = "https://gitlab.com/" [sources.gitlab-onprem] type = "gitlabci" token = "${GITLAB_ONPREM_TOKEN}" # Token for self-hosted instance url = "https://gitlab.internal.com/" ``` ### Resource Filtering You can filter which GitLab resources ggscout collects using include and exclude patterns: ```toml [sources.gitlab-filtered] type = "gitlabci" token = "${GITLAB_CI_TOKEN}" url = "https://gitlab.com/" env = "production" owner = "devops-team@example.com" # Include only specific projects or groups [[sources.gitlab-filtered.include]] resource_ids = ["my-group/*", "important-project"] # Exclude test or development projects [[sources.gitlab-filtered.exclude]] resource_ids = ["*/test-*", "dev-*", "sandbox/*"] ``` ### Configuration Parameters | Parameter | Description | Required | Example | |-----------|-------------|----------|---------| | `type` | Must be `"gitlabci"` | Yes | `"gitlabci"` | | `token` | GitLab access token | Yes | `"${GITLAB_CI_TOKEN}"` | | `url` | GitLab instance URL | Yes | `"https://gitlab.com/"` | | `env` | Environment label for categorizing secrets | No | `"production"` | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | `"devops-team@example.com"` | | `[[sources..include]]` | Table of resource_id patterns to include | No | See filtering section | | `[[sources..exclude]]` | Table of resource_id patterns to exclude | No | See filtering section | **Note:** - Use `[[sources..include]]` and `[[sources..exclude]]` tables to specify multiple include/exclude rules. Each table must have a `resource_ids` array. - Patterns support wildcards (*) only at the end for prefix matching. For exact matches, specify the complete name without wildcards. ## Running ggscout ### Using Docker Create a `.env` file: ```bash GITLAB_CI_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx GITGUARDIAN_API_KEY=your-gitguardian-api-key ``` Then run ggscout to collect GitLab data: ```bash docker run --rm -ti \ -v ${PWD}/config.toml:/tmp/config.toml:ro \ --env-file .env \ ghcr.io/gitguardian/ggscout/chainguard:latest \ fetch-and-send /tmp/config.toml ``` ### Using Helm Deploy ggscout with GitLab integration using the official Helm chart: ```bash # Add the ggscout Helm repository helm repo add ggscout https://gitguardian.github.io/ggscout-helm-charts helm repo update # Create a values file for GitLab integration cat > gitlab-values.yaml << EOF config: sources: gitlab: type: "gitlabci" token: "${GITLAB_CI_TOKEN}" url: "https://gitlab.com/" gitguardian: api_token: "${GITGUARDIAN_API_KEY}" endpoint: "https://api.gitguardian.com/v1" secrets: GITLAB_CI_TOKEN: "glpat-xxxxxxxxxxxxxxxxxxxx" GITGUARDIAN_API_KEY: "your-gitguardian-api-key" schedule: "0 */6 * * *" # Run every 6 hours EOF # Install ggscout with GitLab integration helm install ggscout-gitlab ggscout/ggscout -f gitlab-values.yaml ``` ## Data Collected The GitLab integration collects the following data: - **Project Variables**: CI/CD variables defined at the project level - **Variable Metadata**: Variable names, visibility settings, and environment scopes - **Project Information**: Project names, paths, and accessibility ## Troubleshooting ### Debug Mode Enable debug logging to troubleshoot issues: ```bash # Using Docker docker run --rm -ti \ -v ${PWD}/config.toml:/tmp/config.toml:ro \ --env-file .env \ -e RUST_LOG=debug \ ghcr.io/gitguardian/ggscout/chainguard:latest \ fetch /tmp/config.toml --verbose -o /tmp/inventory.json ``` --- ## Kubernetes # Kubernetes Integration ggscout supports integration with Kubernetes clusters to collect secrets and gather information about various Kubernetes resources. This integration provides comprehensive visibility into both sensitive data and resource configurations within your clusters. ## Supported Features - **Multiple resource types**: Secrets, ConfigMaps, Deployments, Service Accounts, and External Secrets - **Comprehensive data collection**: Collects both secrets and general resource information - **Namespace filtering**: Target specific namespaces using glob patterns - **Multiple authentication methods**: KubeConfig file or in-cluster authentication - **Multi-cluster support**: Monitor multiple Kubernetes clusters simultaneously - **Resource filtering**: Fine-grained control over which resources to scan :::info The Kubernetes integration is read-only and does not support writing secrets back to the cluster. ::: ## Supported Resource Types ggscout can scan the following Kubernetes API resources: | Resource Type | Description | |---------------|-------------| | **Secrets** | Native Kubernetes Secret resources | | **ConfigMaps** | Configuration data stored in the cluster | | **Deployments** | Application deployment configurations | | **Service Accounts** | Kubernetes service account configurations | | **External Secrets** | External Secrets Operator resources | ## Configuration To configure ggscout to work with Kubernetes, add the following configuration to your `ggscout.toml` file: ### KubeConfig File Authentication For external access to Kubernetes clusters using a kubeconfig file: ```toml [sources.k8s-production] type = "kubernetes" config_source = "kubeconfigfile" kubeconfig_path = "/path/to/kubeconfig" # Optional, defaults to ~/.kube/config contexts = ["production-cluster", "staging-cluster"] # Optional, all contexts if not specified namespaces = ["default", "production-*", "app-*"] # Optional, all namespaces if not specified env = "production" owner = "devops-team@example.com" ``` ### In-Cluster Authentication For ggscout running inside a Kubernetes cluster: ```toml [sources.k8s-cluster] type = "kubernetes" config_source = "incluster" name = "production-cluster" # Cluster name (required for in-cluster mode) namespaces = ["default", "production-*"] # Optional namespace filtering env = "production" owner = "devops-team@example.com" ``` ### Configuration Parameters | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `type` | Must be set to `"kubernetes"` | Yes | | | `config_source` | Authentication method: `"kubeconfigfile"` or `"incluster"` | Yes | | | `namespaces` | List of namespace patterns to scan | No | | | `env` | Environment identifier | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `mode` | Integration mode (only `"read"` is supported for Kubernetes) | No | `"read"` | #### KubeConfig File Parameters | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `kubeconfig_path` | Path to kubeconfig file | No | `~/.kube/config` | | `contexts` | List of contexts to use from kubeconfig | No | | #### In-Cluster Parameters | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `name` | Name of the Kubernetes cluster | Yes | | ### Setting Up Authentication #### Authentication Setup Steps 1. Configure a ClusterRole The easiest way to set up your kubernetes integration is to use our ggscout [Helm charts](https://github.com/GitGuardian/ggscout-helm-charts). Then you only need to configure this in your `values.yaml`: ```yaml clusterRole: create: true ``` If you don't use our Helm charts, check the [role](https://github.com/GitGuardian/ggscout-helm-charts/blob/main/charts/ggscout/templates/clusterrole.yaml) we are using to see the list of required rules Also see this full [values.yaml](https://github.com/GitGuardian/ggscout-helm-charts/blob/main/charts/ggscout/examples/k8s_incluster/values.yaml) example. ## Namespace Filtering Use glob patterns to control which namespaces ggscout scans: ```toml # Scan specific namespaces namespaces = ["production", "staging", "development"] # Use wildcards (only at the end) to match patterns namespaces = ["app-*", "service-*"] # Combine exact matches and patterns namespaces = ["default", "kube-system", "production-*"] ``` ## Resource Filtering Control which specific resources are scanned using include/exclude filters: ```toml [sources.k8s-filtered] type = "kubernetes" config_source = "incluster" name = "production-cluster" # Include filters - only scan these resources [[sources.k8s-filtered.include]] resource_ids = ["secret:*", "configmap:*"] # Exclude filters - skip these resources [[sources.k8s-filtered.exclude]] resource_ids = ["secret:kube-system/*"] ``` ## Multi-Cluster Configuration Monitor multiple Kubernetes clusters by defining multiple sources: ```toml [sources.k8s-production] type = "kubernetes" config_source = "kubeconfigfile" contexts = ["production"] env = "production" owner = "devops-team@example.com" [sources.k8s-staging] type = "kubernetes" config_source = "kubeconfigfile" contexts = ["staging"] env = "staging" owner = "devops-team@example.com" [sources.k8s-development] type = "kubernetes" config_source = "incluster" name = "dev-cluster" env = "development" owner = "devops-team@example.com" ``` ## Troubleshooting ### Common Issues **Authentication Failures** - Verify kubeconfig file path and permissions - Check RBAC permissions for the configured user/service account - Ensure cluster connectivity **Missing Resources** - Confirm RBAC permissions include all required resource types - Check namespace filtering configuration - Verify resource filtering rules **Performance Issues** - Reduce scope with namespace filtering - Use resource filtering to limit scanned resource types - Consider cluster size and API rate limits --- ## Secrets Managers integrations :::info Business Feature Only workspaces with a Business plan can access this functionality. ::: GitGuardian integrates with Secrets Managers through ggscout, enabling you to synchronize secrets incidents with secrets stored in your Secrets Managers. Connect your Secrets Managers using the guidelines provided in the subsequent sections. You may also follow the guidelines provided in the [Secrets Managers integrations](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-managers) page from your GitGuardian platform. ![Scout Flow](/img/ggscout/secrets-managers-integrations.png) --- ## Akeyless # Akeyless Integration GGScout supports integration with Akeyless to collect and monitor your secrets. This guide will help you set up and configure the integration. ## Supported Features - Multiple secret versions collection - API key authentication - Regular accessibility mode - Cross-environment support ## Configuration To configure GGScout to work with Akeyless, add the following configuration to your `ggscout.toml` file: ```toml [sources.akeyless] type = "akeyless" api_url = "https://api.akeyless.io" access_id = "${AKEYLESS_ACCESS_ID}" access_key = "${AKEYLESS_ACCESS_KEY}" accessibility = "regular" auth_mode = "apikey" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" [[sources.akeyless.include]] resource_ids = ["/app/*", "/database/*", "/api-key"] [[sources.akeyless.exclude]] resource_ids = ["/test/*", "/temp/*", "/old-secret"] ``` ### Configuration Parameters | Parameter | Description | Required | Default Value | | -------------------- | ------------------------------------------ | -------- | ------------- | | `type` | Must be set to `"akeyless"` | Yes | | | `access_id` | Your Akeyless access ID | Yes | | | `access_key` | Your Akeyless access key | Yes | | | `accessibility` | Accessibility mode (default: "regular") | No | "regular" | | `auth_mode` | Authentication mode (e.g., "apikey") | Yes | | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `api_url` | Akeyless API URL | No | "https://api.akeyless.io" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `[[sources..include]]` | Table of resource_id patterns to include (see below) | No | | | `[[sources..exclude]]` | Table of resource_id patterns to exclude (see below) | No | | **Note:** - Use `[[sources..include]]` and `[[sources..exclude]]` tables to specify multiple include/exclude rules. Each table must have a `resource_ids` array. - Patterns support wildcards (*) only at the end for prefix matching. For exact matches, specify the complete name without wildcards. ### Authentication GGScout supports authentication with Akeyless through: 1. **API Key**: Using access ID and access key 2. **Environment Variables**: Using standard Akeyless environment variables ### Environment Variables - `AKEYLESS_ACCESS_ID`: Your Akeyless access ID - `AKEYLESS_ACCESS_KEY`: Your Akeyless access key ## Best Practices 1. Use environment variables for sensitive credentials 2. Follow the principle of least privilege for access policies 3. Enable `fetch_all_versions` to track changes in your secrets over time 4. Regularly rotate access keys 5. Use separate access IDs for different environments 6. Implement proper secret rotation policies 7. Monitor access logs for suspicious activity --- ## AWS Secrets Manager # AWS Secrets Manager Integration GGScout supports integration with AWS Secrets Manager to collect and monitor your secrets. This guide will help you set up and configure the integration. ## Configuration To configure GGScout to work with AWS Secrets Manager, add the following configuration to your `ggscout.toml` file: ```toml [sources.aws-source-playground] type = "awssecretsmanager" fetch_all_versions = true profile_name = "default" regions = ["us-east-1"] mode = "read" env = "production" owner = "devops-team@example.com" [[sources.aws-source-playground.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.aws-source-playground.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` ### Configuration Parameters | Parameter | Description | Required | Default Value | | -------------------- | ------------------------------------------ | -------- | ------------- | | `type` | Must be set to `"awssecretsmanager"` | Yes | | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `profile_name` | AWS profile name to use | No | | | `regions` | AWS regions where secrets are stored | No | | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `[[sources..include]]` | Table of resource_id patterns to include (see below) | No | | | `[[sources..exclude]]` | Table of resource_id patterns to exclude (see below) | No | | **Note:** - Use `[[sources..include]]` and `[[sources..exclude]]` tables to specify multiple include/exclude rules. Each table must have a `resource_ids` array. - Patterns support wildcards (*) only at the end for prefix matching. For exact matches, specify the complete name without wildcards. ### Authentication GGScout uses the AWS Rust client for authentication, which follows the standard AWS credential resolution process. The authentication is handled automatically by the AWS SDK, and the TOML configuration file only allows specifying the `profile_name` parameter. :::note Authentication methods cannot be directly configured in the TOML file. Instead, you must provide the necessary AWS credentials through environment variables or AWS credential files. ::: ### AWS Credential Resolution The AWS Rust client will attempt to load credentials in the following order: 1. Environment variables: - `AWS_ACCESS_KEY_ID` - `AWS_SECRET_ACCESS_KEY` - `AWS_SESSION_TOKEN` (if using temporary credentials) 2. AWS credential files: - `~/.aws/credentials` - `~/.aws/config` 3. IAM roles for Amazon EC2 or ECS tasks 4. IAM user federation ### Environment Variables For direct authentication, you must set the following environment variables: - `AWS_ACCESS_KEY_ID`: Your AWS access key ID - `AWS_SECRET_ACCESS_KEY`: Your AWS secret access key - `AWS_SESSION_TOKEN`: Your AWS session token (if using temporary credentials) - `AWS_REGION`: The AWS region where your secrets are stored :::tip For production environments, it's recommended to use IAM roles or instance profiles rather than hardcoding credentials in environment variables. ::: ## Required AWS Permissions To fetch secrets from AWS Secrets Manager, the identity used by GGScout must have the appropriate IAM permissions. The minimum required permissions are: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue", "secretsmanager:BatchGetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds" ], "Resource": "arn:aws:secretsmanager:*:*:secret:*" }, { "Effect": "Allow", "Action": [ "secretsmanager:ListSecrets" ], "Resource": "*" } ] } ``` As stated in [AWS documentation](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssecretsmanager.html), it is not possible to restrict the `"secretsmanager:ListSecrets"` permissions to a subset of secrets. ## Best Practices 1. Use IAM roles or instance profiles when running on AWS infrastructure 2. Follow the principle of least privilege for IAM permissions 3. Enable `fetch_all_versions` to track changes in your secrets over time 4. Regularly rotate access keys 5. Use separate AWS accounts or regions for different environments --- ## Azure Key Vault # Azure Key Vault Integration GGScout supports integration with Azure Key Vault to collect and monitor your secrets. This guide will help you set up and configure the integration. ## Supported Features - Multiple secret versions collection - DefaultAzureCredential authentication - Managed Identity authentication - Service Principal authentication - Cross-tenant access ## Configuration To configure GGScout to work with Azure Key Vault, add the following configuration to your `ggscout.toml` file: ```toml [sources.azure-source-playground] type = "azurekeyvault" fetch_all_versions = true subscription_id = "${AZURE_SUBSCRIPTION_ID}" mode = "read" env = "production" owner = "devops-team@example.com" [[sources.azure-source-playground.include]] resource_ids = ["app-*", "database-*", "api-key"] [[sources.azure-source-playground.exclude]] resource_ids = ["test-*", "temp-*", "old-secret"] ``` ### Configuration Parameters | Parameter | Description | Required | Default Value | | -------------------- | ------------------------------------------ | -------- | ------------- | | `type` | Must be set to `"azurekeyvault"` | Yes | | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `subscription_id` | Your Azure subscription ID | Yes | | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `[[sources..include]]` | Table of resource_id patterns to include (see below) | No | | | `[[sources..exclude]]` | Table of resource_id patterns to exclude (see below) | No | | **Note:** - Use `[[sources..include]]` and `[[sources..exclude]]` tables to specify multiple include/exclude rules. Each table must have a `resource_ids` array. - Patterns support wildcards (*) only at the end for prefix matching. For exact matches, specify the complete name without wildcards. ### Authentication GGScout uses the DefaultAzureCredential for authentication, which attempts to authenticate using the following methods in order: 1. Environment variables 2. Workload Identity 3. Managed Identity 4. Shared Token Cache 5. Visual Studio 6. Azure CLI 7. Azure PowerShell 8. Azure Developer CLI 9. Interactive Browser :::note Authentication methods cannot be directly configured in the TOML file. Instead, you must provide the necessary environment variables for your chosen authentication method. ::: ### Environment Variables For Service Principal authentication, you must set the following environment variables: - `AZURE_SUBSCRIPTION_ID`: Your Azure subscription ID - `AZURE_TENANT_ID`: Your Azure tenant ID - `AZURE_CLIENT_ID`: Your service principal client ID - `AZURE_CLIENT_SECRET`: Your service principal client secret For other authentication methods, refer to the [Azure Identity documentation](https://learn.microsoft.com/en-us/dotnet/api/azure.identity.defaultazurecredential?view=azure-dotnet) for the required environment variables. ## Required Azure Permissions To fetch secrets from Azure Key Vault, the identity used by GGScout (whether it's a Managed Identity, Service Principal, or user account) must have the appropriate permissions assigned. ### RBAC Permissions The identity must have at least one of the following built-in roles assigned to the Key Vault: 1. **Key Vault Secrets User** (`Key Vault Secrets User`): Allows reading secret values 2. **Key Vault Secrets Officer** (`Key Vault Secrets Officer`): Allows reading and managing secrets 3. **Key Vault Administrator** (`Key Vault Administrator`): Full access to Key Vault For more granular control, you can create a custom role with the following permissions: ```json { "Name": "GGScout Key Vault Reader", "Description": "Allows GGScout to read secrets from Key Vault", "Actions": [ "Microsoft.KeyVault/vaults/secrets/read", "Microsoft.KeyVault/vaults/secrets/versions/read", "Microsoft.KeyVault/vaults/secrets/list" ], "NotActions": [], "DataActions": [], "NotDataActions": [], "AssignableScopes": [ "/subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.KeyVault/vaults/{vault-name}" ] } ``` ### Access Policy (Legacy) If your Key Vault is using the older Access Policy model instead of RBAC, the identity must have the following permissions: - **Get** and **List** permissions for secrets :::tip For production environments, it's recommended to use RBAC for Key Vault access management as it provides more granular control and better integration with Azure's identity management. ::: ## Best Practices 1. Use Managed Identity when running on Azure infrastructure 2. Follow the principle of least privilege for role assignments 3. Enable `fetch_all_versions` to track changes in your secrets over time 4. Regularly rotate service principal credentials 5. Use separate Key Vaults for different environments --- ## CyberArk Secrets Manager SaaS # CyberArk Secrets Manager SaaS Integration ggscout supports integration with CyberArk Secrets Manager SaaS to collect and monitor your secrets. This guide will help you set up and configure the integration. ## Supported Features - Multiple secret versions collection - CyberArk authentication - Tenant-specific configuration - Subdomain support ## Configuration The following table lists the available configuration options for ggscout when integrating with CyberArk Secrets Manager SaaS: | Parameter | Description | Required | Default Value | |----------------------|-------------------------------------------------------------------------------------------|----------|-------------| | `type` | Must be set to `"cyberarksaas"` | Yes | | | `auth.auth_mode` | Authentication mode (one of: "cyber_ark", "workload", "k8s") | Yes | | | `subdomain` | Your company's subdomain | Yes | | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `include` | List of path patterns to include in secret collection | No | | | `exclude` | List of path patterns to exclude from secret collection | No | | With additional parameters depending on the chosen authentication mode: For CyberArk Authentication: | Parameter | Description | Required | Default Value | |----------------------|-------------|----------|-------------| | `auth.client_id` | The client ID for authentication | Yes | | | `auth.client_secret` | The client secret for authentication | Yes | | | `auth.tenant_id` | The tenant ID | Yes | | For Workload Authentication: | Parameter | Description | Required | Default Value | |----------------|-------------|----------|-------------| | `auth.api_key` | Your Conjur API key | Yes | | | `auth.login` | Your Conjur login | Yes | | For Kubernetes Authentication: | Parameter | Description | Required | Default Value | |-------------------|-------------|----------|-------------| | `auth.service_id` | The ID of your JWT authenticator in CyberArk Secrets Manager SaaS | Yes | | ## Authentication ggscout supports multiple authentication methods for CyberArk Secrets Manager SaaS: ### CyberArk Authentication ```toml [sources.cyberarksaas] type = "cyberarksaas" auth.auth_mode = "cyber_ark" auth.client_id = "${CYBERARK_CLIENT_ID}" auth.client_secret = "${CYBERARK_CLIENT_SECRET}" auth.tenant_id = "${CYBERARK_TENANT_ID}" cyberarksaas_url = "${CYBERARK_SAAS_URL}" subdomain = "my-company" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" [[sources.cyberarksaas.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.cyberarksaas.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` ### Workload Authentication ```toml [sources.cyberarksaas] type = "cyberarksaas" auth.auth_mode = "workload" api_key = "${CONJUR_API_KEY}" login = "${CONJUR_LOGIN}" subdomain = "my-company" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" [[sources.cyberarksaas.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.cyberarksaas.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` ### Kubernetes Authentication ```toml [sources.cyberarksaas] type = "cyberarksaas" auth.auth_mode = "k8s" auth.service_id = "k8s-cluster-name" subdomain = "my-company" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" [[sources.cyberarksaas.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.cyberarksaas.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` #### Detailed Setup Instructions For applications running in Kubernetes clusters, you can configure CyberArk Secrets Manager SaaS to use JWT-based authentication. This allows your Kubernetes workloads to authenticate with CyberArk Secrets Manager SaaS using service account tokens. #### Prerequisites - A running CyberArk Secrets Manager SaaS instance - A running Kubernetes cluster - `kubectl` CLI installed and configured #### Step 1: Retrieve Kubernetes OIDC Configuration ##### For AWS EKS Get the OIDC issuer URL for your EKS cluster: ```bash aws eks describe-cluster --name --query "cluster.identity.oidc.issuer" --output text ``` The output will be a URL like `https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED5A3C59576A0175F11F3414644`. The JWKS URI is the issuer URL with `/keys` appended: `https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED5A3C59576A0175F11F3414644/keys` ##### For Other Kubernetes Clusters For clusters that expose the OIDC discovery endpoint: ```bash # Get the OIDC issuer URL kubectl get --raw /.well-known/openid-configuration | jq -r '.issuer' # Get the public keys (JWKS) kubectl get --raw /openid/v1/jwks ``` #### Step 2: Configure JWT Authenticator in CyberArk Secrets Manager SaaS You can create the JWT authenticator using the CyberArk Secrets Manager SaaS UI, API, or CLI. ##### Using CyberArk Secrets Manager SaaS UI 1. Navigate to the **Authenticators** page in CyberArk Secrets Manager SaaS 2. Click **Create authenticator** 3. Select **JWT** as the authenticator type 4. Enter a unique name for the authenticator (e.g., `k8s-cluster-name`) 5. Configure the following variables: | Variable | Description | Required | Example Value | |----------|-------------|------|---------------| | `jwks-uri` | The JWKS URI of your Kubernetes cluster | Yes (or use `public-keys`) | `https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLE/keys` | | `public-keys` | JWKS content as JSON string | Yes (or use `jwks-uri`) | Use for local/private clusters | | `issuer` | The OIDC issuer URL | Yes | `https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLE` | | `token-app-property` | JWT claim for application identity | Yes | `sub` | | `audience` | Expected audience for the JWT | Recommended | `cyberark` | ##### Policy Example When using policy files, your JWT authenticator policy should look like this: ```yaml - !policy id: conjur/authn-jwt/k8s-cluster-name body: - !webservice annotations: description: JWT authenticator for Kubernetes cluster - !variable id: jwks-uri - !variable id: issuer - !variable id: token-app-property - !variable id: audience - !group users - !host-factory id: host-factory layers: [ !layer users ] ``` Then populate the variables: ```bash # Set the JWKS URI conjur variable set -i conjur/authn-jwt/k8s-cluster-name/jwks-uri -v "https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLE/keys" # Set the issuer conjur variable set -i conjur/authn-jwt/k8s-cluster-name/issuer -v "https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLE" # Set the token app property (IMPORTANT: Use 'sub' for Kubernetes) conjur variable set -i conjur/authn-jwt/k8s-cluster-name/token-app-property -v "sub" # Set the audience conjur variable set -i conjur/authn-jwt/k8s-cluster-name/audience -v "conjur" ``` #### Step 3: Create Workload Branch and Identity Before creating workloads in CyberArk Secrets Manager SaaS, you need to set up the policy structure and workload identities. ##### Create Policy Branch (CLI Required) If you're using the UI to create workloads, you must first create the policy branch using the CLI, as this cannot be done through the UI. 1. **Log in to Conjur CLI**: ```bash conjur login ``` 2. **Create the workload branch policy**: Save the following as `workload-branch.yaml`: ```yaml - !policy id: ``` Where `` is the name of your branch (for example, `myspace/jwt-apps` or `k8s-apps`). 3. **Load the policy branch**: ```bash conjur policy load -f workload-branch.yaml -b data ``` ##### Create Workload Identity After creating the policy branch, you can create the workload identity using either the UI or CLI. ###### Option A: Using CyberArk Secrets Manager SaaS UI 1. Navigate to **Workloads** in the CyberArk Secrets Manager SaaS UI 2. Click **Create workload** 3. Select **JWT** as the authentication method 4. Choose your JWT authenticator (e.g., `k8s-cluster-name`) 5. Configure the workload: - **Workload ID**: `system:serviceaccount:my-namespace:my-service-account` - **Policy Branch**: The branch you created (e.g., `myspace/jwt-apps`) - **Annotations**: Add relevant metadata - `kubernetes/namespace`: `my-namespace` - `kubernetes/service-account`: `my-service-account` ###### Option B: Using CLI Policy (Detailed Steps) **Step 1: Create the workload host policy** Save the following policy in a file named `authn-jwt-hosts.yaml`: ```yaml - !policy id: body: - !group - !host id: annotations: authn-jwt//: - !grant role: !group member: !host ``` Where: - `` is the name of the branch (e.g., `myspace/jwt-apps` or `k8s-apps`) - `` is the name of the workload. **For Kubernetes JWT authentication using `token-app-property`, this must be the value of the JWT claim** (e.g., `system:serviceaccount:my-namespace:my-service-account`) - `` is the name of your JWT authenticator (e.g., `k8s-cluster-name`) - `` is the name of a JWT claim (e.g., `sub`, `namespace`, etc.) - `` is the value of the specified JWT claim **For Kubernetes workloads**, here's a concrete example using the `sub` claim: ```yaml - !policy id: k8s-apps body: - !group - !host id: system:serviceaccount:ggscout-namespace:ggscout-service-account annotations: kubernetes/namespace: ggscout-namespace kubernetes/service-account: ggscout-service-account workload/type: ggscout - !grant role: !group member: !host ``` **Step 2: Load the workload policy** ```bash conjur policy load -f authn-jwt-hosts.yaml -b data ``` **Step 3: Grant workload permissions to JWT authenticator** Create a policy file `authn-jwt-grant.yaml`: ```yaml - !grant role: !group conjur/authn-jwt/k8s-cluster-name/users member: !group /data/k8s-apps ``` Load the policy in the JWT authenticator branch: ```bash conjur policy load -f authn-jwt-grant.yaml -b conjur/authn-jwt/k8s-cluster-name ``` **Step 4: Create comprehensive workload policy with secrets** For a complete setup including secrets and permissions, create `k8s-workload-complete.yaml`: ```yaml - !policy id: k8s-apps body: # Create the workload host with proper annotations - !host id: system:serviceaccount:ggscout-namespace:ggscout-service-account annotations: authn-jwt/k8s-cluster-name/sub: system:serviceaccount:ggscout-namespace:ggscout-service-account kubernetes/namespace: ggscout-namespace kubernetes/service-account: ggscout-service-account description: "ggscout service account for Kubernetes cluster authentication" # Create secrets that this workload can access - !variable id: database/password - !variable id: api/token # Create a group for this workload's permissions - !group id: ggscout-consumers # Grant the workload access to the consumer group - !grant role: !group ggscout-consumers member: !host system:serviceaccount:ggscout-namespace:ggscout-service-account # Grant read permissions to secrets - !permit role: !group ggscout-consumers privilege: [ read, execute ] resource: !variable database/password - !permit role: !group ggscout-consumers privilege: [ read, execute ] resource: !variable api/token ``` Load the complete policy: ```bash conjur policy load -f k8s-workload-complete.yaml -b data ``` ##### Multiple Workloads Example For multiple Kubernetes workloads, you can create them in batch: ```yaml - !policy id: myspace/jwt-apps body: # ggscout workload - !host id: system:serviceaccount:ggscout-namespace:ggscout-service-account annotations: kubernetes/namespace: ggscout-namespace kubernetes/service-account: ggscout-service-account workload/type: ggscout # Application workload - !host id: system:serviceaccount:app-namespace:app-service-account annotations: kubernetes/namespace: app-namespace kubernetes/service-account: app-service-account workload/type: application # Grant authentication permissions to both - !grant role: !group conjur/authn-jwt/k8s-cluster-name/users members: - !host system:serviceaccount:ggscout-namespace:ggscout-service-account - !host system:serviceaccount:app-namespace:app-service-account ``` ##### Workload Naming Conventions For Kubernetes workloads using JWT authentication, follow these naming conventions: - **Host ID Format**: `system:serviceaccount::` - **Policy Branch**: Use logical groupings like `k8s-apps`, `/k8s`, or `/jwt-workloads` - **Annotations**: Include metadata for better organization: - `kubernetes/namespace` - `kubernetes/service-account` - `environment` (dev, staging, prod) - `team` or `application` #### Step 4: Configure ggscout for JWT Authentication Add the JWT authentication configuration to your `ggscout.toml`: ```toml [sources.cyberarksaas-k8s] type = "cyberarksaas" auth.auth_mode = "k8s" auth.service_id = "k8s-cluster-name" subdomain = "my-company" fetch_all_versions = true mode = "read" owner = "devops-team@example.com" ``` #### Important Notes 1. **Always use `sub` as `token-app-property`**: For Kubernetes workloads, the `sub` (subject) claim contains the service account identity in the format `system:serviceaccount::`. 2. **Follow least privilege**: Create specific host identities for each workload and grant only the minimum required permissions. 3. **Workload ID matching**: Ensure the workload ID in CyberArk Secrets Manager SaaS exactly matches the Kubernetes service account format: `system:serviceaccount::`. #### Step 6: Grant Access to Variables/Secrets After creating your workload identity, you need to grant it access to the specific secrets it requires. This is done through the policy system using groups, layers, and permit statements. ##### Method 1: Direct Variable Assignment Create variables and assign privileges directly to a group or layer: ```yaml - !policy id: ggscout-secrets body: # Define the variables/secrets - &variables - !variable id: db-password kind: password - !variable id: api-token kind: API token - !variable id: ssl/private_key kind: SSL private key mime_type: application/x-pem-file # Create a layer for workloads that need these secrets - !layer app # Grant access to the variables - !permit role: !layer app privileges: [read, execute] resources: *variables # Add your workload to the layer - !grant role: !layer app member: !host /data/k8s-apps/system:serviceaccount:ggscout-namespace:ggscout-service-account ``` ##### Method 2: Policy-Based Secret Organization For better organization, create a dedicated policy for your application's secrets: ```yaml - !policy id: ggscout-app-secrets owner: !group devops annotations: description: This policy contains secrets for ggscout application body: # Define secret variables using YAML anchor - &app-secrets - !variable id: database/password - !variable id: database/url - !variable id: database/username - !variable id: external-api/token - !variable id: encryption/key # Create a group for consumers of these secrets - !group consumers # Grant read and execute permissions to the consumer group - !permit role: !group consumers privileges: [ read, execute ] resources: *app-secrets # Add your ggscout workload to the consumers group - !grant role: !group consumers member: !host /data/k8s-apps/system:serviceaccount:ggscout-namespace:ggscout-service-account ``` ##### Load the Secret Policies After creating your secret policies, load them into CyberArk Secrets Manager SaaS: ```bash # Load the policy conjur policy load -f ggscout-secrets.yaml -b data # Set the secret values (example) conjur variable set -i ggscout-secrets/db-password -v "your-secure-password" conjur variable set -i ggscout-secrets/api-token -v "your-api-token" ``` --- ## CyberArk Secrets Manager Self-Hosted # CyberArk Secrets Manager Self-Hosted Integration ggscout supports integration with CyberArk Secrets Manager Self-Hosted (Conjur Enterprise and OSS) to collect and monitor your secrets. This guide will help you set up and configure the integration. ## Supported Features - Multiple secret versions collection - User and API authentication - Self-hosted server configuration - Account-based access ## Configuration The following table lists the available configuration options for ggscout when integrating with CyberArk Secrets Manager Self-Hosted: | Parameter | Description | Required | Default Value | |------------------------|-------------------------------------------------------------------------------------------|----------|---------------| | `type` | Must be set to `"cyberarkselfhosted"` | Yes | | | `server_url` | The URL of your self-hosted CyberArk Secrets Manager server | Yes | | | `account` | The Conjur account name | Yes | | | `auth_mode` | Authentication mode (one of: "user", "api") | Yes | | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `accept_invalid_certs` | Accept invalid/self-signed certificates (for development only) | No | `false` | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `include` | List of path patterns to include in secret collection | No | | | `exclude` | List of path patterns to exclude from secret collection | No | | With additional parameters depending on the chosen authentication mode: For User Authentication: | Parameter | Description | Required | Default Value | |------------|----------------------------------|----------|---------------| | `username` | Username for authentication | Yes | | | `password` | Password for authentication | Yes | | For API Authentication: | Parameter | Description | Required | Default Value | |-----------|---------------------------------------------------------|----------|---------------| | `login` | Login identity (including `host/` prefix for workloads) | Yes | | | `api_key` | API key for authentication | Yes | | ## Authentication ggscout supports two authentication methods for CyberArk Secrets Manager Self-Hosted: ### User Authentication Use this method when authenticating with a username and password: ```toml [sources.cyberarkselfhosted] type = "cyberarkselfhosted" server_url = "https://conjur.example.com" account = "myorg" auth_mode = "user" username = "${CONJUR_USERNAME}" password = "${CONJUR_PASSWORD}" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" [[sources.cyberarkselfhosted.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.cyberarkselfhosted.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` ### API Authentication Use this method when authenticating with an API key and login identity. This is the recommended approach for workloads: ```toml [sources.cyberarkselfhosted] type = "cyberarkselfhosted" server_url = "https://conjur.example.com" account = "myorg" auth_mode = "api" login = "${CONJUR_LOGIN}" api_key = "${CONJUR_API_KEY}" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" [[sources.cyberarkselfhosted.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.cyberarkselfhosted.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` :::tip For host/workload authentication, the `login` parameter should include the `host/` prefix followed by the host identity path. For example: `host/myapp/production/ggscout`. ::: ## Self-Signed Certificates If your self-hosted CyberArk Secrets Manager uses self-signed certificates, you can disable certificate verification for development environments: ```toml [sources.cyberarkselfhosted] type = "cyberarkselfhosted" server_url = "https://conjur.example.com" account = "myorg" auth_mode = "api" login = "${CONJUR_LOGIN}" api_key = "${CONJUR_API_KEY}" fetch_all_versions = true accept_invalid_certs = true # Only for development! ``` :::warning Setting `accept_invalid_certs = true` disables TLS certificate verification. This should **only** be used in development environments, never in production. ::: ## Include and Exclude Patterns You can control which secrets are collected using include and exclude patterns: ```toml [sources.cyberarkselfhosted] type = "cyberarkselfhosted" server_url = "https://conjur.example.com" account = "myorg" auth_mode = "api" login = "${CONJUR_LOGIN}" api_key = "${CONJUR_API_KEY}" fetch_all_versions = true # Only collect secrets matching these patterns [[sources.cyberarkselfhosted.include]] resource_ids = ["production/*", "shared/*"] # Exclude secrets matching these patterns [[sources.cyberarkselfhosted.exclude]] resource_ids = ["test-*", "temp-*"] ``` ## Write Mode To enable secret synchronization (writing secrets back to CyberArk Secrets Manager Self-Hosted), set the mode to `read/write` or `write`: ```toml [sources.cyberarkselfhosted] type = "cyberarkselfhosted" server_url = "https://conjur.example.com" account = "myorg" auth_mode = "api" login = "${CONJUR_LOGIN}" api_key = "${CONJUR_API_KEY}" fetch_all_versions = true mode = "read/write" ``` :::note The identity must have `update` privileges on the target variables to write secrets. ::: --- ## Delinea Secret Server # Delinea Secret Server Integration GGScout supports integration with Delinea Secret Server to collect and monitor your secrets. This guide will help you set up and configure the integration. ## Supported Features - Multiple secret versions collection - OAuth authentication - Tenant-specific configuration - Cross-environment support ## Configuration To configure GGScout to work with Delinea Secret Server, add the following configuration to your `ggscout.toml` file: ```toml [sources.delinea] type = "delineasecretserver" auth_mode = "oauth" client_id = "${DELINEA_CLIENT_ID}" client_secret = "${DELINEA_CLIENT_SECRET}" fetch_all_versions = true tenant = "${DELINEA_TENANT}" tld = "com" mode = "read" env = "production" owner = "devops-team@example.com" [[sources.delinea.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.delinea.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` ### Configuration Parameters | Parameter | Description | Required | Default Value | | -------------------- | ------------------------------------------ | -------- | ------------- | | `type` | Must be set to `"delineasecretserver"` | Yes | | | `auth_mode` | Authentication mode (e.g., "oauth") | Yes | | | `client_id` | The client ID for OAuth authentication | Yes | | | `client_secret` | The client secret for OAuth authentication | Yes | | | `tenant` | Your Delinea tenant ID | Yes | | | `tld` | Top-level domain (e.g., "com") | No | "com" | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `[[sources..include]]` | Table of resource_id patterns to include (see below) | No | | | `[[sources..exclude]]` | Table of resource_id patterns to exclude (see below) | No | | **Note:** - Use `[[sources..include]]` and `[[sources..exclude]]` tables to specify multiple include/exclude rules. Each table must have a `resource_ids` array. - Patterns support wildcards (*) only at the end for prefix matching. For exact matches, specify the complete name without wildcards. ### Authentication GGScout supports authentication with Delinea Secret Server through: 1. **OAuth**: Using client ID and secret 2. **Environment Variables**: Using standard Delinea environment variables ### Environment Variables - `DELINEA_CLIENT_ID`: Your Delinea client ID - `DELINEA_CLIENT_SECRET`: Your Delinea client secret - `DELINEA_TENANT`: Your Delinea tenant ID ## Best Practices 1. Use environment variables for sensitive credentials 2. Follow the principle of least privilege for access policies 3. Enable `fetch_all_versions` to track changes in your secrets over time 4. Regularly rotate client secrets 5. Use separate tenants for different environments 6. Implement proper secret rotation policies 7. Monitor access logs for suspicious activity 8. Use strong password policies for secrets --- ## Google Secret Manager # Google Secret Manager Integration GGScout supports integration with Google Secret Manager to collect and monitor your secrets. This guide will help you set up and configure the integration. ## Supported Features - Multiple secret versions collection - Multiple authentication methods (service account, Kubernetes Workload Identity, Application Default Credentials) - Native GCP infrastructure support (automatic metadata endpoint detection) - Project-specific secret collection - IAM role-based access ## Configuration To configure GGScout to work with Google Secret Manager, add the following configuration to your `ggscout.toml` file: ### Service Account Key File Authentication Use a JSON key file for authentication: ```toml [sources.gcp] type = "gcpsecretmanager" fetch_all_versions = true projects = ["some-project-id-441517"] mode = "read" env = "production" owner = "devops-team@example.com" auth.auth_mode = "service_account_key_file" auth.key_file = ".secure_files/.gcp_key.json" [[sources.gcp.include]] resource_ids = ["app-*", "database-*", "api-key"] [[sources.gcp.exclude]] resource_ids = ["test-*", "temp-*", "old-secret"] ``` ### Application Default Credentials (Recommended for GCP) When running ggscout on GCP infrastructure (GCE, GKE, Cloud Run, etc.), use Application Default Credentials for automatic authentication: ```toml [sources.gcp] type = "gcpsecretmanager" fetch_all_versions = true projects = ["some-project-id-441517"] mode = "read" env = "production" owner = "devops-team@example.com" auth.auth_mode = "default" [[sources.gcp.include]] resource_ids = ["app-*", "database-*", "api-key"] [[sources.gcp.exclude]] resource_ids = ["test-*", "temp-*", "old-secret"] ``` :::tip Running on GCP Infrastructure When using `auth_mode = "default"`, ggscout automatically detects its environment and uses the most appropriate authentication method: - **On GCE/GKE**: Automatically calls GCP's metadata endpoint to retrieve credentials - **With GOOGLE_APPLICATION_CREDENTIALS**: Uses the service account key file specified by the environment variable - **Local development**: Falls back to `gcloud auth application-default login` credentials This is the recommended approach for production deployments on GCP infrastructure. ::: ### Kubernetes Workload Identity Federation For GKE clusters using Workload Identity: ```toml [sources.gcp] type = "gcpsecretmanager" fetch_all_versions = true projects = ["some-project-id-441517"] mode = "read" env = "production" owner = "devops-team@example.com" auth.auth_mode = "k8s" auth.project_id = "my-gcp-project" auth.project_number = "123456789012" auth.pool_id = "my-workload-identity-pool" auth.provider_id = "my-provider" auth.gcp_service_account_name = "ggscout-sa" auth.kubernetes_namespace = "ggscout" # Optional auth.kubernetes_service_account = "ggscout-k8s-sa" # Optional [[sources.gcp.include]] resource_ids = ["app-*", "database-*", "api-key"] [[sources.gcp.exclude]] resource_ids = ["test-*", "temp-*", "old-secret"] ``` ### Configuration Parameters | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `type` | Must be set to `"gcpsecretmanager"` | Yes | | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `projects` | List of GCP project IDs to collect secrets from | No | All accessible projects | | `auth.auth_mode` | Authentication method: "service_account_key_file", "k8s", or "default" | No | "default" | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `[[sources..include]]` | Table of resource_id patterns to include (see below) | No | | | `[[sources..exclude]]` | Table of resource_id patterns to exclude (see below) | No | | **Service Account Key File Authentication Parameters:** | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `auth.key_file` | Path to the service account JSON key file | Yes (for service_account_key_file mode) | | **Kubernetes Workload Identity Federation Parameters:** | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `auth.project_id` | GCP Project ID where the service account is located | Yes (for k8s mode) | | | `auth.project_number` | GCP Project Number | Yes (for k8s mode) | | | `auth.pool_id` | Workload Identity Pool ID | Yes (for k8s mode) | | | `auth.provider_id` | Workload Identity Provider ID | Yes (for k8s mode) | | | `auth.gcp_service_account_name` | Google Service Account name (without @project.iam.gserviceaccount.com) | Yes (for k8s mode) | | | `auth.kubernetes_namespace` | Kubernetes namespace where the service account is located | No | | | `auth.kubernetes_service_account` | Kubernetes service account name to use for authentication | No | | | `auth.audience` | Custom audience for the WIF provider | No | Standard WIF provider URL format | | `auth.token_expiration_seconds` | Token expiration time in seconds | No | 1800 (30 minutes) | ### Authentication GGScout supports three authentication methods for Google Cloud: #### 1. Application Default Credentials (Recommended for GCP) The `default` authentication mode automatically infers its configuration based on the environment: - **Running on GCP infrastructure (GCE, GKE, Cloud Run)**: Automatically calls GCP's metadata endpoint to retrieve instance or workload credentials - **GOOGLE_APPLICATION_CREDENTIALS environment variable set**: Uses the service account key file specified - **Local development**: Falls back to credentials from `gcloud auth application-default login` This is the most secure and convenient method when running ggscout on GCP infrastructure as it eliminates the need to manage service account key files. #### 2. Service Account Key File Explicitly specify a JSON key file path for authentication. This method works in any environment but requires managing and securing the key file. #### 3. Kubernetes Workload Identity Federation Use Kubernetes service account tokens with GCP Workload Identity Federation. This is the most secure method for GKE deployments as it: - Eliminates the need for service account key files - Provides short-lived, automatically rotated credentials - Follows cloud-native security best practices **Prerequisites:** Before setting up the integration, ensure that you have activated the **Cloud Resource Manager API** in your GCP account, in addition to the **Secret Manager API**. ### Environment Variables For Service Account Key File authentication: - `GOOGLE_APPLICATION_CREDENTIALS`: Path to the service account key file (when using default mode) For Application Default Credentials: - No environment variables required when running on GCP infrastructure - `GOOGLE_APPLICATION_CREDENTIALS`: Optional, can be used to specify a key file ## Best Practices 1. **Use Application Default Credentials (`auth_mode = "default"`)** when running on GCP infrastructure (GCE, GKE, Cloud Run) for automatic, secure authentication without managing key files 2. **For GKE deployments**: Use Kubernetes Workload Identity Federation for the most secure, keyless authentication 3. **Avoid service account key files** in production when possible - use Application Default Credentials or Workload Identity instead 4. Follow the principle of least privilege for IAM permissions 5. Enable `fetch_all_versions` to track changes in your secrets over time 6. If you must use service account key files, store them securely and rotate them regularly 7. Use separate projects for different environments 8. When deploying on GCP, leverage the automatic metadata endpoint detection for seamless authentication **Note:** - Use `[[sources..include]]` and `[[sources..exclude]]` tables to specify multiple include/exclude rules. Each table must have a `resource_ids` array. - Patterns support wildcards (*) only at the end for prefix matching. For exact matches, specify the complete name without wildcards. --- ## HashiCorp Vault # HashiCorp Vault Integration GGScout supports integration with HashiCorp Vault to collect and monitor your secrets, including both **Vault Community Edition** and **Vault Enterprise** (self-hosted and HashiCorp Cloud Dedicated). This guide will help you set up and configure the integration. ## Supported Features Available on all editions (Community and Enterprise): - KV1 and KV2 secret engines - Multiple secret versions collection - Path-based filtering - Token-based authentication - Optional explicit mount type (`kv-v1`/`kv-v2`) to skip `sys/*` auto-detection Available on Vault Enterprise and HashiCorp Cloud Dedicated (HCD) only: - Namespace support ## HashiCorp Cloud Dedicated Support GGScout fully supports HashiCorp Cloud Dedicated (HCD) environments. When using HCD, namespaces are automatically included as part of the exported `resource_id`, following the Vault API pattern described in the [HashiCorp documentation](https://developer.hashicorp.com/vault/docs/enterprise/namespaces#vault-api-and-namespaces). ## Namespace Filtering ### Restricting Namespace Access (Enterprise and HCD only) Namespaces are a Vault Enterprise and HCD feature. With these editions, you can limit which namespaces ggscout accesses using the `namespaces` configuration parameter: ```toml [sources.vault] type = "hashicorpvault" vault_address = "${VAULT_ADDR}" fetch_all_versions = true namespaces = ["admin", "prod", "shared"] # Only fetch from these namespaces ``` :::info If the `namespaces` parameter is not specified, ggscout will fetch secrets from **all accessible namespaces**. Use this parameter to limit the scope of secret collection and improve performance. ::: ### Resource-Level Filtering You can also filter secrets by namespace directly in your include/exclude patterns. The namespace becomes part of the resource path, allowing for precise filtering: ```toml # Include all secrets from the 'admin' namespace, 'kv' mount, under 'my_app' path [[sources.vault.include]] resource_ids = ["admin/kv/my_app/*"] # Include secrets from multiple namespaces [[sources.vault.include]] resource_ids = ["admin/kv/*", "dev/secrets/*", "prod/database/*"] # Exclude test secrets from all namespaces [[sources.vault.exclude]] resource_ids = ["*/test/*", "*/temp/*"] ``` The filtering works seamlessly with the namespace structure, where the resource_id format follows: `namespace/mount/path` ## Configuration To configure GGScout to work with HashiCorp Vault, add the following configuration to your `ggscout.toml` file: ### Token-based Authentication ```toml [sources.vault] type = "hashicorpvault" vault_address = "${VAULT_ADDR}" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" auth.auth_mode = "token" auth.token = "${VAULT_TOKEN}" # Optional: Limit to specific namespaces (Vault Enterprise and HCD only) namespaces = ["admin", "prod", "shared"] # Standard filtering (works on all editions including Vault Community Edition) [[sources.vault.include]] resource_ids = ["app/*", "database/*", "api-key"] # Namespace-aware filtering (Vault Enterprise and HCD only) [[sources.vault.include]] resource_ids = ["admin/kv/my_app/*", "prod/secrets/database/*"] [[sources.vault.exclude]] resource_ids = ["*/test/*", "*/temp/*", "dev/old-secret"] ``` ### HashiCorp Cloud Dedicated Configuration For HashiCorp Cloud Dedicated environments, the configuration is identical, but the filtering automatically works with namespaces: ```toml [sources.vault_hcd] type = "hashicorpvault" vault_address = "${HCD_VAULT_ADDR}" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" auth.auth_mode = "token" auth.token = "${HCD_VAULT_TOKEN}" # Optional: Limit to specific namespaces namespaces = ["admin", "prod", "shared"] # Namespace-specific filtering [[sources.vault_hcd.include]] resource_ids = [ "admin/kv/my_app/*", # All secrets in admin namespace, kv mount, my_app path "prod/database/credentials/*", # Database credentials in prod namespace "shared/api-keys/*" # Shared API keys across teams ] [[sources.vault_hcd.exclude]] resource_ids = [ "*/test/*", # Exclude test secrets from all namespaces "dev/temp/*", # Exclude temporary secrets in dev namespace "*/legacy/*" # Exclude legacy secrets from all namespaces ] ``` ### Kubernetes Authentication ```toml [sources.vault] type = "hashicorpvault" vault_address = "${VAULT_ADDR}" fetch_all_versions = true mode = "read" env = "production" owner = "devops-team@example.com" auth.auth_mode = "k8s" auth.k8s.service_account = "${KUBERNETES_SERVICE_ACCOUNT}" auth.k8s.namespace = "${KUBERNETES_NAMESPACE}" auth.k8s.role = "${KUBERNETES_ROLE}" [[sources.vault.include]] resource_ids = ["app/*", "database/*", "api-key"] [[sources.vault.exclude]] resource_ids = ["test/*", "temp/*", "old-secret"] ``` ### Configuration Parameters | Parameter | Description | Required | Default Value | | -------------------- | ------------------------------------------- | -------- | ------------- | | `type` | Must be set to `"hashicorpvault"` | Yes | | | `vault_address` | The address of your Vault server | Yes | | | `fetch_all_versions` | Whether to collect all versions of secrets | Yes | | | `namespaces` | List of Vault namespaces to fetch from (Vault Enterprise and HCD only). If not specified, fetches from all accessible namespaces | No | All accessible namespaces | | `mount_type` | Secret engine type of the pinned mount(s): `"kv-v1"` or `"kv-v2"`. When set, ggscout uses the declared type and skips `sys/*` mount-detection. Only applies when `include`/`path` pins the mount(s). | No | Auto-detected | | `auth.auth_mode` | Authentication mode (e.g., "token", "k8s") | Yes | | | `mode` | Integration mode (one of: "read", "write", "read/write") | No | "read" | | `env` | Environment label for categorizing secrets (e.g., "production", "staging", "development") | No | | | `owner` | Owner of this source (an email, usually of an employee or a team) | No | | | `[[sources..include]]` | Table of resource_id patterns to include (see below) | No | | | `[[sources..exclude]]` | Table of resource_id patterns to exclude (see below) | No | | With additional parameters depending on the chosen authentication mode: For Token-based Authentication: | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `auth.token` | The Vault authentication token | Yes | | For Kubernetes Authentication: | Parameter | Description | Required | Default Value | |-----------|-------------|----------|-------------| | `auth.k8s.service_account` | The Kubernetes service account | Yes | | | `auth.k8s.namespace` | The Kubernetes namespace | Yes | | | `auth.k8s.role` | The Kubernetes role | Yes | | ### Environment Variables - `VAULT_ADDR`: The address of your Vault server (e.g., `http://localhost:8200`) For Token-based Authentication: - `VAULT_TOKEN`: Your Vault authentication token For Kubernetes Authentication: - `KUBERNETES_SERVICE_ACCOUNT`: The Kubernetes service account - `KUBERNETES_NAMESPACE`: The Kubernetes namespace - `KUBERNETES_ROLE`: The Kubernetes role ## Skipping mount detection with `mount_type` ggscout auto-detects each mount's KV engine version, so this is optional — see [Required Vault Policies](#required-vault-policies) below for why no `sys/*` access is needed. Declaring the type with `mount_type` skips detection entirely, which helps when your token is denied `sys/*` or when you want to avoid extra calls on every scheduled run: ```toml [sources.vault] type = "hashicorpvault" vault_address = "${VAULT_ADDR}" mount_type = "kv-v1" # or "kv-v2" auth.auth_mode = "token" auth.token = "${VAULT_TOKEN}" # mount_type only applies when an include pattern (or the deprecated `path`) pins the mount: [[sources.vault.include]] resource_ids = ["secret/app/*"] ``` :::info `mount_type` only takes effect when a mount is pinned by an `include` pattern (or the deprecated `path`). If no mount is pinned, ggscout falls back to auto-detection. The value applies to every mount the filters pin, so use it when those mounts share the same engine version. ::: ## Required Vault Policies GGScout needs permission to **read the secrets you want to inventory**. It detects the KV engine type and version automatically (using the same per-path lookup as the `vault kv` CLI), so granting **`sys/mounts` is not required**. How broad the policy needs to be depends on whether you collect a whole mount or scope to a specific `path`. For write modes (`mode = "write"` or `"read/write"`), also grant `create` and `update` on the `data` paths. ### Collect a whole mount The simplest option — grant access across the mount: ```hcl # KV2 path "secret/metadata/*" { capabilities = ["read", "list"] } path "secret/data/*" { capabilities = ["read"] } # KV1 path "secret/*" { capabilities = ["read", "list"] } ``` ### Scope to a specific path (least privilege) When you set a `path` (or an include filter), grant access only to that path. GGScout collects it whether the path is a **folder** of secrets or a **single secret** — no access to the rest of the mount (or to `sys/mounts`) is needed. **A folder** — every secret under a path, e.g. `path = "secret/app/team"`: ```hcl # KV2 path "secret/metadata/app/team" { capabilities = ["list"] } path "secret/metadata/app/team/*" { capabilities = ["read", "list"] } path "secret/data/app/team/*" { capabilities = ["read"] } ``` **A single secret**, e.g. `path = "secret/app/db-creds"`: ```hcl # KV2 path "secret/metadata/app/db-creds" { capabilities = ["read"] } path "secret/data/app/db-creds" { capabilities = ["read"] } ``` For **KV1**, drop the `data/` and `metadata/` segments (e.g. `path "secret/app/team/*"`). ### For HashiCorp Cloud Dedicated & Enterprise (with Namespaces) When using HCD or Vault Enterprise with namespaces, policies are scoped to the namespace where they are created. Each namespace has its own policy space, and you create policies within specific namespaces rather than using wildcards to match across namespaces. For namespace-specific policies, you would create policies within each namespace: ```hcl # Policy created within the 'admin' namespace for KV2 secrets path "kv/data/*" { capabilities = ["read", "list"] } path "kv/metadata/*" { capabilities = ["read", "list"] } # Policy for specific paths within a namespace using the + wildcard path "kv/data/my_app/+/config" { capabilities = ["read", "list"] } path "kv/metadata/my_app/+/config" { capabilities = ["read", "list"] } ``` :::info When working with namespaces, policies are created and managed within each namespace's scope. The `+` wildcard character can be used within path segments as documented in the [HashiCorp Vault Policies documentation](https://developer.hashicorp.com/vault/docs/concepts/policies), but cross-namespace policy wildcards are not supported. For more information about namespaces, see the [HashiCorp Vault Namespace documentation](https://developer.hashicorp.com/vault/docs/enterprise/namespaces). ::: ## Best Practices 1. **Use environment variables** for sensitive values like `auth.token` 2. **Leverage namespace filtering** in Vault Enterprise and HCD environments to precisely control which secrets are collected 3. **Consider using path restrictions** to limit the scope of secret collection 4. **Enable `fetch_all_versions`** to track changes in your secrets over time 5. **Use a dedicated service account** with minimal required permissions 6. **For HCD environments**, take advantage of the automatic namespace inclusion in resource_ids for fine-grained filtering 7. **Use wildcard patterns** like `*/test/*` to exclude test secrets across all namespaces --- ## ggscout for self-hosted installations The GitGuardian Self-Hosted deployment comes with a ready-to-use Helm chart that you can use to deploy ggscout alongside your Self-Hosted instance. The following procedure will help you deploy and configure ggscout. :::success **No secrets get out of your environment!** Secrets values will never leave your environment in clear! Secrets values are hashed using the [HMSL hashing algorithm](https://blog.gitguardian.com/hasmysecretleaked-building-a-trustless-and-secure-protocol/) before they are sent to your GitGuardian self-hosted instance. Other non-sensitive metadata like the secret names, paths in the vault, creation date, lease time, etc... are also collected to help you in the remediation process. Find **[instructions on how to run ggscout in audit mode](./what-is-ggscout#keep-full-authority-on-ggscout-execution)** to review what is sent to GitGuardian. ::: ggscout also works in Airgap mode. Follow the [Airgap documentation](../self-hosting/installation/airgap-installation-existing-cluster-helm) to ensure all necessary images are available in your private registry. ### Helm-based installation 1. Create a Service Account Token in GitGuardian Navigate to **Settings > Service accounts** and generate a token with NHI permissions. ![Scout SAT](/img/ggscout/scout-sat.png) 2. Create a kubernetes secret to store the GitGuardian SAT and your sources authentication token (e.g. Hashicorp Vault token, ... ) To create or update the secrets, you directly use Kubernetes Secrets API. Create `secrets.yaml` with the following content (replacing the values with your secrets): ```yaml apiVersion: v1 kind: Secret metadata: name: gitguardian-ggscout-secrets stringData: GITGUARDIAN_API_KEY: "my_gitguardian_api_key" HASHICORP_VAULT_TOKEN: "my_vault_token" ``` To apply the secrets to your cluster/namespace, run the following command: `kubectl apply -f secrets.yaml -n ` 3. Configure ggscout in Self-Hosted helm value file ggscout is a sub chart of GitGuardian Self-Hosted chart. All the configuration for ggscout happens under `ggscout`. Follow documentation on [https://github.com/GitGuardian/ggscout-helm-charts](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples). The GitGuardian endpoint is automatically computed based on your current instance but you can run it in a different namespace and specify the GitGuardian endpoint. Update your Helm value file with the following configuration steps: Use the [examples provided in the Scout GitHub repository](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples). If you deploy over an OpenShift cluster, check [OpenShift installation](../self-hosting/installation/openshift). Example with Hashicorp Vault: ```yaml ggscout: enabled: true # to activate the ggscout sub-chart inventory: config: sources: hashicorpvault: # example of Hashicorp vault secrets collector type: hashicorpvault vault_address: https://vault.example.com # Replace with the actual Vault address auth: auth_mode: "token" token: "${HASHICORP_VAULT_TOKEN}" fetch_all_versions: false # Fetch all versions of secrets or not gitguardian: # Pushes the inventory to the GitGuardian workspace. If the endpoint is empty, it will not push the inventory details. endpoint: 'https:///exposed/v1' # optional; if not specified, the current self-hosted GitGuardian instance URL will be used api_token: "${GITGUARDIAN_API_KEY}" jobs: # Job to fetch defined sources fetch: enabled: true schedule: '*/15 * * * *' send: true # send hashed secrets to GitGuardian # Job to be able to sync/write secrets from GitGuardian into you vault sync: enabled: true schedule: '* * * * *' envFrom: - secretRef: name: gitguardian-ggscout-secrets ``` 4. Use the `helm upgrade` command and specify the same version as the one currently installed to prevent unwanted upgrades to the latest version. To find the release name and the version currently installed, use `helm ls`: ```bash helm ls NAME UPDATED STATUS CHART APP VERSION 2025-03-20 12:40 deployed gitguardian-2025.3.0 2025.3.0 ``` Here, the version installed is `2025.3.0`. To install ggscout, you would run the following command, using the version installed in your environment: ```bash helm upgrade -n oci://registry.replicated.com/gitguardian/gitguardian --version 2025.3.0 -f local-values.yaml ``` Replace `` with the name used during the initial installation. If needed, specify the Kubernetes namespace with `-n` (the default namespace is used if not specified). ### KOTS-based installation 1. Create a Service Account Token in GitGuardian Navigate to **Settings > Service accounts** and generate a token with NHI permissions. ![Scout SAT](/img/ggscout/scout-sat.png) 2. Enable and configure ggscout in the [KOTS Admin Console](../self-hosting/management/infrastructure-management/admin-console). Currently, the only available source is HashiCorp Vault. If you'd like to configure other [sources](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples), please contact support@gitguardian.com. ![Scout KOTS Configuration](/img/ggscout/scout-kots-config.png) --- ## Secret synchronization The `sync-secrets` command allows ggscout to receive secrets from your GitGuardian platform and write them directly into your integrated secrets managers. This enables a secure way to provision secrets discovered elsewhere into your vault infrastructure. ## How sync-secrets Works 1. **GitGuardian identifies unvaulted secrets** in your monitored sources 2. **You mark secrets for vaulting** through the GitGuardian platform 3. **ggscout receives sync instructions** from GitGuardian when running `sync-secrets` 4. **ggscout writes the secrets** to your configured destination integrations ## Example Workflow 1. **Secret Discovery**: GitGuardian finds a leaked secret in your code. Thanks to the inventory provided by ggscout, you can see that this secret is not vaulted. 2. **Platform Review**: Security team reviews the secret in GitGuardian platform 3. **Mark for Vaulting**: Team marks the secret to be moved to HashiCorp Vault 4. **Automatic Sync**: ggscout `sync-secrets` command receives the instruction 5. **Vault Writing**: Secret is securely written to the specified Vault path 6. **Confirmation**: GitGuardian platform is notified of successful vaulting ## Requirements To use the `sync-secrets` command, you need: - **GitGuardian API token with `nhi:write-vault` scope** - See [GitGuardian Authentication](./configure-ggscout#1-gitguardian-authentication) for setup instructions - **Integration configured in `read/write` or `write` mode** - Only [certain integrations](#integration-write-support) support writing - **Proper write permissions** in your destination secrets manager ## Command Usage ```bash # Write secrets from GitGuardian directly into your destination integration ggscout sync-secrets config.toml ``` The sync-secrets command is typically run on a schedule (every minute in production deployments) to ensure secrets are synchronized promptly when requested through the GitGuardian platform. ## Integration Write Support Not all integrations support writing secrets. The table below shows which integrations support the `sync-secrets` command: | Integration Type | Integration Name | Write Support | Notes | |------------------|------------------|---------------|-------| | **Secrets Managers** | HashiCorp Vault (`hashicorpvault`) | ✅ Yes | Full read/write support | | | AWS Secrets Manager (`awssecretsmanager`) | ✅ Yes | Full read/write support | | | CyberArk Secrets Manager SaaS (`cyberarksaas`) | ✅ Yes | Full read/write support | | | CyberArk Secrets Manager Self-Hosted (`cyberarkselfhosted`) | ✅ Yes | Full read/write support | | | Akeyless (`akeyless`) | ✅ Yes | Full read/write support | | | Delinea Secret Server (`delineasecretserver`) | ✅ Yes | Full read/write support | | | Azure Key Vault (`azurekeyvault`) | ❌ No | Read-only support | | | Google Secret Manager (`googlesecretsmanager`) | ❌ No | Read-only support | | **CI/CD Systems** | GitLab CI (`gitlabci`) | ❌ No | Read-only support | | **Infrastructure** | Kubernetes (`kubernetes`) | ❌ No | Read-only support | :::info Integrations that don't support writing can still be used for secret discovery and monitoring with the `fetch` and `fetch-and-send` commands. ::: ## Configuration Example To enable writing, set the integration mode to `read/write` or `write`: ```toml [sources.my-vault] type = "hashicorpvault" vault_address = "https://vault.example.com" mode = "read/write" # Enables both reading and writing # ... other configuration options ``` ## Deployment Considerations ### Scheduling The `sync-secrets` command should run frequently to ensure timely secret provisioning: - **Production**: Every minute (`* * * * *`) - **Development**: Every 5 minutes (`*/5 * * * *`) ### Error Handling ggscout handles various error scenarios gracefully: - **Permission errors**: Logged with details for debugging - **Already exists**: Can be configured as recoverable or non-recoverable - **Network issues**: Retry logic with exponential backoff - **Invalid data**: Clear error messages for troubleshooting ## Troubleshooting ### Common Issues **Authentication Failures** - Verify the GitGuardian API token has `nhi:write-vault` scope - Check that integration credentials have write permissions **Permission Denied** - Review vault policies and ensure write access to target paths - Verify service account permissions in cloud environments **Secret Already Exists** - Configure error handling policy for duplicate secrets - Review vault versioning settings **Network Connectivity** - Ensure ggscout can reach both GitGuardian platform and destination vault - Check firewall rules and network policies ### Debug Mode Enable debug logging for detailed troubleshooting: ```bash ggscout sync-secrets config.toml --verbose debug ``` This provides detailed information about: - API calls to GitGuardian platform - Authentication attempts - Write operations to destination vaults - Error details and stack traces --- ## What is ggscout? GitGuardian Scout (ggscout) is a command-line application that collects secrets and their metadata from your Secrets Managers and synchronizes this data with your GitGuardian platform. ## Why Collect Secrets? When a secret is leaked in your code repository or exposed in your infrastructure, a critical question arises: **Is this secret currently in use, and where?** Without an inventory of your production secrets, answering this question is time-consuming and error-prone. ggscout solves this problem by: 1. **Creating an inventory** of secrets stored in your Secrets Managers (HashiCorp Vault, AWS Secrets Manager, etc.) 2. **Classifying each value** with the [Secrets Detection Engine](/secrets-detection/secrets-detection-engine/detectors/introduction) before hashing 3. **Hashing these secrets** locally using the [HMSL algorithm](https://blog.gitguardian.com/hasmysecretleaked-building-a-trustless-and-secure-protocol/): secrets never leave your infrastructure in clear text 4. **Reconciling** this inventory with secrets detected by GitGuardian in your codebase or other sources This reconciliation enables three key capabilities: ### 1. Extend Detection Coverage By maintaining an inventory of vaulted secrets, you can detect when these secrets are compromised elsewhere in your perimeter. When GitGuardian detects a leaked secret, it can immediately tell you if it matches a secret currently stored in your vault. **Example**: A developer accidentally commits an API key to a public repository. With ggscout, you instantly know this key is from your production HashiCorp Vault and which application uses it. ### 2. Improve Incident Prioritization Vaulted secrets come with valuable metadata: vault paths, lease times, rotation policies, associated applications, and environments. This context helps you prioritize which incidents to remediate first. **Example**: Two secrets are leaked. One has a 90-day lease and is only used in a development environment. The other has a 365-day lease and is used by a production payment service. The metadata from ggscout helps you prioritize the production secret first. ### 3. Bootstrap Incident Remediation By identifying secrets that are **not** in your vault (unvaulted secrets), ggscout can help you secure them. It can automatically push unvaulted secrets into your Secrets Manager, providing your developers with the vault path to update their code. **Example**: GitGuardian detects a hardcoded database password in an old repository. Using ggscout, you can push this secret to your vault and provide developers with the exact path to reference it, streamlining the remediation process. :::success **No secrets get out of your environment!** Secrets values will never leave your environment in clear! Secrets values are hashed using the [HMSL hashing algorithm](https://blog.gitguardian.com/hasmysecretleaked-building-a-trustless-and-secure-protocol/) before they are sent to your GitGuardian workspace. Other non-sensitive metadata like the secret names, paths in the vault, creation date, lease time, etc... are also collected to help you in the remediation process. ::: ## Safely collect secrets to ease incident remediation Once you deployed and configured ggscout in your environment, it runs as follows: 1. It collects the secrets and associated metadata from the Secrets Managers you configured. 2. It classifies each value with the Secrets Detection Engine. 3. It hashes the secrets using the [HMSL hashing algorithm](https://blog.gitguardian.com/hasmysecretleaked-building-a-trustless-and-secure-protocol/). 4. It sends the collected data to GitGuardian and reconciles it with existing secrets incidents. ![Scout Flow](/img/ggscout/scout-flow.png) That’s it, you can start leveraging these capabilities from your GitGuardian Platform! ## Classify secrets with the Secrets Detection Engine {#classify-secrets-with-the-secrets-detection-engine} Before hashing, ggscout runs each collected value through the same [Secrets Detection Engine](/secrets-detection/secrets-detection-engine/detectors/introduction) used for code scanning: 600+ specific and generic detectors. Classification is based on the **value**, not only the key name. A secret stored under a generic name such as `CONFIG_3` is recognized if the value matches a detector. A key named `MY_TOKEN` whose value is `disabled` is not treated as a credential. When a detector matches, ggscout attaches that detector to the secret. GitGuardian then derives detector type (generic or specific), secret family, category, and provider, and surfaces them in the [NHI inventory](/nhi-governance/discover-your-nhis). Values that match no detector are still inventoried and labeled **Unknown**. Nothing is dropped. ggscout also handles values that contain more than one secret: - A plain-text file such as a `.env` is split into one inventory entry per detected secret, each with its own hash, so it can be correlated with leaks of those tokens. - Sibling fields that form one credential (for example a username and password in the same vault object) are classified together. :::warning Requires ggscout 0.32.0 or later You must run **ggscout 0.32.0 or later** for classification to appear in NHI Governance. Pin Docker images and Helm charts to that version or to `latest` after it ships. Classification is always on: there is nothing to enable in `ggscout.toml`. ::: ## Safely store unvaulted secrets With ggscout, you will be able to identify unvaulted secrets from your incidents list. What’s more, you will also be able to push these secrets to your Secret Managers and bootstrap the remediation of these incidents! Here is the standard scenario: - Once a secret incident is prioritized, you can insert the secret within your Secrets Manager - Your developers fix their code by properly invoking the secret from the right path provided in the Secret Incident detail - Once the code fixing is done, revoke the right secret from the vault using the hyperlink provided in the Secret Incident detail ggscout supports this entire process using the following simple flow: 1. ggscout retrieves the secret incident that has not yet been vaulted. 2. ggscout writes the secret to the specified location. ![Push-to-Vault](/img/ggscout/push-to-vault.png) :::success This capability is optional You can choose not to grant write access. You can also restrict the locations where the scout can write secrets (e.g., a temporary path specific to ggscout). ::: ## Keep full authority on ggscout execution :::success Transparency matters! No sensitive information ever leaves your infrastructure. ::: Having an external program like ggscout allows you to: - Have your team control its execution and accesses (e.g. having partial accesses, having one instance for read access and another for write access) - Have your team monitor what data is being processed ggscout is auditable. - You can run the fetch-only mode and write a JSON report on your disk so that you can audit the data collected by ggscout, and ensure no secret values in clear are collected. The data available in the report is exactly the data sent to the GitGuardian in default mode. - You can request access to the source code ## Getting Started Ready to try ggscout? Head over to the [Deploy and configure ggscout](./configure-ggscout) page, which includes a Quick Start guide for local testing with the CLI binary or Python package, as well as production deployment options using Docker or Kubernetes. ## No GitGuardian Platform Access? If you are deploying ggscout in a Kubernetes cluster but lack access to the GitGuardian platform, preventing you from sending the hashed secrets, **ggbridge** is the solution. It establishes a secure, mTLS-authenticated gateway between your network and the GitGuardian platform, enabling ggscout to communicate with the GitGuardian public API and transmit the inventory data. For detailed setup instructions and additional information, please refer to the [ggbridge documentation](https://github.com/GitGuardian/ggbridge/tree/main/examples/ggscout). --- ## Configuration ## Dependencies between the dashboard and ggshield The following paragraph describes how the GitGuardian REST API and ggshield (CLI) work in relation to the dashboard and how you can customize the dashboard experience to best fit your approach to secrets scanning in developer workflows. Here is the complete list of settings and interactions between the dashboard and the API or CLI: - **Ignored secret incidents** Secrets for which the related incident has been ignored on your GitGuardian dashboard will no longer be raised by ggshield. - **Resolved secret incidents** If the [Regression setting is OFF](https://dashboard.gitguardian.com/settings/workspace/general), secrets for which the related incident has been resolved on your GitGuardian dashboard will no longer be raised by ggshield. However, if the Regression setting is turned ON, ggshield will raise them. - **Disabled/enabled detectors** Secrets associated with detectors you have disabled on your GitGuardian dashboard will not be raised by ggshield. - **Activated/de-activated validity checks for secret** ggshield follows the [validity check setting](../secrets-detection/customize-detection/validity-checks#enabling-and-disabling-validity-checks) of your GitGuardian dashboard. If this setting is turned OFF, ggshield will no longer perform validity checks, and neither will your dashboard. - **Filepath exclusions** Secrets found in a [filepath excluded on your GitGuardian dashboard](../secrets-detection/customize-detection/exclusion-rules#filepath-exclusions) will not be raised by ggshield. **For each secret found with ggshield, we indicate whether it is known by your GitGuardian dashboard**. If a secret incident already exists on your GitGuardian dashboard, ggshield will also print the URL of the associated secret incident to your console. This information can be leveraged by using the [`--ignore-known-secrets` option](./reference/secret/scan/overview.md), which makes ggshield ignore secrets that are already known to your dashboard. ## General Configuration When it comes to configuration, you can fine-tune ggshield's behavior using three sources of parameters. From higher priority to lower priority: - CLI options - Environment variables - Configuration files This means that CLI options override environment variables, which override settings set in configuration files. ### CLI options A few configuration parameters are available as CLI options. We recommend using `--help` with the command you intend to use to get more insights on what behaviors can be configured this way. ### Environment Variables Some of ggshield's behaviors can be tuned via environment variables. When starting up, ggshield will attempt to load environment variables from different environment files in the following order: - the file pointed by the `GITGUARDIAN_DOTENV_PATH` environment variable. - A `.env` file at the current working directory. - A `.env` file at the root of the current git directory. Only one of the env files will be loaded out of the three. #### List of supported environment variables - `GITGUARDIAN_API_KEY`: API Key for the GitGuardian API. Use this if you don't want to use the `ggshield auth` commands. - `GITGUARDIAN_INSTANCE`: Custom URL of the GitGuardian dashboard. The API URL will be inferred from it. - `GITGUARDIAN_DONT_LOAD_ENV`: If set to any value then environment variables won't be loaded from a file. - `GITGUARDIAN_DOTENV_PATH`: If set to a path, ggshield will attempt to load the environment from the specified file. - `GITGUARDIAN_TIMEOUT`: If set to a float, `ggshield secret scan pre-receive` will timeout after the specified value. Set to 0 to disable the timeout. - `GITGUARDIAN_MAX_COMMITS_FOR_HOOK`: If set to an int, `ggshield secret scan pre-receive` and `ggshield secret scan pre-push` will not scan more than the specified value of commits in a single scan. - `GITGUARDIAN_CRASH_LOG`: If set to True, ggshield will display a full traceback when crashing. - `GITGUARDIAN_LOG_FILE`: If set to a file, ggshield will send log output to it. You can also set it to `-` to send output to stderr. Equivalent to the [`--log-file` option](reference/overview#options). ### Configuration files Configuration files selection in `ggshield` follows a global to local hierarchy. `ggshield` will first search for a **global** configuration file in the user's home directory: - `~/.gitguardian.yaml` on Linux or MacOS - `%USERPROFILE%\.gitguardian.yaml` on Windows `ggshield` will then search for a **local** configuration file in the current working directory (i.e.: `./.gitguardian.yaml`). Alternatively, the `--config-path` or `-c` option can be used to specify a custom configuration file: ```shell ggshield --config-path ~/Desktop/custom_config.yaml secret scan path -r . ``` In this case, neither local nor global configuration files will be evaluated. Here is a sample configuration file: ```yml # Required, otherwise ggshield considers the file to use the deprecated v1 format version: 2 # Set to true if the desired exit code for the CLI is always 0, otherwise the # exit code will be 1 if incidents are found. exit_zero: false # default: false verbose: false # default: false instance: https://dashboard.gitguardian.com # default: https://dashboard.gitguardian.com # Maximum commits to scan in a hook. max_commits_for_hook: 50 # default: 50 # Disable SSL/TLS certificate verification (not recommended). # Was called `allow_self_signed` before. insecure: false # default: false secret: # Exclude files and paths by globbing ignored_paths: - 'LICENSE' # exact file at the root - '*.log' # all .log files in the root directory - 'doc/*' # all files directly inside doc/ - 'tests/**/*' # all files anywhere inside tests/ - '**/*.generated.ts' # all .generated.ts files in any directory - '**/README.md' # all README.md files in any directory # Ignore security incidents with the SHA256 of the occurrence obtained at output or the secret itself ignored_matches: - name: match: 530e5a4a7ea00814db8845dd0cae5efaa4b974a3ce1c76d0384ba715248a5dc1 - name: credentials match: MY_TEST_CREDENTIAL show_secrets: false # default: false ignore_known_secrets: false # default: false # Detectors to ignore. ignored_detectors: # default: [] - Generic Password ``` ## Support for self-signed certificates If your network access requires self-signed certificates, the recommended approach is to install your certificate in your system's trust store. With Python 3.10 or later, ggshield automatically uses the system trust store, providing secure certificate validation. If you can't use Python 3.10, the alternative is to use the `insecure: true` option, but this is not recommended because it skips all certificate validation checks. This means your connection to the GitGuardian API is vulnerable to man-in-the-middle (MITM) attacks. API keys, scanned content and results can be intercepted and modified. ## Size limits and API call volume considerations `ggshield` relies on the GitGuardian API to perform secret scanning. The maximum size for a document that can be scanned is 1MB. Any files larger than 1MB will be ignored. Using the `--verbose` option will show information about any files skipped when performing a secret scan. The GitGuardian API limits batches of files per call to a maximum of 20 documents. If a repository or folder contains more than 20 documents, `ggshield` will bundle files into groups of 20 or fewer to be scanned per API call. Scanning repositories containing more than 20 documents will result in multiple API calls. You can explore this topic further in the [GitGuardian API reference documentation](https://api.gitguardian.com/docs#tag/Scan-Methods). ## Specificities for on-premise configuration `ggshield` can also be configured to run on your on-premise GitGuardian instance. First, you need to point ggshield to your instance, by either defining the `instance` key in your `.gitguardian.yaml` configuration file or by defining the `GITGUARDIAN_INSTANCE` environment variable. Then, you need to authenticate against your instance using the `ggshield auth login --instance https://mygitguardianinstance.mycorp.local` command using the `--instance` option, or by obtaining an API key from your dashboard administrator and storing it in the `GITGUARDIAN_API_KEY` environment variable. --- ## Getting started(Ggshield-docs) ![](https://cdn.jsdelivr.net/gh/gitguardian/ggshield/doc/logo.svg) `ggshield` is a CLI application that runs in your local environment or in a CI environment to help you detect 600+ types of secrets. > ggshield is open source on GitHub and accessible [here](https://github.com/GitGuardian/ggshield). `ggshield` can run: - **in your local environment** to scan local files and repositories or as a pre-commit hook. - **in a CI environment**, - **in a pre-receive hook**, if you have a self-managed VCS instance **Note :** `ggshield` uses our [public API](https://api.gitguardian.com/docs) through [py-gitguardian](../platform/gitguardian-suite/python-sdk.md) to scan files. Only metadata such as call time, request size and scan mode is stored when launching a scan with ggshield, therefore secrets incidents will not be displayed on your dashboard and **your files and secrets won't be stored**. ## Step 1: Install ggshield ### Requirements `ggshield` works on macOS, Linux and Windows. It requires **a supported version of Python (not EOL)** (except for standalone packages) and git. `ggshield` follows the [Python release cycle](https://devguide.python.org/versions/) and does not support versions that have reached EOL. Some commands require additional programs: - docker: to scan docker images. - pip: to scan pypi packages. ### Install script (Recommended) The quickest way to install `ggshield`. The script also runs the [`ggshield auth login`](#option-1-automatically) command, so installation and authentication happen in one step. Linux / macOS: ```shell curl -sSfL \ https://raw.githubusercontent.com/GitGuardian/ggshield/main/scripts/install/install.sh | bash ``` Windows (PowerShell): ```powershell irm https://raw.githubusercontent.com/GitGuardian/ggshield/main/scripts/install/install.ps1 | iex ``` Or, if you prefer `curl` (bundled with Windows 10+): ```powershell curl.exe -sSL https://raw.githubusercontent.com/GitGuardian/ggshield/main/scripts/install/install.ps1 | powershell -NoProfile -ExecutionPolicy Bypass -Command - ``` The script accepts options such as `--instance` and `--plugin` (install a plugin). For the EU workspace or a self-hosted instance, set the `GITGUARDIAN_INSTANCE` environment variable (or pass `--instance `) before running. See [`scripts/install/README.md`](https://github.com/GitGuardian/ggshield/blob/main/scripts/install/README.md) for the full list of options, the other install methods, and how to uninstall. The methods below install the CLI manually instead. ### macOS #### Homebrew You can install `ggshield` using Homebrew: ```shell brew install ggshield ``` Upgrading is handled by Homebrew. #### Standalone .pkg package Alternatively, you can download and install a standalone .pkg package from [`ggshield` release page](https://github.com/GitGuardian/ggshield/releases). This package _does not_ require installing Python, but you have to manually download new ggshield versions. Package will be installed in `/usr/bin/ggshield` or `/usr/local/bin/ggshield` directory. ### Linux #### Deb and RPM packages Deb and RPM packages are available on [Cloudsmith](https://cloudsmith.io/~gitguardian/repos/ggshield/packages/). Setup instructions: - [Deb packages](https://cloudsmith.io/~gitguardian/repos/ggshield/setup/#formats-deb) - [RPM packages](https://cloudsmith.io/~gitguardian/repos/ggshield/setup/#formats-rpm) Upgrading is handled by the package manager. ### Windows #### Chocolatey `ggshield` is available via the [Chocolatey package manager](https://chocolatey.org/packages/ggshield): ```shell choco install ggshield ``` Upgrading is handled by Chocolatey. #### MSI installer Download the MSI installer from the [`ggshield` release page](https://github.com/GitGuardian/ggshield/releases) and install it: ```powershell msiexec /i ggshield-VERSION-x86_64-pc-windows-msvc.msi ``` #### Standalone .zip archive We provide a standalone .zip archive on the [`ggshield` release page](https://github.com/GitGuardian/ggshield/releases). Unpack the archive on your disk, then add the directory containing the `ggshield.exe` file to `%PATH%`. This archive _does not_ require installing Python, but you have to manually download new versions. ### All operating systems `ggshield` can be installed on all supported operating systems via its [PyPI package](https://pypi.org/project/ggshield). #### Using pipx The recommended way to install `ggshield` from PyPI is to use [pipx](https://pipx.pypa.io), which will install it in an isolated environment: ```shell pipx install ggshield ``` To upgrade your installation, run: ```shell pipx upgrade ggshield ``` #### Using pip You can also install `ggshield` from PyPI using pip, but this is not recommended because the installation is not isolated, so other applications or packages installed this way may affect your `ggshield` installation. This method will also not work if your Python installation is declared as externally managed (for example when using the system Python on operating systems like Debian 12): ```shell pip install --user ggshield ``` To upgrade your installation, run: ```shell pip install --user --upgrade ggshield ``` ## Step 2: Authenticate with your GitGuardian workspace `ggshield` requires an API key to authenticate the CLI with your GitGuardian workspace. There are 2 different types of API keys: - **Service Accounts:** a special type of token 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. - **Personal Access Tokens:** a token intended for the use of the GitGuardian API and command-line application ggshield by individual developers on their local workstations (e.g. pre-commit or pre-push git hooks). :::note If you installed `ggshield` with the [install script](#install-script-recommended), it already authenticated you — you can skip this step. ::: ### Option 1: Automatically If you want to set up **ggshield for use on your local workstation (e.g. to scan repos or in a pre-commit or pre-push git hook)**, we recommend running the following command: ```shell ggshield auth login ``` This will open a new window in your web browser. Simply follow the steps to login to your workspace (or create a new account) and GitGuardian will automatically provision a personal access token and store it in your configuration. You can find more details in the [login command reference section](./reference/auth/login). ### Option 2: Manually You can also provision your API key manually. This is useful when you want to set up **ggshield in your CI environment** for example. #### Create your API key To create your API key manually, please follow the steps described in the [API authentication section](../api-docs/authentication.md). Once you have your API key ready, follow the rest of the guide on this page. #### Source your API key in your environment Alternatively, you can create your personal access token manually and store it in the `GITGUARDIAN_API_KEY` environment variable to complete the setup. If you're using an on-premise version of GitGuardian, you also need to set the `GITGUARDIAN_INSTANCE` environment variable with your on-premise instance URL (eg: `https://dashboard.gitguardian.mycorp.local`). ## Step 3: Scan your first content with ggshield You can scan one of your repositories for secrets with the following command: ```shell ggshield secret scan repo /path/to/your/repo ``` You can also run `ggshield -h` to get help on the CLI. ## Go further with ggshield > If you are looking to configure a CI/CD integration, take a look at our [CI/CD Integrations page](./integrations/overview#cicd-integrations-secrets-detection-in-your-cicd-workflow). > If you are looking to use GitGuardian at the git hooks level (pre-commit, pre-receive), take a look at our [Git hooks documentation page](./integrations/overview#git-hooks-prevent-secrets-from-reaching-your-vcs). > If you want to scan a whole workstation or server (secrets that live *outside* Git, like `~/.aws` credentials, SSH keys, and `.env` files), take a look at [Endpoint Protection](../endpoint-protection/getting-started.md): Machine Scan, the `ggshield machine` plugin you can set up in two steps. *Limited to Business accounts.* --- ## Secret scanning for AI coding tools Developers increasingly rely on AI coding tools like Cursor, Claude Code, and Codex to write and modify code. These tools can inadvertently expose secrets: a developer might paste credentials into a prompt, or the AI agent might read a file or run a command that contains API keys or tokens. Once a secret reaches the AI model, it may be logged, cached, or sent to third-party services. `ggshield` integrates with AI coding tools through their hook systems to scan interactions in real time. When a secret is detected, ggshield blocks the action before it reaches the model and tells the developer to remove the secret. ## How it works AI coding tools support hooks: custom commands that run at specific points during an AI interaction. `ggshield` registers as a hook and scans content at three stages: | Stage | What it does | Behavior | |-------|-------------|----------| | **Prompt submission** | Scans the user's prompt before it is sent to the AI model | Blocks the prompt if secrets are found | | **Pre-tool use** | Scans commands, file reads, and MCP calls before the AI executes them | Blocks the action if secrets are found | | **Post-tool use** | Scans tool outputs after execution | Sends a desktop notification if secrets are found | `ggshield` uses the same detection engine as all other scanning commands, covering 600+ types of secrets. ## Prerequisites - `ggshield` version 1.53.0 or later for `ggshield machine setup` (hooks themselves work from 1.49.0, 1.51.0 for Codex, and 1.54.0 for Mistral Vibe) - A GitGuardian API key (see [Getting started](/ggshield-docs/getting-started)) - One of the supported AI coding tools: Cursor, Claude Code, Codex, Copilot CLI, VS Code, or Mistral Vibe ## Installation One command configures the hook for every AI coding tool on your machine: ```shell ggshield machine setup ``` `machine setup` detects which agents you have installed and writes the correct hook configuration for each one, registering `ggshield` on all three hook stages. It skips agents that are not present, so nothing is written for tools you do not use. The command also installs the git pre-commit and pre-push hooks and plants a honeytoken. To set up the AI hooks alone: ```shell ggshield machine setup --no-git-hooks --no-honeytokens ``` To target specific assistants, use `--agent` or `--exclude-agent`, which accept `claude-code`, `codex`, `copilot`, `cursor`, `vibe`, and `vscode`: ```shell ggshield machine setup --agent cursor --agent claude-code ``` ### Where the hooks are written `machine setup` writes hooks for the current user, in the following files: | Tool | Hook configuration | |---|---| | Cursor | `~/.cursor/hooks.json` | | Claude Code | `~/.claude/settings.json` | | Codex | `~/.codex/hooks.json` | | Copilot CLI and VS Code | `~/.copilot/hooks/hooks.json` | | Mistral Vibe | `~/.vibe/hooks.toml` | Those are Copilot's own hook files rather than an editor's settings, so a single install covers Copilot wherever it runs: the Copilot CLI in a terminal, VS Code, and any other IDE whose Copilot extension runs the Copilot CLI. :::tip `ggshield` merges its hooks into an existing configuration without touching other hooks, so `machine setup` is safe to re-run: it adds what is missing and leaves existing entries alone. It then verifies that it can authenticate to GitGuardian, reports whether the hook is ready to scan, and tells you how to fix it if not. On macOS, this also triggers the system keychain authorization prompt while you can still approve it interactively. ::: ### Installing for a single project To scope hooks to the current repository instead of your whole user account, install per tool with the `local` mode: ```shell ggshield install -t cursor -m local ``` Use `--force` to overwrite ggshield's own hooks, for example if they were customized and you want to reset them. For GitHub Copilot, a `local` install writes to `.github/hooks/hooks.json` in the repository. Prefer the global install: Copilot loads repository hooks only after you confirm folder trust, and skips them in prompt mode (`copilot -p`) unless you opt in through an environment variable. :::note `ggshield install -t ` is deprecated for global installs as of ggshield 1.53.0. It still works, and it remains the way to install git hooks (`-t pre-commit` and `-t pre-push`), but `ggshield machine setup` is now the recommended way to configure AI hooks. ::: :::caution Mistral Vibe only loads project hooks from folders you have marked as trusted, so a `local` install there takes effect once the folder is trusted. ::: ## What the developer sees When `ggshield` detects a secret, the AI coding tool displays a blocking message. For example, in Cursor: > **Detected 1 secret** > - Google API Key (**valid**): AIzaSyC\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*-\*\*\*\*\*\*\*\*\*d5oii7Y > > Please remove the secrets from the content before proceeding. The prompt or action is blocked until the developer removes the secret and retries. For post-tool-use detections (where the action already ran), `ggshield` sends a desktop notification alerting the developer. ## When ggshield cannot scan If `ggshield` cannot scan an interaction — for example because it is not authenticated, the GitGuardian API is unreachable, or its API token cannot be read — it does **not** block the action. Instead, it allows the interaction and shows a warning in the AI coding tool noting that the content was not scanned for secrets, along with how to fix it. This fail-open design keeps your AI coding tool usable when `ggshield` is misconfigured. To restore scanning, follow the remediation in the warning (typically re-authenticating with `ggshield auth login`), then confirm with `ggshield machine doctor`, which reports whether each agent's hook is installed and whether your token can reach GitGuardian. ## Handling false positives If `ggshield` blocks an action on a secret that is a known false positive, you can tell ggshield to ignore it: ```shell ggshield secret ignore --last-found ``` This adds the detected secret to your `.gitguardian.yaml` ignore list. Future scans (including AI hook scans) will skip it. ## Uninstallation To remove the hooks, delete the `ggshield` entries from the tool's configuration file, using the paths listed in [Where the hooks are written](#where-the-hooks-are-written). ## Deploying at fleet scale The commands above set up hooks on one machine. To push them across every developer workstation through your MDM, without asking each developer to opt in, see [Prevent leaks with AI Hooks](/endpoint-protection/ai-hooks). ## See also - [ggshield secret scan ai-hook reference](/ggshield-docs/reference/secret/scan/ai-hook): CLI reference for the underlying scan command - [Getting started with ggshield](/ggshield-docs/getting-started): Installation and authentication --- ## Azure pipelines ## Prelude GitGuardian CI/CD integration with Azure Pipelines is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. > ⚠ Azure Pipelines does not support commit ranges outside of GitHub Pull Requests, therefore on push events in a regular branch only your latest commit will be scanned. > This limitation doesn't apply to GitHub Pull Requests where all the commits in the pull request will be scanned. ## Preview ![Azure Pipelines output](/img/ggshield/cicd-integrations/azure_pipelines/azure-pipelines-secret-scan-ci.png) ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `gitguardianApiKey` secret variable in your pipeline settings. - [How to define secret variables in Azure Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#secret-variables) 3. Add a new job using ggshield to your Azure pipeline ```yaml jobs: - job: GitGuardianShield pool: vmImage: 'ubuntu-latest' container: gitguardian/ggshield:latest steps: - script: ggshield secret scan ci env: GITGUARDIAN_API_KEY: $(gitguardianApiKey) ``` ## Scan all pipelines with the Azure DevOps extension If you want to add ggshield secret scanning to every pipeline in your Azure DevOps organization without editing each one individually, use the ggshield Azure DevOps extension instead. The extension adds a pipeline decorator that automatically injects the ggshield secret scan job into every pipeline run in your organization. It also lets you share a single GitGuardian service account token across all your Azure DevOps CI jobs, instead of configuring a secret variable in each pipeline. :::note Microsoft doesn't allow extensions that use a pipeline decorator to be listed publicly on the Visual Studio Marketplace. Because of this, our extension is only available privately. Contact GitGuardian's support team if you want us to share it with you. ::: --- ## Bitbucket pipelines ## Prelude GitGuardian CI/CD integration with Bitbucket pipeline is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. > ⚠ Bitbucket pipelines do not support commit ranges therefore only your latest commit in a pushed group or in a new branch will be scanned. ## Preview ![Bitbucket pipeline output](/img/ggshield/cicd-integrations/bitbucket_pipelines/bitbucket-pipelines-ggshield-secret-scan-ci.png) ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `GITGUARDIAN_API_KEY` environment variable in your project settings. ![Bitbucket pipelines env](/img/ggshield/cicd-integrations/bitbucket_pipelines/env_variable_setting.png) 3. Add a new step using ggshield to your Bitbucket repository's pipeline. ```yaml stages: - scanning gitguardian scan: image: gitguardian/ggshield:latest stage: scanning script: ggshield secret scan ci ``` > You may be interested in using GitGuardian's [Bitbucket integration](../../../internal-monitoring/integrate-sources/vcs-integrations/bitbucket.md) to ensure full coverage of your Bitbucket repositories as well as full git history scans and reporting. --- ## CircleCI ## Prelude GitGuardian CI/CD integration with CircleCI is performed through our CLI application: [`ggshield`](../../getting-started.md). ggshield is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. CircleCI is supported in `ggshield` through [ggshield-orb](https://github.com/GitGuardian/gg-shield-orb). ## Preview ![CircleCI output](/img/ggshield/cicd-integrations/circle_ci/output.png) ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `GITGUARDIAN_API_KEY` environment variable in your project settings. 3. In order to add ggshield to your pipelines configure your `.circleci/config.yml` add the ggshield orb: ```yaml orbs: ggshield: gitguardian/ggshield workflows: main: jobs: - ggshield/scan: name: ggshield-scan # best practice is to name each orb job base_revision: << pipeline.git.base_revision >> revision: <> ``` --- ## Drone CI ## Prelude GitGuardian CI/CD integration with Drone CI is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. ## Preview ![Drone CI](/img/ggshield/cicd-integrations/drone_ci/drone-ci-ggshield-secret-scan-ci.png) ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `GITGUARDIAN_API_KEY` environment variable in your project settings. It should be available for Drone CI runners. 3. In order to add ggshield to your pipelines, configure your `.drone.yml` to add a ggshield scanning step. ```yml kind: pipeline type: docker name: default steps: - name: ggshield image: gitguardian/ggshield:latest commands: - ggshield secret scan ci ``` --- ## GitHub Actions ## Prelude GitGuardian CI/CD integration with GitHub comes in the form of GitHub Actions and is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. `ggshield` actions are found in the [actions directory](https://github.com/GitGuardian/ggshield/tree/main/actions) of the GitHub repository. **Note:** If you want to ensure full coverage of your GitHub repositories as well as full git history scans and reporting, you may be interested in using GitGuardian's [GitHub integration](../../../internal-monitoring/integrate-sources/vcs-integrations/github.md). ## Preview ![GitHub Actions output](/img/ggshield/cicd-integrations/github_actions/output.png) If there are secret leaks or other security issues in your commit, your workflow will be marked as failed. ![GitHub Actions checks list](/img/ggshield/cicd-integrations/github_actions/checks_list.png) Be sure to add `GitGuardian scan` to your required status checks in your repository settings to stop pull requests with security issues from being merged. ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `GITGUARDIAN_API_KEY` environment variable in your project settings. You can set the `GITGUARDIAN_API_KEY` value in the "Secrets" page of your repository's settings. 3. Add a new job to your GitHub workflow using the GitGuardian/ggshield-action action `.github/workflows/gitguardian`. ### Template for secret scanning ```yaml name: GitGuardian scan on: [push, pull_request] jobs: scanning: name: GitGuardian scan runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 # fetch all history so multiple commits can be scanned - name: GitGuardian scan uses: GitGuardian/ggshield/actions/secret@v1.52.2 env: GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} GITHUB_PULL_BASE_SHA: ${{ github.event.pull_request.base.sha }} GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} ``` --- ## GitLab pipelines ## Prelude GitGuardian CI/CD integration with GitLab CI/CD is performed through our CLI application: [`ggshield`](../../getting-started.md). ggshield is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. **Note:** If you want to ensure full coverage of your GitLab projects as well as full git history scans and reporting, you may be interested in using GitGuardian's [GitLab integration](../../../internal-monitoring/integrate-sources/vcs-integrations/gitlab.md). ## Preview ![GitLab pipelines status](/img/ggshield/cicd-integrations/gitlab_pipelines/status.png) ![GitLab pipelines output](/img/ggshield/cicd-integrations/gitlab_pipelines/gl-pipelines-ggshield-secret-scan-ci.png) ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `GITGUARDIAN_API_KEY` environment variable in your project settings. ![GitLab CI/CD env](/img/ggshield/cicd-integrations/gitlab_pipelines/env_variable_setting.png) 3. Add a new step using ggshield to your GitLab project's pipeline. ```yaml stages: - scanning gitguardian scan: image: gitguardian/ggshield:latest stage: scanning script: ggshield secret scan ci ``` ## Additional notes > For ggshield to scan every commit in a merge request pipeline the CI > must clone the full repository instead of just fetching the branch. > The following snippet ensures this behavior. ```yml variables: GIT_STRATEGY: clone GIT_DEPTH: 0 ``` --- ## Jenkins CI ## Prelude GitGuardian CI/CD integration with Jenkins CI is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. ## Preview ![Jenkins CI status](/img/ggshield/cicd-integrations/jenkins/status.png) ![Jenkins CI output](/img/ggshield/cicd-integrations/jenkins/jenkins-ci-ggshield-secret-scan-ci.png) ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `GITGUARDIAN_API_KEY` environment variable in your project settings. ![Bitbucket pipelines env](/img/ggshield/cicd-integrations/jenkins/env_variable_setting.png) 3. In order to add ggshield to your pipelines configure your `Jenkinsfile` to add a ggshield stage: ```groovy pipeline { agent none stages { stage('GitGuardian Scan') { agent { docker { image 'gitguardian/ggshield:latest' } } environment { GITGUARDIAN_API_KEY = credentials('gitguardian-api-key') } steps { sh 'ggshield secret scan ci' } } } } ``` --- ## Travis CI ## Prelude GitGuardian CI/CD integration with Travis CI is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around the GitGuardian API for secrets detection, an API key is required for authentication. ## Installation > [Service accounts](../../../api-docs/service-accounts.md) are recommended to run this integration. > > Please note that service accounts are only available for workspaces under our Business plan, and their administration is restricted to Managers. If your workspace is under the Free plan, you can still use a [personal access token](../../../api-docs/personal-access-tokens.md) to run this integration. 1. Create a service account from the [API section](https://dashboard.gitguardian.com/workspace/api/service-accounts) of your GitGuardian workspace (or a [personal access token](https://dashboard.gitguardian.com/api/personal-access-tokens) if you are on the Free plan). 2. Add this API key to the `GITGUARDIAN_API_KEY` environment variable in your project settings. 3. In order to add ggshield to your pipelines, configure your `.travis.yml` to add a ggshield scanning job. ```yml jobs: include: - name: GitGuardian Scan language: python python: 3.8 install: - pip install ggshield script: - ggshield secret scan ci ``` For further explanations about how to define encrypted variables in Travis CI, please read [their documentation](https://docs.travis-ci.com/user/environment-variables/#defining-encrypted-variables-in-travisyml). --- ## Docker images ## Prelude `ggshield` docker scanning tool (`ggshield secret scan docker`) is used to scan local docker images for secrets present in the image's creation process (`dockerfile` and build arguments) and in the image's layers' filesystem. `ggshield` is a wrapper around GitGuardian API for secrets detection that requires an API key to work. If the image is not available locally on the user's machine, GitGuardian CLI will attempt to pull the image using `docker pull `. ## Preview ![docker preview](/img/internal-monitoring/integrate-sources/vcs-integrations/docker/docker-secret-scan-output.png) ## Usage - `Docker`: scan a Docker image after exporting its filesystem and manifest with the `docker save` command. ``` Usage: ggshield secret scan docker [OPTIONS] IMAGE_NAME ggshield will try to pull the image if it's not available locally Options: -h, --help Show this message and exit. ``` Example: `ggshield secret scan docker gitguardian/ggshield` ## Example integration (GitHub Actions) In this example integration we build and push the ggshield image on GitHub Actions and then scan this image. ```yml name: ci on: push: branches: - 'master' jobs: docker: runs-on: ubuntu-latest services: registry: image: registry:2 ports: - 5000:5000 container: gitguardian/ggshield:latest steps: - name: Checkout uses: actions/checkout@v2 - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 with: driver-opts: network=host - name: Build and push to local registry uses: docker/build-push-action@v2 with: context: . push: true tags: localhost:5000/gitguardian/ggshield:latest - name: Scan image run: | ggshield secret scan docker localhost:5000/gitguardian/ggshield:latest ``` --- ## Pre-commit ## Prelude A pre-commit hook is a client-side git hook that runs right before the commit is created. Please refer to [our learning center](https://www.gitguardian.com/glossary/git-hooks) for more information. GitGuardian pre-commit hook is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around GitGuardian API for secrets detection that requires an API key to work. ## Preview ![pre-commit preview](/img/internal-monitoring/integrate-sources/vcs-integrations/git-hooks/git-hooks-pre-commit-output.png) :::info Customize the remediation message and add your own to offer developers precise guidance for resolving their code issues and continuing their work. **Read more here - GitGuardian CLI custom remediation message** ::: ## Installation ### The pre-commit framework In order to use `ggshield` with the [pre-commit](https://pre-commit.com/) framework, you need to perform the following steps. 1. Make sure you have pre-commit installed: ```shell pip install pre-commit ``` 2. Create a `.pre-commit-config.yaml` file in your repository's root path with the following content: ```yaml repos: - repo: https://github.com/gitguardian/ggshield rev: v1.52.2 hooks: - id: ggshield language_version: python3 stages: [pre-commit] ``` 3. Then install the hook with the command: ```shell pre-commit install ``` ``` pre-commit installed at .git/hooks/pre-commit ``` Now you're good to go! > Note: If you want to skip all the pre-commit checks, you can add the `-n` parameter as follows: ```shell git commit -m "commit message" -n ``` > Alternatively if you only want to skip ggshield, you can use SKIP=ggshield before the command: ```shell SKIP=ggshield git commit -m "commit message" ``` ### Global pre-commit hook To install pre-commit globally (for all current and future repos): 1. Sign in to your GitGuardian workspace and create a Personal Access Token from your [personal settings](https://dashboard.gitguardian.com/api/personal-access-tokens). 2. Add this Personal Access Token (API key) to the `GITGUARDIAN_API_KEY` environment variable of your development environment. 3. Execute the following command: ```shell ggshield install --mode global ``` It will: - verify if a global hook folder is defined in the global git configuration. - create the `~/.git/hooks` folder (if needed). - create a `pre-commit` file which will be executed before every commit. - give executable access to this file. ### Local pre-commit hook You can install the hook locally on desired repositories: 1. Sign in to your GitGuardian workspace and create a Personal Access Token from your [personal settings](https://dashboard.gitguardian.com/api/personal-access-tokens). 2. Add this Personal Access Token (API key) to the `GITGUARDIAN_API_KEY` environment variable in your repository. 3. Go in the repository and execute the following command: ```shell ggshield install --mode local ``` Notes: - If a pre-commit executable file already exists, it will not be overridden. You can force overriding with the `--force` option: ```shell ggshield install --mode local --force ``` - If you already have a pre-commit executable file and you want to use ggshield, all you need to do is to add this line in the file: ```shell ggshield secret scan pre-commit ``` - If you want to try pre-commit scanning through the docker image: ```shell docker run -e GITGUARDIAN_API_KEY -v $(pwd):/data --rm gitguardian/ggshield ggshield secret scan pre-commit ``` --- ## Pre-push ## Prelude A pre-push hook is a client-side git hook that runs right before a reference is pushed to a remote (`git push`). Please refer to [our learning center](https://www.gitguardian.com/glossary/git-hooks) for more information. GitGuardian pre-push hook is performed through our CLI application: [`ggshield`](../../getting-started.md). `ggshield` is a wrapper around the GitGuardian API for secrets detection that requires an API key to work. ## Preview ![pre-push preview](/img/internal-monitoring/integrate-sources/vcs-integrations/git-hooks/git-hooks-pre-push-output.png) :::info Customize the remediation message and add your own to offer developers precise guidance for resolving their code issues and continuing their work. **Read more here - GitGuardian CLI custom remediation message** ::: ## Installation ### The pre-commit framework In order to use **GitGuardian CLI** with the [pre-commit](https://pre-commit.com/) framework, you need to perform the following steps. 1. Make sure you have the pre-commit framework installed: ```shell pip install pre-commit ``` 2. Create a `.pre-commit-config.yaml` file in your repository's root path: ```yaml repos: - repo: https://github.com/gitguardian/ggshield rev: v1.52.2 hooks: - id: ggshield-push language_version: python3 stages: [pre-push] ``` 3. Then install the hook with the command: ```shell pre-commit install --hook-type pre-push ``` ``` pre-commit installed at .git/hooks/pre-push ``` Now you're good to go! > To avoid long delays, by default the pre-push hook will not scan pushes with more than 50 commits. > This setting can be configured using the `max-commits-for-hook` key in ggshield configuration file. ### Global pre-push hook To install pre-push globally (for all current and future repos): 1. Sign in to your GitGuardian workspace and create a Personal Access Token from your [personal settings](https://dashboard.gitguardian.com/api/personal-access-tokens). 2. Add this Personal Access Token (API key) to the `GITGUARDIAN_API_KEY` environment variable of your development environment. 3. Execute the following command: ```shell ggshield install --mode global -t pre-push ``` It will: - verify that if a global hook folder is defined in the global git configuration. - create the `~/.git/hooks` folder (if needed). - create a `pre-push` file which will be executed before every commit. - give executable access to this file. ### Local pre-push hook You can install the hook locally on desired repositories: 1. Sign in to your GitGuardian workspace and create a Personal Access Token from your [personal settings](https://dashboard.gitguardian.com/api/personal-access-tokens). 2. Add this Personal Access Token (API key) to the `GITGUARDIAN_API_KEY` environment variable in your repository. 3. Go in the repository and execute the following command: ```shell ggshield install --mode local -t pre-push ``` Notes: - If a pre-push executable file already exists, it will not be overridden. You can force override with the `--force` option: ```shell ggshield install --mode local -t pre-push --force ``` --- ## Pre-receive ## Prelude A pre-receive hook allows you to reject commits from being pushed to a git repository if they do not validate every check. Please refer to [our learning center](https://www.gitguardian.com/glossary/git-hooks) for more information. GitGuardian pre-receive hook is performed through our CLI application [ggshield](../../getting-started.md). `ggshield` is a wrapper around GitGuardian API for secrets detection that requires an API key to work. > Since pre-receive hooks are configured to run programmatically on the VCS instance, we recommend the use of a dedicated [service account](../../../api-docs/service-accounts.md) to authenticate ggshield calls. To create a service account, sign in to your GitGuardian workspace and go to the [API section](https://dashboard.gitguardian.com/api/service-accounts). You can find `ggshield`'s pre-receive hook samples in the [doc/pre-receive.sample](https://github.com/GitGuardian/ggshield/blob/main/doc/pre-receive.sample) and [doc/pre-receive-docker.sample](https://github.com/GitGuardian/ggshield/blob/main/doc/pre-receive-docker.sample). :::info GitGuardian supports pre-receive hooks on GitHub Enterprise Server, but GitHub enforces a 5-second timeout for push evaluations. If the evaluation exceeds this limit, the push is rejected. This may affect the reliability of the pre-receive hook. For more details, see [GitHub's pre-receive hooks documentation](https://docs.github.com/en/enterprise-server@3.15/admin/enforcing-policies/enforcing-policy-with-pre-receive-hooks/about-pre-receive-hooks). ::: ## Preview ![pre-receive preview](/img/internal-monitoring/integrate-sources/vcs-integrations/git-hooks/git-hooks-pre-receive-output.png) :::info Customize the remediation message and add your own to offer developers precise guidance for resolving their code issues and continuing their work. **Read more here - GitGuardian CLI custom remediation message** ::: ## Gitlab Self-Managed and Bitbucket Server ### Install ggshield git pre-receive hook The sample script can be found in [**pre-receive.sample**](https://github.com/GitGuardian/ggshield/blob/main/doc/pre-receive.sample). 1. This pre-receive hook requires the host machine to have python>=3.8 and pip installed 2. Install `ggshield` from pip: `pip install ggshield` 3. Move `pre-receive.sample` to `.git/hooks/pre-receive` or to your provider's git hook directory - [GitLab](https://docs.gitlab.com/ee/administration/server_hooks.html) - [Bitbucket Server/Datacenter](https://confluence.atlassian.com/bitbucketserverkb/how-to-create-a-simple-hook-in-bitbucket-data-center-779171711.html#HowtocreateasimplehookinBitbucketDataCenter-ForBitbucketversion8.0andabove:) 4. Mark the script executable with `chmod +x .git/hooks/pre-receive` 5. Define the `GITGUARDIAN_API_KEY` environment variable. Either in a machine wide configuration file or in the `.git/hooks/pre-receive` file, as instructed in the sample file. ### Install ggshield git pre-receive hook with Docker > For the pre-receive hook to work, the directory where the repositories are stored > must also be mounted on the container. The sample script can be found in [**pre-receive-docker.sample**](https://github.com/GitGuardian/ggshield/blob/main/doc/pre-receive-docker.sample) This pre-receive hook requires the host machine to have Docker installed. 1. Download the script as `.git/hooks/pre-receive`: ```shell curl -L https://github.com/GitGuardian/ggshield/raw/main/doc/pre-receive-docker.sample > .git/hooks/pre-receive ``` 2. Make it executable: ```shell chmod +x .git/hooks/pre-receive ``` 3. Either define `GITGUARDIAN_API_KEY` as a machine-wide environment variable or set it in the `.git/hooks/pre-receive` as instructed in the sample file. ## GitHub Enterprise Server :::info The minimum GitHub Enterprise Server version required to support pre-receive hooks is 3.14. ::: Installing a git pre-receive hook on GitHub Enterprise Server requires 2 components: 1. an environment to execute the script in, 2. a script executed for each push event. For more information, visit [GitHub Enterprise Server documentation about pre-receive hook](https://docs.github.com/en/admin/policies/enforcing-policy-with-pre-receive-hooks/managing-pre-receive-hooks-on-the-github-enterprise-server-appliance). ### The pre-receive environment A pre-receive hook environment is a Linux chroot. We provide the [**create-ghe-environment**](https://github.com/GitGuardian/ggshield/blob/main/scripts/create-ghe-environment) script to create a ready-to-upload archive of a pre-receive environment. This script must be run on a Linux machine with Docker installed. Here is how to use it: 1. Clone the ggshield repository: ```shell git clone https://github.com/GitGuardian/ggshield.git cd ggshield ``` 2. Make sure the `GITGUARDIAN_API_KEY` environment variable contains your API key. 3. Run the script: ```shell ./scripts/create-ghe-environment ``` When the script is done, it should print a message like this: > create-ghe-environment: Storing chroot in ggshield-ghe.tar.gz You can now upload this file to the GitHub Enterprise Server and add it using the following command: ```shell ghe-hook-env-create ggshield-environment ~/ggshield-ghe.tar.gz ``` Or you can upload this file to a server and pass its URL to the GitHub Enterprise Server web user interface to add it. ### Script You need to add the following script to a repository hosted in the GitHub Enterprise Server: ```shell #!/bin/bash # If you don't use the SaaS product, you need to setup your onprem public api url: # export GITGUARDIAN_API_URL= export GITGUARDIAN_API_KEY=$(cat /app/api_key) /app/.venv/bin/ggshield secret scan pre-receive ``` This script file should have execute permission. Since the script name appears in the pre-receive hook result, we recommend to name it `pre-receive.sh`. ### Create the pre-receive hook You are now able to follow [GitHub Enterprise Server documentation](https://docs.github.com/en/admin/policies/enforcing-policy-with-pre-receive-hooks/managing-pre-receive-hooks-on-the-github-enterprise-server-appliance) to create the pre-receive hook. ## Skipping the pre-receive hook `ggshield`'s pre-receive hook can be skipped by adding `-o breakglass` to the `git push` command. For the `-o breakglass` option to be taken into account, the remote repository must have the `receive.advertisePushOptions` git configuration option turned on. This option can be turned on by running the following command _on the server side_: ```shell git config receive.advertisePushOptions true ``` Some Git hosting services enable this option globally by default. Others do not. ## FAQ ### How do I avoid getting alerts for secrets already detected on the GitGuardian dashboard? We recommend you use the option `--ignore-known-secrets` on the pre-receive hook. In this case, ggshield will not trigger any alerts, after you run a `git push`, for secrets that are already known by the GitGuardian dashboard (detected in previous commits and pull or merge requests). All known secrets will be ignored, in the commits pushed and the merge/pull request, including those that were hardcoded by other developers. - To enable this option, replace the following in the pre-receive hook ```shell ggshield secret scan pre-receive ``` with: ```shell ggshield secret scan pre-receive --ignore-known-secrets ``` ### How do use a custom config for this pre-receive hook? - Create a `gitguardian.yaml` somewhere in the system. An example config file is available [here](https://github.com/GitGuardian/ggshield/blob/main/.gitguardian.example.yml). - Replace in the pre-receive hook ```shell ggshield secret scan pre-receive ``` with: ```shell ggshield -c secret scan pre-receive ``` --- ## Antigravity Extension The GitGuardian Antigravity extension enhances code security by detecting and preventing the inclusion of sensitive information, such as API keys and credentials, directly within your development environment. This tool integrates seamlessly into Antigravity, providing real-time feedback to developers and promoting secure coding practices. The extension leverages the bundled GitGuardian CLI (`ggshield`) to scan your code for 600+ types of secrets as you write or modify it, ensuring immediate awareness and action when potential security issues are detected. ![Antigravity GitGuardian extension detecting a secret showing hover details](/img/ggshield/ide-integrations/antigravity.png) *The GitGuardian extension detecting AWS keys in Antigravity, showing detailed information about the secret when hovering.* ## Key Features - **Real-Time Secret Detection**: Automatically scans your code as you type, highlighting secrets instantly with clear visual indicators. - **Guided Remediation**: Provides actionable recommendations to fix detected secrets directly within Antigravity. - **Developer-Friendly Integration**: Simple one-click installation with built-in CLI and automatic scanning on save. - **False Positive Management**: Easily mark false positives through `.gitguardian.yaml` configuration. ## Installation From the extension marketplace: 1. Open Antigravity 2. Go to the Extensions view (`Ctrl+Shift+X` or `Cmd+Shift+X`) 3. Search for "GitGuardian" 4. Click "Install" on the "GitGuardian Secret Security" extension 5. Restart Antigravity if prompted ## Configuration ### Authentication After installation, you'll need to authenticate with GitGuardian: 1. Open the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P`) 2. Type "GitGuardian: Authenticate" and select it 3. Follow the authentication flow to connect your GitGuardian account ### Settings The extension can be configured through Antigravity settings: 1. Go to Antigravity → Settings → Extensions (or `Ctrl+,` / `Cmd+,`) 2. Search for "GitGuardian" 3. Configure the available options: #### For SaaS Users - **API URL**: Uses GitGuardian's default API endpoint - **Authentication**: Use the built-in authentication flow #### For Self-Hosted Users - **API URL**: Enter your custom GitGuardian instance URL - **API Key**: Enter your [Personal Access Token](../../../api-docs/personal-access-tokens) from your self-hosted instance To configure for self-hosted instances: ```json { "gitguardian.apiUrl": "https://your-gitguardian-instance.com", "gitguardian.apiKey": "your-personal-access-token" } ``` ## Usage and Results The extension automatically scans files on save and displays results in three ways: - Highlights secrets directly in your code - Shows warning icons in the status bar - Lists issues in the Problems panel (`Ctrl+Shift+M` or `Cmd+Shift+M`) To ignore false positives, add paths to `.gitguardian.yaml`: ```yaml version: 2 secret: # Exclude files and paths by globbing ignored_paths: - '**/README.md' - 'doc/*' - 'LICENSE' ``` :::info Customize the remediation message and add your own to offer developers precise guidance for resolving their code issues and continuing their work. **Read more here - GitGuardian CLI custom remediation message** ::: ## Troubleshooting Common solutions: - Verify authentication and internet connection - For self-hosted instances, check API key and URL - Restart your IDE if issues persist - Exclude large directories in `.gitguardian.yaml` for better performance Need help? Check our [documentation](../../getting-started.md), [GitHub repository](https://github.com/GitGuardian/gitguardian-vscode), or contact [support](mailto:support@gitguardian.com). --- ## Cursor Extension The GitGuardian Cursor extension enhances code security by detecting and preventing the inclusion of sensitive information, such as API keys and credentials, directly within your development environment. This tool integrates seamlessly into Cursor, providing real-time feedback to developers and promoting secure coding practices. The extension leverages the bundled GitGuardian CLI (`ggshield`) to scan your code for 600+ types of secrets as you write or modify it, ensuring immediate awareness and action when potential security issues are detected. ![Cursor GitGuardian extension detecting a secret showing hover details](/img/ggshield/ide-integrations/cursor.png) *The GitGuardian extension detecting AWS keys in Cursor, showing detailed information about the secret when hovering.* ## Key Features - **Real-Time Secret Detection**: Automatically scans your code as you type, highlighting secrets instantly with clear visual indicators. - **Guided Remediation**: Provides actionable recommendations to fix detected secrets directly within Cursor. - **Developer-Friendly Integration**: Simple one-click installation with built-in CLI and automatic scanning on save. - **False Positive Management**: Easily mark false positives through `.gitguardian.yaml` configuration. ## Installation From the extension marketplace: 1. Open Cursor 2. Go to the Extensions view (`Ctrl+Shift+X` or `Cmd+Shift+X`) 3. Search for "GitGuardian" 4. Click "Install" on the "GitGuardian Secret Security" extension 5. Restart Cursor if prompted ## Configuration ### Authentication After installation, you'll need to authenticate with GitGuardian: 1. Open the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P`) 2. Type "GitGuardian: Authenticate" and select it 3. Follow the authentication flow to connect your GitGuardian account ### Settings The extension can be configured through Cursor settings: 1. Go to Cursor → Settings → Extensions (or `Ctrl+,` / `Cmd+,`) 2. Search for "GitGuardian" 3. Configure the available options: #### For SaaS Users - **API URL**: Uses GitGuardian's default API endpoint - **Authentication**: Use the built-in authentication flow #### For Self-Hosted Users - **API URL**: Enter your custom GitGuardian instance URL - **API Key**: Enter your [Personal Access Token](../../../api-docs/personal-access-tokens) from your self-hosted instance To configure for self-hosted instances: ```json { "gitguardian.apiUrl": "https://your-gitguardian-instance.com", "gitguardian.apiKey": "your-personal-access-token" } ``` ## Usage and Results The extension automatically scans files on save and displays results in three ways: - Highlights secrets directly in your code - Shows warning icons in the status bar - Lists issues in the Problems panel (`Ctrl+Shift+M` or `Cmd+Shift+M`) To ignore false positives, add paths to `.gitguardian.yaml`: ```yaml version: 2 secret: # Exclude files and paths by globbing ignored_paths: - '**/README.md' - 'doc/*' - 'LICENSE' ``` :::info Customize the remediation message and add your own to offer developers precise guidance for resolving their code issues and continuing their work. **Read more here - GitGuardian CLI custom remediation message** ::: ## Troubleshooting Common solutions: - Verify authentication and internet connection - For self-hosted instances, check API key and URL - Restart your IDE if issues persist - Exclude large directories in `.gitguardian.yaml` for better performance Need help? Check our [documentation](../../getting-started.md), [GitHub repository](https://github.com/GitGuardian/gitguardian-vscode), or contact [support](mailto:support@gitguardian.com). --- ## Visual Studio Code Extension The GitGuardian VSCode extension enhances code security by detecting and preventing the inclusion of sensitive information, such as API keys and credentials, directly within your development environment. This tool integrates seamlessly into the VS Code editor, providing real-time feedback to developers and promoting secure coding practices. The extension leverages the bundled GitGuardian CLI (`ggshield`) to scan your code for 600+ types of secrets as you write or modify it, ensuring immediate awareness and action when potential security issues are detected. ![VS Code GitGuardian extension detecting a secret showing hover details](/img/ggshield/ide-integrations/vscode-detection.png) *The GitGuardian extension detecting a GitHub token in VS Code, showing detailed information about the secret when hovering.* ## Key Features - **Real-Time Secret Detection**: Automatically scans your code as you type, highlighting secrets instantly with clear visual indicators. - **Guided Remediation**: Provides actionable recommendations to fix detected secrets directly within VS Code. - **Developer-Friendly Integration**: Simple one-click installation with built-in CLI and automatic scanning on save. - **False Positive Management**: Easily mark false positives through `.gitguardian.yaml` configuration. ## Installation From the extension marketplace: 1. Open Visual Studio Code 2. Go to the Extensions view (`Ctrl+Shift+X` or `Cmd+Shift+X`) 3. Search for "GitGuardian" 4. Click "Install" on the "GitGuardian Secret Security" extension 5. Restart VS Code if prompted ## Configuration ### Authentication After installation, you'll need to authenticate with GitGuardian: 1. Open the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P`) 2. Type "GitGuardian: Authenticate" and select it 3. Follow the authentication flow to connect your GitGuardian account ### Settings The extension can be configured through VS Code settings: 1. Go to File → Preferences → Settings (or `Ctrl+,` / `Cmd+,`) 2. Search for "GitGuardian" 3. Configure the available options: #### For SaaS Users - **API URL**: Uses GitGuardian's default API endpoint - **Authentication**: Use the built-in authentication flow #### For Self-Hosted Users - **API URL**: Enter your custom GitGuardian instance URL - **API Key**: Enter your [Personal Access Token](../../../api-docs/personal-access-tokens) from your self-hosted instance To configure for self-hosted instances: ```json { "gitguardian.apiUrl": "https://your-gitguardian-instance.com", "gitguardian.apiKey": "your-personal-access-token" } ``` ## Usage and Results The extension automatically scans files on save and displays results in three ways: - Highlights secrets directly in your code - Shows warning icons in the status bar - Lists issues in the Problems panel (`Ctrl+Shift+M` or `Cmd+Shift+M`) To ignore false positives, add paths to `.gitguardian.yaml`: ```yaml version: 2 secret: # Exclude files and paths by globbing ignored_paths: - '**/README.md' - 'doc/*' - 'LICENSE' ``` :::info Customize the remediation message and add your own to offer developers precise guidance for resolving their code issues and continuing their work. **Read more here - GitGuardian CLI custom remediation message** ::: ## Troubleshooting Common solutions: - Verify authentication and internet connection - For self-hosted instances, check API key and URL - Restart your IDE if issues persist - Exclude large directories in `.gitguardian.yaml` for better performance Need help? Check our [documentation](../../getting-started.md), [GitHub repository](https://github.com/GitGuardian/gitguardian-vscode), or contact [support](mailto:support@gitguardian.com). --- ## Windsurf Extension The GitGuardian Windsurf extension enhances code security by detecting and preventing the inclusion of sensitive information, such as API keys and credentials, directly within your development environment. This tool integrates seamlessly into Windsurf, providing real-time feedback to developers and promoting secure coding practices. The extension leverages the bundled GitGuardian CLI (`ggshield`) to scan your code for 600+ types of secrets as you write or modify it, ensuring immediate awareness and action when potential security issues are detected. ![Windsurf GitGuardian extension detecting a secret showing hover details](/img/ggshield/ide-integrations/windsurf.png) *The GitGuardian extension detecting AWS keys in Windsurf, showing detailed information about the secret when hovering.* ## Key Features - **Real-Time Secret Detection**: Automatically scans your code as you type, highlighting secrets instantly with clear visual indicators. - **Guided Remediation**: Provides actionable recommendations to fix detected secrets directly within Windsurf. - **Developer-Friendly Integration**: Simple one-click installation with built-in CLI and automatic scanning on save. - **False Positive Management**: Easily mark false positives through `.gitguardian.yaml` configuration. ## Installation From the extension marketplace: 1. Open Windsurf 2. Go to the Extensions view (`Ctrl+Shift+X` or `Cmd+Shift+X`) 3. Search for "GitGuardian" 4. Click "Install" on the "GitGuardian Secret Security" extension 5. Restart Windsurf if prompted ## Configuration ### Authentication After installation, you'll need to authenticate with GitGuardian: 1. Open the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P`) 2. Type "GitGuardian: Authenticate" and select it 3. Follow the authentication flow to connect your GitGuardian account ### Settings The extension can be configured through Windsurf settings: 1. Go to Windsurf → Settings → Extensions (or `Ctrl+,` / `Cmd+,`) 2. Search for "GitGuardian" 3. Configure the available options: #### For SaaS Users - **API URL**: Uses GitGuardian's default API endpoint - **Authentication**: Use the built-in authentication flow #### For Self-Hosted Users - **API URL**: Enter your custom GitGuardian instance URL - **API Key**: Enter your [Personal Access Token](../../../api-docs/personal-access-tokens) from your self-hosted instance To configure for self-hosted instances: ```json { "gitguardian.apiUrl": "https://your-gitguardian-instance.com", "gitguardian.apiKey": "your-personal-access-token" } ``` ## Usage and Results The extension automatically scans files on save and displays results in three ways: - Highlights secrets directly in your code - Shows warning icons in the status bar - Lists issues in the Problems panel (`Ctrl+Shift+M` or `Cmd+Shift+M`) To ignore false positives, add paths to `.gitguardian.yaml`: ```yaml version: 2 secret: # Exclude files and paths by globbing ignored_paths: - '**/README.md' - 'doc/*' - 'LICENSE' ``` :::info Customize the remediation message and add your own to offer developers precise guidance for resolving their code issues and continuing their work. **Read more here - GitGuardian CLI custom remediation message** ::: ## Troubleshooting Common solutions: - Verify authentication and internet connection - For self-hosted instances, check API key and URL - Restart your IDE if issues persist - Exclude large directories in `.gitguardian.yaml` for better performance Need help? Check our [documentation](../../getting-started.md), [GitHub repository](https://github.com/GitGuardian/gitguardian-vscode), or contact [support](mailto:support@gitguardian.com). --- ## Scanning Other Data Sources for Secrets ## Prelude `ggshield` supports a generic input format via its `secret scan docset` command. The input files for that command must be in JSONL format, each line containing a "docset" JSON object. A docset represents a set of documents for a given type. Each document has authors and content. Authors may have a name, an email and a role. This is a simple and flexible model to ease preparing data for ggshield consumption. See below for more details. ## The Docset Format ### Docset structure For a more detailed view of the format, here is the structure of a docset: ``` { // Required. Defines the type of data stored in the docset. "type": "", // Required. A string to uniquely identify this docset. // Content depends on the type and is considered opaque but will be displayed in the output. "id": "", // Optional. Authors of the doc set. // Only set if the whole docset has the same authors. "authors": [$author], // Required. The documents of the docset. "documents": [$document] } ``` ### Author's structure ```json { // Required. Content depends on the format and is considered opaque. // Could be an email, a username or a system specific ID. "id": "", // Optional. The author name, if available. "name": "", // Optional. The author email, if available. // This field should be set even if email is used as the ID, since the ID is // considered opaque. "email": "", // Optional. Meaning depends on the format. // For example in a commit it would be "author" or "committer". "role": "" } ``` ### Document's structure ```json { // Required. A string to uniquely identify the document inside the docset. // Content depends on the type and is considered opaque but will be displayed in the output. "id": "", // Optional. If defined, it replaces (not extend) the global docset authors. "authors": [$author], // Required. The content of the document in UTF-8. "content": "" } ``` ## Creating incidents from a custom source Pass the `--source-uuid` option to link a scan to a custom source. Incidents are then created server-side and become visible on the dashboard, under that source. This requires a token with the `scan:create-incidents` scope. ```shell ggshield secret scan docset --source-uuid file1.jsonl ``` A custom source can also be configured to keep only secrets whose detector supports validity checks, filtering out unverifiable matches before incidents are created. This is set per custom source. See [Scan with validated detectors only](/internal-monitoring/integrate-sources/bring-your-own-sources#scan-with-validated-detectors-only). --- ## Overview(Integrations) GitGuardian specializes in detecting secrets within source code, yet we also plan to expand to monitoring other sources such as messaging systems, project management boards, wikis, etc. ### AI coding tools: secret scanning for AI-assisted development AI coding tools like Cursor and Claude Code can inadvertently expose secrets through prompts, commands, and file reads. `ggshield` integrates with these tools through their hook systems to detect and block secrets in real time, before they reach the AI model. GitGuardian currently supports: - [Cursor, Claude Code, Codex, Copilot CLI, VS Code, and Mistral Vibe](./ai-coding-tools/secret-scanning-for-ai-coding-tools.md) ### IDE plugins and extensions: real-time secret detection in your development environment GitGuardian integrates with popular IDEs and code editors to provide real-time secret detection as you write code. GitGuardian currently supports: - [Antigravity](./ide-integrations/antigravity.md) - [Cursor](./ide-integrations/cursor.md) - [Visual Studio Code](./ide-integrations/vscode.md) - [Windsurf](./ide-integrations/windsurf.md) ### CI/CD integrations: secrets detection in your CI/CD workflow. GitGuardian integrates with the most common CI tools via our CLI application: [`ggshield`](../getting-started.md). GitGuardian currently supports: - [Azure pipelines](./cicd-integrations/azure-pipelines.md) - [Bitbucket pipelines](./cicd-integrations/bitbucket-pipelines.md) - [Circle CI](./cicd-integrations/circle-ci.md) - [Drone CI](./cicd-integrations/drone-ci.md) - [GitHub Actions](./cicd-integrations/github-actions.md) - [GitLab pipelines](./cicd-integrations/gitlab-pipelines.md) - [Jenkins CI](./cicd-integrations/jenkins-ci.md) - [Travis CI](./cicd-integrations/travis-ci.md) ### Git hooks: prevent secrets from reaching your VCS. GitGuardian's CLI application, [ggshield](../getting-started.md) enables you to integrate secrets detection in git workflow and shift left your security. GitGuardian currently supports the following hooks: - [pre-commit](./git-hooks/pre-commit.md) - [pre-push](./git-hooks/pre-push.md) - [pre-receive](./git-hooks/pre-receive.md) ### Docker GitGuardian's CLI application, [ggshield](../getting-started.md) enables you to [scan Docker images](./docker/docker_image.md). ### Monitoring other sources GitGuardian intends to progressively support more data sources for secrets scanning in the future. Since version 1.14.1, ggshield supports a new docset input format. Refer to the [corresponding documentation](./other-data-sources/other-data-sources.md) for more details. If GitGuardian does not yet support one of the sources you would like to monitor, you can build your own integration by leveraging our [public API for secrets detection](../../api-docs/introduction.md). ### Troubleshooting connectivity problems In case you experience connectivity problems with your GitGuardian instance, please refer to this [section of GitGuardian internal monitoring documentation](../../internal-monitoring/integrate-sources/monitored-perimeter#troubleshooting-connectivity-problems). --- ## Detect code leakage on public GitHub GitGuardian natively monitors all the commits on public GitHub for secrets getting leaked. As for real secrets, whenever a honeytoken ends up in a public GitHub repository, it will be detected by GitGuardian, and this will trigger specific events. Events originating from the IP addresses of GitGuardian monitoring of public GitHub are marked as `GitGuardian Public Monitoring IP`, and as a result, the honeytoken itself will receive tag `Publicly exposed`. ![Publicly exposed mechanism](/img/honeytoken/publicly-exposed-mechanism.png) Clicking the `Publicly exposed` tag of the honeytoken will display all the public GitHub commits detected by GitGuardian as containing the honeytoken. :::caution This specific bit of feature (returning the list of public GitHub commits) is unfortunately not available for self-hosted installations. ::: Publicly exposed honeytokens can be quickly identified and filtered from the honeytoken list. ![Publicly exposed filter](/img/honeytoken/publicly-exposed-filter.png) --- ## Configure your alerts If a honeytoken is in an Active status, any new event will change the status to Triggered. ## Email notifications Managers will receive an email notification whenever a honeytoken's status is changed to Triggered. This notification can be deactivated in Settings > Personal: Notifications > [Email preferences](https://dashboard.gitguardian.com/settings/personal/notifications). ## Slack notifications You can configure Slack notifications to receive honeytoken alerts directly in your Slack channels. This provides real-time visibility into honeytoken activity alongside your other security notifications. Slack notifications support: - **Honeytoken Triggered**: When a honeytoken status changes to triggered - **New Honeytoken Event**: When a new honeytoken usage is detected To set up Slack notifications, configure your [Slack integration](/platform/configure-alerting/notifiers-integrations/slack) and select the honeytoken event types you want to receive. :::info Honeytoken slack notifications can only be configured in the All-incidents team. ::: ## Microsoft Teams notifications You can configure Microsoft Teams notifications to receive honeytoken alerts directly in your Teams channels. This provides real-time visibility into honeytoken activity alongside your other security notifications. Microsoft Teams notifications support: - **Honeytoken Triggered**: When a honeytoken status changes to triggered - **New Honeytoken Event**: When a new honeytoken usage is detected To set up Microsoft Teams notifications, configure your [Microsoft Teams integration](/platform/configure-alerting/notifiers-integrations/microsoft-teams) and select the honeytoken event types you want to receive. :::info Honeytoken Microsoft Teams notifications can only be configured in the All-incidents team. ::: ## ServiceNow tickets You can create ServiceNow tickets for honeytoken events through the ServiceNow integration. This brings honeytoken activity into the same ticketing workflow as your secret incidents. To set it up, configure your [ServiceNow integration](/platform/configure-alerting/issue-tracking-integrations/servicenow) and select the **Honeytoken** event group. ## Custom webhooks It is possible to configure custom webhooks to receive alerts when honeytokens are triggered or when a new event appears. This allows you to integrate and manage the information directly within your SIEM or other security systems. You can create dedicated webhooks or use the same ones for secrets detection events and refine the "Event Subscription" scopes as needed. ![Custom webhooks for honeytokens](/img/honeytoken/custom-webhooks-honeytoken.png) The possible event subscriptions are: - Honeytoken > Triggers: get a webhook event whenever the status of a honeytoken gets changed to Triggered. - Honeytoken > Events: get a webhook event whenever a new honeytoken event is received. ### Payload structure
Payload for new trigger #### Honeytoken triggered ```json { "source": "GitGuardian", "timestamp": "2023-04-20T08:22:19.913732Z", "action": "honeytoken_triggered", "message": "This honeytoken has been triggered.", "target_user": null, "honeytoken": { "id": "12d14831-6b2b-4bd6-881b-53c83a09f07b", "name": "ht27", "description": "", "created_at": "2023-04-12T10:21:28.972903Z", "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/honeytokens/12d14831-6b2b-4bd6-881b-53c83a09f07b", "status": "triggered", "triggered_at": "2023-04-20T08:22:19.838234Z", "revoked_at": null, "open_events_count": 1, "type": "AWS", "creator_id": 397542, "creator_api_token_id": null, "revoker_id": null, "revoker_api_token_id": null } } ```
Payload for new honeytoken event #### New event ``` json { "source": "GitGuardian", "timestamp": "2023-04-07T15:56:42.171075Z", "action": "new_honeytoken_event", "message": "A new honeytoken event has been received.", "target_user": null, "honeytoken_event": { "id": "2bdc644e-ce7e-49e8-a3a6-56fca0364a63", "honeytoken_id": "12d14831-6b2b-4bd6-881b-53c83a09f07b", "triggered_at": "2023-04-07T15:56:37Z", "status": "open", "ip_address": "54.39.187.211", "action": "GetCallerIdentity", "data": { "event_id": "98a080cf-a268-4a2e-b013-6259122b8a05", "user_agent": "python-requests/2.28.2" }, "tags": [] } } ```
--- ## Core concepts(Honeytoken) See how Honeytoken works in this brief video. ## What are honeytokens? GitGuardian Honeytoken allows you to create decoy credentials called “honeytokens” that do not allow any access to any actual customer resources or data. Instead, they act as tripwires that reveal information about the attacker (eg. IP Address, User Agent, Location, etc.). Our honeytokens look just like any other secret to attackers. We designed our honeytokens to be triggered by all types of secret scanners, like open-source projects TruffleHog or Gitleaks, that are often put to wrong use by attackers. This means that if a hacker uses a secret scanner to search for developer secrets, they will trip on the honeytoken, triggering an alert that notifies the security team of a potential security incident. ## Why should you use honeytokens? Honeytokens are a useful tool for the software development life cycle (SDLC) and software supply chain for several reasons: 1. **An essential function in secrets remediation:** Honeytoken serves as the initial line of defense for users grappling with thousands of secrets incidents. It functions as an alarm system. It provides reassurance and buys valuable time when addressing secrets incidents at scale. Moreover, it acts as a prioritization tool, directing focus to critical incidents, when triggered. 2. **Early detection of security breaches**: By planting honeytokens in your SDLC system and supply chain, you can detect security breaches early on before they cause any real damage. Honeytokens can act as an alarm system that signals the presence of an attacker or malicious activity. 3. **Strengthened supply chain security**: Honeytokens can be used to quickly detect any breaches and identify if a vendor in the supply chain has been compromised. This helps you to strengthen your supply chain security and prevent further damage from occurring. 4. **Complete visibility of monitored codebase**: Honeytokens provide you with a clear view of where they have been deployed, ensuring they were deployed as intended and identifying if they were mistakenly duplicated in several repositories. 5. **Easy deployment at scale**: Honeytokens can be created, deployed, and managed on a large enterprise scale, allowing you to secure thousands of code repositories simultaneously. The integration of Honeytoken in the GitGuardian code security platform ensures that our secret scanning does not generate useless alerts for the deployed honeytokens. 6. **Detection of code leakage**: By placing our honeytokens in code, you can detect if it has been leaked on public GitHub, saving time and resources by providing an easy and quick way to detect code leakage and prevent further data loss. Read this [blog post](https://blog.gitguardian.com/gitguardian-honeytoken) to learn more about the use cases of our honeytokens. ## Where should you place your honeytokens? Our honeytokens are tailor-made for deployment in **Version Control Systems (git repositories).** Git repositories are your treasure troves, packed with valuable code essential for your software's functionality. If unauthorized access occurs, it could lead to code theft, tampering, or disruption of your operations.Deploy in all your repositories to detect when your codebase is compromised. Check our detailed [guide](https://blog.gitguardian.com/how-to-secure-your-scm-repositories-with-gitguardian-honeytokens). Additionally, leverage honeytokens in other critical areas (where your real secrets might be found). Here are some examples: - Insert them into **[CI/CD tools](https://blog.gitguardian.com/how-to-add-gitguardian-honeytokens-in-ci-cd-pipelines/)** to detect compromised pipelines. - Plant them in **[Docker images](https://blog.gitguardian.com/how-to-secure-your-container-registries-with-gitguardians-honeytoken/)** or other **internal packages**. - Place them in [project management tools](https://blog.gitguardian.com/secure-your-productivity-tools-with-gitguardian-honeytoken/) like **Jira**, internal wikis like **Confluence**, or messaging tools like **Slack**. - Plant them on **developer machines**, in the local credential file that credential harvesting malware reads first. See [Protect endpoints with Honeytokens](/endpoint-protection/honeytoken-protection). :::tip We recommend that each honeytoken be deployed in a unique place. If it appears in several places, then if it gets triggered, you would not be able to identify for sure which place is compromised. ::: --- ## Deployment jobs :::info Business feature Only workspaces under Business plan can access the Deployment jobs feature. ::: ## Introduction Deployment jobs are a key feature enabling the efficient dissemination of honeytokens across multiple code repositories. This process involves creating pull requests to insert a file containing a honeytoken into the targeted repositories. During a deployment job, for each selected repository, GitGuardian will: 1. Create a unique honeytoken. 2. Place it within an appropriate file context. 3. Create a pull request to insert the honeytoken into the repository. It's important to note that the decision to merge each honeytoken into the main branch rests with the user, who must perform this action directly in the VCS. GitGuardian's function is limited to opening the pull request. In any case, you should consider the honeytoken as deployed as soon as the pull request is created, since it is now visible in the git repository. :::info We use "Pull request" universally across all Version Control Systems (VCSs). For GitLab, this is equivalent to "Merge requests". ::: ## Prerequisites :::info Currently, this feature supports GitLab and GitHub sources only. Azure DevOps and BitBucket are not supported at present. ::: To use deployment jobs, GitGuardian requires write access to the repositories being monitored. - **For GitLab projects:** No extra setup is needed. - **For GitHub and GitHub Enterprise Server repositories:** Additional steps are required to enable write permissions. See detailed instruction in the integration guides for [GitHub](../../internal-monitoring/integrate-sources/vcs-integrations/github) or [GitHub Enterprise Server](../../internal-monitoring/integrate-sources/vcs-integrations/github-enterprise). ## Creating a deployment Job Navigate to the “[Deployment jobs](https://dashboard.gitguardian.com/honeytokens/deployment-jobs)” tab within the Honeytoken module and click Create deployment job. ![Deployment jobs page](/img/honeytoken/deploy-honeytokens/deployment-jobs/create-deployment-job.png) 1. **Name**: Assign a descriptive name to your deployment job, indicating its scope or purpose. 2. **Context creation strategy**: Choose a strategy for the types of files to be used for honeytoken insertion. Details on the context creation strategies are available in a [dedicated section](#context-creation-strategy). 3. **Tags**: Assign custom tags to the honeytokens generated in this job, aiding in identification and filtering. For example, **`auto-deploy:true`** could denote honeytokens created from deployment jobs. 4. **Sources**: Select the repositories where you wish to deploy honeytokens. :::info Some sources might not be eligible for deployment jobs, including Azure DevOps, BitBucket, GitHub repositories without write permissions, sources outside the monitored perimeter, and public sources. Refer to the help section for troubleshooting. ::: Note: The number of sources selected cannot exceed the number of available honeytokens for creation. ## Context creation strategy {#context-creation-strategy} In the [Honeytoken settings](https://dashboard.gitguardian.com/settings/secrets/honeytoken), you can view and modify context creation strategies. These strategies determine the file types into which honeytokens may be inserted, classified as either "generic" or "dynamic": :::info “Generic” refer to file types that could realistically be found in any repository, irrespective of programming language, such as .env, .txt, .csv, .yaml, .json. “Dynamic” refer to file types and content aligned with the main language of the target repository. Our dynamic contexts are generated by AI using the requested language. **Note that no code is ever sent to the model**. ::: When creating or editing a strategy, you must select a "context creation" option, as well as the generic context types that you want to allow: ![Context creation strategy](/img/honeytoken/deploy-honeytokens/deployment-jobs/new-strategy.png) Even when selecting the “Dynamic contexts” option, you still need to select at least one type of generic context: should the repository language not be existing or available, the system will fallback on a generic file. ## Follow the progress of your Deployment job Once a deployment job is created, you can view the status of each individual deployment: ![Deployment jobs page](/img/honeytoken/deploy-honeytokens/deployment-jobs/deployment-job-detail.png) - **`Processing`**: The pull request is pending. - **`Pull request created`**: GitGuardian has successfully created the honeytoken and the pull request. - **`Merged`**: The proposed change has been approved and merged. - **`Pull request closed`**: The proposed change has been declined, closing the pull request. - **`Error`**: An issue occurred during deployment (details available in the side panel upon clicking the deployment). For statuses other than “Processing” and “Error,” you'll find links to the honeytoken, the pull request, and the inserted file. It's important to note that a honeytoken is considered deployed once the pull request is created, as it becomes visible in the repository, irrespective of whether it's merged. If a pull request is closed, the honeytoken remains unless the branch and pull request are explicitly deleted. ## Characteristics of honeytokens created from deployment jobs Honeytokens created via deployment jobs have the following characteristics: - **The name:** Corresponds to the source name, appended with a suffix based on the deployment job - **Custom tags:** As specified during the deployment job creation. - **Link:** When the source is detected and the information added to the honeytoken (shortly after the pull request is created), there is a link to redirect to the associated deployment. ![Honeytoken deployed by GitGuardian](/img/honeytoken/deploy-honeytokens/deployment-jobs/honeytoken-deployed-by-gitguardian.png) --- ## Deployment methods Deploying honeytokens can be accomplished through various methods, each suited to different needs and scenarios: ## Automatically and at scale with Deployment jobs :::info Deployment jobs are only available for workspaces under the Business plan. ::: Deployment jobs enable the automated deployment of honeytokens into code repositories that are integrated with GitGuardian. For an in-depth exploration of Deployment jobs, please refer to [our detailed page on this topic](../deploy-honeytokens/deployment-jobs). This approach is highly recommended for broad coverage across numerous repositories, offering an efficient and streamlined process. ## On developer endpoints with ggshield If you use [Endpoint Protection](/endpoint-protection/home), `ggshield` can plant a honeytoken directly on each developer machine and keep it reconciled with GitGuardian. The decoy lands in the local credential file that credential harvesting malware reads first, so an attempt to steal it raises an alert naming the compromised machine. This is the right method for extending honeytoken coverage to your fleet of laptops and workstations. Deployment runs through your MDM alongside endpoint scanning. See [Protect endpoints with Honeytokens](/endpoint-protection/honeytoken-protection). ## Manually Manual deployment of honeytokens is always an option. This involves creating a honeytoken from the GitGuardian dashboard, copying the AWS key, and then inserting it into the asset you wish to monitor. Detailed instructions for this process can be found on our [Getting Started](../getting-started.md#create-and-deploy-your-first-honeytoken) page. This method is particularly useful for assets not under GitGuardian's monitoring or in scenarios where automation is not feasible. It is best suited for situations involving a smaller number of assets. :::caution When manually inserting honeytokens into assets not integrated with GitGuardian, it's crucial to assign them distinctive names and descriptions. This way, should the honeytoken be triggered, you'll be able to identify which asset was compromised. We recommend naming the honeytoken after the asset itself and using the description field to provide additional details about its precise location. [Custom tags](../../platform/collaboration-and-sharing/custom-tags) can also be utilized to categorize your honeytokens effectively. ::: ## Via custom scripts leveraging the GitGuardian API For those with specific needs or seeking greater flexibility, creating custom deployment scripts is a viable option. You can craft scripts that generate honeytokens by leveraging [GitGuardian's Honeytoken API](https://api.gitguardian.com/docs#tag/Honeytokens), insert them into the desired context, and then deploy them to your target assets. This method offers a high degree of customization and control but requires a significant technical investment from the user. It is a good choice for covering a vast array of assets not supported by GitGuardian's integrations, or if you prefer to dictate the exact context in which your honeytokens are deployed. --- ## Monitor the deployment of your honeytokens :::info Reminder You can deploy honeytokens [anywhere in your SDLC](../core-concepts#where-should-you-place-your-honeytokens), but for source code repositories in particular, GitGuardian has the capability to detect the deployment of your honeytokens and monitor it in its dashboard. ::: ## Source information In the case of honeytokens deployed in git repositories that are integrated with GitGuardian, the source (and file) where the honeytoken has been placed is automatically detected and displayed. ![Honeytoken source detected](/img/honeytoken/source-detected.png) Again, watch out for honeytokens that get duplicated in several repositories: you would not know which source is compromised if it gets triggered. You can identify from there if a honeytoken gets propagated to several different repositories (eg. by forking a repository or copying code). :::tip If the repository where your honeytoken has been planted contains secret incidents that we have already detected, we will provide you with a link to quickly navigate to those secret incidents. Indeed, If a honeytoken alerts you that a repository has been compromised, it means that **all the secrets contained within it are at maximum risk**. ::: ## Monitor honeytoken coverage across your entire perimeter The Perimeter page now presents information related to honeytokens. ![Perimeter](/img/honeytoken/perimeter.png) For each source, monitor how many honeytokens are deployed, if any of them are triggered, and also if any have been found “Publicly exposed”. The right panel also displays how much of your perimeter is covered by honeytokens. --- ## Troubleshoot sources for Deployment jobs Refer to this document if you cannot find or select your sources in the Honeytoken Deployment jobs. ## Understand eligibility criteria for source selection ### Monitored repositories and projects In order to be used in deployment jobs, your source needs to be [monitored](../../internal-monitoring/integrate-sources/monitored-perimeter#source-status) by GitGuardian. Sources excluded from the monitored perimeter can, therefore, not be selected in deployment jobs. ### Active repositories and projects If your repository or project is archived and thus read-only, it cannot be used by deployment jobs. Therefore, only active sources are available for selection. ### Non-public repositories and projects Honeytokens should **not** be deployed on purpose in public locations. They would be immediately triggered for “normal” reasons as a result of being in the public space without it indicating a security incident. This is why we do not make them available when creating deployment jobs. If, for any reason, you wish to deploy a honeytoken in a public location, you will need to do it manually. ## Troubleshooting for each VCS integration ### GitLab sources Unless your GitLab project is public, it should be available for selection in Deployment jobs. If it’s not the case: - Check [here](https://dashboard.gitguardian.com/settings/integrations/gitlab) that the project is successfully integrated and monitored by GitGuardian. If you have checked the above and still encounter an issue, reach out to our [support team](mailto:support@gitguardian.com). ### GitHub.com sources GitHub.com sources (non-public and monitored) can be targeted for Honeytoken Deployment jobs, on the condition that a GitHub app with write access is enabled for these sources. Refer to our [GitHub integration guide](../../internal-monitoring/integrate-sources/vcs-integrations/github) for instructions on granting GitGuardian write access to your GitHub repositories. ### GitHub Enterprise Server sources GitHub Enterprise Server sources (non-public) can be targeted for honeytokens Deployment jobs, on the condition that a GitHub app with write access is enabled for these sources. Refer to our [GitHub Enterprise Server integration guide](../../internal-monitoring/integrate-sources/vcs-integrations/github-enterprise) for instructions on granting GitGuardian write access to your GitHub Enterprise Server repositories. ### Azure DevOps sources Unfortunately, Azure DevOps integration is not supported for Honeytoken Deployment jobs at the moment. If you’re interested in this feature, let us know through our [Support Page](/support/home). In the meantime, you can check [our other solutions](../deploy-honeytokens/deployment-methods) to deploy honeytokens. ### Bitbucket sources Unfortunately, Bitbucket integration is not supported for Honeytoken Deployment jobs at the moment. If you’re interested in this feature, let us know through our [Support Page](/support/home). In the meantime, you can check [our other solutions](../deploy-honeytokens/deployment-methods) to deploy honeytokens. --- ## Frequently Asked Questions ### What is the difference between a honeytoken and a traditional honeypot? A honeypot is a decoy system or network that is set up to simulate vulnerabilities, lure attackers, and detect or deflect their malicious activities. It's a trap that is designed to deceive attackers and redirect them away from the actual network. The honeypot can be a physical or virtual system, and it can be set up with vulnerable applications or services to attract attackers. The goal of a honeypot is to identify and study attackers' tactics, techniques, and procedures (TTPs) to help organizations better defend against real attacks. On the other hand, **a honeytoken is a piece of dummy credential that is deliberately placed in your SDLC to detect unauthorized access or malicious activity**. The goal of honeytokens is to provide an early warning of an attack, indicating that an attacker has gained access to the system or is attempting to access the false credential. Honeytokens do offer some unique benefits over traditional honeypots: 1. **Precision**: Honeytokens are highly precise. They can be deployed with specific and customized information, such as a unique username or a fake file name, which makes it easier to detect exactly what is being targeted. Traditional honeypots, on the other hand, require attackers to engage with a broader system, making it more difficult to pinpoint the specific vulnerability that is being exploited. 2. **Simplicity**: Honeytokens are relatively simple to implement and maintain. They require fewer resources to deploy and monitor than traditional honeypots, which can be time-consuming and costly to set up and maintain. 3. **Scalability**: Honeytokens can be easily scaled to different parts of an organization’s supply chain, allowing them to be deployed more broadly and monitored more effectively. Traditional honeypots can be more difficult to scale, as they require more resources and may not be as precise as honeytokens. 4. **Early detection**: Honeytokens can help organizations detect attacks earlier in the attack lifecycle. Since honeytokens are designed to detect unauthorized access attempts, they can alert organizations to potential security breaches before attackers are able to execute their attacks fully. Overall, honeytokens are a useful addition to an organization's security toolkit, as they offer specific benefits that traditional honeypots may not provide. ### Is it easy for an attacker to recognize a honeytoken? To automate their attacks, attackers often use secrets scanning tools that can quickly scan and identify secrets in a system. It's highly unlikely that an attacker would inspect each secret manually, as this would be an extremely time-consuming and inefficient process. It can be difficult for an attacker to recognize a honeytoken like a dummy AWS credential if it is properly implemented and hidden within a system. Since we are using actual AWS keys as honeytokens, attackers have no way of discovering them. ### How are honeytokens triggered? When an attacker tries to use a honeytoken, the login attempt is logged in AWS, giving us detailed information about the attack. This triggers an alert in GitGuardian's system, letting you know that someone has accessed the honeytoken along with valuable info about the attack. ### Why should you choose the GitGuardian Honeytoken SaaS version instead of using open-source projects? GitGuardian's Honeytoken SaaS version offers a number of benefits over open-source alternatives. For example, GitGuardian offers a more user-friendly interface and dashboard for easy honeytoken management. You can also monitor their deployment, in particular in the codebase, thanks to the synergy with our Secret Detection capabilities. GitGuardian's Honeytoken is specifically designed to detect code leakage by instantly alerting you if a honeytoken you've placed in your code is found on public GitHub. Our solution creates easily recognizable events that tag exposed honeytokens as "Publicly Exposed," so you can quickly identify which repo and honeytoken have been compromised and take swift action to safeguard your sensitive data. This ability sets GitGuardian apart from its competitors. It is much easier to roll out the solution. You don’t have to spend time and effort on installation. You can also get expert support and guidance from the GitGuardian team. --- ## Getting started(Honeytoken) ## Discover GitGuardian's Honeytoken Honeytoken is a new module in the GitGuardian platform. You can request a [live demo](https://www.gitguardian.com/book-a-demo)! :::info The module is restricted to Managers The Honeytoken module is reserved for users with a "Manager" access level on the GitGuardian workspace. ::: ## Create and deploy your first honeytoken {#create-and-deploy-your-first-honeytoken} ![Create first honeytoken](/img/honeytoken/create-first-honeytoken.png) In the Honeytoken module, click “Create honeytoken”. Enter a name for the honeytoken, and optionally a description. The description may contain more detail about where and how exactly you will place this honeytoken. You can also select or create some [custom tags](./manage#assigning-tags-to-honeytokens) to define your honeytoken in a more structured way. ![Create honeytoken](/img/honeytoken/create-honeytoken.png) > **Note:** For now, we are only proposing AWS keys, but we are exploring other types of honeytokens. ![Honeytoken created](/img/honeytoken/honeytoken-created.png) Congratulations! Your honeytoken creation is confirmed, and you get your honeytoken key. Insert this key [in the asset you want to protect](./core-concepts#where-should-you-place-your-honeytokens)! If an attacker ever trips on the honeytoken, you'll get an instant alert letting you know that it has happened. :::info This method allows you to decide exactly where and how your honeytoken will be inserted, but is quite manual. If you seek a more automated and effortless solution for deploying honeytokens across numerous repositories, explore our [Deployment Jobs](../honeytoken/deploy-honeytokens/deployment-jobs.md) feature. ::: ## Test your honeytoken If you want to test the triggering and alerting mechanism, you can trigger your own honeytoken. :::info To use the following method, ensure that the AWS CLI is installed on your system. If not, refer to the official [AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) for instructions on how to install it. ::: In the honeytoken detail page, click “How to test your honeytoken”. ![Test honeytoken](/img/honeytoken/test-honeytoken.png) Copy the AWS “get-caller-identity” command and run it in your terminal or command prompt. This will generate an event and thus trigger the honeytoken. Don’t forget to reset your honeytoken afterward to be alerted of any “real” trigger on it. --- ## Manage your population of honeytokens ## Overview The Honeytoken module homepage presents the list of your honeytokens, displaying the main information as well as the status of each one. ![Overview](/img/honeytoken/overview.png) You can filter the honeytokens based on a number of filters: - Type of honeytokens - Source (monitored repositories where the honeytoken is located) - Status (Active, Triggered, Revoked) - GitGuardian Tag (`Publicly exposed`) - [Custom Tag](../platform/collaboration-and-sharing/custom-tags) Clicking on the honeytoken name will direct you to its detail page. ![Honeytoken detailed page](/img/honeytoken/detailed-page.png) - The Information section summarises the main information about your honeytoken and allows you to edit the name, description and custom tags. - The Events section is where any usage of the honeytoken will get logged. - The Timeline section provides the history of the honeytoken: when and where it was created, edited, deployed in a monitored source, triggered… It is also possible to add comments there. ## Assigning Tags to Honeytokens Each honeytoken can receive one or several custom tags. Please note that when assigning custom tags to a honeytoken, only one value from each key may be used. ## Number of allowed honeytokens AWS honeytokens are available in a limited number. If you have reached this limitation, it is not possible to create new honeytokens anymore. Revoked honeytokens are not included in the count of honeytokens. Only active and triggered honeytokens are included. If you don’t have enough honeytokens, you can reach out to GitGuardian to discuss extending your limitation. --- ## Respond to a triggered honeytoken GitGuardian helps you by providing as much contextual information as possible about the events and some general guidelines: ![Reset](/img/honeytoken/guidelines.png) ## The lifecycle of a honeytoken The lifecycle of a honeytoken and the possible actions are shown in the following schema: ```mermaid graph LR Active -.->|Event happens!| Triggered Triggered -->|Reset| Active Triggered -->|Revoke| Revoked Active -->|Revoke| Revoked ``` ## Reset a triggered honeytoken If your investigation has determined that the trigger alert was a false alarm, such as when one of your developers genuinely tried to use the honeytoken, or when it was triggered for test purpose, you should reset the honeytoken. Resetting the honeytoken changes its status back to Active, allowing it to be triggered again on future attempts. After resetting, your honeytoken is as good as new! ![Reset](/img/honeytoken/reset.png) ## Revoke a triggered honeytoken If your investigation has confirmed a real security incident, and you have taken the necessary steps to remediate the incident and ensure that your environment is protected, it is important to revoke the triggered honeytoken. This honeytoken is now compromised and thus useless. Revoking the honeytoken will deactivate it entirely by deleting the associated AWS key pair. Events will no longer be logged on this honeytoken. :::caution Remember to create a new honeytoken to replace the compromised one in order to be alerted of new incidents in the same environment! ::: ![Revoke](/img/honeytoken/revoke.png) --- ## Honeytoken for self-hosted installations ## Enabling Honeytoken on self-hosted environments :::info Honeytoken is available to self-hosted installations as an add-on on top of the Secret Detection license. ::: To enable Honeytoken in your self-hosted GitGuardian instance, please contact support@gitguardian.com. Please note that this feature is not compatible with self-hosted installations in an airgapped environment as it requires access to AWS. After your request, we'll enable the feature, establish your dedicated AWS infrastructure for Honeytokens, and reach out to finalize the setup. ### Synchronize license After receiving confirmation from your GitGuardian contact regarding the feature activation for your instance(s), it is crucial to ensure that the GitGuardian application's [license is synchronized accordingly](/self-hosting/license-management). Once this task is completed, Honeytoken will appear on your GitGuardian dashboard within a few minutes. However, note that you won't be able to create any honeytokens until you complete the next step. ### Set up the AWS integration To configure the AWS integration required for the AWS honeytokens, your GitGuardian contact will share a download link for the json file (`aws_honeytoken_config.json`). Follow these steps to complete the configuration: 1. Access the Admin area of your GitGuardian dashboard (administrative rights are necessary). 2. Navigate to Settings > Honeytoken and upload the provided JSON file. 3. This action triggers the configuration process, which establishes users and keys within your dedicated AWS organization. 4. While the full setup may take some time, you can start using available honeytokens immediately. 5. Monitor the dashboard to observe the honeytoken count increasing as the setup progresses. Navigate to the Admin area in your GitGuardian dashboard (admin rights required). Go to Settings > Honeytoken and upload the provided JSON file. This triggers the configuration process, setting up users and keys within your dedicated AWS organization. Full setup may take some time, but you can begin using available honeytokens immediately. Monitor the dashboard to see your honeytoken count rise as the setup progresses. ## Health checks The Health Checks page in the Admin area contains a Honeytoken section, showing the AWS integration statuses. ### AWS integration health checks There are two types of health checks: - "Access to AWS resources": - This health check verifies whether the instance can successfully create AWS users and keys intended for use as honeytokens. - Additionally, it ensures that access to the S3 bucket containing logs is operational. - If any issues arise during this check, it can be manually restarted by clicking the "Check again" button. - “Reception of events”: - This health check monitors the seamless functioning of the various methods we employ to collect honeytoken events. - Unlike the previous check, this one is scheduled to run at regular intervals and cannot be manually restarted. ![Healthchecks](/img/honeytoken/healthchecks.png) ## Network requirements ### Inbound rules | Port | Source | Destination | Description | |------|--------|-------------|-------------| | 443 | AWS* | All K8S nodes | Non real-time events webhook | | 443 | AWS* | All K8S nodes | Real-time events webhook | \* [AWS IP address ranges](https://docs.aws.amazon.com/vpc/latest/userguide/aws-ip-ranges.html) ### Outbound rules Outbound requests include the creation of AWS tokens, and retrieving the logs with events. Every outbound communications between your GitGuardian instance and AWS are HTTPS protocol on port 443. | Port | Source | Destination | Description | |:----:|-------:|----------------------------------------------------:|---------------------------------------:| | 443 | All K8S nodes | `sts.amazonaws.com` | Authentication AWS API | | 443 | All K8S nodes | `sts.us-west-2.amazonaws.com` | Regional Authentication AWS API | | 443 | All K8S nodes | `iam.amazonaws.com` | AWS Identity and Access Management API | | 443 | All K8S nodes | `s3-accesspoint.us-west-2.amazonaws.com` | Regional S3 AWS API | | 443 | All K8S nodes | `organizations.us-east-1.amazonaws.com` | Organizations AWS API | --- ## Understand honeytoken events and trigger mechanism An event in the context of honeytokens represents the recorded use of a honeytoken. When a honeytoken is in `Active` status, any new event will immediately change its status to `Triggered`, initiating the corresponding alerts. :::info Exception The trigger mechanism differs for allowed events. See the [related section](#open-vs-archived-vs-allowed-events) for more details. ::: ```mermaid graph LR A[Honeytoken is Active] -->|New event!| B{Is the event allowed?} B -->|Yes| C[Honeytoken remains Active] B -->|No| D[Honeytoken is Triggered] ``` ## Events data Events can be seen in the honeytoken detail page. For AWS honeytokens, you can observe the following information: - **Timestamp**: The exact moment of honeytoken usage - **IP address and country**: Location information linked to the honeytoken usage - **User-agent**: The accessing software's identity (may be blank). - **Action**: Specific action performed like `GetCallerIdentity`, `ListBuckets`, etc. ## Events tags Event tags provide additional context based on the event's IP address. You can create custom tags using the [IP rules](#ip-rules-configuration) settings. Furthermore, GitGuardian manages some default tags: - `GitGuardian Public Monitoring IP`: Implies the event originates from an IP address used by GitGuardian to monitor public GitHub. This indicates that the honeytoken itself has been leaked and is publicly exposed on GitHub. - `AWS internal IP`: Signifies the event originates from within AWS, commonly occurring when a honeytoken is publicly exposed on GitHub. Note that for this particular case there is no actual IP address attached to the event. ## Open vs. archived vs. allowed events Events can be categorized into three states: - **Open**: The default state of events. - **Archived**: Initiated by resetting or revoking a honeytoken, resulting in the archiving of all open events.. - **Allowed:**: Events from IPs on the allow-list, ignored by the trigger mechanism. Archived and allowed events remain present, but they are hidden by default. You can use the status filter in the Events section to see them. ![Events-with-archived-allowed](/img/honeytoken/events-with-archived-allowed.png) Both archived and allowed events are still stored but are hidden by default. Use the status filter in the Events section to view them. Archived and allowed events are displayed in grey, with allowed events marked by a green tick next to the IP address. ## Pausing events reception When a honeytoken accumulates 100 open events, the reception of new events will be paused. We pause event reception at this threshold because additional events beyond this number are unlikely to provide new information and could negatively impact performance. This situation typically occurs in the following scenarios: - The honeytoken becomes [publicly exposed on GitHub](./code-leakage), causing scanners to detect and test it. In this case, the honeytoken should definitely be considered compromised, and revoked. - Some internal and known tools regularly call the honeytoken for legitimate reasons. In this case, you may want to [allow](#ip-allowlisting) these calls and then reset the honeytoken. Note that events reception will resume if the honeytoken is reset, as this action resets the count of open events to zero. ## Using IP rules to enrich and manage events IP rules help in declaring known IP ranges for better identification and management of events, serving two purposes: IP tagging and IP allow-listing. ### IP tagging The feature enables you to attach custom tags to events based on IP addresses, useful for identifying events from familiar sources like your company's internal network. ### IP allowlisting Each tag and its associated IP range can be added to an allowlist. Events from these IPs are ignored and do **not** trigger the honeytoken. :::caution Handle this feature cautiously as it might lead to overlooking unauthorized attempts on your honeytokens. ::: Events from allowed IPs are recorded but greyed out and excluded by default. You can opt to display them using the “status” filter. ### IP rules configuration To manage custom IP rules, go to Settings > Honeytoken > [IP rules](https://dashboard.gitguardian.com/settings/secrets/honeytoken). While GitGuardian sets some uneditable rules, you can create and manage your own using valid CIDRs for IP ranges. ![IP-rules](/img/honeytoken/ip-rules.png) ![Modify-IP-rule](/img/honeytoken/modify-ip-rule.png) :::caution No retroactive application of the IP rule on existing events Adding, modifying, or deleting IP rules won't affect existing honeytoken events. Only future events will be impacted. ::: :::info Behavior in case of several rules for same IP range Multiple rules for the same IP range are allowed. Events matching these rules receive all associated tags. If any rule has "allow-list" selected, those events will be considered 'allowed', except for events from GitGuardian Public Monitoring IPs, which cannot be overridden. ::: --- ## Analytics GitGuardian's Analytics offers robust data visualization and actionable insights, empowering you to monitor your security posture, track performance trends, and make informed decisions. :::info Analytics are only accessible to: - Workspace **Owner** and **Managers**. - **Members** with `Full access` incident permissions on the **All-incidents** team. ::: The Internal Monitoring Analytics is structured to deliver clear, in-depth insights across four key security areas: - **Protect:** Provides an overview of your current monitoring coverage — are your sources monitored effectively? Do you have any gaps? - **Detect:** Helps you identify the sources and teams involved in leaks, including recurring issues, so you can plan training or actions to reduce and prevent them. - **Remediate:** Guides you in addressing existing incidents, prioritizing the most critical cases, and leveraging GitGuardian's automated remediation tools. - **Prevent:** Helps you track and assess whether your prevention strategy is effective, and ensures that appropriate measures are in place to prevent future problems. For detailed information on each analytics dimension, available metrics, and how to use the analytics tools, see the [Internal Monitoring Analytics guide](/platform/analytics/internal-monitoring). --- ## Collaboration between Application Security and development teams ## What is the AppSec Shared Responsibility Model? Shared responsibility essentially means that security should be owned by various teams acting in collaboration to implement its various layers all along the SDLC: - Developers are provided with access to the right tools to set up their guardrails and remediate the security issues they’re the most familiar with, in context. - Security engineers are responsible for defining and implementing security policies as well as their controls. Sharing responsibility means they can dedicate more time investigating complex or low-assurance findings. - Platform/Ops can be tasked with ad-hoc responsibilities to make sure security CI/CD controls are correctly configured, or even to take ownership of certain types of vulnerabilities. ## Why do we need it? Security can no longer be an afterthought or solely addressed once applications start running in production environments. The everything-as-code approach or the collapse of the Software Development Lifecycle (SDLC) into Source Control Management (source code, CI/CD configurations, policy-as-code, infrastructure-as-code, documentation-as-code) has spawned a whole new range of attack vectors. In turn, this has led to a shift in the priorities of attackers from applications in runtime to the tools that make up the development environments and CI/CD pipelines. Organizations can only mitigate such threats by addressing security continuously throughout the SDLC, with the help of the developers designing and authoring the code going to production. Our observations show that, on average, organizations run application security programs with one to two security engineers for every 100 developers. In such a configuration, the vulnerabilities introduced in source code outmatch the capacity of security teams to handle them. Only an **Application Security Shared Responsibility Model**, where developers contribute their fair share, can scale in this new environment. ## How can GitGuardian help your organization achieve it? ### For AppSec teams GitGuardian aims to: - Provide AppSec teams with visibility and control over the SCM, DevOps tools and all other components of the SDLC. - Ease the burden of remediation by pulling developers who own the context closer to the process. ### For development teams GitGuardian aims to: - Guide developers throughout the remediation process (feedback collection, steps to follow, etc.) and empower them to resolve incidents by themselves when possible. - Equip developers with supportive tooling (command-line interface, SDKs, REST API) to implement security guardrails in the environments they are most familiar with. --- ## How Internal Monitoring works GitGuardian scans your internal sources to detect secrets in real-time, preventing credentials from being exposed across your organization's infrastructure. This includes version control repositories, container registries, documentation platforms, messaging systems, and more. ## How it works GitGuardian integrates with your internal sources through various methods depending on the platform: - **APIs**: Direct integration with platform APIs for comprehensive scanning - **Webhooks**: Real-time event notifications for immediate scanning - **Native integrations**: Platform-specific apps and connectors When content is created or modified, GitGuardian immediately scans it using our comprehensive [library of secrets detectors](../../secrets-detection/secrets-detection-engine/detectors/introduction). If a secret is detected: 1. An incident is created in your dashboard instantly 2. You receive real-time alerts 3. Your team can respond immediately to prevent exposure ### VCS integration specifics GitGuardian's internal repository monitoring product integrates natively with your VCS (Version Control System), hence on the **server side**. This is done through a GitHub app or a webhook for GitLab, Bitbucket and Azure repos. GitGuardian "listens" to all the events reaching the **post-receive hook stage**. GitGuardian integrates directly with your VCS at the server level through native integrations: - **GitHub**: GitHub App - **GitLab, Bitbucket, Azure Repos**: Webhooks This server-side approach means GitGuardian monitors all events that reach the **post-receive hook stage**—after code is pushed but before it's fully committed to your repository. Read our [blog article](https://blog.gitguardian.com/git-hooks-automated-secrets-detection/) to learn more about git hooks and why they're essential for automated secrets detection. ## Real-time vs historical scanning ### Real-time scanning GitGuardian continuously monitors your internal sources for new content and changes. When new data is detected, it's immediately scanned for secrets, ensuring rapid response to potential exposures. ### Historical scanning Beyond real-time monitoring, GitGuardian can scan existing content that was created before you installed GitGuardian. This comprehensive audit ensures no legacy secrets remain hidden across your systems. We encourage running historical scans to get complete visibility into your security posture. --- ## Incident statuses :::info A secret incident can be in one of two overall states: - **Open**: including Triggered and Assigned statuses - **Closed**: including Resolved and Ignored statuses ::: **Triggered**: A triggered incident is an incident detected and stored by GitGuardian but not yet investigated by a member of your dashboard. **Assigned**: An assigned incident is being investigated by a specific member of the dashboard. It is not resolved or ignored yet. **Resolved:** A resolved incident is an incident considered as remediated. In the case of secrets incidents, you must revoke the secret (and optionally erase all evidence from the git history) before considering it resolved. > Erasing all evidence from the git history is optional and depends on your code policy. - If you consider a new occurrence of an incident that has already been resolved to be problematic, you will want the regression behavior enabled. When the regression behavior is turned `On` and a new occurrence is detected by real-time scanning of a connected source, GitGuardian reopens the incident, changes its status back to **Triggered**, and raises a notification. The regression behavior only applies to occurrences detected through real time monitoring. A resolved incident won't be reopened if a new occurrence is uncovered by a historical scan. - If rewriting the git history is not important to you and only revocation matters, you can turn `Off` the regression behavior and GitGuardian will silently add the occurrence to the existing resolved incident without delivering any notifications. > The regression behavior can be configured in the [Incidents lifecycle section of your workspace General settings](https://dashboard.gitguardian.com/settings/workspace/general). ![Regression setting](/img/internal-monitoring/remediate/incidents/regression_setting.png) **Ignored**: An ignored incident is an incident not considered as such by a member of your team and does not require remediation. For secrets incidents, ignore reasons can be: - this is not a secret (false positive) - this is test credential - this is low risk secret > Ignoring an incident means that you don't want GitGuardian to consider it anymore. If a new occurrence appears for an ignored incident, GitGuardian will not reopen it or alert you. ```mermaid graph LR Triggered --> Assigned Assigned --> Resolved Assigned --> Ignored Ignored -.->|Reopen| Triggered Resolved -.->|Reopen or regression| Triggered ``` ## Lifecycle of an incident ### 1. Receiving incidents alerts As explained in the section [How Internal Monitoring works](../core-concepts/how-internal-monitoring-works), GitGuardian scans every commit in real-time and sends an alert **upon detection of a new incident**. All the members of the dashboard are alerted by email, and on their alerting integrations, in order to tackle the new incident as quickly as possible. > Note that for incidents detected thanks to historical scanning, we do not send an alert per incident but rather an email recap with all the incidents discovered on a given historical scan. As mentioned above, all the members of the dashboard receive alert upon regression of an already-resolved incident. ### 2. Assigning incidents Investigation and remediation of an incident can take some time. So let your teammates know that you are **currently working on a given incident**, by declaring the assignee, in order not to duplicate work within your team. **Prioritizing and knowing which incident is more severe than another can be very challenging**, especially when you are dealing with a large number of incidents. Have a look at our [Prioritize and explore guide](../remediate/prioritize-incidents.md) to read our good pratices for spotting the incidents you need to tackle first. ### 3. Collaborate and remediate Once you decide which incident you want to work on, a new phase of collaboration and remediation starts. GitGuardian helps you by providing as much as **contextual information** as possible and features that help you **get in touch with the appropriate stakeholders** and **check that the incident has been properly remediated**. Read more about this topic in our [Remediating incidents](../remediate/remediate-incidents.md) section. Ultimately, you can resolve or ignore the incident. You will always have the possibility to reopen it manually. In the specific case of resolved incidents for which new occurrences are detected again, you can configure GitGuardian to automatically re-open incidents and receive alerts or not by choosing your preferred [Regression setting.](https://dashboard.gitguardian.com/settings/workspace/general) All user activity and team notes attached to a given incident can be found in the **Timeline section** of the incident page. ![Incident timeline](/img/internal-monitoring/remediate/incident-detail/timeline.png) --- ## Secrets incidents ## What is a secret incident? What are its implications? Secret incidents are open issues that need your attention to be resolved. They are created thanks to [our secrets detection engine](../../secrets-detection/home) that scans your internal sources for [hardcoded secrets](../../secrets-detection/core-concepts/what-is-a-secret.md) to display them in your dashboard. Leaving a secret in plain text represents a threat for the security of the resources that are protected by that secret. To learn more about why hardcoded secrets are a vulnerability that needs your Application or Product Security teams' attention, read the related paragraph in our [Core Concepts](../../secrets-detection/core-concepts/what-is-a-secret) section. --- ## Secrets occurrences ## What are the occurrences of an incident? The **same secret can be seen multiple times** in your VCS. They are referred to as occurrences. GitGuardian streamlines the remediation process by automatically **grouping multiple occurrences of the same secret into a single secret incident**. Thus, an occurrence of a secret incident is uniquely identified by the combination of the following parameters: - the source (for instance: a GitHub repository or a GitLab project) impacted by the secret occurrence, - the commit in which we detected the secret occurrence, - the commit file containing the secret occurrence, - the line within the commit file where the secret occurred. Alerts are sent only when a new incident is created or reopened because of a regression. A new occurrence attached to an already-existing open secret incident won't raise any alerts. > GitGuardian sets a maximum limit of 1,000 occurrences for a single secret incident (this does not apply to the self-hosted platform). ### Grouping of occurrences into secret incidents GitGuardian enhances the remediation process by automatically **grouping multiple occurrences of the same secret into a single secret incident**. However, within Business Workspaces, the workspace Owner has the exclusive ability to adjust how these secret occurrences are grouped within the [settings](https://dashboard.gitguardian.com/settings/workspace/settings/secrets/general). Two levels of granularity are available: 1. **per secret** [default] - All occurrences of the same secret across different sources (e.g., repositories) are consolidated into a single secret incident. - This means if a particular secret is found in multiple sources, it will generate only one secret incident. 2. **per secret x source:** - Occurrences of the same secret are grouped into separate secret incidents based on their respective sources. - This means that if the same secret appears in multiple sources, each source will have its own individual secret incident. - You can still know as a manager if the same incident has created other incidents in different sources (if you need help filtering by these related incidents via the API, contact support@gitguardian.com for example script). This configuration helps tailor the grouping strategy to align with your company's remediation processes and data privacy policies. ![Occurrences grouping setting](/img/internal-monitoring/detect/occurrences_grouping_setting.png) :::warning Changing the occurrence grouping setting should be done **with utmost care, as it has a significant impact on secret incident population and analytics**. This modification should be considered a **one-off action**. Upon changing this setting, all existing secret incidents will be migrated to comply with the new grouping mode, and please note that this migration process may take some time. ![Occurrences grouping setting warning modal](/img/internal-monitoring/detect/occurrences_grouping_setting_warning_modal.png) ::: Alerts are sent only when a new incident is created or reopened because of a regression. A new occurrence attached to an already-existing open secret incident won't raise any alerts. > GitGuardian sets a maximum limit of 1,000 occurrences for a single secret incident (this does not apply to the self-hosted platform). --- ## Export data GitGuardian allows you to export data in the form of a CSV report. ## CSV report ### Export options CSV reports are currently only available for secrets incidents. To export data, use the menu in the view, then select the options for the export: - **Individual secrets incidents vs All occurrences**. - **Individual secrets incidents** gives you the list of the secrets incidents present on your perimeter without details about multiple occurrences they may contain. It is useful for high level reporting. - **All occurrences** gives you the detailed list of all the occurrences and their location. Such reports can be used for remediation or more granular analysis. These two reports are consistent between one another and you can cross-reference their data using the common key `incident_id`. - **Show secrets vs Hide secrets**: fighting secrets sprawl, GitGuardian gives you the option to hide the secret itself in your CSV exports. - **Filtering**: CSV reports can reflect your filtering and selection. - **Matching the current filters and search query**: only incidents matching your current filtering criteria will be exported. - **Matching view**: incidents matching the filters from the active view will be exported. If you have unsaved modifications in the view, they will not apply. - **No filters**: all incidents will be exported, regardless of the view or filters applied. - **Separator**: customize the separator of the report. - **comma-separated** - **tab-separated** ![export_as_csv](/img/internal-monitoring/tracking-performance/export_as_csv_from_view.png) ![csv_export_modal](/img/internal-monitoring/tracking-performance/csv_export_modal.png) Note that it is also possible to export incidents that have been manually selected. Select your incidents and hit Download from the bulk actions bar: ![export_selection](/img/internal-monitoring/tracking-performance/export_selection.png) ### Export format The format of the CSV export will look like the below examples. #### Individual secrets incidents | incident_id | created_at | secret_hash | detector_name | matches | occurrences_count | assignees | resolved_at | ignored_at | gitguardian_url | severity | risk_score | validity | status | ignore_reason | custom_tags | secret_revoked | tags | incident_name | | ----------- | -------------------------------- | ---------------------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------- | ----------------- | -------------------- | -------------------------------- | ---------- | -------------------------------------------------------------- | -------- | ---------- | -------- | --------- | ------------- | ------------------------------ | -------------- | -------------- | ---------------------- | | 186644 | 2020-11-17 08:19:48.374388+00:00 | CKRCZ36VU1JgnPTN2oWtW5Rn2fE7p/d9G+XQveEXlSg0d+Vjq3vgT7VWMTb6ax/h | Slack User Token | \{"apikey": "xoxp-6378355290-4543728424-36021270421-7714dc2119e296b6e8be1cb6cde31ef5"\} | 2 | | | | `https://dashboard.gitguardian.com/workspace/8/incidents/186644` | Critical | 55 | valid | TRIGGERED | | | | | Slack User Token in... | | 49568 | 2020-03-25 13:26:11.134688+00:00 | kFXL5aDL5Pvf3odFhfS1Sfxxguqg7/tFOLgmM94+EPnMHwNGLCAWyy4SR5jhsuGk | AWS Keys | \{"client_id": "AROAK1XZAJSZHCUDQSHT", "client_secret": "cH1SL1LFzSwWoJV5wDtn8rcTSNiieufBOe58b6Lu"\} | 4 | john.doe@company.com | 2020-11-03 14:48:41.634750+00:00 | | `https://dashboard.gitguardian.com/workspace/8/incidents/49568` | Medium | 30 | invalid | RESOLVED | | team:backend\|env:production | TRUE | SENSITIVE_FILE | AWS Keys in config.yml | | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | - **incident_id**: id of the GitGuardian incident - **created_at**: date of the incident - **secret_hash**: hash of the actual secret matches. It is unique per secret. - **detector_name**: type of the secret detected by GitGuardian secrets detection engine - **matches**: the actual secret. Sometimes it can be composed of several components that GitGuardian calls matches (eg: `client_id`, `client_secret`). That's why it is under JSON format. Empty if you select **Hide secrets** option. - **occurrences_count**: count of occurrences of the secret incident - **assignees**: email of the incident assignee who is member of the GitGuardian workspace - **resolved_at**: timestamp of incident resolution date. If not empty, it means that the status of the incident is **resolved** - **ignored_at**: timestamp of incident ignore date. If not empty, it means that the status of the incident is **ignored** - **gitguardian_url**: link to the incident page on your GitGuardian workspace - **severity**: severity level for the incident - **risk_score**: risk score of the incident (integer, can be null) - **validity**: validity of the secret (valid, invalid, no_checker, failed_to_check, unknown) - **status**: status of the incident (TRIGGERED, ASSIGNED, RESOLVED, IGNORED) - **ignore_reason**: declarative ignore reason by the person who ignored the incident (test_credential, false_positive, low_risk, invalid) - **custom_tags**: custom tags assigned to the incident, pipe-separated key:value pairs (e.g. `team:backend|env:production`) - **secret_revoked**: declarative information indicating whether or not the secret is revoked by the person who resolved the incident (True or False) - **tags**: tags of the incident (CHECK_RUN_SKIP_FALSE_POSITIVE, CHECK_RUN_SKIP_LOW_RISK, CHECK_RUN_SKIP_TEST_CRED, DEFAULT_BRANCH, FALSE_POSITIVE, FROM_HISTORICAL_SCAN, IGNORED_IN_CHECK_RUN, PUBLIC, PUBLICLY_LEAKED, REGRESSION, REVOCABLE_BY_GG, SENSITIVE_FILE, TEST_FILE). Note: The `PUBLICLY_LEAKED` tag indicates any type of public exposure. See [Public exposure information](./remediate/investigate-incidents.md#public-exposure-information) for details on exposure types. - **incident_name**: display name of the incident #### All occurrences | created_at | secret_hash | detector_name | matches | source_url | source_name | commit_url | commit_sha | commit_author | author_email | filepath | incident_id | gitguardian_url | validity | presence | occurrence_id | tags | element_url | author_name | incident_name | | -------------------------------- | ---------------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------- | ---------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ------------- | ---------------------------- | -------- | ----------- | -------------------------------------------------------------- | -------- | -------- | ------------- | ---------------- | -------------------------------------------------------- | ----------- | ---------------------- | | 2020-11-17 10:19:41.495062+00:00 | CKRCZ36VU1JgnPTN2oWtW5Rn2fE7p/d9G+XQveEXlSg0d+Vjq3vgT7VWMTb6ax/h | Slack User Token | \{"apikey": "xoxp-6378355290-4543728424-36021270421-7714dc2119e296b6e8be1cb6cde31ef5"\} | `https://github.com/my-org/my-repos` | my-org/my-repos | `https://github.com/my-org/my-repos/commit/722682f316a934129996eccc4286d56a33812212#diff-568470d013cd12e4f388206520da39ab9a4e4c3c6b95846cbc281abc1ba3c959L3` | 722682f316a934129996eccc4286d56a33812212 | Lucius Fox | lucius-fox-gg@protonmail.com | app.py | 186644 | `https://dashboard.gitguardian.com/workspace/8/incidents/186644` | valid | present | 4367688 | PUBLICLY_EXPOSED | `https://github.com/my-org/my-repos/commits/commit-leaked` | John Doe | Slack User Token in... | | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | - **created_at**: date of the occurrence - **secret_hash**: hash of the actual secret matches. It is unique per secret. - **detector_name**: type of the secret detected by GitGuardian secrets detection engine - **matches**: the actual secret. Sometimes it can be composed of several components that GitGuardian calls matches (eg: `client_id`, `client_secret`). That's why it is under JSON format. Empty if you select **Hide secrets** option. - **source_url**: VCS link of the source - **source_name**: name of the source - **commit_url**: VCS link of the commit (deprecated, please use element_url instead) - **commit_sha**: sha of the commit - **commit_author**: git name of the commit author (deprecated, please use author_name instead) - **author_email**: email of the occurrence element author - **filepath**: filepath containing the occurrence - **incident_id**: id of the GitGuardian incident the occurrence belongs to - **gitguardian_url**: link of the incident page on your GitGuardian workspace - **validity**: validity of the secret (valid, invalid, no_checker, failed_to_check, unknown) - **presence**: presence in git history of the occurrence (present, removed) - **occurrence_id**: id of the occurrence - **tags**: tags of the occurrence (CHECK_RUN_SKIP_FALSE_POSITIVE, CHECK_RUN_SKIP_LOW_RISK, CHECK_RUN_SKIP_TEST_CRED, DEFAULT_BRANCH, FALSE_POSITIVE, FROM_HISTORICAL_SCAN, IGNORED_IN_CHECK_RUN, PUBLIC, PUBLICLY_EXPOSED, PUBLICLY_LEAKED, REGRESSION, REVOCABLE_BY_GG, SENSITIVE_FILE, TEST_FILE) - **element_url**: link to the occurrence element - **author_name**: name of the occurrence element author - **incident_name**: display name of the incident ## Public monitoring CSV export The following fields are specific to **public monitoring** exports. They differ from internal monitoring exports due to the nature of publicly exposed secrets. ### Individual secrets incidents (public monitoring) The public monitoring incidents export includes all the fields from the base incidents export (incident_id through custom_tags), plus the following fields instead of secret_revoked: | incident_id | created_at | secret_hash | detector_name | matches | occurrences_count | assignees | resolved_at | ignored_at | gitguardian_url | severity | risk_score | validity | status | ignore_reason | custom_tags | ignore_reason | resolve_reason | tags | sources_count | attachment_reasons | | ----------- | ---------- | ----------- | ------------- | ------- | ----------------- | --------- | ----------- | ---------- | --------------- | -------- | ---------- | -------- | ------ | ------------- | ----------- | ------------- | -------------- | ---- | ------------- | ------------------ | | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | Fields shared with internal monitoring are documented above. The following are **specific to public monitoring**: - **resolve_reason**: reason provided when the incident was resolved - **sources_count**: number of distinct sources where the secret was found - **attachment_reasons**: space-separated list of reasons the incident is attached to the account's perimeter - **tags**: tags of the incident, space-separated (COMPANY_NAME_IN_COMMIT, DECODED_BASE64, DECRYPTED, DOMAIN, FALSE_POSITIVE, FROM_EXPLORE, FROM_HISTORICAL_SCAN, FROM_SECRET_GRASPER, INTERNALLY_LEAKED, IS_COMPANY_CONTEXT, JWT_PROPERTIES, MINIFIED_FILE, PROD, SENSITIVE_FILE, TEST_FILE, WHITELISTED) ### All occurrences (public monitoring) The public monitoring occurrences export has a different structure from internal monitoring, with additional actor information from GitHub: | created_at | secret_hash | detector_name | matches | source_url | source_name | filepath | commit_url | commit_sha | committer_name | committer_email | committer_github_id | committer_github_login | author_email | author_name | author_github_id | author_github_login | actor_github_id | actor_github_login | incident_id | incident_status | gitguardian_url | validity | presence | occurrence_id | tags | attachment_reasons | | ---------- | ----------- | ------------- | ------- | ---------- | ----------- | -------- | ---------- | ---------- | -------------- | --------------- | ------------------- | ---------------------- | ------------ | ----------- | ---------------- | ------------------- | --------------- | ------------------ | ----------- | --------------- | --------------- | -------- | -------- | ------------- | ---- | ------------------ | | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | .... | Fields shared with internal monitoring are documented above. The following are **specific to public monitoring occurrences**: - **committer_name**: name of the commit committer - **committer_email**: email of the commit committer - **committer_github_id**: GitHub ID of the committer - **committer_github_login**: GitHub login of the committer - **author_github_id**: GitHub ID of the commit author - **author_github_login**: GitHub login of the commit author - **actor_github_id**: GitHub ID of the pusher - **actor_github_login**: GitHub login of the pusher - **incident_status**: status of the parent incident (TRIGGERED, ASSIGNED, RESOLVED, IGNORED) - **tags**: tags of the occurrence, space-separated (COMPANY_NAME_IN_COMMIT, DECODED_BASE64, DECRYPTED, DOMAIN, FALSE_POSITIVE, FROM_EXPLORE, FROM_HISTORICAL_SCAN, FROM_SECRET_GRASPER, IS_COMPANY_CONTEXT, JWT_PROPERTIES, MINIFIED_FILE, PROD, SENSITIVE_FILE, TEST_FILE, WHITELISTED) - **attachment_reasons**: space-separated list of reasons the occurrence is attached to the account's perimeter --- ## Bring Your Own Sources Extend secret detection to any custom data source beyond GitGuardian's native integrations. ## Why Use Bring Your Own Sources? Every organization has unique systems, legacy platforms, and custom tools where secrets can hide beyond standard integrations. Bring Your Own Sources bridges the gap by enabling you to scan CI/CD logs, legacy databases, internal scripts, file shares, and any proprietary system where developers might store or accidentally expose credentials, ensuring comprehensive secret detection across your entire technology stack. **Key benefits:** - **Complete coverage**: Extend GitGuardian to any system or data source in your environment - **Flexible scanning**: Use scripts, automation tools, or manual processes to feed data - **Unified monitoring**: Manage custom source incidents alongside native integrations - **API-first approach**: Programmatically integrate with existing workflows and toolchains ## Capabilities | Feature | Support | Details | | ----------------------- | --------------- | -------------------------------------------------------- | | **On-demand Scanning** | ✅ | Trigger scans via API or scripts | | **Monitored Perimeter** | ✅ | Custom source organization and categorization | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ | Not applicable for custom data sources | | **File Scanning** | ⏳ (Coming Soon) | PDF, Office documents, archives, etc... are not scanned | **What we scan:** - Raw text, logs and code files - Docker images' layers and, dockerfile and build arguments :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Business** or **Enterprise** plan for custom source functionality - **Custom scanning implementation** using ggshield, scripts, or automation tools ## How It Works With Bring Your Own Sources, connect any data source to GitGuardian in minutes: 1. [**Set up a custom source**](./bring-your-own-sources#setting-up-a-custom-source) in the GitGuardian dashboard or via the GitGuardian API. 2. **Scan your custom sources** using **[ggshield](./bring-your-own-sources#scanning-custom-sources-using-ggshield)**, simple scripts, or **[an automation tool](#scanning-custom-sources-using-an-automation-workflow-for-example-n8n)**. Incidents are automatically created and linked to your custom integration. 3. [**Filter, view, and manage incidents**](#filter-view-and-manage-incidents) from your custom sources just like with native integrations in the GitGuardian dashboard. ## Setting Up a Custom Source ### Step 1: Create a Custom Integration 1. Navigate to **Settings > Integrations > Sources** in your GitGuardian dashboard. 2. From the **Secrets scanning** tab, in the **Custom Sources** section, click **Add Custom Source**. ![Find Custom Sources](/img/internal-monitoring/integrate-sources/bring-your-own-sources/byos-from-sources.jpg) 3. Give your source a clear name (required) and description (optional). ![Create Custom Source](/img/internal-monitoring/integrate-sources/bring-your-own-sources/create-byos.jpg) 4. Click **Create Integration**. Once saved, note the generated UUID; you’ll need it shortly. Alternatively, you can create your custom source using the [custom-sources endpoint of our Public API](https://api.gitguardian.com/docs#tag/Sources/operation/create-custom-source). You will need a dedicated Service Account Token with the `scan` and `scan:create-incidents` permissions to proceed. Upon creation, you'll receive: - A **unique integration ID** to attach findings and declare incidents to your custom integration. You can view it at any time after creation. - Instructions for setting up a service account. ![Custom Source Created](/img/internal-monitoring/integrate-sources/bring-your-own-sources/byos-created.jpg) ### Step 2: Configure a Service Account 1. Create a dedicated [Service Account](/api-docs/service-accounts#creating-a-service-account) with the following permissions: `scan` and `scan:create-incidents`. This allows scanning and creating incidents from your custom sources. 2. Configure your environment with the necessary credentials, depending on your internal processes (for example, environment variables or a direct connection to your secrets manager, etc.): ```bash export GITGUARDIAN_API_KEY="your-service-account-token" export GITGUARDIAN_INSTANCE="https://api.gitguardian.com" # For SaaS US # export GITGUARDIAN_INSTANCE="https://api.eu1.gitguardian.com" # For SaaS EU # export GITGUARDIAN_INSTANCE="https://your-instance.com/exposed" # For self-hosted ``` :::info **Security note** We recommend creating a dedicated service account for each custom source integration to maintain proper access control and audit trails. ::: ### Scan with validated detectors only A custom source can be configured to keep only secrets whose detector supports validity checks. When this option is enabled, a scan linked to the source drops matches from detectors that have no validator before the validity check runs, so only secrets that can be checked for validity are turned into incidents. This reduces noise on sources that generate many matches which cannot be verified. The option is opt-in and set per custom source. :::note This filtering applies to scans linked to a custom source, whether run with ggshield (`--source-uuid`) or through the `POST /v1/scan/create-incidents` API. Incidents are created server-side, so the filtering happens there. ::: ## Scanning Custom Sources using ggshield You can use our CLI, **[ggshield](/ggshield-docs/integrations/overview)**, to scan for exposed secrets in files, directories, build logs, and CI/CD artifacts. Create incidents by providing your integration’s unique ID so findings are attached to your custom data source in the GitGuardian dashboard. Here are a few examples to get you started. Use `ggshield secret scan --help` to get more details. #### Scan files ```bash ggshield secret scan path /path/to/file.txt --source-uuid YOUR_INTEGRATION_ID ``` #### Scan directories ```bash ggshield secret scan path -r /path/to/directory --source-uuid YOUR_INTEGRATION_ID ``` #### Scan Jenkins build logs ```bash ggshield secret scan path /var/jenkins_home/jobs/*/builds/*/log --source-uuid YOUR_INTEGRATION_ID ``` #### Scan GitLab CI artifacts ```bash find /builds -name "*.log" -exec ggshield secret scan path {} --source-uuid YOUR_INTEGRATION_ID \+ ``` #### Scan application logs ```bash ggshield secret scan path /var/log/legacy-app.log --source-uuid YOUR_INTEGRATION_ID ``` #### Scan Docker images ```bash ggshield secret scan docker ubuntu:22.04 --source-uuid YOUR_INTEGRATION_ID ``` ## Scanning Custom Sources using the API directly You can send documents to GitGuardian via the `POST /v1/scan/create-incidents` endpoint. Each document in the request supports the following fields: | Field | Required | Description | | -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `filename` | ✅ | A name or identifier for the document | | `document` | ✅ | The text content to scan | | `location.url` | ❌ | A URL pointing to the document's origin (e.g., a wiki page, ticket, or config file). Displayed in incident details for easy navigation to the origin of the leak. | **Example:** ```json { "source_uuid": "550e8400-e29b-41d4-a716-446655440000", "documents": [ { "filename": "document.txt", "document": "", "location": { "url": "https://wiki.example.com/my-config-page" } } ] } ``` ## Scanning Custom Sources using an automation workflow (for example, n8n) You can also use your existing automation tool or simple scripts to scan content from any of your data sources. Here is a sample scenario using n8n to send GitHub Issues content to GitGuardian via a GitHub webhook. ### Step 1: Set Up GitGuardian Authentication 1. Once your custom source is created, set up a Header Auth credential in n8n. 2. Provide both values: - Header Name: Authorization - Value: Bearer `` (replace with your GitGuardian token) ### Step 2: Trigger the Workflow with a GitHub Webhook 1. Add a Webhook node as the trigger. 2. Copy its test URL, then go to your GitHub repository’s settings. 3. Under Webhooks, add the n8n URL and set it to trigger on “Issues” events. ### Step 3: Send Issues to GitGuardian’s API 1. Add an HTTP node in n8n. 2. Configure it to send a POST request to `https://api.gitguardian.com/v1/scan/create-incidents` using your Header Auth credential. 3. For the request body (JSON), use: ```json { "source_uuid": "my_source", "documents": [ { "filename": "{{ $json.body.issue.url }}", "document": {{ JSON.stringify($json.body.issue.body) }}, "location": { "url": "{{ $json.body.issue.url }}" } } ] } ``` The optional `location.url` field links the document to its origin (e.g., a wiki page, ticket, or config page). When provided, this URL appears in the incident details in the GitGuardian dashboard, making it easy to navigate back to the source. 4. Replace "my_source" with your actual source UUID. 5. Test your workflow by clicking **Execute workflow** in n8n, then create an Issue in your GitHub repository—try including a mock secret. Seconds later, you should see your first security incident appear in your GitGuardian dashboard. 6. Go live: activate the workflow. Voilà! You now have real-time secrets detection running on your GitHub Issues. ## Filter, view, and manage incidents Custom sources and their incidents appear in the GitGuardian dashboard just like native integrations. ### Filtering and Organization Use dashboard filters to organize incidents: - **Integration**: Select the custom source integration. - **Source**: Filter by the source name provided within your integration. - **Source type**: Select Custom Source. - **Standard filters**: Apply date, severity, and status filters as usual. ![Filter per Custom Source](/img/internal-monitoring/integrate-sources/bring-your-own-sources/byos-incidents-filter.jpg) ### Viewing Custom Source Incidents All incidents created from custom sources appear in the Incidents and Incident Details pages: - Secret preview in the list. ![Custom Source Incident Preview](/img/internal-monitoring/integrate-sources/bring-your-own-sources/byos-incidents-preview.jpg) - Full incident details and context. - Source identification showing your custom integration name. - Standard incident management capabilities (assign, resolve, ignore, etc.). ![Custom Source Incident Detail](/img/internal-monitoring/integrate-sources/bring-your-own-sources/byos-incident-detail.jpg) ### Perimeter Visibility Custom sources appear in the Monitored Perimeter with: - Disabled status (cannot be scanned from the dashboard). - Integration name and description. ![Custom Source in Perimeter](/img/internal-monitoring/integrate-sources/bring-your-own-sources/byos-perimeter.jpg) ## Considerations ### Current Limitations - File size: Individual files are limited to 50 MB due to API limits. - Sources per integration: Each custom integration supports one source. - Batch scanning: Large datasets should be scanned in batches for optimal performance. ### Performance Considerations - API rate limits: The GitGuardian API limits batches to 20 documents per call. - Large directories: Scanning directories with more than 20 files will result in multiple API calls. - Network timeouts: Consider network stability for large scanning operations. ### Future Enhancements - Support for multiple sources per integration. - Increased file size limits. - Enhanced batch processing capabilities. ## Pro Tips and Best Practices ### Security - Use a dedicated Service Account Token for each custom source. - Rotate Service Account Tokens regularly. - Apply the principle of least privilege for token permissions. - Avoid storing tokens in plaintext files. ### Performance - Scan files in batches rather than individually when possible. - Use the `--recursive` flag judiciously with large directory trees. - Monitor API usage to avoid rate limiting. - Consider scheduling scans during off-peak hours for large datasets. ### Organization - Use descriptive names for custom integrations. - Add meaningful descriptions to provide context for team members. - Implement consistent naming conventions across custom sources. - Document your custom scanning workflows for team knowledge sharing. ## Troubleshooting ### Common Issues #### Authentication Errors - Verify your Service Account Token has the `scan` and `scan:create-incidents` permissions. - Ensure the GitGuardian API key has been properly configured for ggshield or your custom script. - Check that your instance URL is correct for SaaS or self-hosted deployments. #### Integration ID Not Found - Confirm the integration ID is correctly set in your ggshield command or custom script. - Verify the integration is active and not deleted. #### File Size Errors - Files larger than 50 MB will be skipped. - Use the `--verbose` flag to see which files are skipped. - Consider splitting large files into smaller chunks. #### Network Connectivity - Verify network connectivity to your GitGuardian instance. - Check firewall rules and proxy configurations. - Refer to the connectivity troubleshooting guide. ### Getting Help For additional support: - Check the [ggshield documentation](/ggshield-docs/home) for general CLI usage. - Review the [API documentation](https://api.gitguardian.com/docs#tag/Scan-Methods/operation/scan_create_incidents) for advanced integrations. - Contact our Support team at support@gitguardian.com. ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification When implementing custom source scanning, consider informing relevant teams and users about the secret detection process. Here's a suggestion for a message you may want to use: > As part of our internal information security process, the company scans custom data sources for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only business-related systems and data sources may be monitored and that users shall refrain from including personal or sensitive data not relevant to business purposes.* ## Managing your integration ### Monitoring health and Maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to the integration name 3. Click **Configure** 3. Click the delete icon next to your resource 4. Confirm the removal **Note:** Removing the integration preserves your incident history, but stops future scanning and presence checks for the integrations that support it. --- ## Integrate Amazon ECR Secure your containerized applications by monitoring Amazon Elastic Container Registry for exposed secrets in container images and Docker configurations. ## Why Monitor Amazon ECR? Amazon ECR serves as the gateway between your development pipeline and AWS production environments. Container images in ECR often contain AWS credentials, RDS connection strings, and service account keys that, when exposed, can grant attackers complete access to your cloud infrastructure, databases, and sensitive customer data across multiple AWS services. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing images and their layers | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All sources are considered as private | | **File Attachments** | N/A | Not applicable for container registries | **What we scan:** - All container image layers - Dockerfiles and build configurations - Environment variables in image metadata :::info This integration automatically scans your monitored repositories, downloading Docker images which may incur [bandwidth costs](https://aws.amazon.com/ecr/pricing/). To optimize costs and reduce false positives, carefully select the sources to monitor and use our [filepath exclusion feature](../../../secrets-detection/customize-detection/exclusion-rules#filepath-suggestions). ::: :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Amazon ECR integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **AWS IAM permissions** to create roles and policies in your AWS account GitGuardian integrates with Amazon ECR using **IAM roles** with **read-only access** to your repositories. You can install GitGuardian on multiple Amazon ECR instances to monitor your repositories. To set up the Amazon ECR integration, you shall create an **IAM role** in your AWS account, and configure it with an **AWS External ID** generated by GitGuardian for your workspace. ### Connect GitGuardian with your Amazon ECR account 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Install** next to **Amazon ECR** in the **Container registries** section ![Amazon ECR install](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-install.png) 3. Click **Install** on the [Amazon ECR integration](https://dashboard.gitguardian.com/settings/integrations/aws_ecr) page 4. Retrieve the **Role name**. By default, it is `GitGuardianECRScanning`, but you can customize it. This role allows GitGuardian to scan your ECR repositories. 5. For SaaS users only : Retrieve the **AWS External ID**, unique to your workspace. You will need this when defining the trust policy for the IAM role. Keep this ID confidential! 6. Click **Connect with Amazon ECR** to link GitGuardian with your Amazon ECR account. ![Amazon ECR install](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-connect.png) 7. Create a new IAM role in the AWS [IAM Console](https://console.aws.amazon.com/iam/home#/roles) for GitGuardian. **For SaaS users:** 8. Select **AWS account** for the trusted entity type, and choose **Another AWS account**. 9. Enter the GitGuardian’s **Account ID**: `762233768605` 10. Select **Require external ID**, enter your **AWS External ID** (5) and ensure to leave **Require MFA** disabled. For more details, see how to use an external ID when granting access to your AWS resources to a third party in the [AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html). 11. Click **Next**. 12. Attach the `AmazonEC2ContainerRegistryReadOnly` role to enable resource collection. 13. Click **Next**. 14. Name the role using the **Role name** (4) defined earlier (`GitGuardianECRScanning` by default), and provide a description. 15. Click **Create Role**. **For Self-Hosted users:** 8. Select **Web Identity** for the trusted entity type. And Click **Create New** 9. Select **OpenID Connect**, 10. Use `https://the-url-of-your-gitguardian.com/exposed` as the **Provider URL**, and `sts.amazonaws.com` as the **Audience** 11. Click **Add provider** and use it for the Role. 12. Still within the Web identity section, Click **Add condition**, and use : - Key : `the-url-of-your-gitguardian.com/exposed:sub` (meaning the `sub` claim of the JWT token) - Condition : StringEquals - Value : `gitguardian-account-id:YOUR_GITGUARDIAN_ACCOUNT_ID` 13. Attach the `AmazonEC2ContainerRegistryReadOnly` role to enable resource collection. 14. Click **Next**. 15. Name the role using the **Role name** (4) defined earlier (`GitGuardianECRScanning` by default), and provide a description. 16. Click **Create Role**. Here is the resulting structure of the trust policy for On-Prem users : ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRoleWithWebIdentity", "Principal": { "Federated": "arn:aws:iam::YOUR_AWS_ACCOUNT_ID:oidc-provider/the-url-of-your-gitguardian.com/exposed" }, "Condition": { "StringEquals": { "the-url-of-your-gitguardian.com/exposed:sub": "gitguardian-account-id:YOUR_GITGUARDIAN_ACCOUNT_ID", "the-url-of-your-gitguardian.com/exposed:aud": "sts.amazonaws.com" } } } ] } ``` ### Register your Amazon ECR account information 1. Retrieve your **Region** ![Amazon ECR Region](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-region.png) 2. Copy your **Account ID** ![Amazon ECR Account ID](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-account-id.png) 3. Return to the GitGuardian platform to register your Amazon ECR account information 4. Enter your **Region name** (e.g.: `us-west-2`) 5. Paste your **Account ID** 6. Click **Install** ![Amazon ECR integration](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-integration.png) 7. Customize your monitored perimeter: - **Monitor specific Amazon ECR repositories** (Recommended) - No repositories are monitored by default, you will have to select them manually. - Newly created repositories will not be monitored by default. You can adjust this setting at any time. - Recommended to optimize your [bandwidth costs](https://aws.amazon.com/ecr/pricing/). - **Monitor the entire Amazon ECR instance** - All repositories are monitored by default with a full historical scan automatically triggered. - Newly created repositories will be monitored by default. You can adjust this setting at any time. ![Amazon ECR Default Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-default-perimeter.png) That's it! Your Amazon ECR instance is now installed, and GitGuardian is monitoring all Docker images of your selected repositories for secrets. ## Customize your monitored perimeter To customize the monitored repositories, navigate to your [Amazon ECR settings](https://dashboard.gitguardian.com/settings/integrations/aws_ecr). 1. Select/Unselect repositories to include or exclude them from monitoring 2. Confirm by clicking **Update monitored perimeter** ![Amazon ECR Custom Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-custom-perimeter.png) ## Automatic repository monitoring You can enable or disable the automatic addition of newly created repositories to your monitored perimeter by switching the option in your [Amazon ECR settings](https://dashboard.gitguardian.com/settings/integrations/aws_ecr). ![Amazon ECR Automatic Repository Monitoring](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-automatic-monitoring.png) ## Uninstall your Amazon ECR instance To uninstall an Amazon ECR instance: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Amazon ECR** in the **Container registries** section 3. Click the bin icon next to the Amazon ECR instance to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Amazon ECR uninstall](/img/internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr/amazon-ecr-uninstall.png) That's it! Your Amazon ECR instance is now uninstalled. ## Excluded paths GitGuardian automatically excludes files from scanning if their paths contain any of these regular expressions: ``` /__pypackages__/ /\.venv/ /\.tox/ /site-packages/ /venv/ distutils/command/register\.py python.*/awscli/examples/ python.*/dulwich/(tests|contrib/test_) python.*/hgext/bugzilla\.py python.*/mercurial/util\.py python.*/test/certdata/ python.*/urllib/request\.py python.*/pygments/lexers/ /cryptography.+/tests/.+(fixtures|test)_.+\.py /python.+pygpgme.+/tests/ botocore/data/.+/(examples|service)-.+\.json usr(/local)?/lib/python.+/dist-packages /libevent.+/info/test/test/ /conda-.+-py.+/info/test/tests.+/test_.+\.py /python[^/]+/test/ /man/man5/kdc\.conf\.5 erlang.*(inets|ssl).*/examples/ /gems/.*httpclient.*/(test|sample)/ /gems/.*faraday.*/ /vendor/bundle/ /\.gem/ ruby-[^/]+/test/openssl/ /(g|G)o/src/cmd/go/internal/.*_test\.go /(g|G)o/src/cmd/go/internal/.*/testdata/ /(g|G)o/src/cmd/go/testdata/ /(g|G)o/src/crypto/x509/platform_root_key\.pem /(G|g)o/src/crypto/(tls|x509)/.*_test\.go /(g|G)o/src/net/(url|http)/.*_test\.go src/github.com/DataDog/datadog-agent/.*test.*\.go google/internal/.*_test\.go golang.org.*oauth2@.*/.*\.go /flutter/.*/packages/flutter_tools/test/data/ /flutter/.*/examples/image_list/lib /\.pub-cache etc/ssl/private/ssl-cert-snakeoil\.key perl.*Cwd\.pm ansible/.*/tests/(integration|unit)/ ansible/.*/test/awx ansible/collections/ansible_collections/.*/plugins/ /curl/.*/(tests|docs|lib/url\.c) /doc/wget.+/NEWS dist/awscli/examples/ usr(/local)?/lib/aws-cli/examples/ /google-cloud-sdk/(lib|platform)/ \.git/modules/third[-_]?party/ \.git/modules/external/ /\.npm/_cacache /node_modules/ /\.parcel-cache/ /\.yarn/cache/ /\.m2/ /\.ivy2/cache/ /\.mix/ /\.hex/ /composer/cache/ /\.nuget/packages/ /libgpg-error/errorref\.txt /Homebrew/Library/Taps/ /tcl[^/]+/http-.+\.tm /tcl[^/]+/[^/]+/http-.+\.tm usr/share/lua/[^/]+/posix/init\.lua openssl/openssl-[^/]+/test/recipes/ usr/share/doc/libssl-doc/demos/ boringssl/src/third_party/[^/]+test[^/]+/[^/]+_test\.json ``` ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **86400** (1 day) - Minimum value: **1800** (30 minutes) ## Privacy Country-specific laws and regulations may require you to inform your users that your repositories are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its repositories for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only repositories relating to the company’s activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the repository’s purpose.* --- ## Integrate Azure Container Registry Secure your containerized applications by monitoring Azure Container Registry for exposed secrets in container images and Docker configurations. ## Why Monitor Azure Container Registry? Azure Container Registry hosts the container images that power your Azure applications and services. These images frequently contain Azure service principal credentials, storage account keys, and database connection strings that provide direct access to your Azure infrastructure, making any secret exposure a critical threat to your entire cloud environment. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing images and their layers | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All sources are considered as private | | **File Attachments** | N/A | Not applicable for container registries | **What we scan:** - All container image layers - Dockerfiles and build configurations - Environment variables in image metadata :::info This integration automatically scans your monitored repositories, downloading Docker images which may incur [bandwidth costs](https://azure.microsoft.com/en-us/pricing/details/bandwidth/). To optimize costs and reduce false positives, carefully select the sources to monitor and use our [filepath exclusion feature](../../../secrets-detection/customize-detection/exclusion-rules#filepath-exclusions). ::: :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Azure Container Registry integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Azure admin permissions** to create tokens in your Azure Container Registry - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. GitGuardian integrates with Azure Container Registry via a **Token** with **read-only access** to your repositories. You can install GitGuardian on multiple Azure Container Registry instances to monitor your repositories. 1. Make sure you're logged as an administrator in your Azure Portal 2. Browse your Container Registries and select the one you want to integrate 3. Go to the **Overview** section 4. Copy the **Login server** ![Azure Container Registry Login Server](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-login-server.png) 5. Go to the **Repository permissions > Tokens** section 6. Click **Add** to create a new token ![Azure Container Registry Add Token](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-add-token.png) 7. Provide a **Token** name: `GitGuardian` 8. Click **Create new scope map** ![Azure Container Registry Create Token](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-create-token.png) 9. Name the **Scope map** (e.g.: `gg-readonly`) 10. Type `*` in **Repository** to select them all 11. Select `content/read` and `metadata/read` as **Permissions** 12. Click **Create** to create the new scope map ![Azure Container Registry Create Scope Map](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-create-scope-map.png) 13. Click **Create** to create the new token ![Azure Container Registry Create Token Confirmation](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-create-token-confirmation.png) 14. Select newly created Token 15. Click **password1** (You have 2 passwords by default) 16. Click **Generate** to generate a new password 17. Copy the **Password** ![Azure Container Registry Copy Password](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-copy-password.png) 18. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 19. Click **Install** next to **Azure Container Registry** in the **Container registries** section ![Azure Container Registry install](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-install.png) 20. Click **Install** on the [Azure Container Registry integration](https://dashboard.gitguardian.com/settings/integrations/azure_cr) page 21. Paste your **Login server** (4) in the **Azure Container Registry instance URL** field (Complete with `https://` at the beginning of the URL if missing) 22. Paste your **Password** (13) in the **Personal Access Token** field 23. Paste your **Token** name (7) in the **Username** field 24. Click **Add** ![Azure Container Registry integration](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-integration.png) 25. Customize your monitored perimeter: - **Monitor specific Azure Container Registry repositories** (Recommended) - No repositories are monitored by default, you will have to select them manually. - Newly created repositories will not be monitored by default. You can adjust this setting at any time. - Recommended to optimize your [bandwidth costs](https://azure.microsoft.com/en-us/pricing/details/bandwidth/). - **Monitor the entire Azure Container Registry instance** - All repositories are monitored by default with a full historical scan automatically triggered. - Newly created repositories will be monitored by default. You can adjust this setting at any time. ![Azure Container Registry Default Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-default-perimeter.png) That's it! Your Azure Container Registry instance is now installed, and GitGuardian is monitoring all Docker images of your selected repositories for secrets. ## Customize your monitored perimeter To customize the monitored repositories, navigate to your [Azure Container Registry settings](https://dashboard.gitguardian.com/settings/integrations/azure_cr). 1. Select/Unselect repositories to include or exclude them from monitoring 2. Confirm by clicking **Update monitored perimeter** ![Azure Container Registry Custom Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-custom-perimeter.png) ## Automatic repository monitoring You can enable or disable the automatic addition of newly created repositories to your monitored perimeter by switching the option in your [Azure Container Registry settings](https://dashboard.gitguardian.com/settings/integrations/azure_cr). ![Azure Container Registry Automatic Repository Monitoring](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-automatic-monitoring.png) ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Managing your integration ### Monitoring health and Maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to the integration name 3. Click **Configure** 3. Click the delete icon next to your resource 4. Confirm the removal **Note:** Removing the integration preserves your incident history, but stops future scanning and presence checks for the integrations that support it. To uninstall an Azure Container Registry instance: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Azure Container Registry** in the **Container registries** section 3. Click the bin icon next to the Azure Container Registry instance to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Azure Container Registry uninstall](/img/internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry/azure-container-registry-uninstall.png) That's it! Your Azure Container Registry instance is now uninstalled. ## Excluded paths GitGuardian automatically excludes files from scanning if their paths contain any of these regular expressions: ``` /__pypackages__/ /\.venv/ /\.tox/ /site-packages/ /venv/ distutils/command/register\.py python.*/awscli/examples/ python.*/dulwich/(tests|contrib/test_) python.*/hgext/bugzilla\.py python.*/mercurial/util\.py python.*/test/certdata/ python.*/urllib/request\.py python.*/pygments/lexers/ /cryptography.+/tests/.+(fixtures|test)_.+\.py /python.+pygpgme.+/tests/ botocore/data/.+/(examples|service)-.+\.json usr(/local)?/lib/python.+/dist-packages /libevent.+/info/test/test/ /conda-.+-py.+/info/test/tests.+/test_.+\.py /python[^/]+/test/ /man/man5/kdc\.conf\.5 erlang.*(inets|ssl).*/examples/ /gems/.*httpclient.*/(test|sample)/ /gems/.*faraday.*/ /vendor/bundle/ /\.gem/ ruby-[^/]+/test/openssl/ /(g|G)o/src/cmd/go/internal/.*_test\.go /(g|G)o/src/cmd/go/internal/.*/testdata/ /(g|G)o/src/cmd/go/testdata/ /(g|G)o/src/crypto/x509/platform_root_key\.pem /(G|g)o/src/crypto/(tls|x509)/.*_test\.go /(g|G)o/src/net/(url|http)/.*_test\.go src/github.com/DataDog/datadog-agent/.*test.*\.go google/internal/.*_test\.go golang.org.*oauth2@.*/.*\.go /flutter/.*/packages/flutter_tools/test/data/ /flutter/.*/examples/image_list/lib /\.pub-cache etc/ssl/private/ssl-cert-snakeoil\.key perl.*Cwd\.pm ansible/.*/tests/(integration|unit)/ ansible/.*/test/awx ansible/collections/ansible_collections/.*/plugins/ /curl/.*/(tests|docs|lib/url\.c) /doc/wget.+/NEWS dist/awscli/examples/ usr(/local)?/lib/aws-cli/examples/ /google-cloud-sdk/(lib|platform)/ \.git/modules/third[-_]?party/ \.git/modules/external/ /\.npm/_cacache /node_modules/ /\.parcel-cache/ /\.yarn/cache/ /\.m2/ /\.ivy2/cache/ /\.mix/ /\.hex/ /composer/cache/ /\.nuget/packages/ /libgpg-error/errorref\.txt /Homebrew/Library/Taps/ /tcl[^/]+/http-.+\.tm /tcl[^/]+/[^/]+/http-.+\.tm usr/share/lua/[^/]+/posix/init\.lua openssl/openssl-[^/]+/test/recipes/ usr/share/doc/libssl-doc/demos/ boringssl/src/third_party/[^/]+test[^/]+/[^/]+_test\.json ``` ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **86400** (1 day) - Minimum value: **1800** (30 minutes) ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your users that your repositories are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its repositories for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only repositories relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the repository's purpose.* --- ## Integrate Docker Hub Secure your containerized applications by monitoring Docker Hub repositories for exposed secrets in container images, Dockerfiles, and environment configurations. ## Why Monitor Docker Hub? Docker Hub repositories contain container images that are distributed to production environments, customer systems, and third-party platforms. When developers build images with hardcoded API keys, database credentials, or private certificates embedded in layers, these secrets become accessible to anyone who pulls the image, creating widespread security vulnerabilities. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing images and their layers | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All sources are considered as private | | **File Attachments** | N/A | Not applicable for container registries | **What we scan:** - All container image layers - Dockerfiles and build configurations - Environment variables in image metadata :::info This integration automatically scans your monitored repositories, downloading Docker images which may incur [bandwidth costs](https://www.docker.com/pricing/). To optimize costs while minimizing false positives, carefully select the sources to monitor and use our [filepath exclusion feature](../../../secrets-detection/customize-detection/exclusion-rules#filepath-exclusions). ::: :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Docker Hub integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Docker Hub account** with access to the repositories you want to monitor GitGuardian integrates with Docker Hub via a **Personal Access Token** with **read-only access** to your repositories. You can install GitGuardian on multiple Docker Hub instances to monitor your repositories. 1. Make sure you're logged as an administrator in your Docker Hub instance and that you selected the right namespace ![Docker Hub Namespace](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-namespace.png) 2. Go to **Account settings** 3. Go to **Personal access tokens** ![Docker Hub PAT](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-pat.png) 4. Click **Generate new token** ![Docker Hub Generate New Token](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-generate-new-token.png) 5. Type an **Access token description** (e.g.: `GitGuardian`) 6. Select `Read-only` as **Access permissions** 7. Click **Generate** ![Docker Hub Generate Token](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-generate-token.png) 8. Copy the **Personal access token** ![Docker Hub Copy PAT](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-copy-pat.png) 9. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 10. Click **Install** next to **Docker Hub** in the **Container registries** section ![Docker Hub install](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-install.png) 11. Click **Install** on the [Docker Hub integration](https://dashboard.gitguardian.com/settings/integrations/docker_hub) page 12. Paste your **Personal access token** 13. Type your **Username** 14. Type your **Namespace** - Either the name of the organization as seen on step 1 if you are monitoring an organisation - Or your username again if you are monitoring the images of your user 15. Click **Add** ![Docker Hub integration](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-integration.png) 16. Customize your monitored perimeter: - **Monitor specific Docker Hub repositories** (Recommended) - No repositories are monitored by default, you will have to select them manually. - Newly created repositories will not be monitored by default. You can adjust this setting at any time. - Recommended to optimize your [bandwidth costs](https://www.docker.com/pricing/). - **Monitor the entire Docker Hub instance** - All repositories are monitored by default with a full historical scan automatically triggered. - Newly created repositories will be monitored by default. You can adjust this setting at any time. ![Docker Hub Default Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-default-perimeter.png) That's it! Your Docker Hub instance is now installed, and GitGuardian is monitoring all Docker images of your selected repositories for secrets. ## Customize your monitored perimeter To customize the monitored repositories, navigate to your [Docker Hub settings](https://dashboard.gitguardian.com/settings/integrations/docker_hub). 1. Select/Unselect repositories to include or exclude them from monitoring 2. Confirm by clicking **Update monitored perimeter** ![Docker Hub Custom Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-custom-perimeter.png) ## Automatic repository monitoring You can enable or disable the automatic addition of newly created repositories to your monitored perimeter by switching the option in your [Docker Hub settings](https://dashboard.gitguardian.com/settings/integrations/docker_hub). ![Docker Hub Automatic Repository Monitoring](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-automatic-monitoring.png) ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Managing your integration ### Monitoring health and Maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to the integration name 3. Click **Configure** 3. Click the delete icon next to your resource 4. Confirm the removal **Note:** Removing the integration preserves your incident history, but stops future scanning and presence checks for the integrations that support it. ![Docker Hub uninstall](/img/internal-monitoring/integrate-sources/container-registries-integrations/docker-hub/docker-hub-uninstall.png) ## Excluded paths GitGuardian automatically excludes files from scanning if their paths contain any of these regular expressions: ``` /__pypackages__/ /\.venv/ /\.tox/ /site-packages/ /venv/ distutils/command/register\.py python.*/awscli/examples/ python.*/dulwich/(tests|contrib/test_) python.*/hgext/bugzilla\.py python.*/mercurial/util\.py python.*/test/certdata/ python.*/urllib/request\.py python.*/pygments/lexers/ /cryptography.+/tests/.+(fixtures|test)_.+\.py /python.+pygpgme.+/tests/ botocore/data/.+/(examples|service)-.+\.json usr(/local)?/lib/python.+/dist-packages /libevent.+/info/test/test/ /conda-.+-py.+/info/test/tests.+/test_.+\.py /python[^/]+/test/ /man/man5/kdc\.conf\.5 erlang.*(inets|ssl).*/examples/ /gems/.*httpclient.*/(test|sample)/ /gems/.*faraday.*/ /vendor/bundle/ /\.gem/ ruby-[^/]+/test/openssl/ /(g|G)o/src/cmd/go/internal/.*_test\.go /(g|G)o/src/cmd/go/internal/.*/testdata/ /(g|G)o/src/cmd/go/testdata/ /(g|G)o/src/crypto/x509/platform_root_key\.pem /(G|g)o/src/crypto/(tls|x509)/.*_test\.go /(g|G)o/src/net/(url|http)/.*_test\.go src/github.com/DataDog/datadog-agent/.*test.*\.go google/internal/.*_test\.go golang.org.*oauth2@.*/.*\.go /flutter/.*/packages/flutter_tools/test/data/ /flutter/.*/examples/image_list/lib /\.pub-cache etc/ssl/private/ssl-cert-snakeoil\.key perl.*Cwd\.pm ansible/.*/tests/(integration|unit)/ ansible/.*/test/awx ansible/collections/ansible_collections/.*/plugins/ /curl/.*/(tests|docs|lib/url\.c) /doc/wget.+/NEWS dist/awscli/examples/ usr(/local)?/lib/aws-cli/examples/ /google-cloud-sdk/(lib|platform)/ \.git/modules/third[-_]?party/ \.git/modules/external/ /\.npm/_cacache /node_modules/ /\.parcel-cache/ /\.yarn/cache/ /\.m2/ /\.ivy2/cache/ /\.mix/ /\.hex/ /composer/cache/ /\.nuget/packages/ /libgpg-error/errorref\.txt /Homebrew/Library/Taps/ /tcl[^/]+/http-.+\.tm /tcl[^/]+/[^/]+/http-.+\.tm usr/share/lua/[^/]+/posix/init\.lua openssl/openssl-[^/]+/test/recipes/ usr/share/doc/libssl-doc/demos/ boringssl/src/third_party/[^/]+test[^/]+/[^/]+_test\.json ``` ## Additional Self-Hosted configuration For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **86400** (1 day) - Minimum value: **1800** (30 minutes) ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your users that your repositories are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its repositories for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only repositories relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the repository's purpose.* --- ## Integrate Google Artifact Registry Secure your containerized applications by monitoring Google Artifact Registry for exposed secrets in container images and build artifacts. ## Why Monitor Google Artifact Registry? Google Artifact Registry is the central hub for your containerized applications running on Google Cloud Platform. Container images stored here typically contain service account keys, Cloud SQL credentials, and API tokens that grant access to Google Cloud services, making any secret exposure a direct pathway to compromising your entire GCP infrastructure. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing images and their layers | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All sources are considered as private | | **File Attachments** | N/A | Not applicable for container registries | **What we scan:** - All container image layers - Dockerfiles and build configurations - Environment variables in image metadata :::info This integration automatically scans your monitored repositories, downloading artifacts which may incur [bandwidth costs](https://cloud.google.com/vpc/network-pricing). To optimize costs and reduce false positives, carefully select the sources to monitor and use our [filepath exclusion feature](../../../secrets-detection/customize-detection/exclusion-rules#filepath-exclusions). ::: :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Google Artifact Registry integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Google Cloud admin permissions** to create Service Accounts in your GCP project GitGuardian integrates with Google Artifact Registry via a **Service Account** with **read-only access** to your repositories. You can install GitGuardian on multiple Google Artifact Registry instances to monitor your repositories. 1. Make sure you're logged as an administrator in your Google Cloud Console 2. Click **Select a project** and select the project you want to integrate ![Google Artifact Registry Project](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-project.png) 3. Open the ![platform icon](/img/icons/three-dots-menu.svg) menu and go to the **Project settings** ![Google Artifact Registry Project Settings](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-project-settings.png) 4. Go to the **Service Accounts** section 5. Click **CREATE SERVICE ACCOUNT** ![Google Artifact Registry Create Service Account](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-create-service-account.png) 6. Type a **Service account name** and click **CREATE AND CONTINUE** ![Google Artifact Registry Service Account Name](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-service-account-name.png) 7. Select `Artifact Registry Reader` as a role and click **CONTINUE** ![Google Artifact Registry Service Account Role](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-service-account-role.png) 8. You can skip the 3rd step and click **DONE** 9. Click the ![platform icon](/img/icons/three-dots-menu.svg) menu next to the new service account and select **Manage keys** ![Google Artifact Registry Manage Keys](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-manage-keys.png) 10. Click the **ADD KEY** menu and select **Create new key** ![Google Artifact Registry Create New Key](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-create-news-key.png) 11. Select **JSON** as a key type and click **CREATE** ![Google Artifact Registry Download JSON File](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-download-json-file.png) This will create your new key and download it locally in a JSON file 12. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 13. Click **Install** next to **Google Artifact Registry** in the **Container registries** section ![Google Artifact Registry install](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-install.png) 14. Click **Install** on the [Google Artifact Registry integration](https://dashboard.gitguardian.com/settings/integrations/google_artifact) page 15. Type your **Region** (e.g.: `us-west2`) 16. Paste your **Service Account Key** in JSON format 17. Click **Add** ![Google Artifact Registry integration](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-integration.png) 18. Customize your monitored perimeter: - **Monitor specific Google Artifact Registry repositories** (Recommended) - No repositories are monitored by default, you will have to select them manually. - Newly created repositories will not be monitored by default. You can adjust this setting at any time. - Recommended to optimize your [bandwidth costs](https://cloud.google.com/vpc/network-pricing). - **Monitor the entire Google Artifact Registry instance** - All repositories are monitored by default with a full historical scan automatically triggered. - Newly created repositories will be monitored by default. You can adjust this setting at any time. ![Google Artifact Registry Default Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-default-perimeter.png) That's it! Your Google Artifact Registry instance is now installed, and GitGuardian is monitoring all Docker images of your selected repositories for secrets. ## Customize your monitored perimeter To customize the monitored repositories, navigate to your [Google Artifact Registry settings](https://dashboard.gitguardian.com/settings/integrations/google_artifact). 1. Select/Unselect repositories to include or exclude them from monitoring 2. Confirm by clicking **Update monitored perimeter** ![Google Artifact Registry Custom Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-custom-perimeter.png) ## Automatic repository monitoring You can enable or disable the automatic addition of newly created repositories to your monitored perimeter by switching the option in your [Google Artifact Registry settings](https://dashboard.gitguardian.com/settings/integrations/google_artifact). ![Google Artifact Registry Automatic Repository Monitoring](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-automatic-monitoring.png) ## Uninstall your Google Artifact Registry instance To uninstall a Google Artifact Registry instance: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Google Artifact Registry** in the **Container registries** section 3. Click the bin icon next to the Google Artifact Registry instance to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Google Artifact Registry uninstall](/img/internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry/google-artifact-registry-uninstall.png) That's it! Your Google Artifact Registry instance is now uninstalled. ## Excluded paths GitGuardian automatically excludes files from scanning if their paths contain any of these regular expressions: ``` /__pypackages__/ /\.venv/ /\.tox/ /site-packages/ /venv/ distutils/command/register\.py python.*/awscli/examples/ python.*/dulwich/(tests|contrib/test_) python.*/hgext/bugzilla\.py python.*/mercurial/util\.py python.*/test/certdata/ python.*/urllib/request\.py python.*/pygments/lexers/ /cryptography.+/tests/.+(fixtures|test)_.+\.py /python.+pygpgme.+/tests/ botocore/data/.+/(examples|service)-.+\.json usr(/local)?/lib/python.+/dist-packages /libevent.+/info/test/test/ /conda-.+-py.+/info/test/tests.+/test_.+\.py /python[^/]+/test/ /man/man5/kdc\.conf\.5 erlang.*(inets|ssl).*/examples/ /gems/.*httpclient.*/(test|sample)/ /gems/.*faraday.*/ /vendor/bundle/ /\.gem/ ruby-[^/]+/test/openssl/ /(g|G)o/src/cmd/go/internal/.*_test\.go /(g|G)o/src/cmd/go/internal/.*/testdata/ /(g|G)o/src/cmd/go/testdata/ /(g|G)o/src/crypto/x509/platform_root_key\.pem /(G|g)o/src/crypto/(tls|x509)/.*_test\.go /(g|G)o/src/net/(url|http)/.*_test\.go src/github.com/DataDog/datadog-agent/.*test.*\.go google/internal/.*_test\.go golang.org.*oauth2@.*/.*\.go /flutter/.*/packages/flutter_tools/test/data/ /flutter/.*/examples/image_list/lib /\.pub-cache etc/ssl/private/ssl-cert-snakeoil\.key perl.*Cwd\.pm ansible/.*/tests/(integration|unit)/ ansible/.*/test/awx ansible/collections/ansible_collections/.*/plugins/ /curl/.*/(tests|docs|lib/url\.c) /doc/wget.+/NEWS dist/awscli/examples/ usr(/local)?/lib/aws-cli/examples/ /google-cloud-sdk/(lib|platform)/ \.git/modules/third[-_]?party/ \.git/modules/external/ /\.npm/_cacache /node_modules/ /\.parcel-cache/ /\.yarn/cache/ /\.m2/ /\.ivy2/cache/ /\.mix/ /\.hex/ /composer/cache/ /\.nuget/packages/ /libgpg-error/errorref\.txt /Homebrew/Library/Taps/ /tcl[^/]+/http-.+\.tm /tcl[^/]+/[^/]+/http-.+\.tm usr/share/lua/[^/]+/posix/init\.lua openssl/openssl-[^/]+/test/recipes/ usr/share/doc/libssl-doc/demos/ boringssl/src/third_party/[^/]+test[^/]+/[^/]+_test\.json ``` ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **86400** (1 day) - Minimum value: **1800** (30 minutes) ## Privacy Country-specific laws and regulations may require you to inform your users that your repositories are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its repositories for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only repositories relating to the company’s activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the repository’s purpose.* --- ## Integrate JFrog Container Registry Secure your containerized applications by monitoring JFrog Container Registry for exposed secrets in container images and build artifacts. :::tip Looking to scan non-container artifacts such as npm, Maven, or PyPI packages? Check out the [JFrog Package Registries](../package-registries-integrations/jfrog-package-registry) integration. ::: ## Why Monitor JFrog Container Registry? JFrog Container Registry serves as the enterprise-grade repository for your organization's production-ready container images. These images often contain production database credentials, enterprise API keys, and internal service tokens that, when exposed, can compromise critical business applications and provide unauthorized access to proprietary systems and sensitive customer data. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing images and their layers | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All sources are considered as private | | **File Attachments** | N/A | Not applicable for container registries | **What we scan:** - All container image layers - Dockerfiles and build configurations - Environment variables in image metadata :::info This integration automatically scans your monitored repositories, downloading container images which may incur [bandwidth costs](https://jfrog.com/pricing/). To optimize costs and reduce false positives, carefully select the sources to monitor and use our [filepath exclusion feature](../../../secrets-detection/customize-detection/exclusion-rules#filepath-exclusions). ::: :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your JFrog Container Registry integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **JFrog admin permissions** to create Access Tokens in your JFrog instance - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. GitGuardian integrates with JFrog Container Registry via an **Access Token** with **read-only access** to your repositories. You can install GitGuardian on multiple JFrog Container Registry instances to monitor your repositories. 1. Make sure you're logged as an administrator in your JFrog Platform 2. Go to **Administration** > **User Management** > **Access Tokens** 3. Click **Generate Token** ![JFrog Platform Access Tokens page](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-access-tokens.png) 4. Type a Description (e.g.: `GitGuardian`) 5. Select `Group` as **Token scope** 6. Select `readers` as **Groups** 7. Uncheck **All** and select `Artifactory` as **Service** 8. Click **Generate** ![JFrog Platform Generate Token modal](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-generate-token.png) 9. Get the **Username** and copy the **Token** ![JFrog Platform Token value modal](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-copy-token.png) 10. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 11. Click **Install** next to **JFrog Container Registry** in the **Container registries** section ![JFrog Container Registry install button](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-install.png) 12. Click **Install** on the [JFrog Container Registry integration](https://dashboard.gitguardian.com/settings/integrations/jfrog_artifact) page 13. Type your **JFrog Container Registry instance URL** (e.g.: `https://acme.jfrog.io/`) 14. Paste your **Personal access token** 15. Type the associated **Username** (e.g.: `admin@acme.com`) 16. Click **Add** ![JFrog Container Registry integration](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-integration.png) 17. Customize your monitored perimeter: - **Monitor specific JFrog Container Registry repositories** (Recommended) - No repositories are monitored by default, you will have to select them manually. - Newly created repositories will not be monitored by default. You can adjust this setting at any time. - Recommended to optimize your [bandwidth costs](https://jfrog.com/pricing/). - **Monitor the entire JFrog Container Registry instance** - All repositories are monitored by default with a full historical scan automatically triggered. - Newly created repositories will be monitored by default. You can adjust this setting at any time. ![JFrog Container Registry Default Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-default-perimeter.png) That's it! Your JFrog Container Registry instance is now installed, and GitGuardian is monitoring all Docker images of your selected repositories for secrets. ## Customize your monitored perimeter To customize the monitored repositories, navigate to your [JFrog Container Registry settings](https://dashboard.gitguardian.com/settings/integrations/jfrog_artifact). 1. Select/Unselect repositories to include or exclude them from monitoring 2. Confirm by clicking **Update monitored perimeter** ![JFrog Container Registry Custom Monitored Perimeter](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-custom-perimeter.png) ## Automatic repository monitoring You can enable or disable the automatic addition of newly created repositories to your monitored perimeter by switching the option in your [JFrog Container Registry settings](https://dashboard.gitguardian.com/settings/integrations/jfrog_artifact). ![JFrog Artifactory Automatic Repository Monitoring](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-automatic-monitoring.png) ## Uninstall your JFrog Container Registry instance To uninstall a JFrog Container Registry instance: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **JFrog Container Registry** in the **Container registries** section 3. Click the bin icon next to the JFrog Container Registry instance to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![JFrog Container Registry uninstall](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-uninstall.png) That's it! Your JFrog Container Registry instance is now uninstalled. ## Excluded paths GitGuardian automatically excludes files from scanning if their paths contain any of these regular expressions: ``` /__pypackages__/ /\.venv/ /\.tox/ /site-packages/ /venv/ distutils/command/register\.py python.*/awscli/examples/ python.*/dulwich/(tests|contrib/test_) python.*/hgext/bugzilla\.py python.*/mercurial/util\.py python.*/test/certdata/ python.*/urllib/request\.py python.*/pygments/lexers/ /cryptography.+/tests/.+(fixtures|test)_.+\.py /python.+pygpgme.+/tests/ botocore/data/.+/(examples|service)-.+\.json usr(/local)?/lib/python.+/dist-packages /libevent.+/info/test/test/ /conda-.+-py.+/info/test/tests.+/test_.+\.py /python[^/]+/test/ /man/man5/kdc\.conf\.5 erlang.*(inets|ssl).*/examples/ /gems/.*httpclient.*/(test|sample)/ /gems/.*faraday.*/ /vendor/bundle/ /\.gem/ ruby-[^/]+/test/openssl/ /(g|G)o/src/cmd/go/internal/.*_test\.go /(g|G)o/src/cmd/go/internal/.*/testdata/ /(g|G)o/src/cmd/go/testdata/ /(g|G)o/src/crypto/x509/platform_root_key\.pem /(G|g)o/src/crypto/(tls|x509)/.*_test\.go /(g|G)o/src/net/(url|http)/.*_test\.go src/github.com/DataDog/datadog-agent/.*test.*\.go google/internal/.*_test\.go golang.org.*oauth2@.*/.*\.go /flutter/.*/packages/flutter_tools/test/data/ /flutter/.*/examples/image_list/lib /\.pub-cache etc/ssl/private/ssl-cert-snakeoil\.key perl.*Cwd\.pm ansible/.*/tests/(integration|unit)/ ansible/.*/test/awx ansible/collections/ansible_collections/.*/plugins/ /curl/.*/(tests|docs|lib/url\.c) /doc/wget.+/NEWS dist/awscli/examples/ usr(/local)?/lib/aws-cli/examples/ /google-cloud-sdk/(lib|platform)/ \.git/modules/third[-_]?party/ \.git/modules/external/ /\.npm/_cacache /node_modules/ /\.parcel-cache/ /\.yarn/cache/ /\.m2/ /\.ivy2/cache/ /\.mix/ /\.hex/ /composer/cache/ /\.nuget/packages/ /libgpg-error/errorref\.txt /Homebrew/Library/Taps/ /tcl[^/]+/http-.+\.tm /tcl[^/]+/[^/]+/http-.+\.tm usr/share/lua/[^/]+/posix/init\.lua openssl/openssl-[^/]+/test/recipes/ usr/share/doc/libssl-doc/demos/ boringssl/src/third_party/[^/]+test[^/]+/[^/]+_test\.json ``` ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **86400** (1 day) - Minimum value: **1800** (30 minutes) ## Privacy Country-specific laws and regulations may require you to inform your users that your repositories are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its repositories for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only repositories relating to the company’s activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the repository’s purpose.* --- ## Integrate Red Hat Quay Secure your containerized applications by monitoring Red Hat Quay for exposed secrets in container images. :::tip Red Hat Quay supports both SaaS (quay.io) and self-hosted deployments. This integration works with both variants. ::: ## Why Monitor Red Hat Quay? Red Hat Quay serves as an enterprise-grade, OCI-compliant container image registry for your organization's production-ready container images. These images often contain production database credentials, enterprise API keys, and internal service tokens that, when exposed, can compromise critical business applications and provide unauthorized access to proprietary systems and sensitive customer data. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing images and their layers | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repositories | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All sources are considered as private | | **File Attachments** | N/A | Not applicable for container registries | **What we scan:** - All container image layers - Dockerfiles and build configurations - Environment variables in image metadata :::info This integration automatically scans your monitored repositories, downloading container images which may incur bandwidth costs. To optimize costs and reduce false positives, carefully select the sources to monitor and use our [filepath exclusion feature](../../../secrets-detection/customize-detection/exclusion-rules#filepath-exclusions). ::: :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Setup your Red Hat Quay integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Admin permissions** on your Red Hat Quay organization to create OAuth Applications - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. GitGuardian integrates with Red Hat Quay via **OAuth2** with **read-only access** to your repositories. You can install GitGuardian on multiple Red Hat Quay instances to monitor your repositories. ### Step 1: Create an OAuth Application in Quay 1. Log in to your Red Hat Quay instance (quay.io or your self-hosted Quay) 2. Navigate to your **Organization** and go to **Applications** (under Organization Settings) 3. Click **Create New Application** 4. Give it a name (e.g., `GitGuardian`) 5. After creation, click on the application to edit it 6. Set the **Homepage URL** to your GitGuardian dashboard URL (e.g., `https://dashboard.gitguardian.com`) 7. Set the **Redirect/Callback URL Prefix** to: ``` https://dashboard.gitguardian.com/api/v1/red-hat-quay/install/callback/ ``` ![Red Hat Quay OAuth Application settings](/img/internal-monitoring/integrate-sources/container-registries-integrations/red-hat-quay/red-hat-quay-oauth-application.png) 8. The application will request the following permission when users authorize it: - `View all visible repositories` ![Red Hat Quay Authorize Application](/img/internal-monitoring/integrate-sources/container-registries-integrations/red-hat-quay/red-hat-quay-authorize-application.png) 9. Save the application and note the **Client ID** and **Client Secret** ### Step 2: Connect Red Hat Quay to GitGuardian 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Install** next to **Red Hat Quay** in the **Container registries** section 3. Click **Install** on the Red Hat Quay integration page 4. Type your **Red Hat Quay instance URL** (e.g., `https://quay.io` or `https://quay.example.com`) 5. Paste the **Client ID** from the OAuth Application you created 6. Paste the **Client Secret** from the OAuth Application you created 7. Click **Add** 8. Customize your monitored perimeter: - **Monitor specific Red Hat Quay repositories** (Recommended) - No repositories are monitored by default, you will have to select them manually. - Newly created repositories will not be monitored by default. You can adjust this setting at any time. - **Monitor the entire Red Hat Quay instance** - All repositories are monitored by default with a full historical scan automatically triggered. - Newly created repositories will be monitored by default. You can adjust this setting at any time. That's it! Your Red Hat Quay instance is now installed, and GitGuardian is monitoring all container images of your selected repositories for secrets. ## Customize your monitored perimeter To customize the monitored repositories, navigate to your Red Hat Quay settings from the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page. 1. Select/Unselect repositories to include or exclude them from monitoring 2. Confirm by clicking **Update monitored perimeter** ## Automatic repository monitoring You can enable or disable the automatic addition of newly created repositories to your monitored perimeter by switching the option in your Red Hat Quay settings. ## Managing your integration ### Monitoring health and Maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to the integration name 3. Click **Configure** 3. Click the delete icon next to your resource 4. Confirm the removal **Note:** Removing the integration preserves your incident history, but stops future scanning and presence checks for the integrations that support it. ## Excluded paths GitGuardian automatically excludes files from scanning if their paths contain any of these regular expressions: ``` /__pypackages__/ /\.venv/ /\.tox/ /site-packages/ /venv/ distutils/command/register\.py python.*/awscli/examples/ python.*/dulwich/(tests|contrib/test_) python.*/hgext/bugzilla\.py python.*/mercurial/util\.py python.*/test/certdata/ python.*/urllib/request\.py python.*/pygments/lexers/ /cryptography.+/tests/.+(fixtures|test)_.+\.py /python.+pygpgme.+/tests/ botocore/data/.+/(examples|service)-.+\.json usr(/local)?/lib/python.+/dist-packages /libevent.+/info/test/test/ /conda-.+-py.+/info/test/tests.+/test_.+\.py /python[^/]+/test/ /man/man5/kdc\.conf\.5 erlang.*(inets|ssl).*/examples/ /gems/.*httpclient.*/(test|sample)/ /gems/.*faraday.*/ /vendor/bundle/ /\.gem/ ruby-[^/]+/test/openssl/ /(g|G)o/src/cmd/go/internal/.*_test\.go /(g|G)o/src/cmd/go/internal/.*/testdata/ /(g|G)o/src/cmd/go/testdata/ /(g|G)o/src/crypto/x509/platform_root_key\.pem /(G|g)o/src/crypto/(tls|x509)/.*_test\.go /(g|G)o/src/net/(url|http)/.*_test\.go src/github.com/DataDog/datadog-agent/.*test.*\.go google/internal/.*_test\.go golang.org.*oauth2@.*/.*\.go /flutter/.*/packages/flutter_tools/test/data/ /flutter/.*/examples/image_list/lib /\.pub-cache etc/ssl/private/ssl-cert-snakeoil\.key perl.*Cwd\.pm ansible/.*/tests/(integration|unit)/ ansible/.*/test/awx ansible/collections/ansible_collections/.*/plugins/ /curl/.*/(tests|docs|lib/url\.c) /doc/wget.+/NEWS dist/awscli/examples/ usr(/local)?/lib/aws-cli/examples/ /google-cloud-sdk/(lib|platform)/ \.git/modules/third[-_]?party/ \.git/modules/external/ /\.npm/_cacache /node_modules/ /\.parcel-cache/ /\.yarn/cache/ /\.m2/ /\.ivy2/cache/ /\.mix/ /\.hex/ /composer/cache/ /\.nuget/packages/ /libgpg-error/errorref\.txt /Homebrew/Library/Taps/ /tcl[^/]+/http-.+\.tm /tcl[^/]+/[^/]+/http-.+\.tm usr/share/lua/[^/]+/posix/init\.lua openssl/openssl-[^/]+/test/recipes/ usr/share/doc/libssl-doc/demos/ boringssl/src/third_party/[^/]+test[^/]+/[^/]+_test\.json ``` ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **86400** (1 day) - Minimum value: **1800** (30 minutes) ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your users that your repositories are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its repositories for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only repositories relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the repository's purpose.* --- ## Integrate Confluence Cloud Monitor Confluence Cloud spaces for exposed secrets in pages, documentation, and collaborative content. :::info Attachment scanning and permissions **File attachment scanning** requires Confluence attachment access in OAuth scopes, including **`readonly:content.attachment:confluence`**. If you integrated with Confluence Cloud prior the 27th of April 2026, we recommend you **uninstall and reinstall** your Confluence Cloud site from [**Sources**](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) to benefit from this new feature. ::: ## Why Monitor Confluence Cloud? Confluence Cloud serves as the central repository for your organization's technical knowledge and documentation. Teams frequently embed API keys, database credentials, and configuration secrets in wiki pages, setup guides, and troubleshooting documentation, creating long-lasting security vulnerabilities that can be accessed by anyone with space permissions and are often overlooked during security reviews. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Manual Trigger) | Analyze existing spaces and their histories | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of spaces | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | Not applicable for Space content | | **Source Visibility** | ❌ (Not Supported) | All spaces show as `private` | | **File Attachments** | ✅ (Supported) | Uploaded file attachments are scanned | **What we scan:** - Confluence pages and blog posts - Comments and page histories - File attachments - Space documentation and wikis :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Confluence Cloud integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Confluence Cloud administrator** permissions for the sites you want to monitor GitGuardian integrates with Confluence Cloud via an **OAuth2 app** with **read-only access** to your spaces. You can install GitGuardian on multiple Confluence Cloud sites to monitor your spaces. 1. Make sure you're logged in the Confluence Cloud site you want to install 2. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 3. Click **Install** next to **Confluence Cloud** in the **Documentation** section ![Confluence Cloud install](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-install.png) 4. Click **Install** on the [Confluence Cloud integration](https://dashboard.gitguardian.com/settings/integrations/confluence_cloud) page 5. Click **Connect with Confluence Cloud** in the installation modal ![Confluence Cloud install - Step 1](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-install-1.png) 6. Make sure you are connected to the right Confluence Cloud site 7. Click **Accept** to grant the permissions requested by GitGuardian ![Confluence Cloud permissions](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-permissions.png) That's it! Our OAuth2 app is now authorized on your Confluence Cloud site and will start monitoring pages, blogs, and comments in your spaces for secrets. :::warning **Previous installations** If you integrated **before** GitGuardian requested attachment access for Confluence, **uninstall and reinstall** your Confluence Cloud site from **Settings → Integrations → Sources** so the OAuth app can obtain **`readonly:content.attachment:confluence`** and the other documented scopes. If you manage a **custom Confluence Cloud app** (self-hosted GitGuardian), add the missing scopes in the Atlassian developer console first, then reinstall the site connection in GitGuardian. ::: ## Setup Confluence Cloud for self-hosted GitGuardian :::info We recommend using dedicated workers for Confluence Cloud. For more detailed information on scaling and configuration, please visit our [scaling](../../../self-hosting/management/infrastructure-management/scaling#configure-scaling-settings) page. ::: If you are using a self-hosted GitGuardian instance, you must first configure a dedicated Confluence Cloud App so that you own the entire data stream. This will ensure that your Confluence Cloud App is created with all the appropriate rights. ### 1. Create a Confluence Cloud app 1. Navigate to the [Confluence Cloud integration](https://dashboard.gitguardian.com/settings/integrations/confluence_cloud) page 2. Click **Configure Confluence Cloud app** ![Confluence Cloud app configure](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-configure.png) #### As a Confluence Cloud administrator 1. Click **Create Confluence Cloud app** (Alternatively, if you're not a GitGuardian Manager, you can access the [Atlassian developer console](https://developer.atlassian.com/console/myapps/create-3lo-app) directly) 2. Type the name of your new Confluence Cloud app: `GitGuardian` 3. Agree to Atlassian's developer terms by checking: **I agree to be bound by Atlassian's developer terms.** 4. Click **Create** ![Confluence Cloud app create](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-create.png) 5. Go to the **Permissions** page 6. Click **Add** next to the **Confluence API** line ![Permissions - Confluence API add](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-permissions-confluence-api-add.png) 7. Click **Configure** next to the **Confluence API** line 8. In the **Classic scopes** tab, click **Edit Scopes** in the **Confluence platform REST API** section ![Confluence Cloud - Classic scopes edit](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-classic-scopes-edit.png) 9. Select the following **classic scopes**: - `read:confluence-content.all` - `read:confluence-content.permission` - `read:confluence-content.summary` - `read:confluence-groups` - `read:confluence-props` - `read:confluence-space.summary` - `read:confluence-user` - `readonly:content.attachment:confluence` (**required for attachment scanning**) - `search:confluence` 10. Click **Save** ![Confluence Cloud - Classic scopes](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-classic-scopes.png) 11. In the **Granular scopes** tab, click **Edit Scopes** ![Confluence Cloud - Granular scopes edit](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-granular-scopes-edit.png) 12. Select the following **granular scopes**: - `read:blogpost:confluence` - `read:comment:confluence` - `read:page:confluence` - `read:space:confluence` 13. Click **Save** ![Confluence Cloud - Granular scopes](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-granular-scopes.png) 14. Go to the **Authorization** page 15. Click **Add** next to the **OAuth 2.0 (3LO)** line ![Authorization - OAuth 2.0 add](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-authorization-oauth-2.0-add.png) 16. Enter the callback URL based on your GitGuardian self-hosted instance URL: `https:///api/v1/confluence-cloud/app/install_callback/` 17. Click **Save changes** ![Confluence Cloud - Callback URL](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-callback-url.png) 18. Go to the **Overview** page 19. Get your App details (`App ID`) (alternatively, you can find and copy it more easily from the URL) ![Confluence Cloud - Overview credentials](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-overview-credentials.png) 20. Go to the **Settings** page 21. Get your Authentication details (`Client ID`, `Secret`) ![Confluence Cloud - Settings credentials](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-settings-credentials.png) That's it! Your Confluence Cloud app has been created and you can now [declare your Confluence Cloud app in the GitGuardian Platform](confluence-cloud#2-declare-your-confluence-cloud-app-in-the-gitguardian-platform). Alternatively, if you are not a GitGuardian Manager, you can now return the Confluence Cloud app credentials to your requester in the secure way of your choice (`App ID`, `Client ID`, `Secret`). #### As a non Confluence Cloud administrator If you don't have the right to create a Confluence Cloud app, please ask your Confluence Cloud administrator to do it for you. You can easily forward a request with this procedure: 1. Click the **Send a request to a Confluence administrator** link to easily forward your request 2. They should in turn provide you with the Confluence Cloud app credentials to proceed with the [rest of the configuration](confluence-cloud#2-declare-your-confluence-cloud-app-in-the-gitguardian-platform). ### 2. Declare your Confluence Cloud app in the GitGuardian Platform 1. Paste your Confluence Cloud app credentials (`App ID`, `Client ID`, `Secret`) 2. Click **Save and close** ![Confluence Cloud app credentials](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-credentials.png) That's it! Your Confluence Cloud configuration is ready and you can now [setup your Confluence Cloud integration](#setup-your-confluence-cloud-integration). ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Scanning your Confluence Cloud history GitGuardian enables you and encourages you to **scan the entire history of your perimeter**. By executing historical scanning, all secrets present in your Confluence sources prior to installing GitGuardian will be detected. Unlike Version Control Systems, historical scanning has to be manually executed from your [perimeter page](https://dashboard.gitguardian.com/workspace/perimeter), by: - Selecting your Confluence sources - Clicking scan from the top action bar ## Edit your Confluence Cloud app configuration In case you need to edit your Confluence Cloud app configuration, due to an error when declaring your Confluence Cloud app credentials or due to a secret rotation, you can do so as follows: 1. Click **Edit Confluence Cloud app** 2. Update your Confluence Cloud app credentials 3. Click **Save and close** ![Confluence Cloud app configuration edit](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-app-configuration-edit.png) ## Delete your Confluence Cloud app configuration In case you need to delete your Confluence Cloud app configuration, you can do so as follows: 1. Click **Edit Confluence Cloud app** 2. Click **Delete configuration** 3. Confirm by clicking **Delete configuration** in the confirmation modal :::info Deleting your Confluence Cloud app configuration will uninstall all your Confluence Cloud integrations. However, all your existing incidents detected on Confluence Cloud will remain available on your dashboard. Note that deleting the Confluence Cloud app configuration will only delete the configuration, not the Confluence Cloud app. If you want to delete your Confluence Cloud app, you must do so from your Confluence Cloud site. ::: ## Uninstall your Confluence Cloud site To uninstall a Confluence Cloud site: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Confluence Cloud** in the **Documentation** section 3. Click the bin icon next to the Confluence Cloud site to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Confluence Cloud uninstall](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-uninstall.png) That's it! Your Confluence Cloud site is now uninstalled. ## Remove the GitGuardian OAuth2 app from your Confluence Cloud site Uninstalling a Confluence Cloud site from the GitGuardian platform does not remove the GitGuardian OAuth2 app from your Confluence Cloud site. This is not a mandatory step, but you can remove it manually after uninstalling your Confluence Cloud site from the GitGuardian platform. To remove the GitGuardian OAuth2 app from your Confluence Cloud site: 1. Go to the **[Connected apps](https://id.atlassian.com/manage-profile/apps)** page of your Confluence Cloud site 2. Click **Remove access** next to the **GitGuardian Confluence** app 3. Confirm by clicking **Remove** in the confirmation modal ![Confluence Cloud - Remove app](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-remove-app.png) That's it! The GitGuardian OAuth2 app is now removed from your Confluence Cloud site. ## Installing the GitGuardian Connect App (for self-hosted version earlier than 2025.9.0) For GitGuardian Self-Hosted versions earlier than 2025.9.0, installing a Confluence Connect App on each Confluence Cloud site is required in addition to authorizing the OAuth2 app. 1. In your Confluence Cloud site, go to **Settings** → **Manage apps** 2. Click **Settings** (top-right of the Manage apps page) 3. Check **Enable development mode** and click **Apply** ![Confluence Cloud Development Mode](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-development-mode.png) 4. Back on the **Manage apps** page, click **Upload app** 5. Paste your GitGuardian Connect App descriptor URL and click **Upload**: - For GitGuardian Self-Hosted: `https:///api/v1/confluence-cloud/connect-app/app-descriptor/` Replace `https://` with your GitGuardian Self-Hosted base URL ![Confluence Cloud Upload app](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud/confluence-cloud-upload-app.png) 6. Verify the app appears under installed apps. The Connect App will now stream page, blog, and comment events to your GitGuardian instance. Notes: - Repeat these steps on every Confluence Cloud site you want to monitor. - When you upgrade GitGuardian Self-Hosted to version 2025.9.0 or later, the Connect App is no longer required. You can safely uninstall it from Confluence (**Manage apps** → select the app → **Uninstall**). ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your Confluence Cloud users that your spaces are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the Confluence Cloud spaces for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only spaces relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the space's purpose.* --- ## Integrate Confluence Data Center Monitor Confluence Data Center spaces for exposed secrets in pages, documentation, and collaborative content. ## Why Monitor Confluence Data Center? Confluence Data Center houses your organization's most critical technical documentation and knowledge base content in a self-hosted environment. Enterprise teams regularly embed production credentials, internal API keys, and infrastructure secrets in technical documentation, deployment guides, and troubleshooting pages, creating persistent security vulnerabilities within your most trusted knowledge repositories. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Manual Trigger) | Analyze existing spaces and their histories | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of spaces | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | Not applicable for Space content | | **Source Visibility** | ❌ (Not Supported) | All spaces show as `private` | | **File Attachments** | ✅ (Supported) | Uploaded file attachments are scanned | **What we scan:** - Confluence pages and blog posts - Comments and page histories - File attachments - Space documentation and wikis :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Confluence Data Center integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Confluence Data Center administrator** permissions to create Personal Access Tokens - **confluence-administrators** group membership to access all pages and spaces - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. :::info Rate limits If your instance enforces API rate limits, the default values may be too low and can slow down GitGuardian's scanning. To scan in a reasonable time, raise the limits or exempt the account, token, or service account that GitGuardian uses from rate limiting. See [Rate limits on self-hosted sources](/internal-monitoring/integrate-sources/monitored-perimeter#rate-limits-on-self-hosted-sources). ::: GitGuardian integrates with Confluence Data Center via an **administrator Personal Access Token** with **read-only access** to your spaces. You can install GitGuardian on multiple Confluence Data Center sites to monitor your spaces. 1. Make sure you're logged as an administrator in the Confluence Data Center site you want to install 2. Go to the **Settings** page ![Confluence Data Center settings](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center/confluence-data-center-settings.png) 3. Go to the **Personal Access Tokens** section and click **Create token** to create a new PAT ![Confluence Data Center PAT](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center/confluence-data-center-pat.png) 4. Provide a **Token Name**, an optional **Expiry date** and click **Create** ![Confluence Data Center PAT form](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center/confluence-data-center-pat-form.png) 5. Copy your new PAT and click **Close** ![Confluence Data Center PAT copy](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center/confluence-data-center-pat-copy.png) 6. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 7. Click **Install** next to **Confluence Data Center** in the **Documentation** section ![Confluence Data Center install](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center/confluence-data-center-install.png) 8. Click **Install** on the [Confluence Data Center integration](https://dashboard.gitguardian.com/settings/integrations/confluence_data_center) page 9. Paste your **Confluence Data Center site URL**, your **administrator Personal Access Token** and click **Add** ![Confluence Data Center integration](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center/confluence-data-center-integration.png) That's it! Your Confluence Data Center site is now installed, and GitGuardian is monitoring all pages, blogs and comments of your spaces for secrets. :::info GitGuardian no longer renews PATs. See the [customer notice](/support/customer-notices/jira-confluence-data-center-token-renewal). ::: ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Scanning your Confluence Data Center history GitGuardian enables you and encourages you to **scan the entire history of your perimeter**. By executing historical scanning, all secrets present in your Confluence sources prior to installing GitGuardian will be detected. Unlike Version Control Systems, historical scanning has to be manually executed from your [perimeter page](https://dashboard.gitguardian.com/workspace/perimeter), by: - Selecting your Confluence Data Center sources - Clicking **scan** from the top action bar ## Update your Personal Access Token You can replace the PAT used by an installed site at any time, for example before it expires or after rotating it. Updating the token in place keeps your configuration and monitored perimeter intact, so there is no need to reinstall. 1. Create a new **administrator** PAT in Confluence Data Center, following steps 1 to 5 above 2. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 3. Click **Edit** next to **Confluence Data Center** in the **Documentation** section 4. Update the token of the Confluence Data Center site with your new PAT GitGuardian validates the new token and runs a health check, so an unhealthy integration recovers immediately. ## Uninstall your Confluence Data Center site To uninstall a Confluence Data Center site: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Confluence Data Center** in the **Documentation** section 3. Click the bin icon next to the Confluence Data Center site to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Confluence Data Center uninstall](/img/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center/confluence-data-center-uninstall.png) That's it! Your Confluence Data Center site is now uninstalled. ## Additional considerations **Occurrence metadata:** Author's email is not determined ## Privacy ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. Country-specific laws and regulations may require you to inform your Confluence Data Center users that your spaces are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the Confluence Data Center spaces for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only spaces relating to the company’s activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the space’s purpose.* --- ## Integrate AWS S3 Monitor your AWS S3 buckets for exposed secrets in stored objects, configuration files, and data exports. :::info This integration is available on **GitGuardian SaaS only**. Self-hosted support is not available at this stage. ::: ## Why monitor AWS S3? AWS S3 is one of the most widely used storage services in cloud environments, and it accumulates a wide variety of content over time: database backups, application logs, data exports, Infrastructure-as-Code artifacts, configuration files, and CI/CD build outputs. Each of these categories is a common source of leaked credentials: API keys embedded in configuration files, database passwords in backup scripts, or cloud provider secrets hardcoded in Terraform state files. Because S3 buckets often sit outside the direct visibility of code review and version control workflows, secrets stored there tend to go undetected for long periods. Integrating GitGuardian with your S3 buckets gives your security team continuous coverage of this blind spot. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing objects across your selected buckets | | **Recurrent Scanning** | ⏳ (Coming soon) | Scheduled scanning for new and modified objects | | **Monitored Perimeter** | ✅ (Supported) | Granular selection of which buckets to monitor | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | Not applicable for object storage | | **Source Visibility** | ❌ (Not Supported) | All sources are considered private | | **File Scanning** | ✅ (Supported) | Comprehensive file type support | **What we scan:** - Object files: scripts, configuration files, IaC artifacts, logs, and data exports - Archives containing any of the above :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Set up your AWS S3 integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **AWS IAM permissions** to create an OIDC identity provider and an IAM role in your AWS account GitGuardian integrates with Amazon S3 using **IAM role assumption via OIDC**. Rather than using long-lived credentials, GitGuardian's SaaS platform assumes a read-only IAM role in your own AWS account. You create and fully control that role. ### Step 1: Configure AWS authentication In your AWS account, you need to set up an OIDC identity provider for GitGuardian and create an IAM role that trusts it. **Add the GitGuardian OIDC provider and create the IAM role** by following the instructions in [AWS IAM Integration](/nhi-governance/aws-iam-integration). The trust policy uses `sts:AssumeRoleWithWebIdentity` and a `sub` condition scoped to your GitGuardian account ID to prevent confused-deputy attacks. When configuring the IAM role's permission policy, attach read-only S3 permissions along with `cloudwatch:GetMetricData`, which GitGuardian uses to get a size estimate: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:Get*", "s3:List*", "s3:Describe*", "s3-object-lambda:Get*", "s3-object-lambda:List*" ], "Resource": "*" }, { "Effect": "Allow", "Action": ["cloudwatch:GetMetricData"], "Resource": "*" } ] } ``` :::tip We recommend scoping the S3 statement's `Resource` to only the specific bucket ARNs you intend to monitor (for example, `arn:aws:s3:::my-bucket` and `arn:aws:s3:::my-bucket/*`) to follow least-privilege principles. The `cloudwatch:GetMetricData` action does not support resource-level permissions and must keep `"Resource": "*"`. ::: ### Step 2: Register your integration in GitGuardian Once the IAM role is ready, register the integration in GitGuardian: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page. 2. Find **AWS S3** in the **File Storage** section. Use the search bar if needed. 3. Click **Install**. ![AWS S3 integration card](/img/internal-monitoring/integrate-sources/file-storage-integrations/aws-s3/aws-s3-install.png) 4. Provide the following information: - **AWS account ID**: the ID of the AWS account where you created the IAM role (for example, `123456789012`). - **Role name**: the name of the IAM role you created (for example, `GitGuardianS3Scanning`). 5. Click **Install** to complete the setup. ![AWS S3 integration registration form](/img/internal-monitoring/integrate-sources/file-storage-integrations/aws-s3/aws-s3-register.png) ## Region handling By default, GitGuardian scans only buckets located in the region configured for the integration. This avoids unintended cross-region data transfer costs. If you store objects in multiple regions, you can enable cross-region scanning in the integration settings. This option is **off by default**. Enabling it may incur additional AWS data transfer charges depending on your usage. ## Storage classes and cost control By default, GitGuardian scans only objects stored in the S3 Standard storage class. Objects in storage classes that can incur retrieval or transfer costs (for example, S3 Standard-IA, S3 One Zone-IA, and the S3 Glacier classes) are **not scanned by default**. You can opt in to scanning those storage classes in the integration settings. Keep in mind that retrieving objects from these classes may incur additional AWS retrieval and data transfer costs. ## Customize your monitored perimeter The AWS S3 integration lets you control precisely which buckets GitGuardian monitors. To update your monitored perimeter: 1. Navigate to your [AWS S3 integration settings](https://dashboard.gitguardian.com/settings/integrations/aws_s3). 2. Use the bucket list to enable or disable monitoring for specific buckets. 3. Click **Save** to apply your changes. 4. Changes take effect for the next scheduled scan. ![AWS S3 perimeter customization](/img/internal-monitoring/integrate-sources/file-storage-integrations/aws-s3/aws-s3-perimeter.png) ## Understanding scanning capabilities ### Historical scanning To trigger a historical scan, go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the AWS S3 sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. A historical scan analyzes all existing objects in the selected buckets. Because S3 buckets can accumulate content over months or years, the initial scan may surface a large number of secrets. Plan time to triage the resulting incidents. ### Recurrent scanning Recurrent scanning automatically re-scans your buckets at regular intervals to detect secrets in newly added or modified objects. This capability is **coming soon**. ### Comprehensive file support GitGuardian integration supports a wide range of file types: 1. **Text and code files:** - Source code (.py, .js, .java, .cpp, .cs, .rb, .go, .php, etc.) - Configuration files (.yaml, .json, .xml, .ini, .conf, .properties, etc.) - Documentation (.txt, .md, .rst, .log, etc.) 2. **Office documents:** - Microsoft Office (.docx, .xlsx, .pptx, .doc, .xls, .ppt) - OpenOffice/LibreOffice (.odt, .ods, .odp) - Rich text formats (.rtf) - Others (.epub) 3. **Archive and compressed files (experimental):** - Archive formats (.zip, .7z, .rar, .tar, .gz, .tgz or .tar.gz, .bz2, .tbz2 or .tar.bz2, .xz, .txz or .tar.xz, .ar, .cpio, .pack) - Container images (through .tar extensions) 4. **Other document formats:** - PDF documents (.pdf) - Email formats (.eml, .msg) - Web files (.html, .css) **File size considerations:** Large files are skipped to maintain optimal performance. Size thresholds are as follows: - 100 MB for any text file type. - 500 MB for PDFs. - 1 GB for any other file type listed. ## Managing your integration ### Monitor integration health Track scanning progress and integration status from the [integration dashboard](https://dashboard.gitguardian.com/settings/integrations/aws_s3). ### Uninstalling the integration If you need to remove the integration: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). 2. Click **Edit** next to **AWS S3**. 3. Click the delete icon next to the integration instance. 4. Confirm the removal. ![AWS S3 uninstall](/img/internal-monitoring/integrate-sources/file-storage-integrations/aws-s3/aws-s3-uninstall.png) Removing the integration preserves your existing incident history but stops future scanning. To complete the cleanup, delete the IAM role and OIDC provider from your AWS account. ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your teams that your S3 bucket contents are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its AWS S3 buckets for potential secret leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only buckets relating to the company's activity and business may be monitored and that users shall refrain from storing personal or sensitive data not relevant to the bucket's purpose.* --- ## Integrate Microsoft OneDrive Monitor OneDrive for Business for exposed secrets in user files and shared documents. ## Why Monitor Microsoft OneDrive? OneDrive for Business serves as personal cloud storage where employees frequently save scripts, configuration files, and project documents containing sensitive credentials. Unlike centralized repositories, OneDrive files often escape security oversight, allowing hardcoded API keys, database passwords, and service account tokens to remain hidden in personal storage, creating significant security blind spots. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing files and their histories | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of users and drives | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | Not applicable for personal files | | **Source Visibility** | ❌ (Not Supported) | All drives show as `private` | | **File Scanning** | ✅ (Supported) | Comprehensive file support | **What we scan:** - Personal and shared file storage - Office documents, PDF files, text documents, etc... :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: **Related integrations:** OneDrive is tied to SharePoint Online - any content in OneDrive is hosted on a SharePoint tenant. Consider also integrating [Microsoft SharePoint Online](./microsoft-sharepoint-online) to scan organizational sites and drives. ## Integration with GitGuardian SaaS **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Microsoft 365 Administrator** or **SharePoint Administrator** permissions in your tenant GitGuardian securely connects to your Microsoft 365 environment using a Microsoft Entra ID Enterprise application with read-only access to your OneDrive content. 1. **Prepare your environment** - Ensure you have an administrator account on your Microsoft 365 organization, with the necessary permissions to install Microsoft Entra ID Enterprise applications. 2. **Install the integration** - Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) - Find **Microsoft OneDrive** in the **File Storage** section. You may use the search bar to quickly find the integration. - Click **Install** ![OneDrive integration card](/img/internal-monitoring/integrate-sources/documentation-integrations/microsoft-onedrive/onedrive-install.png) 3. **Authorize GitGuardian** - Click **Install** on the integration page - Select your Microsoft 365 administrator account when prompted - Review and accept the requested permissions ![Permission consent screen](/img/internal-monitoring/integrate-sources/file-storage-integrations/microsoft-onedrive/onedrive-permission-consent.png) **That's it!** GitGuardian immediately begins scanning your sites pages and files history and starts monitoring for new secrets. ## Integrate with GitGuardian self-hosted ### Infrastructure requirements :::info We recommend using : - dedicated workers for Sharepoint Online / OneDrive integration, - and an Apache Tika cluster (as part of GitGuardian's charts) to be able to scan non-text files (.docx, .xlsx, .pdf, etc.). For more detailed information on scaling and configuration, please visit our [scaling](../../../self-hosting/management/infrastructure-management/scaling#configure-scaling-settings) page. ::: ### Create the Azure Entra ID Application for GitGuardian If you are using a self-hosted GitGuardian instance, you must first configure a dedicated Azure Entra ID Application. :::info You must be logged as a Microsoft Entra ID administrator to complete this process ::: 1. In your Microsoft Azure Tenant, browse to your Entra ID applications and create a new application, and click the "Create your own application" button 2. Choose a name for your application and register it to integrate with Microsoft Entra ID 3. Set a Redirect URI matching your GitGuardian Self-Hosted Instance: `https:///api/v1/microsoft-onedrive/app/install_callback/` ![Create your own application](/img/internal-monitoring/integrate-sources/file-storage-integrations/microsoft-onedrive/entra-id-create-application-3.png) 4. Set permissions for your application Browse to Manage / API Permissions to set the needed permissions. Choose **Application permissions** if you are asked : ![Entra ID app permissions](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/entra-id-application-permissions.png) Your application must be allowed the following Graph API permissions: **Delegated permissions:** - User.Read **Application permissions:** - Files.Read.All - Sites.Read.All - Organization.Read.All - User.ReadBasic.All You must also "Grant admin consent" for all these permissions. ![Create your own application](/img/internal-monitoring/integrate-sources/file-storage-integrations/microsoft-onedrive/onedrive-configured-permissions.png) 5. Generate a Secret for your application Browse to Manage / Certificates & secrets to create a Client Secret, create a secret and copy it while it is displayed. :::tip Store the Application (Client) ID and the Client Secret in a secure location like a vault or a secret manager ::: ### Reference your newly created application in GitGuardian Self-Hosted 1. Navigate to the Microsoft OneDrive integration page 2. Click **Configure Microsoft OneDrive app** ![Configure Microsoft OneDrive app](/img/internal-monitoring/integrate-sources/file-storage-integrations/microsoft-onedrive/self-hosted-configure-app.png) 3. Set the Application ID and Secret you just created in Microsoft Azure Entra Id ### Perform the OAuth2 installation flow 1. **Install the integration** - Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) - Find **Microsoft SharePoint** in the **File Storage** section. You may use the search bar to quickly find the integration. - Click **Install** ![Microsoft OneDrive integration card](/img/internal-monitoring/integrate-sources/documentation-integrations/microsoft-onedrive/onedrive-install.png) 2. **Authorize GitGuardian** - Click **Install** on the integration page - Select your Microsoft 365 administrator account when prompted - Review and accept the requested permissions ![Permission consent screen](/img/internal-monitoring/integrate-sources/file-storage-integrations/microsoft-onedrive/onedrive-permission-consent.png) **That's it!** GitGuardian immediately begins scanning your files and starts monitoring for new secrets. ## Customizing your monitored perimeter Microsoft OneDrive integration offers flexible perimeter control: choose which specific accounts content to monitor, giving you precise control over your scanning scope. To customize your perimeter: 1. Navigate to your [integration settings](https://dashboard.gitguardian.com/settings/integrations/microsoft_onedrive) 2. Use the checkboxes to enable or disable monitoring for specific accounts. 3. Click on **Save** to apply your changes. 4. Changes take effect immediately for new scans. ![Perimeter customization](/img/internal-monitoring/integrate-sources/documentation-integrations/microsoft-onedrive/monitored-perimeter-selection.png) ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate Microsoft OneDrive, GitGuardian performs a comprehensive scan of your entire file history, based on the customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the Microsoft OneDrive sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Real-time scanning **Catch new exposures:** Once integrated, GitGuardian continuously monitors your Microsoft OneDrive files. Any new or modified files containing secrets are detected promptly, allowing you to respond quickly to new exposures. ### Comprehensive file support GitGuardian integration supports a wide range of file types: 1. **Text and code files:** - Source code (.py, .js, .java, .cpp, .cs, .rb, .go, .php, etc.) - Configuration files (.yaml, .json, .xml, .ini, .conf, .properties, etc.) - Documentation (.txt, .md, .rst, .log, etc.) 2. **Office documents:** - Microsoft Office (.docx, .xlsx, .pptx, .doc, .xls, .ppt) - OpenOffice/LibreOffice (.odt, .ods, .odp) - Rich text formats (.rtf) - Others (.epub) 3. **Archive and compressed files (experimental):** - Archive formats (.zip, .7z, .rar, .tar, .gz, .tgz or .tar.gz, .bz2, .tbz2 or .tar.bz2, .xz, .txz or .tar.xz, .ar, .cpio, .pack) - Container images (through .tar extensions) 4. **Other document formats:** - PDF documents (.pdf) - Email formats (.eml, .msg) - Web files (.html, .css) **File size considerations:** Large files are skipped to maintain optimal performance. Size thresholds are as follows: - 100 MB for any text file type. - 500 MB for PDFs. - 1 GB for any other file type listed. ## Managing your integration ### Monitor integration health Track your scanning progress and integration status from the [integration dashboard](https://dashboard.gitguardian.com/settings/integrations/microsoft_onedrive). ### Integration maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to **Microsoft OneDrive** 3. Click **Configure** 3. Click the delete icon next to your tenant 4. Confirm the removal ![Integration removal](/img/internal-monitoring/integrate-sources/documentation-integrations/microsoft-onedrive/uninstall-tenant.png) **Note:** Removing the integration preserves your incident history but stops future scanning. To completely remove the GitGuardian app from Azure, delete it from your **Entra ID registered applications**. ## Current considerations While Microsoft OneDrive integration offers comprehensive coverage, here are some current considerations: - **Team access:** Users must be in the 'All-incidents' team to view OneDrive incidents (enhanced team management coming in future updates). - **Source visibility:** All sources appear as private in the UI. - **Incident context:** Secret matches are shown in incident details, with full file context previews. - **Archive path:** While archives scanning are supported, the complete path of the file in the archive will not be provided in the incident detail. Only the archive name (capability coming in future updates). ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your Microsoft 365 users that your OneDrive users' files are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the OneDrive files for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only sites and files relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the site's or file's purpose.* --- ## Integrate Microsoft SharePoint Online Monitor SharePoint Online sites for exposed secrets in documents, pages, and shared files. ## Why Monitor SharePoint Online? SharePoint serves as your organization's central knowledge repository where teams store technical documentation, configuration guides, and project files. Developers and IT staff frequently embed credentials, API keys, and configuration secrets in SharePoint documents during knowledge sharing and documentation processes, creating security vulnerabilities that can persist undetected for months or years. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing documents and their histories | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of sites and drives | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | Not applicable for documents | | **Source Visibility** | ❌ (Not Supported) | All sites pages and drives show as `private` | | **File Scanning** | ✅ (Supported) | Comprehensive file support | **What we scan:** - SharePoint pages and wiki content - Shared files and document libraries - Office documents, PDF files, text documents, etc... :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: **Related integrations:** Consider also integrating [Microsoft OneDrive](./microsoft-onedrive) to scan user-specific content and private files. ## Integration with GitGuardian SaaS **Prerequisites:** To enable the integration you will need: - **Owner** or **Manager** account on your GitGuardian Dashboard - **Microsoft 365 Administrator** or **SharePoint Administrator** permissions in your tenant 1. **Prepare your environment** - Ensure you have an administrator account on your Microsoft 365 organization, with the necessary permissions to install Microsoft Entra ID Enterprise applications. 2. **Install the integration** - Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) - Find **Microsoft SharePoint** in the **File Storage** section. You may use the search bar to quickly find the integration. - Click **Install** ![SharePoint Online integration card](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/sharepoint-online-install.png) 3. **Authorize GitGuardian** - Click **Install** on the integration page - Select your Microsoft 365 administrator account when prompted - Review and accept the requested permissions ![Permission consent screen](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/sharepoint-permission-consent.png) **That's it!** GitGuardian immediately begins scanning your sites pages and files history and starts monitoring for new secrets. ## Integration with GitGuardian Self-Hosted ### Infrastructure requirements :::info We recommend using dedicated workers for this integration. For more detailed information on scaling and configuration, please visit our [scaling](../../../self-hosting/management/infrastructure-management/scaling#configure-scaling-settings) page. ::: **Additional requirements for SharePoint:** - **Apache Tika deployment** (as part of GitGuardian's charts) to scan non-text files (.docx, .xlsx, .pdf, etc.) ### Create the Azure Entra ID Application for GitGuardian If you are using a self-hosted GitGuardian instance, you must first configure a dedicated Azure Entra ID Application. :::info You must be logged as a Microsoft Entra ID administrator to complete this process ::: 1. In your Microsoft Azure Tenant, browse to your Entra ID applications and create a new application, and click the "Create your own application" button 2. Choose a name for your application and register it to integrate with Microsoft Entra ID 3. Set a Redirect URI matching your GitGuardian Self-Hosted Instance: `https:///api/v1/sharepoint-online/app/install_callback/` ![Create your own application](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/entra-id-create-application-3.png) 4. Set permissions for your application Browse to Manage / API Permissions to set the needed permissions. Choose **Application permissions** if you are asked : ![Entra ID app permissions](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/entra-id-application-permissions.png) Your application must be allowed the following Graph API permissions: **Delegated permissions:** - User.Read **Application permissions:** - Files.Read.All - Sites.Read.All - Organization.Read.All You must also "Grant admin consent" for all these permissions. ![Create your own application](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/sharepoint-configured-permissions.png) 5. Generate a Secret for your application Browse to Manage / Certificates & secrets to create a Client Secret, create a secret and copy it while it is displayed. :::tip Store the Application (Client) ID and the Client Secret in a secure location like a vault or a secret manager ::: ### Reference your newly created application in GitGuardian Self-Hosted 1. Navigate to the Sharepoint Online integration page 2. Click **Configure Sharepoint Online app** ![Configure Sharepoint Online app](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/self-hosted-configure-app.png) 3. Set the Application ID and Secret you just created in Microsoft Azure Entra Id ### Perform the OAuth2 installation flow 1. **Install the integration** - Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) - Find **Microsoft SharePoint** in the **File Storage** section. You may use the search bar to quickly find the integration. - Click **Install** ![SharePoint Online integration card](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/sharepoint-online-install.png) 2. **Authorize GitGuardian** - Click **Install** on the integration page - Select your Microsoft 365 administrator account when prompted - Review and accept the requested permissions ![Permission consent screen](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/sharepoint-permission-consent.png) **That's it!** GitGuardian immediately begins scanning your sites pages and files history and starts monitoring for new secrets. ## Customizing your monitored perimeter Microsoft SharePoint Online integration offers flexible perimeter control: - **Drive-level selection:** Choose which specific SharePoint sites to monitor, giving you precise control over your scanning scope. - **Granular management:** Add or remove individual drives or sites from monitoring without affecting your entire tenant integration. To customize your perimeter: 1. Navigate to your [integration settings](https://dashboard.gitguardian.com/settings/integrations/sharepoint_online) 2. Use the checkboxes to enable or disable monitoring for specific locations, e.g. entire sites or specific nested site or drives. 3. Click on **Save** to apply your changes. 4. Changes take effect immediately for new scans. ![Perimeter customization](/img/internal-monitoring/integrate-sources/documentation-integrations/microsoft-sharepoint-online/monitored-perimeter-selection.png) Sharepoint Online integration also offers the ability to automatically add sources to your monitored perimeter. While this feature assures you complete peace of mind as the perimeter evolves, it may also scan content from sites, pages, or drives that you may not want to scan. Please consider all downsides carefully before enabling this feature. ![automatic sources](/img/internal-monitoring/integrate-sources/documentation-integrations/microsoft-sharepoint-online/automatically-monitor.png) ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ### Comprehensive file support GitGuardian integration supports a wide range of file types: 1. **Text and code files:** - Source code (.py, .js, .java, .cpp, .cs, .rb, .go, .php, etc.) - Configuration files (.yaml, .json, .xml, .ini, .conf, .properties, etc.) - Documentation (.txt, .md, .rst, .log, etc.) 2. **Office documents:** - Microsoft Office (.docx, .xlsx, .pptx, .doc, .xls, .ppt) - OpenOffice/LibreOffice (.odt, .ods, .odp) - Rich text formats (.rtf) - Others (.epub) 3. **Archive and compressed files (experimental):** - Archive formats (.zip, .7z, .rar, .tar, .gz, .tgz or .tar.gz, .bz2, .tbz2 or .tar.bz2, .xz, .txz or .tar.xz, .ar, .cpio, .pack) - Container images (through .tar extensions) 4. **Other document formats:** - PDF documents (.pdf) - Email formats (.eml, .msg) - Web files (.html, .css) **File size considerations:** Large files are skipped to maintain optimal performance. Size thresholds are as follows: - 100 MB for any text file type. - 500 MB for PDFs. - 1 GB for any other file type listed. ## Managing your integration ### Monitoring health and Maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to the integration name 3. Click **Configure** 3. Click the delete icon next to your resource 4. Confirm the removal **Note:** Removing the integration preserves your incident history, but stops future scanning and presence checks for the integrations that support it. ![Integration removal](/img/internal-monitoring/integrate-sources/documentation-integrations/microsoft-sharepoint-online/uninstall-tenant.png) **Additional cleanup:** To completely remove the GitGuardian app from Azure, delete it from your **Entra ID registered applications**. ## Current considerations While archives scanning are supported, the complete path of the file in the archive will not be provided in the incident detail. Only the archive name. ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your Microsoft 365 users that your SharePoint sites and files are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the SharePoint sites files for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only sites and files relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the site's or file's purpose.* --- ## Integrate Microsoft Teams Monitor Microsoft Teams workspaces for exposed secrets in channel messages, conversations, and file attachments. ## Why Monitor Microsoft Teams? Microsoft Teams serves as the central communication hub for enterprise collaboration where employees share technical information, troubleshooting details, and project updates in real-time. During daily conversations and file sharing, team members frequently paste configuration snippets, error logs, and debugging information containing API keys, database credentials, and service account tokens directly into channels and private messages. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Manual Trigger) | Analyze existing messages and chat history | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your teams and channels - private channels require app invitation | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ✅ (Supported) | Private channels show as `private`, public/shared as `public` | | **Group Chats** | ❌ (Not Supported) | Group chats are not scanned | | **File Attachments** | ✅ (Supported) | File attachments are scanned | **What we scan:** - Standard, private, and shared channel messages - Direct messages and conversations - File attachments and shared documents - Thread discussions and replies :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Microsoft Teams administrator** permissions for the tenants you want to monitor GitGuardian integrates with Microsoft Teams via an **Entra ID Enterprise application** with **read-only access** to your channels. ## Setup your Microsoft Teams integration You can install GitGuardian on multiple Microsoft Teams tenants to monitor your standard, private and shared channels. 1. Make sure you're logged as administrator in the Microsoft Teams tenant you want to install 2. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 3. Click **Install** next to **Microsoft Teams** in the **Messaging** section ![Microsoft Teams install](/img/internal-monitoring/integrate-sources/messaging-integrations/microsoft-teams/microsoft-teams-install.png) 4. Click **Install** on the [Microsoft Teams integration](https://dashboard.gitguardian.com/settings/integrations/microsoft_teams) page 5. Select your Microsoft Teams administrator account 6. Click **Accept** to grant the permissions requested by GitGuardian ![Microsoft Teams permissions](/img/internal-monitoring/integrate-sources/messaging-integrations/microsoft-teams/microsoft-teams-permissions.png) That's it! Our GitGuardian Entra app is now automatically installed on your Microsoft Teams tenant. It will now start monitoring all posts shared on your standard, private and shared channels for secrets. ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Setup Microsoft Teams for self-hosted GitGuardian :::info We recommend using dedicated workers for Microsoft Teams. For more detailed information on scaling and configuration, please visit our [scaling](../../../self-hosting/management/infrastructure-management/scaling#configure-scaling-settings) page. ::: If you are using a self-hosted GitGuardian instance, you must first configure a dedicated Azure Entra ID Application. ### Create the Azure Entra ID Application for GitGuardian :::info You must be logged as a Microsoft Entra ID administrator to complete this process ::: 1. In your Microsoft Azure Tenant, browse to your Entra ID applications and create a new application, and click the "Create your own application" button 2. Choose a name for your application and register it to integrate with Microsoft Entra ID 3. Set a Redirect URI matching your GitGuardian Self-Hosted Instance: `https:///api/v1/microsoft-teams/app/install_callback/` ![Create your own application](/img/internal-monitoring/integrate-sources/messaging-integrations/microsoft-teams/entra-id-create-application-3.png) 4. Set permissions for your application Browse to Manage / API Permissions to set the needed permissions.Choose **Application permissions** if you are asked : ![Entra ID app permissions](/img/internal-monitoring/integrate-sources/file-storage-integrations/sharepoint-online/entra-id-application-permissions.png) Your application must be allowed the following Graph API permissions: - Application.ReadWrite.OwnedBy - Channel.ReadBasic.All - ChannelMessage.Read.All - ChatMember.Read.All - ChatMessage.Read.All - Files.Read.All - Group.Read.All - Organization.Read.All - Policy.Read.All - Policy.ReadWrite.ApplicationConfiguration - Team.ReadBasic.All - TeamMember.Read.All - User.Read You must also "Grant admin consent" for all these permissions. ![Create your own application](/img/internal-monitoring/integrate-sources/messaging-integrations/microsoft-teams/entra-id-create-application-4.png) 5. Generate a Secret for your application Browse to Manage / Certificates & secrets to create a Client Secret, create a secret and copy it while it is displayed. :::tip Store the Application ID and the Client Secret in a secure location like a vault or a secret manager ::: ### Reference your newly created application in GitGuardian Self-Hosted 1. Navigate to the Microsoft Teams integration page 2. Click **Configure Microsoft Teams app** ![Configure Microsoft Teams app](/img/internal-monitoring/integrate-sources/messaging-integrations/microsoft-teams/self-hosted-configure-app.png) 3. Set the Application ID and Secret you just created in Microsoft Azure Entra Id ### Attachment Scanning **No blindspot:** GitGuardian scans any attachments uploaded by end-users, except files previously uploaded to SharePoint and shared through the SharePoint link. Please consider using the **[Microsoft SharePoint Online integration](../file-storage-integrations/microsoft-sharepoint-online)** to scan any file from SharePoint Online, shared through Microsoft Teams. ### Comprehensive file support GitGuardian integration supports a wide range of file types: 1. **Text and code files:** - Source code (.py, .js, .java, .cpp, .cs, .rb, .go, .php, etc.) - Configuration files (.yaml, .json, .xml, .ini, .conf, .properties, etc.) - Documentation (.txt, .md, .rst, .log, etc.) 2. **Office documents:** - Microsoft Office (.docx, .xlsx, .pptx, .doc, .xls, .ppt) - OpenOffice/LibreOffice (.odt, .ods, .odp) - Rich text formats (.rtf) - Others (.epub) 3. **Archive and compressed files (experimental):** - Archive formats (.zip, .7z, .rar, .tar, .gz, .tgz or .tar.gz, .bz2, .tbz2 or .tar.bz2, .xz, .txz or .tar.xz, .ar, .cpio, .pack) - Container images (through .tar extensions) 4. **Other document formats:** - PDF documents (.pdf) - Email formats (.eml, .msg) - Web files (.html, .css) **File size considerations:** Large files are skipped to maintain optimal performance. Size thresholds are as follows: - 100 MB for any text file type. - 500 MB for PDFs. - 1 GB for any other file type listed. ## Uninstall your Microsoft Teams tenant To uninstall a Microsoft Teams tenant: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Microsoft Teams** in the **Messaging** section 3. Click the bin icon next to the Microsoft Teams tenant to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Microsoft Teams uninstall](/img/internal-monitoring/integrate-sources/messaging-integrations/microsoft-teams/microsoft-teams-uninstall.png) That's it! Your Microsoft Teams tenant is now uninstalled. ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **21600** (6 hours) - Minimum value: **1800** (30 minutes) ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your Microsoft Teams users that your channels are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the Microsoft Teams channels for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential secret leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only channels relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the channel's purpose.* ## Managing your integration ### Monitoring health and Maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to the integration name 3. Click **Configure** 3. Click the delete icon next to your resource 4. Confirm the removal **Note:** Removing the integration preserves your incident history, but stops future scanning and presence checks for the integrations that support it. --- ## Integrate Slack Monitor Slack workspaces for exposed secrets in channel messages, and team discussions. :::info Attachment scanning, Historical Scanning and Interactive Message A set of new capabilities including **File attachment scanning**, **Historical scanning**, and **Remediation actions in Slack Interactive Messages** were introduced with the **[April 23, 2026 Slack Marketplace release](/releases/saas/2026/04/23/changelog)**. These new features require additional scopes to properly operate. If your workspace was connected **before** that release, **uninstall and reinstall Slack** from [**Settings → Integrations → Sources**](https://dashboard.gitguardian.com/settings/integrations/sources) and complete the OAuth flow again so your workspace grants the updated permissions. ::: ## Why Monitor Slack? Slack serves as the central hub for team collaboration where developers frequently share code snippets, configuration examples, and troubleshooting outputs in real-time discussions. These casual conversations often contain accidentally copied API keys, database credentials, and debug information with embedded secrets, creating immediate security risks that spread across channels and persist in chat history. ## Capabilities | Feature | Support | Details | | ----------------------- | ------------------- | ------------------------------------------------------------------------ | | **Historical Scanning** | ✅ (Manual Trigger) | Analyze existing messages and chat history | | **Real-time Detection** | ✅ (Supported) | Instant detection via Slack Events API | | **Monitored Perimeter** | ✅ (Supported) | Select public channels to monitor - private channels require app invitation | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Direct Messages** | ✅ (Upon Consent) | When explicitly authorized by user | | **File Attachments** | ✅ (Supported) | File attachments dropped in channels/messages are supported | | **Interactive Message** | ✅ (Supported) | Users receive threaded interactive message when a secret is surfaced | **What we scan:** - Public and private channel messages - Direct messages (when explicitly authorized) - Thread discussions and replies :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup GitGuardian for Slack Integration on GitGuardian SaaS **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Slack Workspace Owner** permissions (if app restrictions are enabled) GitGuardian natively integrates with Slack via the [**GitGuardian**](https://slack.com/marketplace/A05PK62HTFH-gitguardian) or [**GitGuardian EU**](https://slack.com/marketplace/A07EQPEG9M1-gitguardian-eu) application on **Slack Marketplace**. The GitGuardian app for Slack has **read-only access** to your channels. You can refer to the [Slack documentation](https://api.slack.com/start/apps) for more information on managing apps. You can install GitGuardian on multiple Slack workspaces to start monitoring for secret leaks. 1. Make sure you're logged in to the Slack workspace you want to install 2. On the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 3. Click **Install** next to **Slack** in the **Messaging** section ![Slack install](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-install.png) 4. Click **Install** on the [Slack integration](https://dashboard.gitguardian.com/settings/integrations/slack) page 5. Select the Slack workspace you want to add 6. Click **Allow** to grant the permissions requested by GitGuardian ![Slack permissions](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-permissions.png) That's it! Our GitGuardian app is now automatically joining all your public channels and will monitor new messages in these channels. You can also invite the GitGuardian app to private channels to monitor these channels as well. ## Integration with GitGuardian Self-Hosted :::info We recommend using dedicated workers for this integration. For more detailed information on scaling and configuration, please visit our [scaling](../../../self-hosting/management/infrastructure-management/scaling#configure-scaling-settings) page. ::: If you are using a self-hosted GitGuardian instance, you must first create and configure a dedicated App on your Slack workspace so that you own the entire data stream. GitGuardian handles it for you programmatically via the creation of your app with a manifest file. This will ensure that your app is appropriately created, with all the necessary permissions. :::info Permissions requested No action needed on your side, the app will automatically request the following Bot Token Scopes: `channels:history`, `channels:join`, `channels:read`, `groups:history`, `groups:read`, `team:read`, `users:read`, `users:read.email`, `files:read`, `chat:write`, `im:write`, `reactions:read`, `reactions:write` ::: ### 1. Create an app on your Slack workspace #### If you are a GitGuardian Manager and you have the permissions to create an app on your Slack workspace 1. Navigate to the Slack integration page 2. Click **Configure app on Slack Marketplace** from your GitGuardian dashboard ![configure](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-configure.png) 3. Click **Create app on your Slack workspace** from the modal This will automatically redirect you to your Slack workspace applications, with a dialog modal opened 4. Select the Slack workspace you would like to monitor with GitGuardian 5. Click **Next** 6. You may review details, scopes and configurations set for the app on Slack Marketplace 7. Click **Create** 8. Go to **Settings > Basic Information > App Credentials** section 9. Get your App Credentials (`App ID`, `Client ID`, `Client Secret`, `Signing Secret`) that will be required for the pairing of the app with your GitGuardian workspace ![App creation](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-creation.gif) That's it! Your app on Slack Marketplace has been created and you can now [pair your app on Slack Marketplace with your GitGuardian Platform](#2-pair-the-app-on-your-slack-workspace-with-your-gitguardian-platform). #### If you are a GitGuardian Manager but you don't have the permissions to create an app on Slack Marketplace If you don't have the right to create an app on your Slack workspace, please ask your Slack administrator to do it for you. You can easily forward a request with this procedure: 1. Navigate to the Slack integration page 2. Click **Configure app on your Slack workspace** ![App configuration](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-configure.png) 3. Click the **Send a request to a Slack administrator** link to easily forward your request 4. They should in turn provide you with the credentials to proceed with the [pairing of the app on your Slack workspace with your GitGuardian Platform](#2-pair-the-app-on-your-slack-workspace-with-your-gitguardian-platform). #### If you are not a GitGuardian Manager but you received a request to create an app on your Slack Workspace You received a request to create a new app on your Slack Workspace so you can use GitGuardian to scan your Slack workspace for secrets. 1. Go to the [App creation](https://api.slack.com/apps?new_app=1&manifest_json=%7B%22display_information%22%3A%7B%22name%22%3A%22GitGuardian%22%7D%2C%22features%22%3A%7B%22bot_user%22%3A%7B%22display_name%22%3A%22GitGuardian%22%2C%22always_online%22%3Afalse%7D%7D%2C%22oauth_config%22%3A%7B%22redirect_urls%22%3A%5B%22https%3A//dashboard.gitguardian.com/api/v1/slack/app/install_callback/%22%5D%2C%22scopes%22%3A%7B%22user%22%3A%5B%5D%2C%22bot%22%3A%5B%22channels%3Ajoin%22%2C%22channels%3Aread%22%2C%22channels%3Ahistory%22%2C%22groups%3Ahistory%22%2C%22groups%3Aread%22%2C%22team%3Aread%22%2C%22users%3Aread%22%2C%22users%3Aread.email%22%5D%7D%7D%2C%22settings%22%3A%7B%22event_subscriptions%22%3A%7B%22request_url%22%3A%22https%3A//dashboard.gitguardian.com/api/v1/receiver/slack/%22%2C%22bot_events%22%3A%5B%22app_uninstalled%22%2C%22channel_archive%22%2C%22channel_created%22%2C%22channel_deleted%22%2C%22channel_history_changed%22%2C%22channel_id_changed%22%2C%22channel_left%22%2C%22channel_rename%22%2C%22channel_shared%22%2C%22channel_unarchive%22%2C%22channel_unshared%22%2C%22email_domain_changed%22%2C%22group_archive%22%2C%22group_deleted%22%2C%22group_history_changed%22%2C%22group_left%22%2C%22group_rename%22%2C%22group_unarchive%22%2C%22member_joined_channel%22%2C%22message.channels%22%2C%22message.groups%22%2C%22team_access_granted%22%2C%22team_access_revoked%22%2C%22team_domain_change%22%2C%22team_rename%22%5D%7D%2C%22org_deploy_enabled%22%3Afalse%2C%22socket_mode_enabled%22%3Afalse%2C%22token_rotation_enabled%22%3Afalse%7D%7D) page 2. Select the Slack workspace on which you will create a new app on your Slack Workspace 3. Click **Next** 4. Click **Edit Configurations** 5. Edit the **redirect_url** and **request_url** in the manifest to fit with the GitGuardian self-hosted instance URL: - **redirect_url**: - replace: `https://dashboard.gitguardian.com/api/v1/slack/app/install_callback/` - with: `https:///api/v1/slack/app/install_callback/` - **request_url**: - replace: `https://dashboard.gitguardian.com/api/v1/receiver/slack/` - with: `https:///api/v1/receiver/slack/` ![App manifest](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-manifest.png) 6. Click **Next** 7. Click **Create** 8. Go to **Settings > Basic Information > App Credentials** section 9. Return the App Credentials to your requester in the secure way of your choice (`App ID`, `Client ID`, `Client Secret`, `Signing Secret`) ![App credentials source](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-credentials-source.png) That's it! Your app has been created, and the requester will be able to declare its configuration in the GitGuardian platform. :::info The Historical Scan feature for Slack workspaces can be affected by [Slack API rate limits on `*:history` scopes](https://api.slack.com/changelog/2025-05-terms-rate-limit-update-and-faq). Please contact your Slack Account Manager for more information. ::: ### 2. Pair the app on your Slack Workspace with your GitGuardian Platform 1. Fill-in the Slack configuration modal opened from your GitGuardian dashboard, with your app credentials (`App ID`, `Client ID`, `Client Secret`, `Signing Secret`) ![App credentials](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-credentials.png) 2. Click **Save and close** Your app is now paired, you now need to finish the installation to start covering your channels. ### 3. Finish the installation You can install GitGuardian on multiple Slack workspaces to start monitoring for secret leaks. 1. Make sure you're logged in to the Slack workspace you want to install 2. On the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 3. Click **Install** next to **Slack** in the **Messaging** section ![Slack install](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-install.png) 4. Click **Install** on the [Slack integration](https://dashboard.gitguardian.com/settings/integrations/slack) page 5. Select the Slack workspace you want to add 6. Click **Allow** to grant the permissions requested by GitGuardian ![Slack permissions](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-permissions.png) That's it! Our GitGuardian app is now automatically joining all your public channels and will monitor new messages in these channels. You can also invite the GitGuardian app to private channels to monitor these channels as well. ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Real-time scanning **Catch new exposures instantly:** Once integrated, GitGuardian continuously monitors your content through event-based detection. Any new or modified content containing secrets are detected immediately, allowing you to respond quickly to new exposures. ## Extend your coverage to private channels :::info By default, GitGuardian only scans public channels. We do not access private channels without your consent. ::: You can also monitor your private channels with the Slack integration. To do so, simply invite our GitGuardian app into the desired private Slack channels: 1. Navigate to the private Slack channel of your choice 2. Go to the **Integrations** tab of your channel settings 3. Click **Add an App** 4. Click **Add** next to the **GitGuardian** app ![App addition](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-addition.gif) That's it! Our GitGuardian app is now invited to your private channel and ready for monitoring. To remove the GitGuardian app from a private Slack channel: 1. Navigate to the private Slack channel of your choice 2. Go to the **Integrations** tab of your channel settings 3. Click the **GitGuardian** app 4. Select **Remove this app from #channel** 5. Confirm by clicking **Remove** ![App removal](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-removal.gif) That's it! Our GitGuardian app is now removed from your private channel and secret detection is disabled. ## Edit the GitGuardian app on your Slack workspace configuration In case you need to edit the GitGuardian app on your Slack workspace configuration, due to an error when declaring your credentials or due to a secret rotation, you can do so as follows: 1. Click **Edit app** 2. Update your app credentials 3. Click **Save and close** ![App configuration edit](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-app-configuration-edit.png) ## Delete your GitGuardian app on your Slack workspace configuration In case you need to delete your GitGuardian app on your Slack workspace configuration, you can do so as follows: 1. Click **Edit app** 2. Click **Delete configuration** 3. Confirm by clicking **Delete configuration** in the confirmation modal :::info Deleting your GitGuardian app on your Slack workspace configuration will uninstall all your Slack integrations. However, all your existing incidents detected on Slack will remain available on your dashboard. Note that deleting the GitGuardian app on your Slack workspace configuration will only delete the configuration, not the app. If you want to delete your GitGuardian app on your Slack workspace, you must do so from your Slack workspace. ::: ## Uninstall your Slack workspace from GitGuardian Platform To uninstall a Slack workspace: 1. In the GitGuardian platform, navigate to the Sources integration page 2. Click **Edit** next to **Slack** in the **Messaging** section 3. Click the bin icon next to the Slack workspace to uninstall 4. Confirm by clicking **Uninstall** in the confirmation modal ![Slack uninstall](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/slack-uninstall.gif) That's it! Your Slack workspace is now uninstalled from GitGuardian Platform. ## Slack Interactive Messages When GitGuardian detects a secret in a Slack message, it automatically sends a threaded response to the original message with interactive actions. This allows users to quickly review and remediate incidents directly within Slack. ### How it works When a secret is detected in a Slack message: 1. GitGuardian sends a **threaded response** in the original Slack thread, reducing channel noise and preserving context. 2. The message includes information about the detected secret and provides quick actions. 3. Users can **ignore the incident** directly from Slack using the interactive button. :::info GitGuardian only triggers **one message per incident per thread**. Subsequent occurrences of the same secret in the same thread will not generate additional messages. ::: ### User identification and permissions GitGuardian uses the **email address** associated with the Slack user to find the corresponding user in the GitGuardian application. This matched user must have the appropriate permissions to perform actions on incidents. - To ignore an incident from Slack, the user must have the **Ignore incidents** permission in GitGuardian. - If a user does not have the necessary permissions, they will see an error message when attempting to ignore an incident. ### Interactive message types #### Secret detected When a secret is detected, GitGuardian posts a threaded message containing: - **Detector Type**: The type of secret detected (e.g., AWS Access Key, GitHub Token) - **Validity**: Whether the secret is valid or invalid (✅ Valid, ❌ Invalid) - **Location**: Link to the original message - **Posted by**: The author who posted the secret Available actions: - **View Incident**: Opens the incident detail page in GitGuardian - **Ignore**: Ignores the incident with the reason "This is a low risk secret" ![Secret detected message](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/interactive-messages/slack_secret_detected.png) #### Incident ignored When an incident is ignored via the Slack interactive message, the original message is updated to reflect the new status: - Shows the incident has been ignored - Displays who resolved the incident - Removes the action buttons ![Incident ignored message](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/interactive-messages/slack_ignored.png) ### Synchronization with GitGuardian Dashboard :::warning Important The synchronization between Slack and GitGuardian dashboard is **one-way for actions performed in GitGuardian**: - **Slack → GitGuardian**: When an incident is ignored through the Slack interactive message, it **will be reflected** in the GitGuardian dashboard. - **GitGuardian → Slack**: When an incident is resolved or ignored from the GitGuardian dashboard, the Slack interactive message **will NOT be updated** and no new message will be sent. ::: ### Error scenarios #### App reinstallation required You may need to **reinstall the Slack integration** and approve new bot scopes when GitGuardian expands what it could access **before [April 23, 2026](/releases/saas/2026/04/23/changelog)**: - **`chat:write`** used for interactive messages in threads. - **`files:read`** and other scopes bundled so **file attachments** is supoprted. Uninstall the workspace from GitGuardian and add Slack again from [**Settings → Integrations → Sources**](https://dashboard.gitguardian.com/settings/integrations/sources), then complete OAuth in Slack. #### Insufficient permissions If a user attempts to ignore an incident but does not have the required permissions in GitGuardian, they will see an error message indicating they do not have permission to perform this action. ![Insufficient permissions error](/img/internal-monitoring/integrate-sources/messaging-integrations/slack/interactive-messages/slack_no_permission.png) ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### App permissions The specific permissions used by our applications are listed on the corresponding Slack Marketplace pages: - [GitGuardian app for SaaS US](https://slack.com/marketplace/A05PK62HTFH-gitguardian?next_id=0&tab=settings) - [GitGuardian EU app for SaaS EU](https://slack.com/marketplace/A07EQPEG9M1-gitguardian-eu?settings=1&tab=settings) ### User notification Country-specific laws and regulations may require you to inform your Slack users that your channels are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the Slack channels for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > _Please note that only channels relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the channel's purpose._ --- ## Manage your monitored perimeter # Monitored Perimeter Management Learn how to effectively manage, monitor, and troubleshoot your integrated sources using GitGuardian's perimeter dashboard and tools. :::tip New to source integrations? For guidance on **which sources to integrate** and **how they compare**, see our [Sources Integration Overview](./overview). ::: ## Understanding your perimeter Your perimeter encompasses all the sources you've integrated with GitGuardian for secret monitoring. This includes repositories, container registries, messaging platforms, documentation systems, and more. If your workspace uses [team perimeter](../../platform/collaboration-and-sharing/teams.md#configure-team-perimeter), incident access follows team assignments. Your [perimeter page](https://dashboard.gitguardian.com/perimeter?sort_health=_&sort_ic=_&sort_source=false) has two main objectives: 1. Identify which of your sources are at risk 2. Ensure that your entire perimeter is well protected by GitGuardian ![Perimeter page](/img/internal-monitoring/integrate-sources/perimeter/plain.png) For effective navigation in the perimeter table, users can leverage [Saved views](../../platform/collaboration-and-sharing/saved-views.md) to switch between different sets of filters. The feature includes non-editable GitGuardian views such as "All sources," "Critical sources," "Scanning issues", "With open secret incidents", "Without honeytoken". ## Differences between historical scanning and real-time protection ### Real-time monitoring The first protection and the most effective one for secrets remediation is the **real-time monitoring**. As you may have read in our [How Internal Monitoring works section](../core-concepts/how-internal-monitoring-works.md), real-time monitoring means that every single push event (and its commits) is scanned for secrets as soon as they arrive on your VCS server (post-receive hooks). We use the same concept for other data sources, such as Slack and Jira, through the subscription to specific events. We then **alert you instantly**, which will save you time in the remediation process. Indeed, **the longer a secret is exposed, the harder the remediation gets.** On the right-hand side panel, we indicate **the percentage of sources covered**, based on the number of sources you integrated with GitGuardian. Note that some sources may not be eligible to be monitored because of plan restrictions. Note that the table of sources displayed on the Perimeter page only contains sources that are monitored in real-time. The sources that are not selected in the integration settings page are not displayed. ![real-time protection coverage](/img/internal-monitoring/integrate-sources/perimeter/real_time_protection_coverage.png) For performance reasons, we limit the number of commits scanned per push event. By default, this limit is 1,000 scanned commits/push event, but this can be customized per workspace on demand. ### Incremental scanning GitGuardian provides ongoing protection through scheduled automated scans of your content when the integration does not offer Webhooks support. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ### Historical scanning The second type of protection offered is the ability to **scan the commit history** of all the sources you integrated with GitGuardian. ![historical scan coverage](/img/internal-monitoring/integrate-sources/perimeter/historical_scan_coverage.png) Size limitations apply to historical scans, depending on your plan: - Free: you can scan sources up to 1GB, - Business and trial: you can scan sources up to 12 GB. :::info For performance reasons, if a historical scan is requested for a repository that has had no new commits on any branch since the last historical scan, GitGuardian will skip the scan to avoid reprocessing the entire history. However, if the tokenscanner version has changed since the last historical scan—with GitGuardian having introduced new detectors—the scan will proceed, even if there are no new commits. ::: #### Scanning orphaned commits and extra Git references during historical scans A standard `git clone` only brings in branches (`refs/heads/*`) and tags (`refs/tags/*`). When you run a **historical scan** on a Version Control System, GitGuardian goes one step further: after the initial clone, it inspects every reference the remote exposes and fetches the ones that aren't already covered. The following namespaces are picked up automatically: | Reference namespace | What it contains | Provider | | ----------------------- | ----------------------------------------------------------------------------- | ------------------------------- | | `refs/pull/*` | Open, closed, and merged pull request head / merge commits | GitHub, Azure DevOps | | `refs/merge-requests/*` | Open, closed, and merged merge request commits | GitLab | | `refs/pull-requests/*` | Pull request head / merge commits | Bitbucket (Cloud & Data Center) | | `refs/changes/*` | Pending and abandoned change refs | Gerrit | | `refs/notes/*` | Git notes (`refs/notes/commits` and any custom notes namespace) | All providers | | `refs/keep-around/*` | Refs GitLab keeps to prevent garbage collection (e.g. CI pipeline commits) | GitLab | | Other custom namespaces | Anything else the remote exposes (e.g. `refs/sandbox/*`, `refs/replace/*`, …) | All providers | #### Potential Errors During Historical Scanning and Their Resolutions | Reason | Error Message | Steps to Resolve | | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | DMCA takedown | The source is unavailable due to a [DMCA](https://docs.github.com/en/site-policy/content-removal-policies/dmca-takedown-policy) takedown. | Contact the source owner to discuss the DMCA takedown. | | Access to the repository is disabled | The source has been disabled. | Reach out to the source owner to request re-enabling access to the repository. | | Account has been disabled | The source’s account has been disabled. | Contact the source owner to resolve the account issues and regain access. | | Access to repository restricted by IP | The source’s account has a configured IP allow list. | Contact the source owner to review and adjust the IP allow list. | | Repository not found | The source could not be found. Please retry and contact the source owner if it persists. | Double-check the repository URL and retry. Contact the source owner if the issue persists. | | Clone operation stuck or too slow | The connection to the server is slow or stuck. | Contact the VCS administrator to investigate server connection issues. | | VCS not ready or responded with an error | The server did not respond after multiple attempts. | Reach out to the VCS administrator to ensure the server is operational and retry the scan. | | Repository disabled in GitLab project | The git repository in the GitLab project has been disabled. | Enable the “repository” functionality in the settings of the GitLab project. | | The repository has been deleted | The target repository has been deleted. | Contact the VCS administrator to confirm and address the deletion of the repository. | | VCS authentication error | The authentication to the VCS has failed. | Verify authentication token under Settings > Integrations and contact the VCS administrator if needed. | | Rate limit error | The rate limit has been exceeded. | Wait for the rate limit to reset or contact the VCS administrator for a resolution. | | Too Large | The historical scan failed because it exceeded the authorized size limit. | Contact GitGuardian [support](mailto:support@gitguardian.com) to discuss options for scanning larger repositories. For self-hosted environments, consider adjusting the `repo_scan_size_limit` in the [preferences](../../self-hosting/management/application-management/preferences#policy) within the [Admin area](../../self-hosting/management/application-management/admin-area#settings). | | Timeout | The historical scan failed due to a timeout error because it exceeded the authorized time limit for an individual scan. | Contact GitGuardian [support](mailto:support@gitguardian.com) for troubleshooting and to potentially extend the scan time limit. For self-hosted environments, consider adjusting the `repo_scan_time_limit_in_sec` in the [preferences](../../self-hosting/management/application-management/preferences#policy) within the [Admin area](../../self-hosting/management/application-management/admin-area#settings). | | Timeout Pending | The historical scan failed due to a timeout error because it exceeded the authorized time limit for a bulk scan. Please contact our [support](mailto:support@gitguardian.com). | Contact GitGuardian support to address bulk scan timeouts and explore alternative solutions. For self-hosted environments, consider adjusting the `repo_scan_pending_limit_in_hours` in the [preferences](../../self-hosting/management/application-management/preferences#policy) within the [Admin area](../../self-hosting/management/application-management/admin-area#settings). | | Scan worker error | The scan failed due to an internal worker error, often caused by memory limitations. | Please reach out to our [support team](mailto:support@gitguardian.com). If you are running GitGuardian in a self-hosted environment, consider increasing the memory allocation for workers to resolve the issue. Additionally, generate a [Support Bundle](../../self-hosting/troubleshoot/support) for further troubleshooting purposes. | | Engine error | The scan failed due to an internal engine error. | Please reach out to our [support team](mailto:support@gitguardian.com). If you are running GitGuardian on a self-hosted environment, generate a [Support Bundle](../../self-hosting/troubleshoot/support) for troubleshooting purposes. | | Process received SIGKILL | The scan process was forcibly terminated (SIGKILL). | Please reach out to our [support team](mailto:support@gitguardian.com). If you are running GitGuardian on a self-hosted environment, generate a [Support Bundle](../../self-hosting/troubleshoot/support) for troubleshooting purposes. | | Filename too long | A filename inside the repository is too long. | Due to internal limitations, repositories with filenames longer than 255 bytes (approximately > 200 characters, depending on the characters used) prevent repositories from being scanned. You can find these files with commands such as `find . -type f \| awk -F/ '{if(length($NF)>200) print}'`. | | Git reference not found | The reference doesn't exist anymore. | This usually happens if the repository uses a submodule but the given reference for the submodule doesn't exist anymore. Contact the source owner to verify the submodules configuration. | | Failsafe limit reached | The source has too many issues to scan. | A failsafe limit of 200,000 incidents per source is in place. This threshold is unlikely to be reached during normal usage, but if you do encounter it, please contact our [support team](mailto:support@gitguardian.com). | | Container image file not found in registry | A layer of the container image was not found in the registry and could not be downloaded. | Verify that the container image still exists in the registry and has not been deleted or garbage-collected. | | Slack app not in channel | Channel installation might still be running. Please retry later. | The GitGuardian app for Slack may still be finishing its installation in the channel. Wait a few minutes for the installation to complete and retry the scan. If the error persists, confirm the GitGuardian app for Slack has been added to the channel. | | Unknown | The scan failed due to an unknown error. | Please reach out to our [support team](mailto:support@gitguardian.com). If you are running GitGuardian on a self-hosted environment, generate a [Support Bundle](../../self-hosting/troubleshoot/support) for troubleshooting purposes. | Historical scanning is also available for Slack. You can scan the entire history of your monitored public and private Slack channels. Conversations and archived channels are not supported. Note that historical scanning is subject to the Slack's API rate limiting. We can scan up to 10.000 messages/min per Slack workspace. Historical Scan reports of Slack and VCS are sent separately. ## Rate limits on self-hosted sources Some source integrations enforce API rate limits. For SaaS services such as GitHub.com or Slack, GitGuardian automatically paces its scanning to stay within the provider's known limits, so there is nothing for you to configure. For self-hosted sources, the limits are controlled by your own instance. When rate limiting is enabled, the default values can be quite low and may throttle GitGuardian's requests, significantly slowing down historical scans and real-time detection, or causing a [Rate limit error](#potential-errors-during-historical-scanning-and-their-resolutions). To scan these sources in a reasonable time, we recommend that you either **raise the rate limits** on your instance or **exempt the account, token, or service account that GitGuardian uses** from rate limiting. Most platforms let you grant a per-user exemption or a higher limit without changing the global setting. The following self-hosted sources let you configure rate limits: | Self-hosted source | Provider documentation | | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [GitHub Enterprise Server](./vcs-integrations/github-enterprise) | [Configuring rate limits](https://docs.github.com/en/enterprise-server@latest/admin/configuring-settings/configuring-user-applications-for-your-enterprise/configuring-rate-limits) | | [GitLab Self-Managed](./vcs-integrations/gitlab) | [User and IP rate limits](https://docs.gitlab.com/administration/settings/user_and_ip_rate_limits/) and [rate limits on the Users, Groups, and Projects APIs](https://docs.gitlab.com/administration/settings/rate_limit_on_users_api/) | | [Bitbucket Data Center/Server](./vcs-integrations/bitbucket) | [Improving instance stability with rate limiting](https://confluence.atlassian.com/bitbucketserver/improving-instance-stability-with-rate-limiting-976171954.html) | | [Jira Data Center](./ticketing-integrations/jira-data-center) | [Improving instance stability with rate limiting](https://confluence.atlassian.com/adminjiraserver/improving-instance-stability-with-rate-limiting-983794911.html) | | [Confluence Data Center](./documentation-integrations/confluence-data-center) | [Improving instance stability with rate limiting](https://confluence.atlassian.com/display/DOC/Improving+instance+stability+with+rate+limiting) | :::tip On Atlassian Data Center products (Bitbucket, Jira, Confluence), rate limiting is turned off by default but, once enabled, applies to REST API traffic. Add the GitGuardian account as an [exemption](https://confluence.atlassian.com/adminjiraserver/improving-instance-stability-with-rate-limiting-983794911.html) so its scanning is not throttled. ::: ## Source status Every source in your perimeter has a status: **Monitored**, **Unmonitored**, **Unreachable**, **Archived**, or **Deleted**. You can filter on this status from the [Perimeter page](https://dashboard.gitguardian.com/perimeter) and the incident list, and save the result as a [view](../../platform/collaboration-and-sharing/saved-views.md), for example to set aside incidents from archived or deleted sources. :::note A valid secret in an archived or deleted source is not necessarily less risky. Archiving or deleting the source does not revoke the secret, so treat these incidents on their own merits. ::: ### Monitored source A source is considered as monitored when the GitGuardian platform is listening for any activity on that source. This is the outcome of: - successfully integrating GitGuardian with the source - and having a plan that supports its monitoring. Monitored sources are listed on the [Perimeter page](https://dashboard.gitguardian.com/perimeter). ### Unmonitored source A source is considered unmonitored when GitGuardian is no longer listening to any activity on that source. This may be the result of: - excluding the source from the monitored perimeter, - or a change in your plan that no longer supports this source. An unmonitored source presents a risk, as no occurrence will be created after a secret has been published in it. Such a source is identified with a striked shield icon next to it. ![unmonitored source](/img/internal-monitoring/integrate-sources/perimeter/source_no_longer_monitored.png) Unmonitored sources are no longer listed on the [Perimeter page](https://dashboard.gitguardian.com/perimeter). :::warning Unmonitoring also removes the source from its teams Unmonitoring a source removes it from all of its [teams](../../platform/collaboration-and-sharing/teams.md#configure-team-perimeter). As a result: - members of those teams lose access to the incidents tied to that source, - and the source no longer shows any team assignment on the perimeter page. Only **managers** and **owners** can monitor or unmonitor a source. ::: ### Unreachable source A source is unreachable when GitGuardian cannot connect to it, for example after credentials expire, access is revoked, or the provider is temporarily down. While a source is unreachable, GitGuardian pauses real-time ingestion and historical scans on it, then auto-resumes them once connectivity is restored. GitGuardian also surfaces an actionable recovery step so you can fix the underlying issue. See the relevant [integration guide](./overview.md) for provider-specific steps. ### Archived source A source is considered archived when it has been archived at the provider, for example an archived repository on GitHub. No new activity is expected on an archived source, but its existing incidents remain visible so you can still act on them. ### Deleted source A source is considered deleted only when GitGuardian receives evidence of its actual deletion. This means that we don't consider a source deleted just because it has been removed from GitGuardian, but rather only when it has been truly erased. Eg: the repository is deleted on GitHub. Such a source is identified with a bin icon next to it. ![deleted source](/img/internal-monitoring/integrate-sources/perimeter/source_deleted.png) Deleted sources are no longer listed on the [Perimeter page](https://dashboard.gitguardian.com/perimeter). ## Source visibility A source is defined by a visibility scope. Depending on the installed instance, a source can be: - `public`: anyone with access to the Internet can view the contents of this source. Your secret is publicly exposed and presents a higher security risk. - `internal` (specific to GitLab): internal GitLab projects can be viewed by any authenticated user except external users. Such a GitLab project is identified by a shield icon next to it. - `private`: Only authorized users with access to the source can view its contents. Such a source is identified by a lock icon next to it. ![source visibility](/img/internal-monitoring/integrate-sources/perimeter/source_private.png) ## Source criticality The source criticality feature enables you to assess and assign a level of importance to your monitored sources, helping you prioritize your incidents effectively. This feature allows you to categorize them as low, medium, high, or critical, or leave it unfilled, based on the potential severity of a security incident's impact. Its value depends on the business context of your source, which will be determined by factors such as the nature of the handled data and its connection to resources in a production environment. ![business criticality edit](/img/internal-monitoring/integrate-sources/perimeter/business_criticality_edit.png) ## Bulk actions on perimeter sources Bulk actions on the perimeter page allow you to manage multiple sources simultaneously, streamlining your perimeter monitoring workflow. ### How to use bulk actions 1. Navigate to your [perimeter page](https://dashboard.gitguardian.com/perimeter) 2. Select multiple sources using checkboxes 3. The bulk actions toolbar appears at the top 4. Choose your desired action :::tip Use the header checkbox to select all sources on the page, or click "Select all X sources" to select all matching your current filters. ::: ### Available actions #### Source management - **Monitor**: Start monitoring the selected sources. - **Unmonitor**: Stop monitoring the selected sources. Unmonitoring a source also removes it from all of its teams, so those teams' members lose access to the source's incidents (see [Unmonitored source](#unmonitored-source)). - **Assign team**: Add the selected sources to a team. Only monitored sources are added to the team; any unmonitored sources in your selection are skipped. - **Set criticality**: Update business criticality levels (Critical, High, Medium, Low) for multiple sources. - **Scan**: Launch historical scans on selected sources (if scanning is enabled). ### Best practices - **Filter first**: Use search and filters to narrow your source selection - **Verify selection**: "Select all" button only selects the displayed sources. Use the "Select all sources that match the filters" to select the entire selection. - **Criticality assessment**: Set source criticality based on business impact and production environments - **Scan**: Consider system load when launching bulk historical scans (self-hosted) ### Permissions Source bulk actions require appropriate workspace permissions: - **Manager**: Can monitor and unmonitor sources, assign sources to teams, update source criticality, and launch scans. - **Member**: Can launch scans on sources within their team's perimeter but cannot monitor or unmonitor sources, assign teams, or update source criticality. ## Adding new sources to your perimeter To expand your monitored perimeter with new integrations, see our comprehensive [Sources Integration Overview](./overview) which provides: - **Capability comparison** across all source types - **Integration guides** organized by category - **Strategic guidance** on prioritizing integrations - **Getting started recommendations** The overview includes detailed information about all available integrations including VCS, container registries, messaging platforms, documentation systems, and custom sources. ## Troubleshooting connectivity problems Most often, connectivity problems arise because a firewall, proxy server, corporate network, or other network is configured in a way that blocks GitGuardian. In case you need to authorize incoming/outgoing connections to/from the SAAS application, this paragraph provides the necessary information. ### Allowing incoming connections from GitGuardian's IP addresses :::tip Retrieve IP addresses programmatically GitGuardian exposes its egress IP addresses through unauthenticated API endpoints. You can use these to keep your firewall rules in sync automatically: - **US**: `GET https://api.gitguardian.com/v1/ips` ([API reference](https://api.gitguardian.com/docs#tag/IPs)) - **EU**: `GET https://api.eu1.gitguardian.com/v1/ips` ([API reference](https://api.eu1.gitguardian.com/docs#tag/IPs)) ::: GitGuardian US uses the following IPs: - 35.161.89.114/32 - 35.162.178.46/32 - 35.163.105.95/32 - 35.83.131.170/32 - 44.224.13.10/32 - 44.231.207.147/32 - 44.239.165.162/32 - 52.25.45.243/32 - 54.184.247.227/32 - 54.188.183.19/32 - 54.189.40.226/32 - 54.212.233.107/32 GitGuardian EU uses the following IP addresses: - 18.153.164.184/32 - 18.158.109.52/32 - 18.184.72.235/32 - 18.198.133.200/32 - 3.127.11.54/32 - 3.64.118.208/32 - 3.75.125.128/32 - 3.76.233.226/32 - 52.28.29.48/32 These IP addresses are used for: - [VCS integrations](./vcs-integrations/github) (eg: GitHub, GitLab) - [Container Registries integrations](./container-registries-integrations/amazon-ecr) (eg: Amazon ECR, Azure Container Registries, Docker Hub, Google Artifact Registry, JFrog Container Registry) - [Messaging integrations](./messaging-integrations/slack) (eg: Slack, Microsoft Teams) - [Ticketing integrations](./ticketing-integrations/jira-cloud) (eg: Jira Cloud, Jira Data Center, ServiceNow) - [Documentation integrations](./documentation-integrations/confluence-cloud) (eg: Confluence Cloud, Confluence Data Center) - [Alerting integrations](../../platform/configure-alerting/alerting-and-notifications) (eg: Slack, Microsoft Teams, PagerDuty, ...) - [Validity checks](../../secrets-detection/customize-detection/validity-checks) ### Allowing outgoing connections to GitGuardian's domains Requests to GitGuardian use IP addresses that change regularly. It is advised to whitelist domains instead. The following domains are used by GitGuardian US: - dashboard.gitguardian.com - hook.gitguardian.com - api.gitguardian.com The following domains are used by GitGuardian EU: - dashboard.eu1.gitguardian.com - hook.eu1.gitguardian.com - api.eu1.gitguardian.com All endpoints are using HTTPS. HTTP is exclusively used to redirect to HTTPS. --- ## Sources Integration Overview GitGuardian's **Internal Monitoring** protects your organization by scanning diverse data sources where secrets might be exposed. From code repositories to collaboration platforms, we help you discover, remediate, and prevent secret leaks across your entire digital ecosystem. ## Why Integrate Multiple Sources? Modern organizations store and share code across numerous platforms and tools. Secrets can leak anywhere: in commit histories, chat messages, documents, or container images. Comprehensive coverage ensures no exposure goes undetected. **Key benefits:** - **Complete visibility**: Monitor your entire attack surface, not just git repositories - **Early detection**: Catch secrets before they reach production environments - **Unified management**: View and manage all incidents from a single dashboard - **Automated remediation**: Leverage our workflows to speed up incident response ## Source Categories ### Version Control Systems (VCS) **Monitor code repositories** where secrets are most commonly exposed through commit history and branches. | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**GitHub**](./vcs-integrations/github) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | [**GitHub Enterprise**](./vcs-integrations/github-enterprise) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | [**GitLab**](./vcs-integrations/gitlab) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | [**Bitbucket Cloud**](./vcs-integrations/bitbucket-cloud) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | [**Bitbucket Server**](./vcs-integrations/bitbucket) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | [**Azure DevOps**](./vcs-integrations/azure-repos) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | **Coverage includes:** - Source code files - Configuration files - Documentation - Commit messages and metadata ### Container Registries **Scan container images** for embedded secrets in application layers, environment variables, and configuration files. | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**Amazon ECR**](./container-registries-integrations/amazon-ecr) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | N/A | | [**Azure Container Registry**](./container-registries-integrations/azure-container-registry) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | N/A | | [**Docker Hub**](./container-registries-integrations/docker-hub) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | N/A | | [**Google Artifact Registry**](./container-registries-integrations/google-artifact-registry) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | N/A | | [**JFrog Container Registry**](./container-registries-integrations/jfrog-container-registry) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | N/A | | [**Red Hat Quay**](./container-registries-integrations/red-hat-quay) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | N/A | **Coverage includes:** - Application code in container layers - Environment variables and startup scripts - Configuration files and SSL certificates - Package dependencies and build artifacts ### Package Registries **Scan package artifacts** for embedded secrets in software packages across multiple ecosystems (npm, Maven, PyPI, NuGet, and more). | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**JFrog Package Registries**](./package-registries-integrations/jfrog-package-registry) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | N/A | **Coverage includes:** - npm, Maven, PyPI, NuGet packages - Configuration files within packages - Build artifacts and metadata - Package manifests and scripts ### Messaging & Collaboration **Monitor communication platforms where secrets might be accidentally shared in conversations or file uploads. | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**Slack**](./messaging-integrations/slack) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | | [**Microsoft Teams**](./messaging-integrations/microsoft-teams) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ✅ | ✅ | **Coverage includes:** - Channel messages and threads - Private messages (when explicitly authorized) - File attachments (select integrations) - Code snippets and pastes ### Documentation **Scan document libraries** for secrets in technical documentation, configuration guides, and shared files. | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**Confluence Cloud**](./documentation-integrations/confluence-cloud) | ✅ | ⏱️ | ✅ | ✅ | ✅ | ❌ | ✅ | | [**Confluence Data Center**](./documentation-integrations/confluence-data-center) | ✅ | ⏱️ | ✅ | ✅ | ✅ | ❌ | ✅ | **Coverage includes:** - Technical documentation and wikis - Office documents (Word, Excel, PowerPoint) - PDF files and presentations - Configuration files and templates ### File Storage **Scan file storage and object storage** for secrets in shared documents, backups, exports, and stored objects. | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**AWS S3**](./file-storage-integrations/aws-s3) | ✅ | ⏳ | ✅ | ✅ | ❌ | ❌ | ✅ | | [**SharePoint Online**](./file-storage-integrations/microsoft-sharepoint-online) | ✅ | ⏱️ | ✅ | ✅ | ✅ | ❌ | ✅ | | [**OneDrive**](./file-storage-integrations/microsoft-onedrive) | ✅ | ⏱️ | ✅ | ✅ | ✅ | ❌ | ✅ | **Coverage includes:** - Cloud file and object storage - Office documents (Word, Excel, PowerPoint) - Backups, logs, and data exports - Configuration files and IaC artifacts ### Ticketing & Project Management **Monitor project tracking tools** where secrets might appear in issue descriptions, comments, or attachments. | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**Jira Cloud**](./ticketing-integrations/jira-cloud) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | | [**Jira Data Center**](./ticketing-integrations/jira-data-center) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | | [**ServiceNow**](./ticketing-integrations/servicenow) | ✅ | ⏱️ | ✅ | ✅ | ❌ | ❌ | ❌ | **Coverage includes:** - Issue descriptions and comments - Project documentation - Ticket attachments - Custom field content ### Custom Sources **Extend monitoring** to any data source with [Bring Your Own Sources](./bring-your-own-sources) | Source | Historical Scan | Real-time | Custom Perimeter | Team Perimeter | Presence Check | Source Visibility | File Attachments | |--------|----------------|-----------|------------------|----------------|----------------|-------------------|------------------| | [**Custom Sources**](./bring-your-own-sources) | Manual | Manual | ✅ | ⏳ | ✅ | ✅ | ✅ | **Sky is the limit! With Custom Sources you can cover:** - CI/CD logs and build artifacts. - Legacy systems and databases. - FTP servers and file shares. - Any custom data source via API. - Etc... ## Feature Information ### Legend | Symbol | Meaning | |--------|---------| | ✅ | Fully supported | | ⏱️ | Incremental scanning (scheduled intervals) | | ⏳ | Coming soon | | ❌ | Not supported | | N/A | Not applicable for this source type | ### Feature Definitions - **Historical Scan**: Scans existing content when integration is first set up, covering the historical debt. - **Real-time**: Event-based monitoring that detects new content instantly as it's created or modified. - **Incremental**: Scheduled monitoring that scans for new content at regular intervals (typically every few hours). - **Custom Perimeter**: Allows granular control over which repositories, channels, or resources are monitored. - **Team Perimeter**: Supports team-based access control for incidents. - **Presence Check**: Verifies if detected secrets are still accessible. - **Source Visibility**: Determines if the source can distinguish between public and private content visibility. - **File Attachments**: Scans files attached to messages or tickets. ## Security & Compliance ### Data Protection - **Read-only access**: Integrations never modify your source data. - **Minimal retention**: We store only metadata necessary for incident management. - **Encryption**: All data is encrypted in transit and at rest. - **Regional compliance**: Available in multiple regions to meet data residency requirements. ### Privacy Considerations - **Explicit consent**: Private channels/repositories require explicit authorization. - **Configurable perimeter**: Control exactly what gets scanned. - **GDPR compliant**: Full support for European data protection regulations. - **Audit trails**: Complete visibility into what data is accessed ## Getting Started 1. **Plan your integration strategy**: Identify your highest-risk sources first. 2. **Start with VCS**: Git repositories typically contain the most critical secrets 3. **Expand gradually**: Add collaboration and documentation platforms 4. **Configure perimeters**: Customize what content gets scanned 5. **Set up alerting**: Configure notifications for your security team ## Managing your integrations Once you've set up your integrations, learn how to effectively **[Monitor Your Perimeter](./monitored-perimeter)**, including dashboard usage, scanning types, source status, and troubleshooting. ## Support & Troubleshooting - **Plan requirements**: Most integrations require Business or Enterprise plans - **Trial available**: 30-day free trial for most integrations - **Support channels**: Available through your GitGuardian dashboard - **Documentation**: Comprehensive guides for each integration Ready to enhance your security posture? Start with our most popular integration: [GitHub](./vcs-integrations/github). --- ## Integrate JFrog Package Registries Secure your software supply chain by monitoring JFrog Package Registries for exposed secrets in package artifacts across multiple ecosystems. ## Why Monitor JFrog Package Registries? JFrog Artifactory serves as the universal package management solution for your organization, hosting packages across multiple ecosystems such as Maven, npm, PyPI, NuGet, Go, Gradle, and more. These packages often contain production database credentials, enterprise API keys, internal service tokens, and other sensitive configuration that, when exposed, can compromise critical business applications and provide unauthorized access to proprietary systems and sensitive customer data. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing packages and their contents | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All sources are considered as private | | **File Attachments** | N/A | Not applicable for package registries | **What we scan:** - Maven artifacts - npm packages - PyPI packages - Gradle artifacts - Go modules - Swift packages - Cargo crates - RubyGems - NuGet packages - Composer packages - Pub packages - Generic repositories :::info This integration automatically scans your monitored repositories, downloading package artifacts which may incur [bandwidth costs](https://jfrog.com/pricing/). To optimize costs and reduce false positives, carefully select the sources to monitor and use our [filepath exclusion feature](../../../secrets-detection/customize-detection/exclusion-rules#filepath-exclusions). ::: :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Setup your JFrog Package Registries integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **JFrog admin permissions** to create Access Tokens in your JFrog instance - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. GitGuardian integrates with JFrog Package Registries via an **Access Token** with **admin scope** on your JFrog instance. Admin scope is required to enumerate repositories and download package artifacts across all package types. You can install GitGuardian on multiple JFrog instances to monitor your package repositories. 1. Make sure you're logged as an administrator in your JFrog Platform 2. Go to **Administration** > **User Management** > **Access Tokens** 3. Click **Generate Token** ![JFrog Platform Access Tokens page](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-access-tokens.png) 4. Type a Description (e.g.: `GitGuardian`) 5. Select `Admin` as **Token scope** 6. Uncheck **All** and select `Artifactory` as **Service** 7. Click **Generate** ![JFrog Platform Generate Token modal](/img/internal-monitoring/integrate-sources/package-registries-integrations/jfrog-package-registry/jfrog-package-registry-generate-token.png) 8. Get the **Username** and copy the **Token** ![JFrog Platform Token value modal](/img/internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry/jfrog-container-registry-copy-token.png) 9. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 10. Click **Install** next to **JFrog Package Registries** in the **Package registries** section ![JFrog Package Registry install button](/img/internal-monitoring/integrate-sources/package-registries-integrations/jfrog-package-registry/jfrog-package-registry-install.png) 11. Click **Install** on the JFrog Package Registries integration page 12. Type your **JFrog instance URL** (e.g.: `https://acme.jfrog.io/`) 13. Paste your **Personal access token** 14. Click **Add** ![JFrog Package Registry integration](/img/internal-monitoring/integrate-sources/package-registries-integrations/jfrog-package-registry/jfrog-package-registry-integration.png) 15. Customize your monitored perimeter: - **Monitor specific JFrog repositories** (Recommended) - No repositories are monitored by default, you will have to select them manually. - Newly created repositories will not be monitored by default. You can adjust this setting at any time. - Recommended to optimize your [bandwidth costs](https://jfrog.com/pricing/). - **Monitor the entire JFrog instance** - All repositories are monitored by default with a full historical scan automatically triggered. - Newly created repositories will be monitored by default. You can adjust this setting at any time. That's it! Your JFrog instance is now installed, and GitGuardian is monitoring all packages of your selected repositories for secrets. ## Customize your monitored perimeter To customize the monitored repositories, navigate to your JFrog Package Registries settings from the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page. 1. Select/Unselect repositories to include or exclude them from monitoring 2. Confirm by clicking **Update monitored perimeter** ## Automatic repository monitoring You can enable or disable the automatic addition of newly created repositories to your monitored perimeter by switching the option in your JFrog Package Registries settings. ## Managing your integration ### Monitoring health and Maintenance If you need to modify your integration settings or troubleshoot connectivity issues, access the management interface through [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning). ### Uninstalling the integration While our goal is to help you maintain comprehensive security coverage, you may uninstall the integration whenever necessary: 1. Navigate to [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) 2. Click **Edit** next to the integration name 3. Click **Configure** 3. Click the delete icon next to your resource 4. Confirm the removal **Note:** Removing the integration preserves your incident history, but stops future scanning and presence checks for the integrations that support it. ## Uninstall your JFrog Package Registries instance To uninstall a JFrog Package Registries instance: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **JFrog Package Registries** in the **Package registries** section 3. Click the bin icon next to the JFrog Package Registries instance to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal That's it! Your JFrog Package Registries instance is now uninstalled. ## Excluded paths GitGuardian automatically excludes files from scanning if their paths contain any of these regular expressions: ``` /__pypackages__/ /\.venv/ /\.tox/ /site-packages/ /venv/ distutils/command/register\.py python.*/awscli/examples/ python.*/dulwich/(tests|contrib/test_) python.*/hgext/bugzilla\.py python.*/mercurial/util\.py python.*/test/certdata/ python.*/urllib/request\.py python.*/pygments/lexers/ /cryptography.+/tests/.+(fixtures|test)_.+\.py /python.+pygpgme.+/tests/ botocore/data/.+/(examples|service)-.+\.json usr(/local)?/lib/python.+/dist-packages /libevent.+/info/test/test/ /conda-.+-py.+/info/test/tests.+/test_.+\.py /python[^/]+/test/ /man/man5/kdc\.conf\.5 erlang.*(inets|ssl).*/examples/ /gems/.*httpclient.*/(test|sample)/ /gems/.*faraday.*/ /vendor/bundle/ /\.gem/ ruby-[^/]+/test/openssl/ /(g|G)o/src/cmd/go/internal/.*_test\.go /(g|G)o/src/cmd/go/internal/.*/testdata/ /(g|G)o/src/cmd/go/testdata/ /(g|G)o/src/crypto/x509/platform_root_key\.pem /(G|g)o/src/crypto/(tls|x509)/.*_test\.go /(g|G)o/src/net/(url|http)/.*_test\.go src/github.com/DataDog/datadog-agent/.*test.*\.go google/internal/.*_test\.go golang.org.*oauth2@.*/.*\.go /flutter/.*/packages/flutter_tools/test/data/ /flutter/.*/examples/image_list/lib /\.pub-cache etc/ssl/private/ssl-cert-snakeoil\.key perl.*Cwd\.pm ansible/.*/tests/(integration|unit)/ ansible/.*/test/awx ansible/collections/ansible_collections/.*/plugins/ /curl/.*/(tests|docs|lib/url\.c) /doc/wget.+/NEWS dist/awscli/examples/ usr(/local)?/lib/aws-cli/examples/ /google-cloud-sdk/(lib|platform)/ \.git/modules/third[-_]?party/ \.git/modules/external/ /\.npm/_cacache /node_modules/ /\.parcel-cache/ /\.yarn/cache/ /\.m2/ /\.ivy2/cache/ /\.mix/ /\.hex/ /composer/cache/ /\.nuget/packages/ /libgpg-error/errorref\.txt /Homebrew/Library/Taps/ /tcl[^/]+/http-.+\.tm /tcl[^/]+/[^/]+/http-.+\.tm usr/share/lua/[^/]+/posix/init\.lua openssl/openssl-[^/]+/test/recipes/ usr/share/doc/libssl-doc/demos/ boringssl/src/third_party/[^/]+test[^/]+/[^/]+_test\.json ``` ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances: - **Worker requirement**: JFrog Package Registries scanning requires dedicated `scanners-db-less` workers. Ensure `scanners-db-less.replicas` is set to a value greater than 0 in your Helm configuration. - **Cache**: The `commit-cache` Redis instance is used for JFrog Package Registries scanning. If the `commit-cache` Redis instance is not configured, the main Redis instance will be used instead. - **Scan frequency** can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **86400** (1 day) - Minimum value: **1800** (30 minutes) **Example Helm configuration:** ```yaml celeryWorkers: scanners-db-less: replicas: 2 ``` ## Privacy ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. Country-specific laws and regulations may require you to inform your users that your repositories are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its repositories for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only repositories relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the repository's purpose.* --- ## Secrets Managers integrations(Secrets-managers-integrations) GitGuardian integrates with Secret Managers through **[ggscout](/ggscout-docs/home)**, enabling you to synchronize secrets incidents with secrets stored in your Secret Managers. Connect your Secret Managers using the guidelines provided in the [Secrets Managers integrations](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-managers) page from your GitGuardian platform. :::success **No secrets get out of your environment!** Secrets values will never leave your environment in clear! Secrets values are hashed using the [HMSL hashing algorithm](https://blog.gitguardian.com/hasmysecretleaked-building-a-trustless-and-secure-protocol/) before they are sent to your GitGuardian workspace. Other non-sensitive metadata like the secrets names, paths in the vault, creation date, lease time, etc... are also collected to help you in the remediation process. ::: By leveraging insights and metadata from vaulted secrets in your GitGuardian dashboard, you can efficiently address various use cases. ### Ease incident prioritization Segregating vaulted and unvaulted secrets helps prioritize your remediation efforts: - Identify secrets incidents by Secret Manager instance. Based on your Secrets Management practices, this enables you to: - Pinpoint the teams responsible for the leak and remediation. - Identify critical secret incidents that should be prioritized. - Have full confidence that an incident is a true positive when it matches a secret stored in your Secret Managers. - Gain a clearer understanding of the remediation effort, depending on whether secrets are already vaulted. ![Secrets Managers Tag](/img/internal-monitoring/integrate-sources/secrets-managers-integrations/secrets-managers-filter.png) ### Accelerate incident remediation Vaulted secrets insights and metadata will streamline your incident remediation with developers: - Bootstrap remediation by inserting unvaulted secrets in your Secrets Managers. - Shorten remediation workflows by identifying vaulted secrets early. - Facilitate and accelerate remediation for vaulted secrets by quickly accessing the secret’s path within the Secret Manager. ![Push secret to vault](/img/internal-monitoring/integrate-sources/secrets-managers-integrations/push-secret-to-vault.png) ![Push to vault form](/img/internal-monitoring/integrate-sources/secrets-managers-integrations/push-to-vault-form.png) ### Identify secrets management bad practices ggscout matches secrets incidents with secrets based on their hashed values. This process provides valuable insights into potential Secrets Management hygiene issues: - Identify duplicated secrets across one or more Secret Manager instances. - Identify weak secrets or secrets templates. ![Duplicated Secrets](/img/internal-monitoring/integrate-sources/secrets-managers-integrations/duplicated-secrets.png) In both cases these secrets should be reviewed and potentially updated. ### Assist with Secrets Managers consolidation strategies As organizations often have multiple Secret Managers, rationalizing them can be complex. The planning, execution, and tracking phases typically involve the following high-level process. ![Vault Migration](/img/internal-monitoring/integrate-sources/secrets-managers-integrations/vault-migration-strategy.png) By identifying and maintaining secrets location in a multi-vault environment GitGuardian saves you countless hours in defining, executing and tracking your consolidation program: - Use filters to plan and prioritize your consolidation strategy. - Create Saved Views to track your program over time. - Identify and purge migrated secrets from their original location. --- ## Integrate Jira Cloud Monitor Jira Cloud projects for exposed secrets in issue descriptions, comments, and project documentation. :::info Attachment scanning and permissions **File attachment scanning** requires Jira attachment access in OAuth scopes, including **`read:attachment:jira`**. If you integrated with Jira Cloud prior the 27th of April 2026, we recommend you **uninstall and reinstall** your Jira Cloud site from [**Sources**](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) to benefit from this new feature. ::: ## Why Monitor Jira Cloud? Jira Cloud serves as the central repository for project management and issue tracking where teams document technical problems, share debugging information, and collaborate on solutions. During troubleshooting and issue resolution, developers frequently paste configuration details, error logs, and code snippets containing API keys, database credentials, and environment secrets directly into issue descriptions and comments. ## Capabilities | Feature | Support | Details | | ----------------------- | ------------------ | ------------------------------------------------------ | | **Historical Scanning** | ✅ (Manual Trigger) | Analyze existing projects issues and their histories | | **Recurrent Scanning** | ✅ (Supported) | Regular scheduled scanning for new and updated content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of projects | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | Not applicable for project management content | | **Source Visibility** | ❌ (Not Supported) | All projects show as `private` | | **File Attachments** | ✅ (Supported) | Uploaded file attachments are scanned | **What we scan:** - Issue descriptions and summaries - Comments and discussion threads - File attachments - Custom fields and project documentation :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Jira Cloud integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Jira Cloud admin** permissions for the sites you want to monitor GitGuardian integrates with Jira Cloud via a **Jira Cloud app** with **read-only access** to your projects. You can install GitGuardian on multiple Jira Cloud sites to monitor your projects. 1. Make sure you're logged in the Jira Cloud site you want to install 2. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 3. Click **Install** next to **Jira Cloud** in the **Ticketing** section ![Jira Cloud install](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-install.png) 4. Click **Install** on the [Jira Cloud integration](https://dashboard.gitguardian.com/settings/integrations/jira_cloud) page 5. Select the Jira Cloud site you want to add 6. Click **Accept** to grant the permissions requested by GitGuardian ![Jira Cloud permissions](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-permissions.png) That's it! Our GitGuardian app is now automatically invited on all your projects. It will now start monitoring all issues of your projects for secrets. ## Integration with GitGuardian Self-Hosted :::info We recommend using dedicated workers for this integration. For more detailed information on scaling and configuration, please visit our [scaling](../../../self-hosting/management/infrastructure-management/scaling#configure-scaling-settings) page. ::: If you are using a self-hosted GitGuardian instance, you must first configure a dedicated Jira Cloud App so that you own the entire data stream. This will ensure that your Jira Cloud App is created with all the appropriate rights. ### 1. Create a Jira Cloud app 1. Navigate to the [Jira Cloud integration](https://dashboard.gitguardian.com/settings/integrations/jira_cloud) page 2. Click **Configure Jira Cloud app** ![Jira Cloud app configure](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-configure.png) #### As a Jira Cloud administrator 1. Click **Create Jira Cloud app** (Alternatively, if you're not a GitGuardian Manager, you can access the [Atlassian developer console](https://developer.atlassian.com/console/myapps/create-3lo-app) directly) 2. Type the name of your new Jira Cloud app: `GitGuardian` 3. Agree to Atlassian's developer terms by checking: **I agree to be bound by Atlassian's developer terms.** 4. Click **Create** ![Jira Cloud app create](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-create.png) 5. Go to the **Permissions** page 6. Click **Add** next to the **Jira API** line ![Permissions - Jira API add](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-permissions-jira-api-add.png) 7. Click **Configure** next to the **Jira API** line 8. In the **Classic scopes** tab, click **Edit Scopes** in the **Jira platform REST API** section ![Jira Cloud - Classic scopes edit](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-classic-scopes-edit.png) 9. Select the following **classic scopes**: - `read:jira-work` - `manage:jira-configuration` - `read:jira-user` - `write:jira-work` - `manage:jira-webhook` (only ≤ 2026.5.0) 10. Click **Save** ![Jira Cloud - Classic scopes](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-classic-scopes.png) 11. In the **Granular scopes** tab, click **Edit Scopes** ![Jira Cloud - Granular scopes edit](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-granular-scopes-edit.png) 12. Select the following **granular scopes**: - `read:application-role:jira` - `read:avatar:jira` - `read:project.avatar:jira` - `read:group:jira` - `read:issue:jira` - `read:issue-meta:jira` - `read:attachment:jira` - `read:comment:jira` - `read:comment.property:jira` - `read:field:jira` - `read:field.default-value:jira` - `read:field.option:jira` - `read:field-configuration:jira` - `read:issue.property:jira` - `read:issue-details:jira` - `read:issue-type:jira` - `read:issue-field-values:jira` - `read:issue-security-level:jira` - `read:issue-type-hierarchy:jira` - `read:issue.changelog:jira` - `read:issue.vote:jira` - `read:issue-event:jira` - `read:user:jira` - `read:project:jira` - `read:project-category:jira` - `read:project.component:jira` - `read:project.property:jira` - `read:project-role:jira` - `read:project-version:jira` - `read:project.feature:jira` - `read:webhook:jira` (only ≤ 2026.5.0) - `write:webhook:jira` (only ≤ 2026.5.0) - `delete:webhook:jira` (only ≤ 2026.5.0) - `read:status:jira` - `read:jql:jira` - `read:project-type:jira` - `read:project.email:jira` - `read:epic:jira-software` 13. Click **Save** ![Jira Cloud - Granular scopes](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-granular-scopes.png) 14. Go to the **Authorization** page 15. Click **Add** next to the **OAuth 2.0 (3LO)** line ![Authorization - OAuth 2.0 add](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-authorization-oauth-2.0-add.png) 16. Enter the callback URL based on your GitGuardian self-hosted instance URL: `https:///api/v1/jira-cloud/app/install_callback/` 17. Click **Save changes** ![Jira Cloud - Callback URL](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-callback-url.png) 18. Go to the **Overview** page 19. Get your App details (`App ID`) (alternatively, you can find and copy it more easily from the URL) ![Jira Cloud - Overview credentials](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-overview-credentials.png) 20. Go to the **Settings** page 21. Get your Authentication details (`Client ID`, `Secret`) ![Jira Cloud - Settings credentials](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-settings-credentials.png) That's it! Your Jira Cloud app has been created and you can now [declare your Jira Cloud app in the GitGuardian Platform](jira-cloud#2-declare-your-jira-cloud-app-in-the-gitguardian-platform). Alternatively, if you are not a GitGuardian Manager, you can now return the Jira Cloud app credentials to your requester in the secure way of your choice (`App ID`, `Client ID`, `Secret`). :::info All these permissions are defined for the creation of your Jira Cloud app. This Jira Cloud app can be used for any type of Jira Cloud integration (secret detection, issue tracking). When installing a Jira Cloud site for a specific integration, only a subset of your Jira Cloud app's permissions will be requested. GitGuardian requires only the minimum number of permissions per integration. ::: #### As a non Jira Cloud administrator If you don't have the right to create a Jira Cloud app, please ask your Jira Cloud administrator to do it for you. You can easily forward a request with this procedure: 1. Click the **Send a request to a Jira administrator** link to easily forward your request 2. They should in turn provide you with the Jira Cloud app credentials to proceed with the [rest of the configuration](jira-cloud#2-declare-your-jira-cloud-app-in-the-gitguardian-platform). ### 2. Declare your Jira Cloud app in the GitGuardian Platform 1. Paste your Jira Cloud app credentials (`App ID`, `Client ID`, `Secret`) 2. Click **Save and close** ![Jira Cloud app credentials](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-credentials.png) That's it! Your Jira Cloud configuration is ready and you can now [setup your Jira Cloud integration](#setup-your-jira-cloud-integration). ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Incremental scanning **Stay protected with regular monitoring:** Once integrated, GitGuardian provides ongoing protection through scheduled automated scans of your content. New and modified content is systematically monitored at regular intervals, ensuring comprehensive coverage and timely detection of any secret exposures. Your source remains under GitGuardian's protection, giving you confidence that secrets won't go unnoticed. ## Scanning your JIRA Cloud history GitGuardian enables you and encourages you to **scan the entire history of your perimeter**. By executing historical scanning, all secrets present in your JIRA sources prior to installing GitGuardian will be detected. Unlike Version Control Systems, historical scanning has to be manually executed from your [perimeter page](https://dashboard.gitguardian.com/workspace/perimeter), by: - Selecting your JIRA sources - Click scan from the top action bar :::warning **Previous installations!** If you previously integrated your sources for real-time scanning, you will need to uninstall and reinstall the GitGuardian app from the Settings > Sources. This step is required as the GitGuardian application requires additional access rights: - read:field.default-value:jira - read:field.option:jira Fresh installations do not require this step. ::: ## Edit your Jira Cloud app configuration In case you need to edit your Jira Cloud app configuration, due to an error when declaring your Jira Cloud app credentials or due to a secret rotation, you can do so as follows: 1. Click **Edit Jira Cloud app** 2. Update your Jira Cloud app credentials 3. Click **Save and close** ![Jira Cloud app configuration edit](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-app-configuration-edit.png) ## Delete your Jira Cloud app configuration In case you need to delete your Jira Cloud app configuration, you can do so as follows: 1. Click **Edit Jira Cloud app** 2. Click **Delete configuration** 3. Confirm by clicking **Delete configuration** in the confirmation modal :::info Deleting your Jira Cloud app configuration will uninstall all your Jira Cloud integrations. However, all your existing incidents detected on Jira Cloud will remain available on your dashboard. Note that deleting the Jira Cloud app configuration will only delete the configuration, not the Jira Cloud app. If you want to delete your Jira Cloud app, you must do so from your Jira Cloud site. ::: ## Uninstall your Jira Cloud site To uninstall a Jira Cloud site: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Jira Cloud** in the **Ticketing** section 3. Click the bin icon next to the Jira Cloud site to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Jira Cloud uninstall](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-uninstall.gif) That's it! Your Jira Cloud site is now uninstalled. ## Remove the GitGuardian app from your Jira Cloud site Uninstalling a Jira Cloud site from the GitGuardian platform does not remove the GitGuardian app from your Jira Cloud site. This is not a mandatory step, but you can remove it manually after uninstalling your Jira Cloud site from the GitGuardian platform. :::caution Warning The GitGuardian app is shared with the [Jira Cloud issue tracking integration](/platform/configure-alerting/issue-tracking-integrations/jira-cloud). Removing the app from your Jira Cloud site will break any existing integration in the GitGuardian platform. Make sure your Jira Cloud site is no longer installed on the GitGuardian platform before removing the GitGuardian app manually. ::: To remove the GitGuardian app from your Jira Cloud site: 1. Go to your Jira Cloud site 2. Select **Settings > Atlassian account settings** ![Jira Cloud Atlassian account settings](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-atlassian-account-settings.png) 3. Go to the **Connected apps** tab 4. Click **Remove access** next to the GitGuardian app ![Jira Cloud - Remove app](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud/jira-cloud-remove-app.png) 5. Click **Remove** in the confirmation modal That's it! The GitGuardian app is now removed from your Jira Cloud site. ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your Jira Cloud users that your projects are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the Jira Cloud projects for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only projects relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the project's purpose.* --- ## Integrate Jira Data Center Monitor Jira Data Center projects for exposed secrets in issue descriptions, comments, and project documentation. ## Why Monitor Jira Data Center? Jira Data Center houses your organization's enterprise project management and issue tracking in a self-hosted environment. Enterprise development teams regularly document technical issues, share debugging information, and collaborate on complex problems, often embedding production credentials, internal API keys, and infrastructure secrets directly in issue descriptions, comments, and custom field configurations. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Manual Trigger) | Analyze existing issues and their histories | | **Real-time Detection** | ✅ (Supported) | Instant detection via Jira webhooks | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of projects | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | Not applicable for project management content | | **Source Visibility** | ❌ (Not Supported) | All projects show as `private` | | **File Attachments** | ✅ (Supported) | Uploaded file attachments are scanned | **What we scan:** - Issue descriptions and summaries - Comments and discussion threads - File attachments - Custom fields and project documentation :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your Jira Data Center integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Jira Data Center administrator** permissions to create Personal Access Tokens - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. :::info Rate limits If your instance enforces API rate limits, the default values may be too low and can slow down GitGuardian's scanning. To scan in a reasonable time, raise the limits or exempt the account, token, or service account that GitGuardian uses from rate limiting. See [Rate limits on self-hosted sources](/internal-monitoring/integrate-sources/monitored-perimeter#rate-limits-on-self-hosted-sources). ::: GitGuardian integrates with Jira Data Center via an **administrator Personal Access Token** with **read-only access** to your projects. You can install GitGuardian on multiple Jira Data Center sites to monitor your projects. 1. Make sure you're logged as an administrator in the Jira Data Center site you want to install 2. Go to the **Profile** page ![Jira Data Center profile](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-profile.png) 3. Go to the **Personal Access Tokens** section and click **Create token** to create a new PAT ![Jira Data Center PAT](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-pat.png) 4. Provide a **Token Name**, an optional **Expiry date** and click **Create** ![Jira Data Center PAT form](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-pat-form.png) 5. Copy your new PAT and click **Close** ![Jira Data Center PAT copy](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-pat-copy.png) 6. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 7. Click **Install** next to **Jira Data Center** in the **Ticketing** section ![Jira Data Center install](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-install.png) 8. Click **Install** on the [Jira Data Center integration](https://dashboard.gitguardian.com/settings/integrations/jira_data_center) page 9. Paste your **Jira Data Center site URL**, your **Administrator Personal Access Token** and click **Add** ![Jira Data Center integration](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-integration.png) That's it! Your Jira Data Center site is now installed, and GitGuardian is monitoring all issues and comments of your projects for secrets. :::info GitGuardian no longer renews PATs. See the [customer notice](/support/customer-notices/jira-confluence-data-center-token-renewal). ::: ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Real-time scanning **Catch new exposures instantly:** Once integrated, GitGuardian continuously monitors your content through event-based detection. Any new or modified content containing secrets are detected immediately, allowing you to respond quickly to new exposures. ## Scanning your Jira Data Center history GitGuardian enables you and encourages you to **scan the entire history of your perimeter**. By executing historical scanning, all secrets present in your Jira sources prior to installing GitGuardian will be detected. Unlike Version Control Systems, historical scanning has to be manually executed from your [perimeter page](https://dashboard.gitguardian.com/workspace/perimeter), by: - Selecting your Jira Data Center sources - Clicking **scan** from the top action bar ## Update your Personal Access Token You can replace the PAT used by an installed site at any time, for example before it expires or after rotating it. Updating the token in place keeps your configuration and monitored perimeter intact, so there is no need to reinstall. 1. Create a new **administrator** PAT in Jira Data Center, following steps 1 to 5 above 2. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 3. Click **Edit** next to **Jira Data Center** in the **Ticketing** section 4. Update the token of the Jira Data Center site with your new PAT GitGuardian validates the new token and runs a health check, so an unhealthy integration recovers immediately. ## Uninstall your Jira Data Center site To uninstall a Jira Data Center site: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **Jira Data Center** in the **Ticketing** section 3. Click the bin icon next to the Jira Data Center site to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![Jira Data Center uninstall](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-uninstall.png) That's it! Your Jira Data Center site is now uninstalled. ## Privacy and compliance ### Data handling GitGuardian processes your data solely to detect exposed secrets: - **Read-only access:** We never require write access unless scoped to creating webhooks to receive and process real-time events - **Minimal data retention:** We store only data and metadata necessary for incident management - **Encryption:** All data in transit and at rest is encrypted - **Compliance:** We follow the same data protection standards as our other integrations ### Regional considerations GitGuardian hosts its services in two AWS regions: eu-central-1 (Frankfurt) and us-west-2 (Oregon). Ensure your GitGuardian deployment region aligns with your data residency requirements. Contact support if you need guidance on compliance with local regulations. ### User notification Country-specific laws and regulations may require you to inform your Jira Data Center users that your projects are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans the Jira Data Center projects for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > > *Please note that only projects relating to the company's activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the project's purpose.* --- ## Integrate ServiceNow Monitor ServiceNow for exposed secrets in tickets, knowledge articles, and service management workflows. ## Why Monitor ServiceNow? ServiceNow serves as the central IT service management platform where IT teams document incidents, manage changes, and maintain knowledge bases. During incident response and troubleshooting, IT staff frequently embed system credentials, configuration details, and service account information in tickets, change requests, and knowledge articles, creating persistent security vulnerabilities within critical IT documentation. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Analyze existing tables and records histories | | **Incremental Scanning** | ✅ (Supported) | Regular scheduled scanning for new content | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of tables | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ❌ (Not Supported) | All occurrences considered present | | **Source Visibility** | ❌ (Not Supported) | All tables show as `private` | | **File Attachments** | ❌ (Not Supported) | File attachments are not scanned | **What we scan:** - Incident and service request descriptions - Change request documentation - Knowledge base articles and procedures - Workflow configurations and scripts :::info **Plan requirements:** Available for GitGuardian **Enterprise** plan. Try it for free with a 30-day trial - any detected incidents remain accessible after the trial ends. **Detector coverage:** To minimize false positives, [Generic High Entropy Secret](/secrets-detection/secrets-detection-engine/detectors/generics/generic_high_entropy_secret) and [Generic Password](/secrets-detection/secrets-detection-engine/detectors/generics/generic_password) are disabled. All other detectors are enabled. ::: ## Setup your ServiceNow integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **ServiceNow admin** permissions to create user accounts with API access - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. GitGuardian integrates with ServiceNow via a dedicated **User** with **read-only access** to your tables. You can install GitGuardian on multiple ServiceNow instances to monitor your tables. ### 1. Create a new user 1. Login to your ServiceNow instance 2. Go to **Organization > Users** and click **New** to create the new user required for authentication ![ServiceNow Create New User](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-create-new-user.png) 3. Set a **User ID** (e.g.: `GitGuardian`) and click **Submit** to create it ![ServiceNow GitGuardian User](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-gitguardian-user.png) ### 2. Give the required roles to the user 1. Click on the **User ID** (e.g.: `GitGuardian`) to edit it and add the required roles 2. Go to the **Roles** tab and click **Edit...** ![ServiceNow Edit User](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-edit-user.png) 3. Add the following roles and click **Save**: - `admin` - `snc_read_only` The `admin` role will give the user access to all tables, while the `snc_read_only` role will restrict access to read-only. ![ServiceNow Edit User](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-user-roles.png) 4. Click **Update** to validate the roles added to the user ![ServiceNow Validate User Edition](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-validate-user-edition.png) ### 3. Set a password to the user 1. Click on the **User ID** (e.g.: `GitGuardian`) to edit it and set a password 2. Click **Set Password** 3. Click **Generate** and copy the password 4. Save by clicking **Save Password** and **Close** 5. Uncheck **Password needs reset** option and click **Update** ![ServiceNow Set Password User](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-set-password-user.png) ### 4. Finalize the configuration in GitGuardian 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Install** next to **ServiceNow** in the **Ticketing** section ![ServiceNow install](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-install.png) 3. Click **Install** on the [ServiceNow integration](https://dashboard.gitguardian.com/settings/integrations/servicenow_data_source) page 4. Paste your ServiceNow instance URL in the **API endpoint URL** field (e.g.: `https://acme.service-now.com/`) 5. Paste the newly created **Username** (e.g.: `GitGuardian`), its associated **Password**, and click **Add** ![ServiceNow integration](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-integration.png) That's it! Your ServiceNow instance is now installed, and GitGuardian is monitoring all records of your tables for secrets. ## Uninstall your ServiceNow instance To uninstall a ServiceNow instance: 1. In the GitGuardian platform, navigate to the [Sources integration](https://dashboard.gitguardian.com/settings/integrations/sources#secrets-scanning) page 2. Click **Edit** next to **ServiceNow** in the **Ticketing** section 3. Click the bin icon next to the ServiceNow instance to uninstall 4. Confirm by clicking **Yes, uninstall** in the confirmation modal ![ServiceNow uninstall](/img/internal-monitoring/integrate-sources/ticketing-integrations/servicenow/servicenow-uninstall.png) That's it! Your ServiceNow instance is now uninstalled. ## Additional Self-Hosted considerations For GitGuardian Self-Hosted instances, scan frequency can be configured in the [Admin Area](../../../self-hosting/management/application-management/admin-area): - Time interval unit: **seconds** - Default value: **3600** (1 hour) - Minimum value: **1800** (30 minutes) ## Privacy Country-specific laws and regulations may require you to inform your users that your tables are being scanned for secrets. Here is a suggestion for a message you may want to use: > As part of our internal information security process, the company scans its tables for potential secrets leaks using [GitGuardian](https://www.gitguardian.com/monitor-internal-repositories-for-secrets). All data collected will be processed for the purpose of detecting potential leaks. To find out more about how we manage your personal data and to exercise your rights, please refer to our employee/partner privacy notice. > *Please note that only tables relating to the company’s activity and business may be monitored and that users shall refrain from sharing personal or sensitive data not relevant to the table’s purpose.* --- ## Integrate Azure DevOps Monitor Azure DevOps repositories for exposed secrets in source files, configuration files, and commit histories. ## Why Monitor Azure DevOps? Azure DevOps repositories are deeply integrated with Azure services, Microsoft 365, and enterprise Active Directory systems. When developers commit credentials or service connection secrets, they risk exposing not just individual applications but entire cloud infrastructures, potentially granting attackers access to production Azure resources and sensitive corporate data. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Complete repository history analysis | | **Real-time Detection** | ✅ (Supported) | Instant detection via webhooks | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your Orgs and repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ✅ (Supported) | Verify if secrets are still accessible | | **File Attachments** | ❌ (Not Supported) | Not applicable for code repositories | **What we scan:** - Source code files, configuration files, and raw text files - All repository branches and commit history ## Setup **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Azure DevOps admin** or **project admin** permissions for the organizations you want to monitor - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. GitGuardian can integrate with Azure Repos in two different ways: **at the instance level or at the organization/collection level**. :::note In Azure Repos the wordings `Organization` and `Collection` refer to the same concept depending on the version of your Azure DevOps. In GitGuardian's dashboard, we use the wording `Organization` as it is the most common, but don't be embarrassed if you have `Collection` in your Azure Repos instance. ::: The Azure DevOps Repos integration requires **a personal access token** for GitGuardian to be able to access your Azure Repos organizations/collections for analysis. :::caution To enable functional real-time scanning of your projects and repository, the personal access token owner must either be an `Organization admin` or a `Project administrator` for all projects within your organization. This can be accomplished by being added to the `Project Collection Administrators` group of the organization. ::: ### Create a Personal Access Token :::tip We highly recommend that you use a bot user in order to generate personal access tokens. ::: 1. Go to your “User setting” section on Azure DevOps. 2. For Azure Repos Service, Dive into “Personal access tokens” section and create a new token. For Azure Repos Server, you first need to dive into "Security", and then select the Personal access tokens page on the left side bar. 3. Set a name (ex: “gitguardian”). 4. Select if you want to provide access for the current organization or for the entire instance. 5. IMPORTANT: You must check the `Read` scope for **Code** and **Graph** (click on the 'Show all scopes' link to display this scope). The `Graph:Read` scope is used for billing purposes as it allows us to look at users, groups and their memberships. 6. We recommend you set the expiration date to 1 year, this is the maximum allowed. :::caution Azure DevOps has a limit of 1 year maximum for the validity of a token. It means you'll have to renew the token if you want to keep the integration up and running. ::: The personal token enables GitGuardian to access your repos through your Azure DevOps permissions. ![Azure Repos personal access token Code](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_PAT.png) Click on the 'Show all scopes' link to display the scope for Graph. ![Azure Repos personal access token show all scopes](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_PAT_show_all.png) ![Azure Repos personal access token Graph](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_PAT_graph.png) :::caution This integration doesn't monitor disabled repositories. If you include disabled repositories in your perimeter, they won't be checked and they will appear with the status `Unknown`. ::: ![Azure Repos disabled repo](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_Disable_repo.png) Please refer to the [Azure DevOps documentation](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate) for more information about personal access tokens. ### Instance-level integration This integration mode will automatically monitor **all projects and repositories on the instance**. When a new project or a new repository is created on any organization, it will be automatically included in the perimeter by GitGuardian. #### Requirements - Azure DevOps Service or self-managed Azure DevOps Server: minimum assured compatible version 2019 - A personal access token with **Read scope for "Code" and "Graph"**. #### Guidelines 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Configure** for Azure Repos. 3. Click on **Start** for the instance-level option: "Monitor the entire Azure Repos instance" ![Azure Repos installation selection](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_Instancelvl.png) 4. Submit your Azure Repos instance url, and the personal access token created. ![Azure Repos token form](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_tokenform.png) :::caution Azure instance URL must be prefixed with `https://`, instances without a secure connection won't be monitored. The URL used should be of type scheme+basename (eg: `https://azuredevops.gitguardian.example`). ::: 5. GitGuardian will start scanning your Azure Repos instance. You can view the projects and repositories monitored in your [Azure Repos settings page](https://dashboard.gitguardian.com/settings/integrations/azure_devops) by clicking on **See my Azure Repos perimeter**. #### Troubleshooting - You can **submit new personal access tokens if you want to monitor more Azure Repos instances**. - GitGuardian automatically detects if the Personal access token becomes invalid (by expiring or being revoked) and will send an email to notify you. All of your existing data will remain accessible. - In case you have a lot of repositories, they may take some time to show up on your perimeter. ### Organization-level integration This integration will **only monitor organizations you select**. When a new project is added to a monitored organization, it will be automatically added to the perimeter. However, new organizations added to the Azure Repos instance will not be automatically included to the GitGuardian perimeter. Note that you can't have an instance-level integration and an organization-level integration at the same time. #### Requirements - Azure DevOps Service or self-managed Azure DevOps Server/Data Center: minimum assured compatible version 2019 - A personal access token with **Read scope for "Code".** #### Guidelines 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Configure** for Azure Repos. 3. Click on **Start** for the instance level option: "Monitor certain Azure Repos organizations only" ![Azure Repos installation selection](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_InstallOrglvl.png) 4. Submit your Azure DevOps instance url and the personal access token created. If you're willing to install only one organization, submit also the name of this organization. ![Azure Repos token form](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_tokenform2.png) :::caution Azure instance URL must be prefixed with `https://`, instances without a secure connection won't be monitored. The URL used should be of type scheme+basename (eg: `https://azuredevops.gitguardian.example`). ::: 5. GitGuardian will display the organization available for monitoring. Clicking `Install`, GitGuardian will access the organization and scan the content of the repositories. ![ADO install form](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_InstallOrg.png) 6. You can view the projects and repositories monitored in your [Azure Repos settings page](https://dashboard.gitguardian.com/settings/integrations/azurerepos) by clicking on **See my Azure Repos perimeter**: #### Troubleshooting - You can **submit new personal access tokens if you want to monitor more Azure Repos instances or organizations**. - GitGuardian automatically detects if the Personal access token becomes invalid (by expiring or being revoked) and will send an email to notify you. All of your existing data will remain accessible. - In case you have a lot of repositories, they may take a short time to show up on your perimeter - If the Azure DevOps user associated with the personal access token used for integration lacks sufficient permissions for real-time project monitoring, a visual icon will be displayed next to the project. This icon indicates that the project is still part of your scope and can be scanned manually, but it cannot be monitored in real time. ![No real-time](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_no-real-time.png) ### Rotate/Replace a Personal Access Token In Azure Repos, the maximum lifetime of a Personal Access Token is 365 days, and there is no option to extend this duration. Additionally, updating the scopes of a Personal Access Token requires creating a new one; it cannot be modified directly. Consequently, it is necessary to replace your Personal Access Token at least once a year to continue scanning your repositories with GitGuardian. To minimize disruption, we recommend: 1. Generate a new Personal Access Token in Azure DevOps before the expiration of the current one. 2. Add this newly created Personal Access Token to the list of tokens in GitGuardian. 3. Only after completing steps 1 and 2, remove the old Personal Access Token. This ensures a seamless transition, allowing the new Personal Access Token to take over in case the current token expires or is deleted, thereby maintaining the functionality of your integration. :::caution For Organization-level installations, the new Personal Access Token should have the same permissions. Failure to do so may result in incomplete access to certain Organizations. GitGuardian will continue monitoring accessible ones and uninstall Organization(s) that are no longer reachable. ::: ## Automatic historical scan By default, GitGuardian performs a historical scan for each newly created Azure Repos repository added to your perimeter. You can deactivate this behavior in your [Azure Repos settings](https://dashboard.gitguardian.com/settings/integrations/azure_devops/instance) if you are a Manager of the workspace. ![Autoscan settings](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_Autoscan.png) ## Automatic repository monitoring By default, GitGuardian automatically monitors repositories added to your perimeter. You can deactivate this behavior in your [Azure Repos settings](https://dashboard.gitguardian.com/settings/integrations/azure_devops/instance) if you are a Manager of the workspace. ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Real-time scanning **Catch new exposures instantly:** Once integrated, GitGuardian continuously monitors your content through event-based detection. Any new or modified content containing secrets are detected immediately, allowing you to respond quickly to new exposures. ## Customize your monitored perimeter Once you have set up your Azure Repos integration, you have the possibility to configure which projects and repositories to monitor in the [Azure Repos settings section](https://dashboard.gitguardian.com/settings/integrations/azure_devops) of your workspace. ![ADO perimeter](/img/internal-monitoring/integrate-sources/vcs-integrations/azure-repos/ADO_Perimeter.png) If you deselect a repository from your monitored perimeter, GitGuardian will not receive any commit for your future scans. --- ## Integrate Bitbucket Cloud Monitor Bitbucket Cloud repositories for exposed secrets in source files, configuration files, and commit histories. # Why Monitor Bitbucket Cloud? Bitbucket Cloud workspaces contain countless repositories where developers inadvertently commit sensitive credentials. These hardcoded secrets become permanently embedded in git history, creating persistent security vulnerabilities that can be discovered and exploited by unauthorized users, potentially leading to complete system compromise. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Complete repository history analysis | | **Real-time Detection** | ✅ (Supported) | Instant detection via webhooks | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your Orgs and repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ✅ (Supported) | Verify if secrets are still accessible | | **File Attachments** | ❌ (Not Supported) | Not applicable for code repositories | **What we scan:** - Source code files, configuration files, and raw text files - All repository branches and commit history ## Setup **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Bitbucket Workspace Owner** permissions for the workspaces you want to monitor GitGuardian integrates with your Bitbucket Cloud workspace using an API token. For more details on API tokens, refer to the [Bitbucket Cloud documentation](https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/). ### Create an API token The API token must be generated by the Workspace Owner of the workspace(s) you intend to monitor. This grants the necessary permissions to automatically create the required webhooks. 1. Log in to Bitbucket Cloud as the Workspace Owner; 2. Navigate to the [Profile and visibility](https://id.atlassian.com/manage-profile/profile-and-visibility) within the Atlassian account settings; 3. Get the email address in the Bitbucket profile settings ![Bitbucket Cloud Email](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket-cloud/bitbucket-cloud-email.png) 4. On the Atlassian account page, navigate to the [API tokens section](https://id.atlassian.com/manage-profile/security/api-tokens) within the security settings; 5. Click on "Create API token with scopes" to start the creation of your API token. Use a simple name such as "GitGuardian". We recommend you set the expiration date to 1 year, this is the maximum allowed. 6. On the "Select app" page, select "Bitbucket". 7. On the "Select scopes" assign the following scopes: - read:project:bitbucket - delete:webhook:bitbucket - read:webhook:bitbucket - write:webhook:bitbucket - read:repository:bitbucket - read:user:bitbucket - read:workspace:bitbucket - read:permission:bitbucket 8. On the final "Create token page", recheck that the scopes are correct: ![API token scopes](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket-cloud/api-token-scopes.png) 6. Get the API token ![API token](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket-cloud/api-token.png) ### Integrate your Bitbucket workspaces with GitGuardian 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations). 2. Click on **Install** for Bitbucket Cloud. 3. Enter the email from your Atlassian account and the API token generated earlier. Add a name for the integration, then click Configure. ![Configure Bitbucket Cloud integration](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket-cloud/configure-bb-cloud-integration.png) 4. On the configuration page, review the list of workspaces your Bitbucket Cloud user has access to. Click Install for each workspace you want to monitor. ![Install Bitbucket Cloud workspaces](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket-cloud/install-bb-cloud-workspaces.png) 5. That's it! You can view the monitored projects and repositories in your [Bitbucket Cloud settings page](https://dashboard.gitguardian.com/settings/integrations/bitbucket_cloud). ![See monitored repositories](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket-cloud/bb-cloud-perimeter.png) ## Automatic historical scan By default, GitGuardian runs a historical scan on every Bitbucket Cloud repository added to the monitored perimeter. To disable this feature, navigate to your [Bitbucket Cloud settings](https://dashboard.gitguardian.com/settings/integrations/bitbucket_cloud). Only workspace Managers can modify this setting. ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Real-time scanning **Catch new exposures instantly:** Once integrated, GitGuardian continuously monitors your content through event-based detection. Any new or modified content containing secrets are detected immediately, allowing you to respond quickly to new exposures. ## Customize your monitored perimeter After installing your Bitbucket Cloud instance(s), you can configure which projects to monitor in the [Bitbucket Cloud settings](https://dashboard.gitguardian.com/settings/integrations/bitbucket_cloud). If you deselect an entity (a repository, a project or a whole workspace) from your monitored perimeter: - GitGuardian will stop fetching commits from that entity, new incidents will not be uncovered and existing incidents won't be updated for this entity. - The webhook will remain active, allowing you to resume monitoring anytime. --- ## Integrate Bitbucket Data Center/Server Monitor Bitbucket Data Center/Server repositories for exposed secrets in source files, configuration files, and commit histories. ## Why Monitor Bitbucket Data Center/Server? Bitbucket Data Center/Server installations house your organization's most critical source code and intellectual property. When developers commit hardcoded secrets into these enterprise repositories, they create vulnerabilities that can expose sensitive production systems, databases, and internal infrastructure to malicious actors or accidental breaches. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Complete repository history analysis | | **Real-time Detection** | ✅ (Supported) | Instant detection via webhooks | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your Orgs and repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ✅ (Supported) | Verify if secrets are still accessible | | **File Attachments** | ❌ (Not Supported) | Not applicable for code repositories | **What we scan:** - Source code files, configuration files, and raw text files - All repository branches and commit history :::info Throughout this page, "Bitbucket Data Center" refers to both Bitbucket Data Center and Bitbucket Server. In the app, you'll see "Data Center" as the label, which also includes Server functionality. We use "Data Center" in our wording because Bitbucket Server is deprecated and Data Center is the latest supported version by Atlassian. ::: ## Integration Overview **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **Bitbucket admin permissions** to create personal access tokens and configure webhooks - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. :::info Rate limits If your instance enforces API rate limits, the default values may be too low and can slow down GitGuardian's scanning. To scan in a reasonable time, raise the limits or exempt the account, token, or service account that GitGuardian uses from rate limiting. See [Rate limits on self-hosted sources](/internal-monitoring/integrate-sources/monitored-perimeter#rate-limits-on-self-hosted-sources). ::: GitGuardian can integrate with your Bitbucket Data Center through two mechanisms: **project-level and instance-level integrations**. :::info Both mechanisms require a personal access token with the following scopes: **Read permissions for projects and Admin permissions for repositories**. This allows GitGuardian to create webhooks for receiving information on repository updates. ::: GitGuardian requires a 3-hour window before synchronizing Bitbucket instance information. This could translate, at worst, to a 3-hour delay before a newly created project is monitored. In order to keep your integration safe, SSL verification is required for integrating Bitbucket instances. All messages between GitGuardian and your Bitbucket instance will be authenticated by HMAC SHA-256. ## Setup ### Create a Personal Access Token :::tip We strongly recommend that you use **a bot user in order to generate personal access tokens**. This is because a personal access token is closely linked to the Bitbucket account that created it. If the Bitbucket account is deleted, the token it generated is also deleted. ::: 1. Navigate to your Bitbucket user settings (typically on your upper right hand corner, under **Manage Account**) 2. Go to **Personal access tokens** section 3. Create a personal access token with a simple name such as "GitGuardian" and **Read** permissions on projects and **Admin** permissions on repositories. Set the **"Automatic Expiry"** option to **"No"**. The personal token enables GitGuardian to create webhooks through your Bitbucket's API. ![Bitbucket personal access token creation form](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket/bb-token.png) Please refer to the [Bitbucket server documentation](https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html) for more information about personal access tokens. > We advise that you never revoke the token before removing your Bitbucket integration on [GitGuardian dashboard](https://dashboard.gitguardian.com/settings/integrations/bitbucket). ### Instance-level integration This integration mode will automatically monitor **all projects and repositories on the instance**. #### Requirements - Self-managed Bitbucket Server/Data Center: minimum assured compatible version 7.6+ - An Administrator (`SYSADMIN` global permission) token with **Read permissions for projects and Admin permissions for repositories** #### Guidelines 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Configure** for Bitbucket. 3. Click on **Start** for the instance level option: "Monitor the entire Bitbucket instance" 4. Submit your Bitbucket instance url and the personal access token created. ![Bitbucket token form](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket/bb-token-form.png) :::caution Bitbucket instance URL must be prefixed with `https://`, instances without a secure connection won't be monitored. The URL used should be of type scheme+basename (eg: `https://bitbucket.gitguardian.example`). ::: 5. GitGuardian will start monitoring your Bitbucket instance. You can view the projects and repositories monitored in your [Bitbucket settings page](https://dashboard.gitguardian.com/settings/integrations/bitbucket) by clicking on **See my Bitbucket perimeter**. #### Events subscription details Our integration will subscribe to the following events: - `Repository update events` - `Push events` #### Troubleshooting - You can **submit new personal access tokens if you want to monitor more Bitbucket instances**. - GitGuardian automatically detects if the Personal access token becomes invalid (by expiring or being revoked) and will send an email to notify you. All of your existing data will remain accessible. - In case you have a lot of repositories, they may take a short time to show up on your perimeter page while GitGuardian sets up the necessary webhooks on each of them. ### Project-level integration This integration will **only monitor projects selected by the user**. When a new repository is added to a monitored project, it will be automatically monitored. Note that you can't have an instance-level integration and a project-level integration at the same time. #### Requirements - Self-managed Bitbucket Server/Data Center: minimum assured compatible version 7.6+ - A token with **Read permissions for projects and Admin permissions for repositories**. A **project-level** integration can be created by any user with Administrator permissions on a Bitbucket project. It does not require the user to be an Administrator of the instance. #### Guidelines 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Configure** for Bitbucket. 3. Click on **Start** for the project level option: "Monitor only certain Bitbucket projects" 4. Submit your Bitbucket instance url and the personal access token created. ![Bitbucket token form](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket/bb-token-form.png) :::caution Bitbucket instance URL\_ must be prefixed with `https://`, instances without a secure connection won't be monitored. ::: 5. GitGuardian will display the projects available for monitoring. Clicking `Install`, GitGuardian will install hooks and allow all repositories of that project to be monitored. ![Bitbucket install form](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket/bb-install-form.png) 6. You can view the projects and repositories monitored in your [Bitbucket settings page](https://dashboard.gitguardian.com/settings/integrations/bitbucket) by clicking on **See my Bitbucket perimeter**. #### Events subscription details Our integration will subscribe to the following events: - `Repository update events` - `Push events` #### Troubleshooting - You can **submit new personal access tokens if you want to monitor more Bitbucket instances or projects**. - GitGuardian automatically detects if the Personal access token becomes invalid (by expiring or being revoked) and will send an email to notify you. All of your existing data will remain accessible. - In case you have a lot of repositories, they may take a short time to show up on your perimeter page while GitGuardian sets up the necessary webhooks on each of them. ## Automatic historical scan By default, GitGuardian performs a historical scan for each newly created Bitbucket repository added to your perimeter. You can deactivate this behavior in your [Bitbucket settings](https://dashboard.gitguardian.com/settings/integrations/bitbucket) if you are a Manager of the workspace. ![Autoscan settings](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket/bb-auto-scan-setting.png) ## Automatic repository monitoring By default, GitGuardian automatically monitors repositories added to your perimeter. You can deactivate this behavior in your [Bitbucket settings](https://dashboard.gitguardian.com/settings/integrations/bitbucket) if you are a Manager of the workspace. ![Autoscan settings](/img/internal-monitoring/integrate-sources/vcs-integrations/bitbucket/bb-auto-monitor-new-projects-setting.png) ## Customize your monitored perimeter Once you have set up your Bitbucket integration, you have the possibility to configure which repositories to monitor in the [Bitbucket settings section](https://dashboard.gitguardian.com/settings/integrations/bitbucket) of your workspace. If you deselect a repository from your monitored perimeter: - GitGuardian will no longer receive any content of its commits - and therefore you won't receive any alerts related to this repository. ## Possible adjustments of Bitbucket Server settings The [Bitbucket Server Config](https://confluence.atlassian.com/bitbucketserver076/bitbucket-server-config-properties-1026535505.html) properties allow you to modify some default behaviors of Bitbucket Server so that it can handle monitoring of a greater number of repositories. Reduce the delay of webhooks (so that GitGuardian incidents do not appear late): - `plugin.webhooks.io.threads` can be increased from the default `3` if the Bitbucket host has enough threads. - `plugin.webhooks.http.connection.host.max` can be increased from the default `5`. --- ## Integrate Gerrit Monitor Gerrit repositories for exposed secrets in source files, configuration files, and commit histories. ## Why monitor Gerrit? Gerrit is widely used for enterprise code review workflows, often hosting sensitive internal repositories. When developers commit credentials or API tokens, those secrets become part of the permanent git history and can be exposed to anyone with repository access, putting internal systems and infrastructure at risk. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Complete repository history analysis | | **Real-time Detection** | ⚠️ (Requires plugin) | Instant detection via the Gerrit webhook plugin | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your repositories | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ✅ (Supported) | Verify if secrets are still accessible | | **File Attachments** | ❌ (Not Supported) | Not applicable for code repositories | **What we scan:** - Source code files, configuration files, and raw text files - All repository branches and commit history ## Setup **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - A Gerrit **HTTP username and HTTP password** (not your SSH or Git credentials - generate these in your Gerrit account settings under **HTTP Credentials**) - **Gerrit admin** access to the instance you want to monitor - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. ### Connect your Gerrit instance 1. Navigate to **Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources)**. 2. Click **Configure** for Gerrit. 3. Submit your Gerrit instance URL, HTTP username, and HTTP password. :::caution The Gerrit instance URL must be prefixed with `https://`. Instances without a secure connection won't be monitored. ::: 4. GitGuardian will instantly start scanning your Gerrit instance. You can see the repositories monitored in your [Gerrit settings page](https://dashboard.gitguardian.com/settings/integrations/gerrit) by clicking on **See my Gerrit perimeter**. :::tip We recommend using a dedicated bot user to generate the HTTP credentials. This avoids disruption if an individual user's account is removed. ::: ### Optional: read replica If your Gerrit instance has a read replica configured, you can provide its URL during setup. GitGuardian will use the replica for cloning repositories to reduce load on your primary Gerrit server. All API calls always use the primary instance URL. ## Historical scanning By default, GitGuardian performs a historical scan of the full commit history for each repository added to your perimeter. :::note **Scanning of Gerrit changes (patchsets) is not enabled by default.** If you need GitGuardian to include Gerrit change patchsets in the historical scan, [contact GitGuardian support](https://support.gitguardian.com) to activate this option for your workspace. ::: GitGuardian uses the **Gitiles plugin** to link detected secrets back to the relevant commit diff in your Gerrit instance. Most public and self-hosted Gerrit instances have this plugin available by default. ## Real-time scanning Real-time scanning detects new secrets as soon as commits are pushed to Gerrit. This requires the **Gerrit webhook plugin** to be installed on your Gerrit instance. **Without the webhook plugin:** Only historical scanning is available. New commits pushed to Gerrit will not be scanned in real time. **With the webhook plugin:** GitGuardian receives push events immediately and scans new commits as they arrive. To enable the webhook plugin, refer to the [Gerrit webhook plugin documentation](https://gerrit.googlesource.com/plugins/webhooks/) and configure it to send events to your GitGuardian webhook URL shown in the integration settings. ### Understanding scanning capabilities #### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire repository history, based on your configured perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Historical scans run automatically when a repository is added to your perimeter. You can also re-trigger one at any time from your [perimeter page](https://dashboard.gitguardian.com/perimeter): select the sources and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. #### Real-time scanning **Catch new exposures instantly:** Once the webhook plugin is installed, GitGuardian continuously monitors your repositories through event-based detection. New commits containing secrets are detected immediately, allowing you to respond quickly to new exposures. ## Customize your monitored perimeter Once you have set up your Gerrit integration, you can configure which repositories to monitor in the Gerrit settings section of your workspace. If you deselect a repository from your monitored perimeter: - GitGuardian will no longer scan new commits for that repository. - You won't receive any alerts related to this repository. - You can re-enable monitoring at any time by selecting it again. --- ## Integrate GitHub Enterprise Server Monitor GitHub Enterprise Server repositories for exposed secrets in source files, configuration files, and commit histories. GitHub Enterprise Server environments contain your organization's most valuable intellectual property and proprietary code. While self-hosting provides control, it also means you're responsible for detecting when developers commit production credentials, internal API keys, or infrastructure secrets that could compromise your entire enterprise network and applications. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Complete repository history analysis | | **Real-time Detection** | ✅ (Supported) | Instant detection via webhooks | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your Orgs and repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ✅ (Supported) | Verify if secrets are still accessible | | **File Attachments** | ❌ (Not Supported) | Not applicable for code repositories | **What we scan:** - Source code files, configuration files, and raw text files - All repository branches and commit history ## Setup **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **GitHub Enterprise Server admin** permissions to install GitHub apps - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. :::info Rate limits If your instance enforces API rate limits, the default values may be too low and can slow down GitGuardian's scanning. To scan in a reasonable time, raise the limits or exempt the account, token, or service account that GitGuardian uses from rate limiting. See [Rate limits on self-hosted sources](/internal-monitoring/integrate-sources/monitored-perimeter#rate-limits-on-self-hosted-sources). ::: GitGuardian integrates with GitHub Enterprise Server via a **GitHub App** with **read-only access** to your repositories. :::info By default, the GitGuardian GitHub app has **only read access** to your code. Optionally, it is possible to grant GitGuardian **write access** to benefit from specific business features (more detail in [this dedicated section](#grant-gitguardian-code-write-permissions)). ::: The pre-existing GitGuardian GitHub App cannot be leveraged to integrate with GitHub Enterprise Server. Instead, you will need to create a separate GitHub App on your own GitHub Enterprise Server instance. This process is straightforward since GitGuardian will automatically indicate the required configurations. You can refer to the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/developers/apps) for more information on GitHub apps. GitGuardian supports [all GitHub Enterprise Server versions supported by GitHub itself](https://docs.github.com/en/enterprise-server@latest/admin/all-releases). ### Setup your GitHub Enterprise Server integration 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Install** for GitHub Enterprise Server. 3. Enter the URL of your GitHub Enterprise Server instance, and select the permission level to grant to GitGuardian. :::info App permissions **Read-only** is sufficient to scan for incidents, while **read and write** permissions are necessary if you want to leverage business features such as Honeytoken deployment jobs. The permission level can be changed later. See the [dedicated section](#grant-gitguardian-code-write-permissions) for more information. ::: ![GitGuardian GHE app creation form](/img/internal-monitoring/integrate-sources/vcs-integrations/github-enterprise/create-ghe-github-app.png) 4. Click on **Create the GitHub app** to be redirected to GitHub Enterprise Server and create your dedicated app 5. Validate the GitHub App creation. We recommend that you choose a simple name for your GitHub app such as **GitGuardian**, which will make it easily recognizable. ![GHE app creation via manifest](/img/internal-monitoring/integrate-sources/vcs-integrations/github/ghe-manifest-validation.png) 6. The GitHub App is now created and you can install it for users and organizations. 7. Follow the [exact same steps](github) as for the GitHub.com SaaS integration. :::caution The GitHub App **belongs to the user who created it**. We recommend that you transfer the ownership to an organization in case the user is later deactivated. ::: ![Transfer GitHub app](/img/internal-monitoring/integrate-sources/vcs-integrations/github/transfer-gh-app.png) > **IMPORTANT**: GitGuardian cannot monitor repositories whose owner has not installed the GitHub App. If the repo is owned by a GitHub organization, the owner of the organization must install the GitHub App. ### Configuration page When you integrate your GitHub Enterprise Server instance, you have access to a configuration page. From this page, you have the possibility to: - integrate another GitHub Enterprise Server instance with GitGuardian. - manage your existing instances and their dedicated GitHub app. GitGuardian tells you which ones are considered inactive. ![GHE configuration page](/img/internal-monitoring/integrate-sources/vcs-integrations/github-enterprise/configuration-page.png) ### Grant GitGuardian code write permissions :::info Some business features require write permission to your repositories in order to open pull requests. Currently, this concerns the [Honeytoken Deployment jobs](../../../honeytoken/deploy-honeytokens/deployment-jobs.md) feature. ::: If write permission was not provided at the time of app creation, you can grant this permission later by updating the existing app: 1. In the configuration page, click "Configure write permission" for your GitHub Enterprise Server instance. ![GHE configuration page](/img/internal-monitoring/integrate-sources/vcs-integrations/github-enterprise/ghe-configure-write-permission.png) 2. You will be redirected to GitHub Enterprise Server, in the tab "Permissions & events" of the app. Under the "Repository permissions" section, change permissions on Contents to "Read and write": ![Update app permissions](/img/internal-monitoring/integrate-sources/vcs-integrations/github/update-app-permissions-gh.png) 3. This change then needs to be propagated to the organizations where this app is installed, by accepting the permission update request: ![App permission update request](/img/internal-monitoring/integrate-sources/vcs-integrations/github/app-permission-update-request.png) ![Confirm app permission update](/img/internal-monitoring/integrate-sources/vcs-integrations/github/app-permission-update-request-step2.png) ## Automatic historical scan By default, GitGuardian performs a historical scan for each newly created GitHub Enterprise Server repository added to your perimeter. You can deactivate this behavior in your [GitHub Enterprise Server settings](https://dashboard.gitguardian.com/settings/integrations/github_enterprise_server) if you are a Manager of the workspace. ![Autoscan settings](/img/internal-monitoring/integrate-sources/vcs-integrations/github/auto_scan_setting.png) ## Automatic repository monitoring By default, GitGuardian automatically monitors repositories added to your perimeter. You can deactivate this behavior in your [GitHub Enterprise Server settings](https://dashboard.gitguardian.com/settings/integrations/github_enterprise_server) if you are a Manager of the workspace. --- ## Integrate GitHub Protect your source code by monitoring GitHub repositories for exposed secrets in commits, branches, and pull requests. ## Why Monitor GitHub? Developers frequently commit API keys, database credentials, and private tokens directly into GitHub repositories. These hardcoded secrets become accessible to anyone with repository access and remain permanently stored in git history, creating lasting security vulnerabilities that can compromise your entire infrastructure. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Complete repository history analysis | | **Real-time Detection** | ✅ (Supported) | Instant detection via webhooks | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your Orgs and repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ✅ (Supported) | Verify if secrets are still accessible | | **File Attachments** | ❌ (Not Supported) | Not applicable for code repositories | **What we scan:** - Source code files, configuration files, and raw text files - All repository branches and commit history ## Setup your GitHub integration **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **GitHub organization admin** or **repository owner** permissions GitGuardian integrates natively with GitHub via a **GitHub app** that you can install on your personal GitHub repositories and on the repositories of your GitHub organizations. You can refer to the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/developers/apps) for more information on GitHub apps. ### Scan for incidents with the GitGuardian GitHub app :::info The GitGuardian GitHub app has **only read access** to your code. Optionally, it is possible to grant GitGuardian **write access** to benefit from specific business features. See [dedicated section](#grant-code-write-permissions-with-the-gitguardian-github-app) for more detail. You will need Owner or Manager rights in GitGuardian to set up an integration or customize your settings. ::: You can install GitGuardian on: - **your personal GitHub account** to monitor your personal repositories, - **a GitHub organization** that you own. 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Install** for GitHub. 3. Click on **Install** to start the GitHub app installation process (you will then be redirected to GitHub). 4. Authenticate on GitHub if you are not already logged in. 5. Choose where to install the GitHub app (either for your personal GitHub account or for the GitHub organization of which you are an admin) ![choose actor](/img/internal-monitoring/integrate-sources/vcs-integrations/github/install-gh-app.png) 6. Choose your preferred installation mode: **All repositories** or **Only select repositories**. - **All repositories**: GitGuardian will be installed on all existing repositories. New repositories will be integrated to GitGuardian automatically. - **Only select repositories**: GitGuardian will only be installed on the repositories you select. New repositories will not automatically be integrated with GitGuardian - the installation process will need to be run again in order to integrate new repositories. We recommend choosing **All repositories** since you can then manually deselect these via the GitGuardian dashboard. ![choose repositories](/img/internal-monitoring/integrate-sources/vcs-integrations/github/gh-app-choose-repos.png) 7. Follow the prompts and your chosen GitHub repositories will be added to your workspace. ![GitGuardian monitored perimeter](/img/internal-monitoring/integrate-sources/vcs-integrations/github/monitored-perimeter.png) :::info If you attempt to install GitGuardian on a GitHub organization where you are only a member, and not the owner, GitHub will prompt you to use a "Request installation" flow. We highly recommend inviting the owner to your GitGuardian workspace to perform the integration, thus attaching the GitHub organization to your workspace. ::: ### Grant code write permissions with the GitGuardian:write GitHub app :::info Some business features require write permissions to your repositories in order to open pull requests. Currently, this concerns the [Honeytoken Deployment jobs](../../../honeytoken/deploy-honeytokens/deployment-jobs.md) feature. Granting write permissions to GitGuardian is done through the installation of a second GitHub app “GitGuardian:write”. ::: 1. Navigate to [GitHub settings section](https://dashboard.gitguardian.com/settings/integrations/github) where your integration is already configured with the main app. 2. Click on Manage sources > Configure write permissions. ![Configure write permissions via GitGuardian:write](/img/internal-monitoring/integrate-sources/vcs-integrations/github/configure-write-permissions.png) 3. Choose on which organization you want to install the GitHub app, then choose your preferred installation mode (all organization or selected repositories). Note that you must install it on repositories where the main GitHub is already installed if you want to see them in the GitGuardian dashboard. ## Integration with GitGuardian Self-Hosted :::info We recommend using dedicated workers for this integration. For more detailed information on scaling and configuration, please visit our [scaling](../../../self-hosting/management/infrastructure-management/scaling#configure-scaling-settings) page. ::: If you are using a self-hosted GitGuardian instance, you must first create a dedicated GitHub App so that you own the entire data stream. GitGuardian handles it for you programmatically via GitHub manifest. This will ensure that your GitHub App is created with all the appropriate rights. :::info By default, the GitGuardian GitHub app has **only read access** to your code. Optionally, it is possible to grant GitGuardian **write access** to benefit from specific business features (more detail in [this dedicated section](#grant-gitguardian-code-write-permissions)). You will need Owner or Manager rights in GitGuardian to set up an integration or customize your settings. ::: 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Configure** for GitHub. 3. Click on **Install** to start the GitHub app creation and installation process. 4. Choose a name and validate the GitHub App creation. ![GHE app creation via manifest](/img/internal-monitoring/integrate-sources/vcs-integrations/github/gh-manifest-validation.png) 5. Once the GitHub app is created, you can now follow the SAAS installation steps from **step 5** above and choose the GitHub organizations to integrate with GitGuardian. :::caution The GitHub App **belongs to the user who created it**. We recommend that you transfer the ownership to an organization in case the user is later deactivated. ::: ![Transfer GitHub app](/img/internal-monitoring/integrate-sources/vcs-integrations/github/transfer-gh-app.png) > **IMPORTANT**: GitGuardian cannot monitor repositories whose owner has not installed the GitHub App. If the repo is owned by a GitHub organization, the owner of the organization must install the GitHub App. ### Grant GitGuardian code write permissions :::info Some business features require write permissions to your repositories in order to open pull requests. Currently, this concerns the [Honeytoken Deployment jobs](../../../honeytoken/deploy-honeytokens/deployment-jobs.md) feature. ::: To allow GitGuardian to open pull requests on the repositories of your instance, go to the app settings page in GitHub, in the tab "Permissions & events". Under the "Repository permissions" section, change permissions on Contents to "Read and write": ![Update app permissions](/img/internal-monitoring/integrate-sources/vcs-integrations/github/update-app-permissions-gh.png) This change then needs to be propagated to the organizations where this app is installed, by accepting the permission update request: ![App permission update request](/img/internal-monitoring/integrate-sources/vcs-integrations/github/app-permission-update-request.png) ![Confirm app permission update](/img/internal-monitoring/integrate-sources/vcs-integrations/github/app-permission-update-request-step2.png) ## Adding new repositories You can add new organizations or repositories by clicking on **add another** on either the list of integrations page or the GitHub integration page. You can also re-configure a previously installed personal GitHub account / GitHub organization and change the installation mode to **All repositories** or **Only select repositories**. ## Automatic historical scan By default, GitGuardian performs a historical scan for each newly created GitHub repository added to your perimeter. You can deactivate this behavior in your [GitHub settings](https://dashboard.gitguardian.com/settings/integrations/github) if you are a Manager of the workspace. ![Autoscan settings](/img/internal-monitoring/integrate-sources/vcs-integrations/github/auto_scan_setting.png) ## Automatic repository monitoring By default, GitGuardian automatically monitors repositories added to your perimeter. You can deactivate this behavior in your [GitHub settings](https://dashboard.gitguardian.com/settings/integrations/github) if you are a Manager of the workspace. ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Real-time scanning **Catch new exposures instantly:** Once integrated, GitGuardian continuously monitors your content through event-based detection. Any new or modified content containing secrets are detected immediately, allowing you to respond quickly to new exposures. ## Customize your monitored perimeter Once you have set up your GitHub integration, you can configure which repositories to monitor in the [GitHub settings section](https://dashboard.gitguardian.com/settings/integrations/github) of your workspace. If you unselect a repository from your monitored perimeter: - GitGuardian will no longer fetch the content of its commits, and therefore alerts won't be raised for this repository. - The GitGuardian GitHub app will remain installed on this repository, therefore you can easily turn the monitoring back on. --- ## Integrate GitLab Protect your source code by monitoring GitLab repositories for exposed secrets in commits, merge requests, and project files. ## Why Monitor GitLab? GitLab repositories serve as the backbone of modern DevOps workflows, making them prime targets for secret exposure. When developers commit credentials, API tokens, or configuration secrets, they create permanent vulnerabilities in git history that can be exploited by anyone gaining repository access, potentially compromising entire development and production environments. ## Capabilities | Feature | Support | Details | |---------|---------|---------| | **Historical Scanning** | ✅ (Supported) | Complete repository history analysis | | **Real-time Detection** | ✅ (Supported) | Instant detection via webhooks | | **Monitored Perimeter** | ✅ (Supported) | Granular monitoring of your Orgs and repos | | **Team Perimeter** | ✅ (Supported) | Team-based access control | | **Presence Check** | ✅ (Supported) | Verify if secrets are still accessible | | **File Attachments** | ❌ (Not Supported) | Not applicable for code repositories | **What we scan:** - Source code files, configuration files, and raw text files - All repository branches and commit history ## Setup **Prerequisites:** - **Owner** or **Manager** account on your GitGuardian Dashboard - **GitLab admin** permissions (for system hooks) or **group owner** permissions (for group hooks) - **Personal access token** with appropriate scopes - **Network connectivity** between GitGuardian and your self-hosted services. Check out [**GitGuardian Bridge**](/platform/deployment-model/ggbridge#supported-integrations) to enable secure connections between GitGuardian SaaS and your self-hosted services in private networks. :::info Rate limits If your instance enforces API rate limits, the default values may be too low and can slow down GitGuardian's scanning. To scan in a reasonable time, raise the limits or exempt the account, token, or service account that GitGuardian uses from rate limiting. See [Rate limits on self-hosted sources](/internal-monitoring/integrate-sources/monitored-perimeter#rate-limits-on-self-hosted-sources). ::: GitGuardian integrates with GitLab in two ways: **instance-level with system hooks** or **group-level with group hooks**. Please refer to the GitLab documentation for more information on [system hooks](https://docs.gitlab.com/ee/administration/system_hooks.html) and [group hooks](https://docs.gitlab.com/ee/api/groups.html#hooks). ### Create a Personal Access Token We highly recommend that you use a bot user in order to generate personal access tokens. :::warning As mentioned above, only personal access tokens are currently supported. Other types of tokens (like group access tokens) are not supported. ::: 1. Navigate to your GitLab user settings 2. Go to **Access Tokens** section 3. Create a personal access token with a simple name such as "GitGuardian" and **`api` scope**. The personal token enables GitGuardian to create webhooks through your GitLab permissions. ![GitLab personal access token](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_personal_access_token.png) Please refer to the [GitLab documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#creating-a-personal-access-token) for more information about personal access tokens. :::info It's also possible to use a personal access token with the **`read_api`** scope. In this case, a hook URL and a secret token will be displayed once you submit the form. Use this hook URL and secret token to [add a new system hook on your GitLab instance](https://docs.gitlab.com/administration/system_hooks/#create-a-system-hook) (or with [Admin API](https://docs.gitlab.com/ee/api/system_hooks.html#add-new-system-hook)). Once this is done, your GitLab integration will be functional. ::: If "*Admin mode*" is enabled on your GitLab instance, you'll need the `admin_mode` scope in addition to the `api` or `read_api` scope. ### Integrate your GitLab instance with system hooks **System hooks** can only be created **by an Administrator of the instance**, they provide access to projects belonging to all users and groups. The system hook integration is only available for the on-premise version of GitLab (such an integration is not possible on GitLab.com). :::tip We recommend that you leverage a bot user when integrating with GitGuardian. ::: #### Requirements - Self-managed GitLab: GitLab Community Edition or any plan of GitLab Enterprise Edition. v11.0+ - GitLab.com (SaaS): **IMPORTANT** GitGuardian cannot integrate with GitLab.com (SaaS) via System hooks. #### Guidelines 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Configure** for GitLab. 3. Click on **Start** for the system hook option: "Monitor the entire GitLab instance" 4. Submit your GitLab instance url and the personal access token created. ![GitLab system hook form](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_system_hook_form.png) :::caution _GitLab instance URL_ must be prefixed with `https://`, instances without a secure connection won't be monitored. ::: 5. GitGuardian will instantly start monitoring your GitLab instance. You can see the projects and groups monitored in your [GitLab settings page](https://dashboard.gitguardian.com/settings/integrations/gitlab) by clicking on **See my GitLab perimeter**: ![GitLab system hook perimeter](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_perimeter.png) #### Events subscription details Our system hook will subscribe to the following events: - `Repository update events` - `Push events` - `Merge request events` and SSL verification will be enabled. #### Troubleshooting - GitGuardian automatically detects if the system hook is deleted from GitLab side or if the Personal access token becomes invalid (by expiring or being revoked). We will send an email to notify you. All of your existing data will remain accessible. - If your GitLab instance is marked as “not monitored" but the personal access token associated is still active, you can reactivate it by clicking on the **synchronize** button. It will recreate a system hook programmatically. ![GitLab system hook instances table](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_system_hook_instances.png) - If the token is invalid you can set a new personal access token by editing it: ![GitLab system hook edit](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_system_hook_edit.png) - If the admin token is revoked, GitGuardian will detect it and automatically deactivate your GitLab integration if no other active token is present. If another token suitable for monitoring exists, the GitLab integration will use that token. All your existing data will remain accessible. :::caution **IMPORTANT**: Do not change the URL or the Personal access token of the system hook from the GitLab admin interface or this will break the integration. ::: ### Integrate your GitLab groups with group hooks **Group hooks** require the user to have **Owner role on the GitLab groups to be monitored**. Group hooks do not support the monitoring of GitLab users personal projects. The group hook integration works for both GitLab on-premise and Gitlab.com. Note that you can only monitor up to 50,000 projects per group for a group hook integration. :::tip We recommend that you leverage a bot user when integrating with GitGuardian. ::: Note that you can't have a system hook integration and a group hook integration at the same time. #### Requirements - Self-managed GitLab: Starter plan and higher tiers. v13.5+ - GitLab.com (SaaS): Premium plan #### Guidelines 1. Navigate to Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources). 2. Click on **Configure** for GitLab. 3. Click on **Start** for the group hook option: "Monitor only certain GitLab groups" 4. Submit your GitLab instance url and the personal access token, and make sure to name this personal access token as you might use several of them in the future to integrate more GitLab groups. ![GitLab group hook form](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_group_hook_form.png) :::caution _GitLab instance URL_ must be prefixed with `https://`, instances without a secure connection won't be monitored. ::: 5. You are then brought to the configuration page of your GitLab integration where you can see the list of all the GitLab groups and subgroups that your personal access token gives access to. Click **Install** for the GitLab groups and subgroups you want GitGuardian to monitor. ![GitLab group hook configuration](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_group_hook_configuration_page.png) :::info If the token has **`read_api`** scope, a hook URL and a secret token will be displayed once you install a new group. Use this hook URL and secret token to add a [new group hook](https://docs.gitlab.com/user/project/integrations/webhooks/#create-a-webhook) (or with [Group API](https://docs.gitlab.com/api/group_webhooks/#create-a-group-hook)). Once this is done, your integration will be functional for this group. ::: 6. You can see the projects and groups monitored in your [GitLab settings page](https://dashboard.gitguardian.com/settings/integrations/gitlab) ![GitLab group hook perimeter](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_perimeter.png) #### Installation remarks - When you choose to install a GitLab group, all its sub-groups will also be installed automatically. In doing so, the "parent" group and "children" subgroups are linked together and if you only want to uninstall one subgroup, you will need to uninstall the "parent" group first. - A GitLab group cannot belong to two personal access tokens. Therefore, when you want to install a "parent" group that has an already-installed subgroup you must first uninstall the "child" subgroup. #### Events subscription details Our group hooks will subscribe to the following events: - `Repository update events` - `Push events` - `Merge request events` and SSL verification will be enabled. #### Troubleshooting - You can **submit new personal access tokens if you want to monitor more GitLab groups**. Multiple tokens can be added for group hooks integration. If several tokens are associated with the same GitLab group, you have to choose which token will be monitoring it. ![GitLab group hook new personal access token](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_group_hook_new_personal_access_token.png) - If the token is revoked, the group will no longer be monitored (you can install it again with another token, but GitGuardian will not arbitrarily choose another token for you). In this scenario you'll receive an email informing of the unmonitored status of the integration. ## Automatic historical scan By default, GitGuardian performs a historical scan for each newly created GitLab project added to your perimeter. You can deactivate this behavior in your [GitLab settings](https://dashboard.gitguardian.com/settings/integrations/gitlab) if you are a Manager of the workspace. ![Autoscan settings](/img/internal-monitoring/integrate-sources/vcs-integrations/gitlab/gitlab_auto_scan_setting.png) ## Automatic repository monitoring By default, GitGuardian automatically monitors repositories added to your perimeter. You can deactivate this behavior in your [GitLab settings](https://dashboard.gitguardian.com/settings/integrations/gitlab) if you are a Manager of the workspace. ## Understanding scanning capabilities ### Historical scanning **Uncover your secret debt:** When you first integrate this source, GitGuardian performs a comprehensive scan of your entire content history, based on your customized perimeter. This reveals secrets that may have been exposed weeks, months, or even years ago - helping you address your existing security debt. **How to trigger a historical scan:** Go to your [perimeter page](https://dashboard.gitguardian.com/perimeter), select the sources you want to scan, and click **Scan** in the bulk actions bar. See [Manage your monitored perimeter](/internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) for plan-based size limits, error handling, and full details. ### Real-time scanning **Catch new exposures instantly:** Once integrated, GitGuardian continuously monitors your content through event-based detection. Any new or modified content containing secrets are detected immediately, allowing you to respond quickly to new exposures. ## Customize your monitored perimeter Once you have set up your GitLab integration, you have the possibility to configure which projects to monitor in the [GitLab settings section](https://dashboard.gitguardian.com/settings/integrations/gitlab) of your workspace. If you deselect a project from your monitored perimeter: - GitGuardian will no longer fetch the content of its commits, therefore you won't receive any alerts related to this project. - The webhook installed on this project will still exist, therefore you can easily turn the monitoring back on at any moment. --- ## Block secrets from the VCS ## Overview Secrets can be blocked from reaching shared repositories with the help of ggshield, the GitGuardian CLI, and through the setup of pre-receive git hooks. This is only applicable for organizations running their own GitHub, GitHub Enterprise Server, or GitLab instances. If this is your case, the VCS site administrator can create and remove pre-receive hooks for your entire organization and its associated repositories.
What is a pre-receive hook? Pre-receive hooks run tests on code pushed to a repository to ensure contributions meet repository or organization policy. If the commit contents pass the tests, the push will be accepted into the repository. If the commit contents contain any secrets, the push will not be accepted. If your push isn’t accepted, you will see an error message corresponding to the failed pre- receive hook.
### Advantages Pre-receive hooks are configured once for the VCS instance and are the most effective tool to prevent secrets from reaching your codebase. ### Integrate ggshield with a pre-receive hook 1. [Create a service account](../../api-docs/service-accounts.md) for the GitGuardian API 2. Set up a [pre-receive hook with ggshield](../../ggshield-docs/integrations/git-hooks/pre-receive.md) --- ## Detect secrets in CI pipelines ## Overview For vulnerabilities that are only exploitable during runtime like buffer overflows, SQL injections, or cross-site scripting, application security testing in the CI pipelines often translates into considerably shorter fix times. In the case of hardcoded credentials, the situation is different. No gains are to be expected in terms of remediation when comparing incidents that surface here against those that are found through the VCS integration (as a matter of fact, incidents detected during CI scans are also raised in the GitGuardian dashboard, since the remote branches live in the centralized repository). You should regard secrets that enter centralized remote repositories as compromised, no matter how they found their way inside. The remediation process needs to get triggered in full in such a case; you should revoke and rotate the credentials before re-running security checks again. ### Advantages Automating security testing in the CI pipelines is a great strategy to quickly raise the awareness of both developer and DevOps engineering teams around the problem of hardcoded secrets. ### Integrate ggshield in CI workflows 1. [Create a service account](../../api-docs/service-accounts.md) for the GitGuardian API 2. Set up CI/CD Integrations with ggshield 1. [Jenkins CI](../../ggshield-docs/integrations/cicd-integrations/jenkins-ci.md) 2. [GitHub Actions](../../ggshield-docs/integrations/cicd-integrations/github-actions.md) 3. [GitLab CI/CD](../../ggshield-docs/integrations/cicd-integrations/gitlab-pipelines.md) 4. [Azure pipelines](../../ggshield-docs/integrations/cicd-integrations/azure-pipelines.md) 5. [Bitbucket pipelines](../../ggshield-docs/integrations/cicd-integrations/bitbucket-pipelines.md) 6. [Circle CI](../../ggshield-docs/integrations/cicd-integrations/circle-ci.md) 7. [Drone CI](../../ggshield-docs/integrations/cicd-integrations/drone-ci.md) 8. [Travis CI](../../ggshield-docs/integrations/cicd-integrations/travis-ci.md) 9. [Scan Docker images](../../ggshield-docs/integrations/docker/docker_image.md) after the build job --- ## Detect secrets in GitHub PRs ## Overview [GitHub Check Runs](https://docs.github.com/en/rest/checks/runs) will be triggered on GitHub pull requests on repositories monitored by GitGuardian. Secret scans in the context of GitHub Check Runs will run server-side on the VCS, at the post-receive stage. GitGuardian secret scans run **on each individual commit that makes up the pull request, and not only the final state of the code** in the pull request. This deep scanning helps uncover cases where one commit A adds a secret and one commit B removes the same secret within the same pull request. This allows the individual developer to get notified when an incident is detected by GitGuardian, **directly in the GitHub interface**. This is particularly useful when a developer opens a pull request to merge an individual branch into a collaborative one. The Check Run will alert the developer before the commits are merged, **limiting the incident to their branch and giving them the opportunity of easier remediation**. The result is secrets-free collaborative branches such as the ones used for QA, staging, and production environments. ## How it looks In the GitHub UI, a GitGuardian check run presents **a table with all findings and their relevant details**: - the **id** of the corresponding secret incident on GitGuardian - the **status** of the corresponding secret incident on GitGuardian Keep in mind that if secret incidents are closed on the GitGuardian dashboard, they will no longer be raised by GitHub checkruns. - the secret type - the commit sha - the filename - and also links to the GitGuardian dashboard if the user wishes to view the incident there and act on it (change status, leave notes, resolve, etc.). ![Checkruns conclusion in GitHub UI](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_conclusion_in_github.png) ![Checkruns details in GitHub UI](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_details_in_github.png) Secrets incidents detected during check runs and raised in the GitGuardian dashboard also link back to the original GitHub pull request. ![Incidents details with pull request links](/img/internal-monitoring/integrate-sources/vcs-integrations/github/pull_requests_list_in_incident_detail.png) > Please note that only GitHub pull requests created after February 10th, 2022 will be visible. ## Monitor your check runs from the dashboard The **GitHub check runs** page lists every check run triggered on your monitored repositories, so you can audit scan coverage and troubleshoot failed runs without leaving GitGuardian. Find it under [**Perimeter** > **Internal monitoring** > **GitHub check runs**](https://dashboard.gitguardian.com/perimeter/internal-monitoring/check-runs/). ![GitHub check runs dashboard](/img/internal-monitoring/integrate-sources/vcs-integrations/github/check_runs_dashboard.png) At the top of the page, three indicators summarize your check run activity: - **Check run mode**: your current [conclusion setting](#choose-the-conclusion-of-check-runs-when-secrets-are-detected) when secrets are detected (blocking or neutral). - **Pull requests with secrets**: the share of scanned pull requests where secrets were found over the last 7 days. - **Success rate**: the share of check runs that completed without finding secrets over the last 7 days. ### Browse and filter check runs Quick tabs split check runs by outcome: **Secrets found**, **Errors**, **Running**, and **No secrets found**. Each check run shows its source repository, status, commit SHA, associated pull requests, linked incidents, last run date, and duration. Use the filter bar to narrow the list by repository, status, or date, or search for a specific commit or pull request. Two status values deserve a closer look: - **Failed**, displayed as `Blocking`: the check run found secrets and its conclusion is set to `Failed`, so the pull request is blocked until the secrets are remediated or the check run is skipped. - **Skipped**: a developer used one of the [skip actions](#enable-or-disable-skip-actions) on the check run in GitHub, or the check run timed out before completing and was skipped automatically to avoid blocking the pull request. ### Act on a check run From the **Incidents** column, jump straight to the secret incidents raised by a check run to start remediation. Each row also provides actions so you can unblock developers without switching to GitHub: - **Re-run** a check run, for example after remediating the detected secrets or when a run ended in error. - **Skip** a check run when it should not block the pull request. ## Manage your GitHub check runs ### Activate or deactivate the GitGuardian check runs As a workspace Manager, you can decide to turn the GitHub Check Runs On or Off for the monitored repositories directly in your [GitHub settings page](https://dashboard.gitguardian.com/settings/integrations/github) or [GitHub Enterprise Server settings page](https://dashboard.gitguardian.com/settings/integrations/github_enterprise_server). ![GitHub Check Runs](/img/internal-monitoring/integrate-sources/vcs-integrations/github/check_runs_settings.png) > Note: If you have integrated both GitHub.com and GitHub Enterprise Server, you will have two different check runs settings. ### Choose the conclusion of check runs when secrets are detected You also have the option to determine the conclusion of the GitHub check runs when secrets are detected. You can choose between two options: - either `Failed` This conclusion will **prevent your developers from merging the pull request** if you have protected branches in place, ensuring that your secrets do not make it to production. To prevent full blockages, GitGuardian provides skip action buttons for developers to bypass blocking check runs. More details can be found below. - or `Neutral` This conclusion **does not block pull requests**. Developers will be notified of secret presence, especially if you enable GitGuardian to post a comment to enhance visibility of detected secrets in the pull request. Refer to the section below for more information. ![Checkruns status setting](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_conclusion_setting.png) ### Skip merge commits in pull request check runs By default, check runs scan **every commit** that makes up a pull request, including merge commits that pull changes in from the target branch. This can surface secrets that were not introduced on the PR branch itself, leading to false positives that the PR author cannot remediate. As a workspace Manager, you can enable **Skip merge commits in pull request check runs** in your [GitHub settings page](https://dashboard.gitguardian.com/settings/integrations/github) or [GitHub Enterprise Server settings page](https://dashboard.gitguardian.com/settings/integrations/github_enterprise_server). When enabled, check runs ignore merge commits and only flag secrets introduced by commits authored on the PR branch. ### Enable or disable skip actions When the conclusion of the checkruns if secrets are detected is "Failed", pull requests are unable to be merged. However, since the detection of secrets is probabilistic, **GitGuardian offers skip action buttons to prevent complete hindrance to developers**. These skip actions mirror the ignore reasons available on the dashboard, with the understanding that skipping a checkrun containing a secret is akin to ignoring the associated incident. The available skip actions include: - `Skip: false positive` - `Skip: test credential` - `Skip: low risk` ![GitHub checkruns skip buttons](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_skip_buttons.png) When a skip action is taken, the corresponding secret incident is tagged to inform dashboard users that a developer intentionally skipped the checkrun after encountering the secret alert. The tags for skipped incidents include: - `Skipped in check run as false positive` - `Skipped in check run as test credential` - `Skipped in check run as low risk` ![Skip actions tags](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_skip_actions_tags.png) As a workspace manager, you have the option to disable the ability to skip check runs entirely in [your settings](https://dashboard.gitguardian.com/settings/integrations/github). ### Post a comment in the pull request timeline To extend the visibility of checkrun results and ensure your developers do not miss it, GitGuardian posts a comment when a secret is detected. ![Pull request comment](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_pull_request_comment.png) Such behavior can be enabled or disabled in [your settings](https://dashboard.gitguardian.com/settings/integrations/github) by workspace Managers. ### Customize remediation guidelines As a workspace Manager, you can customize the remediation guidelines. These guidelines will be displayed in the GitHub interface both in the check run body and in the comment posted on the pull request timeline. ![Customize remediation guidelines](/img/internal-monitoring/integrate-sources/vcs-integrations/github/check_runs_how_to_remediate_guidelines.png) ### Use public share links for incident details When enabled, check runs will automatically generate public share links that allow developers to access and resolve incident details directly from the pull request interface, without requiring GitGuardian dashboard access. The behavior works in conjunction with the "Auto-share incident access to the author of the leak" playbook: **public share links are used when the incident is created by a non-workspace member with a non-generic email address**, while **workspace members receive authenticated URLs** to the GitGuardian dashboard. This requires the [Auto-share incident access playbook](../../platform/automate-with-playbooks/available-playbooks.md#auto-share-incident-public-link-to-involved-developer) and [public sharing capability](../../platform/enterprise-administration/workspace-settings#public-sharing) to be enabled. Share links inherit the same security controls and expiration times as the auto-share playbook. As a workspace Manager, you can enable or disable this feature in [your GitHub settings](https://dashboard.gitguardian.com/settings/integrations/github). ## Dependencies ### GitHub branch protection: rulesets vs branch protection rules GitHub offers two ways to protect your branches: **rulesets** and **branch protection rules**. Understanding the difference is important when configuring GitGuardian check runs: #### Using rulesets If you're using a **ruleset** and require GitGuardian security checks to pass: - You should also enable **"Require a pull request before merging"**. Without this setting, GitHub will block any push made directly to the protected branch, since rulesets apply to all commits including direct pushes. - Your **repository must be actively monitored by GitGuardian**. If it is not, GitHub will be waiting for a check run from GitGuardian that will never be provided, causing a perpetual pending check run. - If the check run conclusion is `Failed`, GitHub will display a specific warning. The `Neutral` conclusion is considered the same as a successful check run. ![rulesets](/img/internal-monitoring/integrate-sources/vcs-integrations/github/gh_rulesets.png) #### Using branch protection rules If you're using **branch protection rules** with the **"Require status checks to pass before merging"** setting: ![Branch protection rule](/img/internal-monitoring/integrate-sources/vcs-integrations/github/gh_branch_protection_rule.png) - **Branch protection rules** only apply to pull requests, not to direct pushes to the branch, so they work seamlessly with GitGuardian check runs without additional configuration. - Your **repository must be actively monitored by GitGuardian**. If it is not, GitHub will be waiting for a check run from GitGuardian that will never be provided, causing a perpetual pending check run. ![Required and pending check run](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_required_and_pending.png) - If the check run conclusion is `Failed`, GitHub will display a specific warning. The `Neutral` conclusion is considered the same as a successful check run. ![Required and failed check run](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_required_and_failed.png) ### Working with forked repositories In a fork process, there are two repositories: 1. **Forked repository**: Your personal copy of the upstream repo, marked as `fork = true` on GitHub. 2. **Upstream repository**: The original repository. #### Forked repositories By default, GitGuardian does **not** generate check runs on monitored forked repositories to prevent rate limiting errors. This issue arises because many forked repositories automatically generate numerous pull requests to stay up-to-date with their upstream repositories, which often have high activity levels. These automated pull requests are resource-intensive and can lead to rate limiting errors during GitGuardian check runs. However, managers of workspaces under the Business plan have the option to [enable GitGuardian check runs on their monitored forked repositories](https://dashboard.gitguardian.com/settings/integrations/github). #### Upstream repositories Check runs are created on monitored upstream repositories. However, when a pull request originating from a forked repository contains secrets, GitGuardian cannot propose the usual "Skip" actions buttons. In this scenario, GitGuardian provides a simple `Skip` button to avoid blocking the developer. ![Forked repositories PR](/img/internal-monitoring/integrate-sources/vcs-integrations/github/checkruns_forked_repositories.png) ### GitHub Merge Queue support When a pull request is added to a GitHub merge queue, GitGuardian responds with a neutral check run because: - Secret scanning is already performed on pull requests **before** they enter the merge queue - The merge queue doesn't create new commits that could introduce new secrets - PRs must pass GitGuardian check runs before being eligible for the merge queue This neutral status will not block the merge queue validation, even if the GitGuardian check is marked as required. ### Very large pull requests Because a check run scans every commit in a pull request through the GitHub API, very large pull requests can generate a high volume of API calls. The GitHub App installation has a shared rate limit of 5,000 requests per hour across your whole organization (see [GitHub's rate limits](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api)), and a single oversized pull request could consume it. A pull request is considered oversized when it exceeds any of these limits: - more than **200 commits** (GitHub's own check run limit is 250) - more than **60,000 files** changed - more than **300,000 lines** changed **Business plan**: instead of reaching the GitHub API commit by commit, GitGuardian scans oversized pull requests by cloning the repository branch and scanning it locally, the same clone-based approach used for historical scans. This avoids consuming your organization's GitHub API rate limit while still scanning the full pull request. The check run reports the same result and annotations as a standard check run, so developers see no difference, though it may take slightly longer to complete. **Other plans**: to protect your organization's API budget, GitGuardian **skips the check-run scan on pull requests above the size limits**. The skip applies only to pull requests above the limits, so it is infrequent, and the outcome is visible as the check run status on the pull request in GitHub. ## Going further: customizing check runs on a per-repository basis GitGuardian offers you the ability to customize the behavior of GitGuardian check runs at the repository level by utilizing GitHub's native features to override the configuration set on the GitGuardian dashboard. ### Using GitHub custom properties [GitHub custom properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization) allow you to customize check runs both at the organization level and the repository level: - whether the checkrun is present or not - specifying the conclusion as either `Failed` or `Neutral` when secrets are detected. - whether the [skip actions](detect-secrets-in-real-time-in-github#enable-or-disable-skip-actions) are available or not. ![custom properties to override check run settings](/img/internal-monitoring/integrate-sources/vcs-integrations/github/create_organization_custom_property_to_override_checkruns_settings.png) > It is crucial to use the exact names of the custom properties given below to ensure the feature functions properly. #### Overriding check runs presence > Supported property types: (Text, Single select, True/False) GitGuardian global configuration Custom property `gitguardian-check-runs-enabled` `true` `false` `null` Check runs are activated ✅ check runs will be present ✅ check runs won’t be present 🚫 check runs will be present ✅ Check runs are deactivated 🚫 check runs will be present ✅ check runs won’t be present 🚫 check runs won’t be present 🚫 #### Overriding check runs conclusion > Supported property types: (Text, Single select) GitGuardian global configuration Custom property `gitguardian-check-runs-secrets-conclusion` `neutral` `failed` `null` or other Check runs conclusion if secrets is Neutral ⬛ check runs conclusion if secrets will be Neutral ⬛ check runs conclusion if secrets will be Failed ❌ (blocking the PR) check runs conclusion if secrets will be Neutral ⬛ Check runs conclusion if secrets is Failure ❌ check runs conclusion if secrets will be Neutral ⬛ check runs conclusion if secrets will be Failed ❌ (blocking the PR) check runs conclusion if secrets will be Failed ❌ (blocking the PR) #### Overriding check runs skip actions presence when the conclusion is Failed > Supported property types: (Text, Single select, True/False) GitGuardian global configuration Custom property `gitguardian-check-runs-actions-enabled` `true` `false` `null` Skip action buttons are enabled ✅ skip action buttons will be present ✅ skip action buttons won’t be present 🚫 skip action buttons will be present ✅ Skip action buttons are disabled 🚫 skip action buttons will be present ✅ skip action buttons won’t be present 🚫 skip action buttons won’t be present 🚫 ### Using GitHub labels for GitHub Enterprise Server < 3.13 :::caution Using [GitHub labels](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels) to customize check runs is deprecated and will be removed in January 2026. Please migrate to [Custom properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization) which are available starting from GitHub Enterprise Server version 3.13. Please get in touch with your account manager to have this feature activated. ::: On GitHub Enterprise Server < 3.13, [GitHub labels](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels) allow you to customize check runs at the repository level: - whether the check run is present or not. - specifying the conclusion as either `Failed` or `Neutral` when secrets are detected. - whether the [skip actions](detect-secrets-in-real-time-in-github#enable-or-disable-skip-actions) are available or not. ![Repo label to override check run settings](/img/internal-monitoring/integrate-sources/vcs-integrations/github/create_repository_label_to_override_checkruns_settings.png) > You are free to customize the label's description and color, but it is essential that the label name remains exact. #### Overriding check runs presence | GitGuardian global configuration | GitHub Enterprise Server repository labels | | | | | -------------------------------- | ------------------------------------------ | --------------------------------- | ----------------------------- | ---------------------------- | | | `gitguardian:check-runs-enabled` | `gitguardian:check-runs-disabled` | No labels | Both labels present | | Check runs are activated ✅ | check runs will be present ✅ | check runs won’t be present 🚫 | check runs will be present ✅ | check runs will be present ✅ | | Check runs are deactivated 🚫 | check runs will be present ✅ | check runs won’t be present 🚫 | check runs won’t be present 🚫 | check runs will be present ✅ | #### Overriding check runs conclusion | GitGuardian global configuration | GitHub Enterprise Server repository labels | | | | | --------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------ | -------------------------------------------------- | | | `gitguardian:check-runs-secrets-conclusion-neutral` | `gitguardian:check-runs-secrets-conclusion-failed` | No labels | Both labels present | | Check runs conclusion if secrets is Neutral ⬛ | check runs conclusion if secrets will be Neutral ⬛ | check runs conclusion if secrets will be Failed ❌ (blocking the PR) | check runs conclusion if secrets will be Neutral ⬛ | check runs conclusion if secrets will be Neutral ⬛ | | Check runs conclusion if secrets is Failure ❌ | check runs conclusion if secrets will be Neutral ⬛ | check runs conclusion if secret will be Failed ❌ (blocking the PR) | check runs conclusion if secret will be Failed ❌ (blocking the PR) | check runs conclusion if secrets will be Neutral ⬛ | #### Overriding check runs skip actions presence when the conclusion is Failed | GitGuardian global configuration | GitHub Enterprise Server repository labels | | | | | ---------------------------------- | ------------------------------------------ | ----------------------------------------- | -------------------------------------- | ------------------------------------- | | | `gitguardian:check-runs-actions-enabled` | `gitguardian:check-runs-actions-disabled` | No labels | Both labels present | | Skip action buttons are enabled ✅ | skip action buttons will be present ✅ | skip action buttons won’t be present 🚫 | skip action buttons will be present ✅ | skip action buttons will be present ✅ | | Skip action buttons are disabled 🚫 | skip action buttons will be present ✅ | skip action buttons won’t be present 🚫 | skip action buttons won’t be present 🚫 | skip action buttons will be present ✅ | --- ## Detect secrets on developer workstations ## Overview Secrets detection can be integrated very early on in the development process. GitGuardian empowers developers, with [ggshield (our command-line interface application)](../../ggshield-docs/home.mdx) to scan their commits for hardcoded secrets before pushing them. The cost of fixing hardcoded secrets is much lower at this stage than once they have reached the central/shared repository, hence the importance of shifting security left and providing developers with early and frequent feedback. ggshield can be integrated into git hooks to automatically scan code before committing staged changes (pre-commit hook) or before pushing code to the shared repository (pre-push hook).
What are git hooks? Like many Version Control Systems, git has a way to fire off custom scripts when certain actions are triggered. There are two groups of these hooks: client-side and server-side. Client-side hooks are triggered by operations such as committing and merging, while server-side hooks run on network operations such as receiving pushed commits. The custom scripts running in git hooks can be used for a variety of purposes like linting, testing, and running security scans on your code.
## Getting started with ggshield 1. Set up [ggshield on your workstation](../../ggshield-docs/getting-started.md) 2. Configure the git hooks with ggshield: - [pre-commit hook](../../ggshield-docs/integrations/git-hooks/pre-commit.md) - [pre-push hook](../../ggshield-docs/integrations/git-hooks/pre-push.md) ## Additional resources - [How To Use ggshield To Avoid Hardcoded Secrets [cheat sheet included]](https://blog.gitguardian.com/how-to-use-ggshield-to-avoid-hardcoded-secrets-cheat-sheet-included/) - [Using ggshield Throughout The Software Development Lifecycle - A Developer's View of GitGuardian [video]](https://www.youtube.com/watch?v=diuBTBjx7Qc) --- ## Overview(Prevent) ## Why should organizations shift security testing left? Shift left is a development principle which states that code quality and security should move from the right or at the very end of the software development life cycle (after code is deployed to runtime environments) to the left – in developer workstations and IDEs, in Continuous Integration (CI) pipelines, etc. In other words, security, and secrets detection, should be integrated and designed into all stages of the development process. This new shift requires developers to take more ownership of security and security principles. ### GitGuardian CLI (ggshield) **ggshield, the GitGuardian CLI (command-line interface)** integrates GitGuardian's secrets detection engine in your developer workflows, [Getting started with ggshield](../../ggshield-docs/getting-started.md). ## FAQ #### I have GitHub, GitLab or an other VCS configured. Why should I use ggshield? GitGuardian CLI or ggshield helps you catch hardcoded secrets earlier in the software development lifecycle. In cases where pre-commit or pre-receive hooks are configured with ggshield, you will be alerted before secrets leave your local workstation and enter the shared/central repositories. This prevents secrets from getting exposed and in turn, avoids you the pain of incident remediation and the revoking and rotating of secrets. #### I have ggshield configured. Should I also scan my GitHub, GitLab and other VCS? GitGuardian CLI is a very flexible tool. It is fast and easy to integrate but does not provide the same security guarantees as real-time monitoring of your Version Control System (VCS). Pre-commit or pre-receive hooks can be bypassed for example on developer workstations. In Continuous Integration (CI) pipelines, ggshield has to be configured individually for each workflow/pipeline to add a secrets scanning job. The GitGuardian Internal Monitoring platform and its native VCS integrations give you: - Complete visibility over all repositories in your perimeter in addition to the possibility to scan their entire commit history (periodically and on-demand), - Real-time protection with automated scanning of every new code commit that reaches the VCS. --- ## Bulk actions on incidents Bulk actions allow you to perform the same action on multiple incidents simultaneously, improving your remediation workflow efficiency. ## How to use bulk actions 1. Navigate to your [incidents page](https://dashboard.gitguardian.com/incidents) 2. Select multiple incidents using checkboxes 3. The bulk actions toolbar appears at the top 4. Choose your desired action :::tip Use the header checkbox to select all incidents on the page, or click "Select all X incidents" to select all matching your current filters. ::: ## Available actions ### Status management - **Assign/Unassign**: Distribute incidents to team members - **Resolve**: Mark incidents as fixed (requires resolution reason) - **Ignore**: Mark as false positives or non-issues (requires ignore reason) - **Reopen**: Change closed incidents back to open status ### Organization - **Set severity**: Update priority levels (Critical, High, Medium, Low) - **Add custom tags**: Categorize incidents (requires workspace configuration) - **Comment**: Add notes visible in incident timelines ### Collaboration - **Share**: Grant access to users or teams (Business plan only) - **Download**: Export incident data as CSV reports ## Using bulk actions with similar incidents GitGuardian's [ML-powered similar incident grouping](./investigate-incidents.md#ml-powered-similar-incident-grouping) helps you identify related incidents that can be efficiently handled together using bulk actions. Once you've identified similar incidents during your investigation: 1. **From incident details**: View similar incidents in the sidebar and click on "View X similar incidents" to see them in the main incidents list 2. **Filter by similarity**: In the search box, use `similar_to` to show only incidents similar to a specific incident 3. **Sort by similarity count**: Use the "Similar incidents" column to sort incidents by highest or lowest number of similar incidents 4. **Apply bulk actions**: Select similar incidents and perform bulk operations like resolving, assigning, or tagging them together This combination is particularly useful for: - **Identifying false positives**: Group and ignore similar false positive incidents in bulk - **Consistent remediation**: Apply the same remediation approach to incidents that require similar fixes - **Reducing incident fatigue**: Focus on unique issues while efficiently handling repetitive incidents [Learn more about ML-powered similar incident grouping](./investigate-incidents.md#ml-powered-similar-incident-grouping) ## Best practices - **Filter first**: Use search and filters to narrow your selection - **Verify selection**: Check the count before executing actions - **Start small**: Begin with smaller batches to learn the workflow - **Document actions**: Use comments to explain bulk decisions - **Use similar grouping**: Leverage ML grouping to identify related incidents before applying bulk actions ## Permissions - **Can view**: No bulk actions available - **Can edit**: All actions except sharing - **Full access**: All bulk actions including sharing :::note Some incidents may be excluded if you lack sufficient permissions for those specific incidents. ::: --- ## Investigate incidents ## Investigation overview Proper investigation is crucial for effective secret remediation. Understanding the full context of a secret exposure helps you make informed decisions about remediation priority and approach. > Before [remediating incidents](./remediation-overview.md), leverage all GitGuardian context and insights for safe and effective remediation. ## Risk score :::info Business feature Only workspaces with a Business plan can access risk score. ::: Each incident includes a **risk score** (0-100) that provides ML-powered prioritization insights, where **100 indicates the highest risk** and **0 the lowest**. The score is displayed prominently in the incident detail page with a detailed explanation of contributing factors. **Key features:** - Dynamic scoring that updates as incident context evolves - Natural language explanation of main risk factors - Feedback mechanism to help improve the feature The risk score helps you quickly assess whether an incident requires immediate attention or can be addressed through standard workflows. → [Learn more about the Risk Score and how to use it](./prioritize-incidents.md#risk-score-ml-powered-prioritization) ## What GitGuardian provides for investigation For every incident, GitGuardian will provide you with the following metadata about the [secret and its occurrences](../detect/secrets-occurrences.md): - Type of secret (raised by the detector) - Date (at which the occurrence of the secret was committed) - Commit author email (involved developer) - Repository name - File name and extension - Commit SHA-1 hash - Git history presence (when possible) - Validity (when possible - see [dedicated section](../../secrets-detection/customize-detection/validity-checks.md)) - Additional tags (e.g., Default branch, From historical scan, Publicly leaked, Vaulted, Regression, Test file, Revocable by GitGuardian, etc.) ## Secret presence checks With the **presence check**, it is possible to verify the presence (and thus reachability) of every occurrence of the secret in your repositories. For each incident, GitGuardian will display the dates at which each occurrence was first and last seen and if it is still present in the repository. ![Occurrences visible in git](/img/internal-monitoring/remediate/incident-detail/presence_check_present.png) Once you have fully deleted the repository or rewritten the git history, return to your incident's page to obtain the secret's occurrence **proof of deletion** (see screenshot below). Once an occurrence is no longer visible in the git history, GitGuardian will stop checking for its presence. ![Occurrences no longer visible in git](/img/internal-monitoring/remediate/incident-detail/presence_check_removed.png) GitGuardian will regularly check for the presence of occurrences, to the best of its ability and considering existing VCS API rate limits, to mirror the state of your git repository. You can also manually run the **presence check** should you need to force update the status of the occurrences of an incident. The frequency of these automated checks depends on your plan and the status and age of secret incidents: | Plan | Incident status | Incident age | Frequency | | -------- | --------------- | -------------------- | ----------- | | Business | Open | Less than a year old | Daily | | Free | Open | Less than a year old | Weekly | | Business | Open | More than a year old | Weekly | | Free | Open | More than a year old | Monthly | | Business | Ignored | Less than a year old | Half-yearly | | Free | Ignored | Less than a year old | Never | | Business | Ignored | More than a year old | Never | | Free | Ignored | More than a year old | Never | | Business | Resolved | Less than a year old | Monthly | | Free | Resolved | Less than a year old | Half-yearly | | Business | Resolved | More than a year old | Half-yearly | | Free | Resolved | More than a year old | Never | > If you host GitGuardian on-premise, you can change these frequencies in your admin area. > **⚠️ Presence checks and orphan commits** > > When you delete a repository, all its commits are permanently deleted. However, using `git push --force` to remove a specific commit in a repository does not permanently delete it. It becomes an orphan commit, still existing but no longer referenced by any branch. It's impossible to see orphan commits in a pull request or in an existing branch unless you have access to the unique id (sha) of the commit. GitGuardian considers a secret's occurrence in an orphan commit as present. > VCSs provide garbage collection, completely emptying the bin of orphan commits. In the case of: > > - GitHub, contacting the support to run the garbage collection is necessary > - GitLab, the frequency of garbage collection is decided by the VCS admin > When you decide to unmonitor a repository, GitGuardian consequently loses access to that repository, which in turn prompts the presence check to lose its ability to update values with regards to its corresponding occurrences. GitGuardian will display an icon to indicate that the repository is no longer monitored. > > For incidents containing occurrences related to more than one repository, the presence check will continue to work for the rest of the occurrences linked to the monitored sources until the last monitored source gets removed from the perimeter. ## Public exposure information When a secret has been found in public locations, GitGuardian marks it with the **Publicly leaked** tag and provides detailed exposure information. Understanding the nature and scope of public exposure is important for effective remediation. ![Secret publicly leaked](/img/internal-monitoring/remediate/incidents/secret-publicly-leaked.png) ### Public exposure types GitGuardian categorizes public exposure into three types: #### Source is publicly visible This exposure type indicates that the incident has at least one occurrence in a monitored source that is publicly visible. **What this means:** - The secret was committed to a source that your organization integrated with GitGuardian Internal Monitoring - That source is publicly visible #### Has linked public incident The same secret also appears in one or more public incidents detected by [GitGuardian Public Monitoring](../../public-monitoring/home). **What this means:** The secret has been found in your company's [public perimeter](../../public-monitoring/perimeter/overview.md) (monitored developer activity or public repositories tracked by Public Monitoring) :::info All SaaS customers can see this exposure type; full details (linked incidents) require Public Monitoring subscription. In Public Monitoring, these incidents show the reciprocal **Internally leaked** tag ::: #### Found outside perimeter The secret has been found in public locations completely outside your company's monitored perimeter. **What this means:** - GitGuardian's HMSL (Has My Secret Leaked) capability detected the secret in public GitHub - The secret appears in repositories or locations not owned or monitored by your organization - This may indicate the secret was copied, shared, or leaked by external parties **Information provided:** For each place where the secret was found (up to 10), GitGuardian provides: - The type of place (GitHub repository) - A link to the original source **Automated check frequency:** GitGuardian regularly checks for new occurrences outside your perimeter. The frequency depends on your plan, incident status, and secret validity: | Plan | Incident status | Secret validity | Incident age | Frequency | | -------- | --------------- | --------------- | -------------------- | --------- | | Business | Opened | Not invalid | Less than a year old | Daily | | Business | Opened | Not invalid | More than a year old | Weekly | | Business | Resolved | Not invalid | Any | Monthly | | Business | Ignored | Not invalid | Any | Never | | Business | Opened | Invalid | Any | Never | | Business | Resolved | Invalid | Any | Never | | Business | Ignored | Invalid | Any | Never | :::note The "Found outside perimeter" check is not supported for **multi-match secrets**. Secrets detected outside your perimeter in more than 10 places are considered false positives (e.g., standard test credentials) and will not show this exposure type. ::: :::info For API users You may encounter two fields, `secret_hash` and `hmsl_hash`, when working with [secret incidents](https://api.gitguardian.com/docs#tag/Secret-Incidents/operation/list-incidents), for instance. - The `secret_hash` field is an internal identifier for each detected secret. - The `hmsl_hash` is associated with GitGuardian's [Has My Secret Leaked](https://www.gitguardian.com/hasmysecretleaked) service. GitGuardian uses the HMSL hashing algorithm to compare your secret—securely and privately—with secrets previously found on public GitHub. This allows GitGuardian to check if your secret has appeared publicly, without exposing the actual secret value. The same hash algorithm is also used with [ggscout](../../ggscout-docs/what-is-ggscout) to identify vaulted secrets. ::: ### Working with public exposure Use the default saved view **"Public exposure"** to focus on incidents that have been publicly exposed. This view shows only publicly leaked open incidents and includes the "Public exposure" column for quick visibility. You can also filter by the **Publicly leaked** tag or by specific exposure types, and add the **Public exposure** column to any custom view. Details for each exposure type are displayed in the side panel of the incident detail page. ![Incident with all three exposure types](/img/internal-monitoring/remediate/incidents/public-exposure-types.png) :::important Self-hosted installations For self-hosted installations, only the **Source publicly visible** exposure type is available. The **Public incident linked** and **Outside perimeter** exposure types are not available at all on self-hosted, as they require GitGuardian's Public Monitoring infrastructure. ::: ## Secret Manager integration insights Understanding your secret management landscape is crucial for effective remediation planning. GitGuardian's integration with Secret Managers through **[ggscout](/ggscout-docs/home)** provides valuable context during investigation. ### Vaulted secrets identification When investigating incidents, GitGuardian can identify if the exposed secret is already stored in one of your connected Secret Managers: - **Vaulted tag**: Incidents are automatically tagged when the secret is found in your Secret Manager. - **Storage location**: See which Secret Manager contains the secret and its path. This information helps you: - Increase confidence the incident is a true positive, when the associated secret is vaulted. This is particularly useful when GitGuardian cannot assess the validity of the secret. - Determine whether applications are using both hardcoded and vaulted versions. - Understand what which steps should be considered for the remediation. ### Push-to-vault readiness assessment During investigation, evaluate if the secret is ready for Secret Manager integration: - **Application architecture**: Can the affected applications retrieve secrets from your Secrets Managers? - **Access patterns**: How frequently is the secret accessed and by which services? - **Environment considerations**: Are there different secrets needed for dev/staging/prod? These questions should help you identify where the secrets should be moved to, in which secret manager instance and in which location? ### Secret Manager workflow implications Your investigation should consider how Secret Manager integration affects remediation: - **Existing infrastructure**: What Secret Manager setup is already in place? - **Access controls**: Who has permissions to manage secrets in your Secret Manager? - **Rotation capabilities**: Does your Secret Manager support automatic rotation for this secret type? - **Deployment dependencies**: How will applications be updated to use the Secret Manager? [Learn more about Secret Manager integrations](../integrate-sources/secrets-managers-integrations/overview.md) ## ML-powered similar incident grouping :::note VCS Sources Only ML-Powered Similar Incident Grouping is currently only available for incidents detected from Version Control Systems (VCS) sources. Non-VCS sources (such as messaging, ticketing, or documentation integrations) are not yet supported. ::: :::note ML-Powered Similar Incident Grouping is available for Business and Enterprise plans. ::: GitGuardian's ML-powered similar incident grouping helps you identify and manage related incidents more efficiently by automatically detecting incidents that share similar characteristics and context. ### How it works When viewing an incident detail page, you'll see a **Similar Incidents** section in the sidebar that displays incidents with similar patterns detected by our machine learning algorithms. This feature analyzes the code context in the patch to identify meaningful relationships between incidents. ### Common grouping scenarios The ML algorithm identifies various types of similar incidents: - **Rotating tokens in automated files**: Same file continuously leaking different tokens through automation - **QA test credentials**: Test keys (Slack bots, Postman API keys) appearing across similar contexts - **Database connection strings**: Multiple connection strings to the same environment with different credentials - **Repeated false positives**: High-entropy strings in logs or test scripts that are likely system-generated - **Templating code leaks**: Multiple developers using shared tutorials or templates with similar leaked secrets - **Known noisy patterns**: Consistent false positives from specific file types or internal services ### Using similar incidents for investigation 1. **From incident details**: View similar incidents in the sidebar and click on "View X similar incidents" to see them in the main incidents list 2. **Filter by similarity**: In the search box, use `similar_to` to show only incidents similar to a specific incident 3. **Sort by similarity count**: Use the "Similar incidents" column to sort incidents by highest or lowest number of similar incidents This feature is particularly useful for: - **Identifying false positives**: Spot patterns that indicate false positive incidents - **Consistent remediation**: Apply the same remediation approach to incidents that require similar fixes - **Understanding incident patterns**: Discover recurring issues in your codebase ![ML Similar Incident Grouping](/img/internal-monitoring/remediate/ml-similar-incident-grouping.png) Once you've identified similar incidents, you can use [bulk actions](./bulk-actions.md) to resolve, assign, or tag them together efficiently. :::note ML-Powered Similar Incident Grouping is available for Business and Enterprise plans. ::: GitGuardian's ML-powered similar incident grouping helps you identify and manage related incidents more efficiently by automatically detecting incidents that share similar characteristics and context. ### How it works When viewing an incident detail page, you'll see a **Similar Incidents** section in the sidebar that displays incidents with similar patterns detected by our machine learning algorithms. This feature analyzes the code context in the patch to identify meaningful relationships between incidents. ### Common grouping scenarios The ML algorithm identifies various types of similar incidents: - **Rotating tokens in automated files**: Same file continuously leaking different tokens through automation - **QA test credentials**: Test keys (Slack bots, Postman API keys) appearing across similar contexts - **Database connection strings**: Multiple connection strings to the same environment with different credentials - **Repeated false positives**: High-entropy strings in logs or test scripts that are likely system-generated - **Templating code leaks**: Multiple developers using shared tutorials or templates with similar leaked secrets - **Known noisy patterns**: Consistent false positives from specific file types or internal services ### Using similar incidents for investigation 1. **From incident details**: View similar incidents in the sidebar and click on "View X similar incidents" to see them in the main incidents list 2. **Filter by similarity**: In the search box, use `similar_to` to show only incidents similar to a specific incident 3. **Sort by similarity count**: Use the "Similar incidents" column to sort incidents by highest or lowest number of similar incidents This feature is particularly useful for: - **Identifying false positives**: Spot patterns that indicate false positive incidents - **Consistent remediation**: Apply the same remediation approach to incidents that require similar fixes - **Understanding incident patterns**: Discover recurring issues in your codebase ## Next steps: moving to remediation Once you've completed your investigation and understand the context of the secret exposure, you're ready to begin remediation. Your investigation should have helped you determine: - **What the secret accesses** - Which systems, services, or resources - **Privilege level** - Administrative, read-only, or limited scope access - **Dependencies** - What applications or services rely on this secret - **Exposure timeline** - When the secret was first exposed and for how long - **Public visibility** - Whether the secret is exposed publicly ### Choose your remediation approach Based on your investigation findings: - **For most internal incidents**: Follow a [real-time or historical workflow](./remediation-scenarios/overview.md) depending on when the secret was detected - **For high-risk secrets needing immediate action**: Use the [emergency response scenario](./remediation-scenarios/overview.md#scenario-1-emergency-response-public-exposure) - **For complex multi-team scenarios**: Consider the [bulk remediation approach](./remediation-scenarios/overview.md#scenario-4-bulk-remediation-post-historical-scan) - **For new detections with available developers**: Use the [real-time incident workflow](./remediation-scenarios/realtime-incidents.md) ### Ready to start remediation? - **[Remediation Overview](./remediation-overview.md)** - Understand GitGuardian's remediation philosophy and approach - **[Remediation Scenarios](./remediation-scenarios/overview.md)** - Comprehensive workflows for different situations - **[Platform Features](./remediate-incidents.md)** - GitGuardian tools for collaboration and automation > **Remember**: The time spent on thorough investigation will save you time and reduce risk during remediation. Don't rush into remediation without understanding the full impact. --- ## Prioritize incidents One of the key challenges of a secrets detection and remediation program is **prioritizing incidents and identifying where you should focus remediation efforts.** > Prioritization is the first step in your remediation journey. After prioritizing incidents, you will need to [investigate](./investigate-incidents.md) to gather context, then lastly [remediate](./remediation-overview.md) to address the most critical ones. GitGuardian focuses on the precision of its secrets detection engine (to raise the highest percentage of true positives). You can refer to our [dedicated documentation for the GitGuardian secrets detection engine](../../secrets-detection/home) for further information. That being said, the severity of a secret incident is still a notion that is hard to grasp from an external standpoint. That is why GitGuardian tries to give as much factual information as possible in order to help you categorize the severity of the secret incident. ## 1. Prioritize with the incidents table You can find a table of all your incidents in the Incident section. Our aim is to help you navigate this table in the most efficient way possible. ### Using saved views Prioritizing incidents efficiently is crucial for effective remediation. The [Saved views](../../platform/collaboration-and-sharing/saved-views.md) feature allows you to quickly access and manage your preferred filter sets, focusing on the most important incidents without repeatedly adjusting filters. Some views are pre-set by GitGuardian, providing a starting point for effective incident management: - **Open**: View all incidents that are currently open and require attention. - **Critical**: Focus on open incidents with a risk score above 80/100, highlighting the highest-priority incidents to address first. - **My open incidents**: Display incidents assigned to the current user, allowing for personalized incident management. - **Closed but valid**: Review incidents that have been resolved or ignored while the secret is still marked as valid. Users can also create their own custom views to fit their specific remediation processes. ### Most recent incidents By default, the table of incidents is sorted by "most recent" incidents. As a matter of fact, **secrets that were detected most recently have the highest probability of being valid and thus harmful**. The date of an incident is the date of its first occurrence. It is especially important to note here that **GitGuardian creates secrets incidents during historical scans**. The date of those incidents is the date of the commit where the secret exposure happened, not the date of the historical scan. Such incidents will be marked with the "From historical scan" tag. Therefore, you can end up with very old incidents as you run GitGuardian on your git history. That is why, we allow you to modify the time frame of the listed incidents and set it to **All time**. By default, this time frame is set to Last Month. ### Secret preview You can **quickly preview the actual secret from the incidents table** with a simple hover. If you would like to further investigate, you can click on the secret incident and visit its dedicated page. Be cautious: **sometimes the broader context of a secret can be much more harmful than the secret itself**. We always recommend going beyond the secret preview and conducting an in-depth investigation before making a decision on a particular incident. ![secret preview](/img/internal-monitoring/remediate/incidents/secret_preview.png) ### Secret validity The table of incidents indicates for each incident if the exposed secret is still valid or not. You can also filter your incidents to view valid secrets only. This can help you prioritize your incidents and focus on secrets that can still be exploited. We recommend you take care of exposed and valid credentials as soon as possible, since they represent a higher risk of exploitation. ![Secret validity preview and filter](/img/internal-monitoring/remediate/incidents/secret_validity_filter.png) For more details on this feature, please refer to the dedicated section on [validity checkers](../../secrets-detection/customize-detection/validity-checks). ### Occurrences count and presence in git history The table of incidents also indicates the number of occurrences for each incident. **The severity of an incident should not be determined simply by its number of occurrences**. This informs you about the potential sprawl of the secret but keep in mind that a secret that is present in more than one place is often not a harmful secret. The total count is split between the occurrences of the incident present in your git repository and the ones that have been rendered non-existent (following the deletion of a repository or rewriting of the git history). ![Occurrences count and breakdown](/img/internal-monitoring/remediate/incidents/occurrence_count.png) Removing any trace of the secret in your git repositories may be one of your requirements for full incident remediation. If that is the case, it is possible to filter your incidents to only view the ones for which at least one occurrence is still present or in other words, the ones for which remediation is incomplete. ![Incident presence filter](/img/internal-monitoring/remediate/incidents/occurrence_presence_filter.png) ### GitGuardian Tags For each incident, we try to give you as much contextual information as possible. **GitGuardian tags are meant to help you quickly evaluate each incident**. In the incidents table, you will see all the tags associated with occurrences of an incident. The different tags are: - **Default branch**: at least one occurrence of the incident is found in the default branch of a repository. - **Publicly leaked**: the secret has been found in one or more public locations. This tag indicates public exposure and should be prioritized for remediation. See [Public exposure information](#public-exposure-information) for details on the types of exposure. - **From historical scan**: one of the occurrences of the incident was detected thanks to a historical scan, as opposed to being detected in real-time. - **Regression**: the incident was once resolved but GitGuardian detected a new occurrence. - **Sensitive file**: one of the occurrences of the incident happened on a potential sensitive file. - **Tagged as false positive in check runs**: one of the occurrences of the incident has been tagged as a false positive in GitHub by one of your developers. - **Test file**: one of the occurrences of the incident happened on a potential test file. A file is automatically classified as a test file if its path contains any of the following patterns (with only numbers or special characters around them): `test`/`tests`, `example`/`examples`, `mock`/`mocks`, `fixture`/`fixtures`, `fake`, `dummy`, `false`, or `testdata`. For example, `.test.env` or `00testdata.json` will match, but `dummydata.json` will not. - **Vaulted**: the secret is stored in one of your Secret Managers, increasing confidence it is a true positive. - **Revocable by GitGuardian**: the secret can be revoked directly from the GitGuardian dashboard. [Learn more about revocation](/internal-monitoring/remediate/remediate-incidents#secret-revocation-from-gitguardian). :::info About the **Default branch** tag. After this feature is activated on your workspace, the tag will be automatically applied to future incidents. For incidents raised by GitGuardian before July 2023, or repositories where the default branch has been modified at the VCS level, a full scan of your repositories needs to be re-run. Please visit the [perimeter](https://dashboard.gitguardian.com/perimeter) page to run a historical scan. ::: ![Tags](/img/internal-monitoring/remediate/incidents/tags.png) ### Public exposure information When a secret has the **Publicly leaked** tag, GitGuardian provides additional details through the **Public exposure** property. There are three types of public exposure: - **Source is publicly visible**: The incident has at least one occurrence in a monitored source that is publicly visible. This information is available to all Internal Monitoring users. - **Has linked public incident**: The secret also appears in one or more public incidents from your company's public perimeter. Seeing full details about the public incidents requires a Public Monitoring subscription. - **Found outside perimeter**: The secret has been found in public locations unrelated to your company (outside of your Internal or Public perimeters). You can filter incidents by exposure type to focus your remediation efforts. For more detailed information about each exposure type, see the [Public exposure information](./investigate-incidents.md#public-exposure-information) section. :::note Self-hosted installations For self-hosted installations, only the "Source is publicly visible" exposure type is available. ::: ### Severity #### Manual severity assignment To help you prioritize incidents during triage, you can set a severity for each incident. You can define the severity of an incident either in its dedicated remediation page, or directly from the table of incidents. The different severity levels are: - **Critical**: concerns a critical service. **Must be tackled as quickly as possible.** - **High**: concerns an important service with a potentially broad impact. - **Medium**: concerns an important service with a potentially limited impact. - **Low**: concerns a minor service with a potentially broad impact. - **Info**: concerns a minor service with a potentially limited impact. - **Unknown**: default level applied by GitGuardian to new incidents. ![Severity](/img/internal-monitoring/remediate/incidents/severity.png) #### Automated severity scoring :::info Only Managers and Owner can activate this feature. ::: Manual severity assignment requires a case-by-case examination of your open incidents and can be time-consuming for your teams. GitGuardian's severity scoring feature automates this approach, where and when applicable, to the incidents in your workspace so that you can save time on their triaging and prioritization. :::tip Automated severity scoring comes in handy after running a historical scan on your perimeter that surfaces hundreds or thousands of incidents. It can help you focus your remediation efforts on the most critical incidents first! ::: To activate the automated severity scoring feature, go to the [Severity rules pages in the Secrets section of your GitGuardian workspace settings](https://dashboard.gitguardian.com/settings/secrets/severity-rules). You can see the coverage of the automated severity scoring engine. GitGuardian computes this by dividing the total number of incidents for which it has automatically assigned a severity by the total number of open incidents in your workspace. ![automated-severity-toggle](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-settings.png) GitGuardian determines the severity of each incident by following a predefined ruleset that can be customized. The rules are evaluated sequentially for each incident from the first to the last. The severity assigned will be that of the first rule whose conditions are met. In case of multiple occurrences for an incident, the rules engine will evaluate all of them and assign the highest severity among them. You can inspect this ruleset in the [Severity rules page of the Secrets section of your settings](https://dashboard.gitguardian.com/settings/secrets/severity-rules). ![automated-severity-ruleset](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-ruleset.png) Each rule of the ruleset is composed of the following: - A **name** identifying the rule - A **description** of the rule - A **severity** to be assigned automatically in case of a match - A **set of conditions** defining the rule - The **total number of incidents** for which the rule has set the severity As a Manager or Owner of the workspace, you can customize this ruleset by clicking on the **Edit ruleset** button. This allows you to maximize the coverage of automatically scored incidents by defining a ruleset related to your own context. ![automated-severity-ruleset-edit](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-ruleset-edit.png) :::info The default ruleset designed by GitGuardian can benefit from regular updates. Once customized, the ruleset will not benefit from these updates as you become the manager of these rules. ::: Once entered the edit mode of the ruleset, you can: - **Add a new rule** by clicking on the `New rule` button _(up to 20 rules)_ - **Edit a rule** by clicking on the pen icon of the rule - **Delete a rule** by clicking on the bin icon of the rule _(You can't empty your entire ruleset)_ - **Reorder rules** by dragging them in relation to each other ![automated-severity-rule-edits](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-rule-edits.png) Creating or editing a rule allows you to define the: - **Name** identifying the rule - **Description** of the rule _(optional)_ - **Set of conditions** defining the rule _(up to 20 conditions)_ - **Severity** to be assigned automatically in case of a match ![automated-severity-rule-edition](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-rule-edition.gif) Once you have customized your ruleset, don't forget to save it by clicking on the `Save changes` button. This will result in a new scoring of your open incidents based on your fresh new ruleset. The scoring time depends on the number of your secret incidents and occurrences. If you wish, you can always reset to the default ruleset defined by GitGuardian by selecting the `Reset to default` option in the `...` menu. This will allow you to benefit from GitGuardian's ruleset updates again. You can also manually recompute your severity scoring by selecting the `Recompute severity scoring` option. ![automated-severity-ruleset-reset](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-ruleset-options.png) In the incidents table view, hovering over the severity badge of an incident will display a tooltip indicating whether it was set manually or automatically. In the latter case, the rule that matched will also be indicated. You can always override the automated severity set by GitGuardian by selecting a severity of your choice. ![automated-severity-tooltip](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-tooltip.png) On the details page of a critical or high incident, you will find a banner indicating the automated severity score and its corresponding rule. ![automated-severity-banner](/img/internal-monitoring/remediate/automated-severity-scoring/automated-severity-banner.png) In case GitGuardian cannot determine the severity of the incident, it will also inform you in the same banner, and you can assign one directly from there – using the dropdown menu. ### Risk score (ML-powered prioritization) :::info Business feature Only workspaces with a Business plan can access risk score. ::: The risk score is an ML-powered feature that automatically assesses the risk level of each incident on a scale of 0-100, where **100 indicates the highest risk** requiring immediate attention and **0 indicates the lowest risk**. It provides an additional layer of prioritization by analyzing multiple risk signals to help you focus on the incidents that pose the greatest threat. The risk score complements severity scoring by providing a more granular, continuously updated risk assessment. #### How it works The risk score is calculated using machine learning models that consider various factors including: - Secret type - Validity (past or present) - Detection context (test files, sensitive files, production environment, etc.) - Secret exposure patterns - Additional contextual signals The score is dynamic and recalculates regularly to reflect changes in the incident's risk profile. #### Using risk score in your workflow :::tip We value your feedback The risk score uses machine learning models that are continuously improved based on user feedback. If you notice incidents with unexpected scores or explanations, we encourage you to share feedback directly through the dashboard — your input helps us refine the scoring model. ::: ##### In the incidents table The risk score can be used to prioritize incidents in multiple ways: **Filtering and sorting**: - **Filter by risk score range**: Use the "Risk score" filter to focus on specific risk levels (e.g., Risk score ≥ 80 for highest priority) - **Sort by risk score**: Select "Sort by Risk score" to order incidents by priority - **Use the "Critical" saved view**: This pre-configured view displays all open incidents with a risk score above 80/100, giving you quick access to the highest-priority incidents **Adding the Risk score column**: By default, the risk score column is not displayed in the incidents table. To view the actual score values: 1. Click the **Columns** button in the top-right of the incidents table 2. Find "Risk score" in the list of available columns 3. Click the eye icon to make it visible 4. The column will now appear in your table, showing the 0-100 score for each incident ![Risk score column configuration](/img/internal-monitoring/remediate/incidents/risk-score-column.png) ##### "Critical" saved view The **"Critical"** saved view is pre-configured to display all open incidents with a risk score above 80/100. This view helps you immediately focus on the incidents that require the most urgent attention. ![Critical saved view](/img/internal-monitoring/remediate/incidents/critical-saved-view.png) :::tip Customize your threshold You can duplicate the "Critical" saved view and adjust the risk score threshold to match your workflow. For example: - Set a higher threshold (e.g., 90/100) to focus on fewer, extremely high-risk incidents - Set a lower threshold (e.g., 70/100) to capture a broader set of incidents for review This flexibility allows you to control the volume of incidents you want to prioritize based on your team's capacity and risk tolerance. ::: ##### In the incident detail page When investigating an incident, you'll find the risk score at the top of the incident detail page showing: - **The current risk score** (0-100) with a visual indicator - **A detailed explanation** of what drives the score, based on the incident's context and characteristics, so you know what to prioritize. - **Feedback buttons** to help us improve the feature (thumbs up/down) ![Risk score in incident detail page](/img/internal-monitoring/remediate/incident-detail/risk-score-explanation-internal-incident.png) **Score evolution:** The risk score is dynamic and recalculates regularly as the incident context evolves. Changes in detection context, exposure patterns, or other risk signals may cause the score to adjust over time. Additionally, our ML model is continuously improved, which may lead to score refinements. **Providing feedback:** Your feedback helps us continuously improve the ML model. In the incident detail page, you can: 1. Review the risk score and its explanation 2. Use the thumbs up button if the score accurately reflects the risk, or the thumbs down button if the score doesn't match your assessment 3. Expand/collapse the explanation using the arrow button Feedback is reviewed by our team to regularly refine the scoring algorithm. #### Risk score vs. Severity Both tools help with prioritization but serve different purposes: | Feature | Risk Score | Severity | |---------|-----------|----------| | Calculation | ML-powered, automatic | Rule-based, can be manual | | Granularity | 0-100 scale | 6 levels (Critical to Unknown) | | Updates | Dynamic, recalculates automatically | Static unless manually changed or rules recomputed | | Best for | Granular risk assessment | Policy-based categorization | ## 2. Explore with the incident page Each incident has a dedicated page in which you can find additional information to help you investigate. ### Secret overview The secret overview provides all the details related to the secret itself and main information: - the type of secret along with the detector information. - the [secret validity](./prioritize-incidents#secret-validity) if available. - the secret values depending on the detector (e.g. client_id, client_secret, etc...). - the [secret analyzer](../../secrets-detection/secrets-detection-engine/secrets_analyzer) if available. - the secret scopes if the above secret analyzer is available and the analysis succeeds. It enables you to perform an initial diagnosis on how critical this incident may be. ### Secret Manager presence GitGuardian integrates with Secret Managers through **[ggscout](/ggscout-docs/home)**, enabling you to synchronize secrets incidents with secrets stored in your Secret Managers. This integration allows you to track whether a specific secret is stored in one or more Secret Managers, providing additional insights such as the secret's path, lease time, and any custom metadata associated with it. ![Duplicated Secrets](/img/internal-monitoring/integrate-sources/secrets-managers-integrations/duplicated-secrets.png) Quickly identifying the location of secrets within your Secret Manager helps save time for you and your developers, while accelerating the remediation process. It can also assist in identifying poor Secret Management practices, such as the presence of duplicated secrets. **[Discover more use cases](/internal-monitoring/integrate-sources/secrets-managers-integrations/overview.md)** that you can benefit from Secrets Managers integrations. ### Impacted perimeter The Impacted Perimeter feature addresses the critical need for comprehensive secret management in modern software development. It provides a quick overview and detailed breakdown of secret occurrences across your codebase and other data sources, enabling teams to rapidly assess vulnerabilities and prioritize remediation efforts. By tracking the status of secrets from detection through remediation, this feature enhances security awareness, streamlines the fix process, and supports compliance efforts. The **Impacted perimeter** is divided in two sections to get either a quick or detailed view of the impact of the incident on your perimeter. **Secret presence** helps you get a glimpse of the incident status across your perimeter by showing the following metrics: - **requiring code fix** which counts the number of *files containing at least one mention of the secret in the last commit of the default branch* - the number of occurrences present **overall** or in **other data sources** The **Vulnerable sources** part lists in details the occurrences of the secret for each impacted source, either requiring code fix or not. N.B. non-monitored and deleted sources are also included. ![Impacted perimeter](/img/internal-monitoring/remediate/incident-detail/impacted_perimeter.jpg) #### Occurrences requiring code fix Occurrences requiring code fix matter particularly as they are *present in the current state of the code when browsing the VCS or when cloning the repository*. It is the current state of the repository that is monitored here. It is possible to change the default branch monitored by updating the default branch directly in the VCS. Therefore, vulnerable files are listed on top in the **files requiring code fix** section, with a link to the file in the VCS. As it is important to fix them as a priority, the **files pending merge** section keeps track of the code fixing. To do so we monitor the pull requests of the source and check if they are about to remediate an incident (i.e. remove at least one mention of the secret), and if so list them and the associated files. Once merged, the pull request is listed next to the files fixed in the **files fixed** section. The pull request names can be clicked to view them in more details on the VCS website. Feature limitations: - *The number of files in the PR is limited to 200 for GitHub* to avoid making too many API calls; above that limit the feature won't work properly. - Currently, the feature *only works for GitHub and GitLab*. #### All occurrences The table of occurrences provides you with the following detailed information: - when the occurrence happened - who is the developer responsible for the leak (git name, git email) - where the occurrence took place (commit, file) - when the occurrence was last seen by GitGuardian and if it still visible in your git history - the tags associated with the occurrence For the needs of conducting further investigation, each occurrence has its own menu, with a link to the actual place of the secret occurrence on the VCS, if still present. ![Occurrence log](/img/internal-monitoring/remediate/incident-detail/occurrence_log.jpg) #### Patch For each occurrence of a given secret incident, you have access to **the patch of the commit where the secret has been detected**. The patch is composed of: - the lines of code added by the commit - the lines of code deleted by the commit - the contextual lines surrounding the added or deleted lines. These lines are also monitored by GitGuardian since they are part of the commit. A secret can consist of several components. For example, an AWS secret is the combination of `client_id` and `client_secret`. You can easily navigate and understand these multiple secret components with the patch in your GitGuardian workspace. ![Patch](/img/internal-monitoring/remediate/incident-detail/patch.jpg) N.B. In the screenshot the secret is obfuscated because the [privacy mode](/platform/security-data-privacy/privacy-mode) is enabled From our experience, **lots of valuable information can be found around the patch of a secret** (other secrets, sensitive data, ...). ## 3. Explore generic incidents (Generic Secret Enricher ML model) After detecting a generic incident, the platform analyzes the entire context of the document to identify the associated provider or category of the secret. **When successful, the enriched secret name automatically replaces the generic detector name** throughout the platform, transforming vague findings like "Generic Database Assignment" into precise, actionable names like "Redis Identifiers" or "PostgreSQL Connection String." This functionality is powered by "Secret Enricher", a specialized machine learning model designed for contextual secret analysis. The enriched names provide immediate context, allowing you to quickly understand what type of secret was exposed without opening each incident. ### How to use it ? #### Enriched names in incident lists Enriched secret names appear automatically in your incident lists—no configuration needed. When the ML model successfully identifies a secret type, you'll see precise names like: - **Redis Identifiers** instead of "Generic Database Assignment" - **Stripe API Key** instead of "Generic High Entropy Secret" - **AWS Access Key** instead of "Generic High Entropy Secret" - **PostgreSQL Connection String** instead of "Generic Database Assignment" This makes incident triage faster and more intuitive, giving you immediate context about what was exposed. #### Customize your views From the incidents list, you can customize how your incidents are displayed by clicking on the "Columns" button in the top-right corner of the table. ![GSE-columns](/img/internal-monitoring/remediate/incidents/customize_columns.png) This allows you to add the "Secret category" and "Secret provider" columns, which display additional enrichment properties alongside the enriched secret name. With this customization, you can quickly spot important categories (such as "Data Storage") or specific providers that might require immediate attention. ![GSE-columns](/img/internal-monitoring/remediate/incidents/gse_predictions.png) #### Filter your data Three filters (Provider, Category, Family) help you identify the most significant or critical incidents, such as those classified under "Data Storage" or linked to the provider "PostgreSQL." You can apply these filters to all enriched incidents or combine them with the "Generic" type filter for focused analysis. ![GSE-filters](/img/secrets-detection/machine-learning/gse-howto.png) With these new filters you can explore your generic incidents and unveil the one that matters for your operations. :::tip Learn More About Categories and Providers For detailed definitions of all GSE categories and providers, including what they mean and how to prioritize them, see our comprehensive [GSE Categories and Providers Reference](../../secrets-detection/secrets-detection-engine/gse-categories-providers-reference). ::: ### FAQ #### Why Aren't These Transformed into Specific Incidents? The analysis might be incomplete. We may only be able to identify the Provider or the Category (or potentially neither). As we continue to refine this feature, our definitions will become more precise. #### What is the model trained to discover? For detailed information about the categories and providers the model can identify, see the [Machine Learning documentation](../../secrets-detection/secrets-detection-engine/machine_learning#what-is-the-model-trained-to-discover) in the Secrets Detection section. ## Next steps: from prioritization to investigation Once you've identified and prioritized your most important incidents, you're ready to investigate them for proper remediation planning. ### What you should have after prioritization - **A focused list** of incidents to work on first (high severity, valid secrets, critical systems, etc...) - **Context about urgency:** which incidents have public exposure or elevated privileges. ### Ready to investigate? Move to the [Investigation phase](./investigate-incidents.md) to: - Understand what each secret accesses - Assess the impact of potential revocation - Gather context needed for safe remediation - Identify dependencies and affected systems > **Pro Tip**: Even urgent incidents benefit from a few minutes of investigation to avoid breaking systems during remediation. Use the investigation phase to make informed decisions about your remediation approach. --- ## Remediate incidents This guide covers GitGuardian's platform features that support your remediation efforts, including collaboration tools, automation capabilities, and integrated secret management. > **New to remediation?** Start with our [Remediation Overview](./remediation-overview.md) to understand GitGuardian's approach, then choose the appropriate [Remediation Scenario](./remediation-scenarios/overview.md) for your situation. ## Collaborating with developers Involving developers is crucial for the remediation. Developers also have knowledge about the secret itself, since they are the ones who used it. They also understand the system's architecture and the services that may depend on the secret. They can provide insight into affected services and the best way to mitigate issues. This knowledge is essential in creating an effective and efficient remediation plan. GitGuardian's goal is to enable easy collaboration with your developers by providing flexible ways to share your incidents. ### Share the incident You can collaborate by sharing the incident in two ways: - Internally, with users registered on the dashboard, via the "Grant access" action. This option is only available for Business workspaces. - Externally, with non-registered users, via the "Public sharing" action. :::info When you share an incident, the **entire incident with all its occurrences** is shared, not just individual occurrences. This provides complete context for effective remediation collaboration. ::: ![share button](/img/platform/collaboration-and-sharing/share-button.png) More details are available in our dedicated [Collaboration and sharing section](../../platform/collaboration-and-sharing/incident-permissions-and-sharing.md). ### Collect the feedback The feedback form enables you to collect standardized feedback about an incident. To fill out the form, registered users require the "Can edit" incident permission. They can also edit or delete their own feedback. ![Feedback form](/img/internal-monitoring/remediate/incident-detail/feedback-form.png) Whenever feedback is submitted for an incident, whether by a registered user or a non-registered user, an email notification is sent: - to the incident assignee, if applicable. - to all users with access to the incident, if there is no assignee. Every action taken by the developer will be logged in the incident details timeline. > The feedback form is not customizable yet. ### Mention members and teams In incident notes and feedback, you can mention a member or a team to notify the right people directly. Type `@`, then pick a member or team from the searchable list. The list only suggests members and teams that already have access to the incident. - **Member mention** (`@name`): the mentioned member receives an email notification linking straight to the incident. - **Team mention** (`@team-name`): every member of the team receives the notification. Mentions respect existing permissions: the picker only lists members and teams with access, and a mentioned person is only notified for incidents they can access. Recipients can manage these emails from their [notification settings](../../platform/user-account/email-preferences.md) under **Workspace**. ## Workflow customization GitGuardian displays a default remediation workflow on each incident's details page to guide remediation efforts. Organizations can customize this workflow to match their specific policies and procedures. ![GitGuardian Remediation section](/img/internal-monitoring/remediate/incident-detail/remediation-section.png) ### Customizing workflows Workspace Managers can customize remediation workflows in the [Secrets detection settings](https://dashboard.gitguardian.com/settings/secrets/general): - **Create custom workflows** - Define up to 20 custom steps with titles, descriptions, and links - **Switch between workflows** - Choose between default GitGuardian workflow and custom versions - **Edit existing workflows** - Add, modify, delete, or reorder steps as needed - **Apply organization-wide** - Custom workflows appear on all incident pages and shared incidents This customization helps ensure remediation follows your organization's established security procedures and compliance requirements. ### Custom messages when using GitGuardian CLI (ggshield) When GitGuardian CLI detects secrets in developers' code, whether in pre-commit or other stages, it is highly beneficial to provide them with clear instructions on using secrets in their code according to company standards (Vaults, Environment variables, ..). Security teams have the ability to customize these messages, which will be disseminated through the CLI at different stages of the Software Development Life Cycle such as pre-commit, pre-push, and pre-receive. [Learn more here](../../ggshield-docs/reference/secret/custom-remediation-messages.md) ## Secret Manager integration GitGuardian integrates with Secret Managers through **[ggscout](/ggscout-docs/home)** to streamline the remediation process: ### Key capabilities - **Push-to-vault** - Move exposed secrets directly to your Secret Manager from the GitGuardian dashboard - **Secret identification** - Automatically tag incidents when secrets are already vaulted - **Remediation tracking** - Monitor progress from detection through secure storage implementation ### Supported integrations GitGuardian works with major Secret Manager platforms to provide seamless remediation workflows. The integration helps identify which secrets need to be moved to secure storage and facilitates the transition process. **[Learn more about Secret Manager integrations](/internal-monitoring/integrate-sources/secrets-managers-integrations/overview.md)** ## Secret revocation from GitGuardian GitGuardian's integrated secret revocation feature enables you to revoke valid secrets directly from the platform for supported providers, drastically reducing the time secrets remain exposed and accelerating your incident response workflows. This feature eliminates the need to switch between multiple tools and platforms during remediation, providing a streamlined path from detection to resolution. :::success Pre-requisites - The secret shall have a **Valid** status. - You shall have `Full Access` permissions on the incident. - The secret revocation is supported by the provider. ::: ### Supported providers Secret revocation is currently available for the following providers: - **GitHub** personal access tokens and fine-grained tokens. - **GitLab** personal access tokens. - **OpenAI** API keys. - **SendGrid** API keys. - **Slack** user tokens and Slackbot tokens. - **Heroku** platform keys. :::info GitGuardian actively advocates with service providers to adopt programmatic revocation capabilities and implement standardized revocation endpoints, making secret management more secure across the ecosystem. Additional providers are being added regularly. Check back for updates or contact support to request specific provider support. ::: ### Enabling secret revocation The secret revocation feature can be toggled on or off in your workspace settings: 1. Navigate to [**Settings > Secrets > General**](https://dashboard.gitguardian.com/settings/secrets/general). 2. Locate the **Secret Revocation** toggle. 3. Toggle the feature on or off as needed. :::info Workspace Managers and Owners can control this setting. When disabled, the revoke button will not appear on incident details pages. ::: ### Filtering for revocable incidents Focus your team's efforts on these high-impact, actionable incidents that can be immediately revoked: 1. Navigate to your incidents list. 2. Filter secrets `Valid` secrets using `Secret Validity`. 3. Filter revocable secrets using `Revocable by GitGuardian` GitGuardian tag. ![Filter Revocable Secrets](/img/internal-monitoring/remediate/revoking-secrets/filtering-revocable-secrets.png) ### Revoking a secret :::warning Assess Revocation Impact Revoking a secret may have dramatic side effects on your systems, applications, or workflows. Therefore, you should always consider checking what the revocation will impact before proceeding. GitGuardian provides you with a lot of context and insights to [assess the impact of the exposure](/internal-monitoring/remediate/investigate-incidents), but more importantly, [measure the impact of the revocation](/nhi-governance/discover-your-nhis#exploration-map), thanks to the identification of the workloads using these credentials. ::: To revoke a secret directly from GitGuardian: 1. **Navigate to the incident**: Open the incident details page for the secret you want to revoke. 2. **Locate the revoke button**: Find the **Revoke** button in the secret details right-panel section. ![Revoke Secret](/img/internal-monitoring/remediate/revoking-secrets/revoke-action.png) 3. **Initiate revocation**: Click **Revoke** to open the confirmation dialog. 4. **Confirm the action**: Confirm the revocation by inserting `revoke` in the modal dialog. ![Confirm Revoke Secret](/img/internal-monitoring/remediate/revoking-secrets/confirm-revocation.png) 5. **Monitor the timeline**: The revocation action will be automatically logged in the incident timeline. ### After revocation Once a secret is revoked, GitGuardian automatically re-runs the validity checker. If successful: - The secret status changes from `Valid` to `Invalid`. - The linked incident status changes to `Resolved` assuming Playbook [Automatically resolves incidents when valid secrets are revoked](../../platform/automate-with-playbooks/available-playbooks.md#auto-resolve-revoked-secrets) is enabled. All revocation activities are logged in the incident timeline for audit and compliance purposes. :::info Provider limitations Most revocation APIs do not explicitly confirm successful revocation. GitGuardian relies on subsequent validity checks to determine if the revocation was successful. ::: ## Automate remediation with playbooks GitGuardian playbooks can automate many remediation tasks for internal incidents, reducing manual work and accelerating response times. Learn more about [configuring playbooks](../../platform/automate-with-playbooks/playbooks-overview.md) for your workspace. The playbooks relevant to Internal Monitoring are: - Auto-share incident access to the author of the leak (link by email) - Auto-grant incident access to author of the leak (in-app) - Auto-resolve incident when valid secret is revoked - Auto-ignore incidents when secrets are tagged as false positive - Auto-ignore incidents when secrets are marked as invalid See the complete detail of [available playbooks](../../platform/automate-with-playbooks/available-playbooks.md). --- ## Secret Remediation Overview ## The GitGuardian Remediation Philosophy At GitGuardian, we believe effective secret remediation requires a balanced approach that prioritizes security while maintaining operational continuity. Our philosophy centers on **informed decision-making** rather than panic-driven responses. ### Core Principles 1. **Assess before Acting** - Understand the full impact of a secret exposure before taking remediation steps 2. **Maintain Operations** - Ensure your systems remain functional throughout the remediation process 3. **Leverage Platform Insights** - Use GitGuardian's investigation tools and NHI governance data to make informed decisions 4. **Collaborate Effectively** - Involve the right stakeholders at the right time for efficient remediation ## Understanding Remediation Context ### Internal vs. External Incidents **Internal incidents** occur within your monitored repositories and typically allow for more controlled remediation: - You have full control over the codebase and deployment process - You can coordinate with development teams for planned updates - You can leverage Secrets Manager integrations for seamless transitions **External incidents** (like public GitHub leaks) require faster response: - The secret is potentially visible to attackers immediately - Limited control over all copies of the exposed secret - May require emergency revocation procedures ### Impact Assessment Framework Before beginning remediation, evaluate: - **Scope of Access**: What resources does this secret protect? - **Privilege Level**: Can this secret access sensitive data or critical systems? - **Usage Patterns**: How frequently is this secret used? By which services? - **Blast Radius**: What would happen if we revoke this secret immediately? GitGuardian provides insights through: - [Incident investigation tools](./investigate-incidents.md) - [NHI governance mapping](/nhi-governance/discover-your-nhis#exploration-map) - Historical usage patterns and context ## The GitGuardian Remediation Approach Our recommended methodology follows a **secure-first approach** that ensures operational continuity while implementing proper secret management: ### 1. Assess before acting - Review the secret's scope and privileges - Identify dependent systems and services - Understand potential operational impact of revocation ### 2. Secure Storage - Store the secret properly in a secret manager or secure vault - Use GitGuardian's [push-to-vault feature](#secrets-manager-integrations) when available - Ensure proper access controls and rotation policies ### 3. Update Code - Modify applications to retrieve secrets from secure storage - Update deployment configurations and environment variables - Implement proper secret management practices ### 4. Test & Deploy - Perform thorough non-regression testing - Deploy changes to production environments - Monitor applications to ensure proper functionality ### 5. Rotate & Revoke - Generate new credentials through the appropriate service - Update the new credentials in your secret manager - Revoke the compromised secret to prevent unauthorized access ### 6. Monitor & Verify - Check access logs for signs of unauthorized usage - Verify that all dependent systems are functioning properly - Document the incident and lessons learned ## Platform Capabilities for Remediation ### Secrets Manager Integrations GitGuardian integrates with popular secret managers through **[ggscout](/ggscout-docs/home)**: - **Push-to-vault**: Seamlessly move exposed secrets to secure storage - **Synchronization**: Keep track of secrets across multiple managers - **Automated workflows**: Streamline the secure storage process [Learn more about Secrets Manager integrations](../integrate-sources/secrets-managers-integrations/overview.md) ### Revocation Features For supported secret types, GitGuardian can help with: - **Automated revocation**: Direct integration with service providers - **Guided revocation**: Step-by-step instructions for manual processes - **Revocation verification**: Confirmation that credentials have been properly disabled ### Collaboration Tools Effective remediation often requires team coordination: - **Incident sharing**: Grant access to relevant stakeholders - **Feedback collection**: Gather input from developers and security teams - **Assignment and tracking**: Ensure accountability and progress monitoring [Learn more about collaboration features](../../platform/collaboration-and-sharing/incident-permissions-and-sharing.md) ## Choosing Your Remediation Approach Different situations require different approaches. The key is matching your response to the specific circumstances: ### By incident type - **Real-time incidents**: Engage with developers while context is fresh - **Historical incidents**: Systematic investigation and prioritization required - **Public exposures**: Balance urgency with proper assessment - **Bulk remediation**: Coordinate across teams with structured processes ### By risk level - **Critical secrets**: May require emergency response procedures - **Standard secrets**: Follow the secure-first approach - **Low-risk secrets**: Can often be handled through standard processes ### By organizational context - **Single team**: Direct developer engagement possible - **Multiple teams**: Coordination and communication essential - **Large scale**: Structured processes and automation needed ## Next Steps Ready to start remediating? Choose the guide that fits your situation: - **[Remediation Scenarios](./remediation-scenarios/overview.md)** - Comprehensive workflows for different situations - **[Investigation Guide](./investigate-incidents.md)** - Thorough assessment techniques - **[Platform Features](./remediate-incidents.md)** - GitGuardian tools for collaboration and automation - **[Prioritization Guide](./prioritize-incidents.md)** - Focus on the most important incidents first > **Remember**: Effective remediation is about making informed decisions, not just moving quickly. Take the time to understand the impact and choose the right approach for your specific situation. --- ## Historical incidents ## Before you start Incidents are not all created equal. Before diving headfirst into remediating hundreds or thousands of your historical incidents, we suggest you set a few rules to prioritize them first. Here are some elements to consider before deciding on the severity of an incident and the priority it should get: | **Criteria** | **Example question** | | ------------------ | ------------------------------------------------------------------- | | **Type** | Are these Kubernetes cluster credentials or Slack webhook URLs? | | **Validity** | Can this secret still be exploited? | | **Presence** | Is it still in the git history? | | **Leak status** | Has my secret leaked outside my organization's perimeter? | | **Exposure** | Is this secret exposed on a public repository my organization owns? | | **Recency** | Is this secret from last quarter or from 5 years ago? | | **Occurrences** | Has this secret been exposed in multiple files and repositories? | | **Test directory** | Is this secret used for testing purposes? | | **Secret Manager** | Is this secret stored in one or several Secret Managers? | In the GitGuardian Internal Monitoring incidents table, make sure you use the searching, filtering, and sorting features to their maximum. ## Tackling historical incidents ### Step 1. Identify your active developers Export all historical incidents from your GitGuardian dashboard: Filter your incidents using the Tags field with the value From historical scan. Alternatively, you can use the REST API for this operation. ### Step 2. Involve developers in the remediation process Notify all developers involved, two options are available: - Option 1 – Share incidents using Developer-in-the-Loop: Use GitGuardian’s REST API to fetch the incidents and generate unique sharing links you will have to send to the active developers by email. - Option 2 – Invite active developers to join your GitGuardian workspace: - To give developers access to all their past incidents, use GitGuardian’s SSO login link with a default access level set to Member for new workspace members in combination with the auto-access granting playbook. - Go ahead and assign the historical incidents to developers: make sure developers are aware of the remediation process and the expectations you have set for them. ### Step 3. Track your developers' remediation progress - Workspace Managers can see all historical incidents. Search for a specific developer/commit author email or filter on a specific assignee to see all their incidents. - View incidents that were left untreated (not ignored or resolved) and leave a note for the developer to get back on the remediation process. If you choose to remediate historical incidents in batches, you can use the REST API to fetch all incidents matching the conditions of your choice. Don’t forget to store the list of incident Ids of the associated batch to poll the API again and verify if remediation has been conducted. Visit the GitGuardian public [API reference documentation](https://api.gitguardian.com/docs). ## The special case of "orphan incidents" Your remediation process for historical incidents needs to factor in an important detail: is the developer involved still on staff? We will refer to incidents that were committed by developers that have left your organization as orphan incidents. These developers can no longer contribute to the remediation process. You will, unfortunately, have to do without their help or context. Here is what you can do when faced in this situation: - If possible, verify the developer is no longer on staff: You can query your LDAP or Active Directory if you have one. In the process, identify which teams the developer belonged to when they were active. - In any case, identify repository admins or users with write access (incident location). Now, replace **Step 2. Involving developers in the remediation process** described above with the following alternative: ### Step 2. Involve team leads or security champions in the remediation process - Once all teams impacted by orphan incidents are identified, you can assign the historical incidents to engineering leads, repo admins, or any other members in the GitGuardian dashboard. - Alternatively, if you have a “Security Champions” program in place, you can leverage this helpful resource. Security Champions can take on the task of remediating historical incidents on behalf of the developers no longer on staff. :::tip Choose your assignees wisely! Team members involved in the remediation process need to be able to access the repositories or files in which the secrets occurrences were found. Without this, their scope for action might be too limited to help move the remediation process forward. ::: --- ## Remediation scenarios and workflows This guide covers different remediation scenarios you'll encounter and provides practical workflows for each. Choose the approach that matches your specific situation and organizational constraints. ## Understanding incident types Not all incidents are created equal. The remediation approach depends heavily on when and how the secret was detected: ### Real-time incidents **Real-time incidents** are detected as they happen - when developers commit secrets to repositories you're actively monitoring. **Characteristics:** - Recent exposure (minutes to hours old) - Developer context is fresh and available - Higher probability of being valid and actively used - Opportunity for immediate intervention **Key considerations:** - Developer is likely still working on the code - Secret may be needed for current development work - Faster remediation possible with developer involvement - Prevention opportunity through education ### Historical incidents **Historical incidents** are discovered during scans of existing repositories - secrets that have been present for days, months, or years. **Characteristics:** - Older exposure (potentially years old) - Developer context may be lost - Unknown validity and current usage - May require investigation to understand impact **Key considerations:** - Original developer may no longer be available - Secret usage patterns may have changed - Potential for widespread distribution - Requires systematic prioritization approach ## Remediation scenarios Depending on the incident nature and the context surfaced, you might fall in one of these different scenarios: ### Scenario 1: Emergency response (public exposure) **Use for:** Secrets detected in public repositories with immediate security impact. **Approach:** 1. **Rapid assessment** - Confirm ownership and access level 2. **Immediate revocation** - Disable secret immediately 3. **Impact containment** - Update critical systems 4. **Post-incident analysis** - Understand how exposure occurred **Timeline:** 5-15 minutes **Success factors:** Clear escalation paths, revocation procedures ### Scenario 2: Real-time incident with active developer **Use for:** Newly detected secrets where the developer is available and context is fresh. **Approach:** 1. **Immediate engagement** - Contact developer while context is fresh 2. **Quick assessment** - Understand intended use and scope 3. **Guided remediation** - Walk through proper secret management 4. **Prevention** - Education to prevent future occurrences **Timeline:** 15-30 minutes **Success factors:** Developer availability, clear communication, established processes [Detailed workflow →](./realtime-incidents.md) ### Scenario 3: Historical incident requiring investigation **Use for:** Older secrets with unknown context, validity, or current usage. **Approach:** 1. **Systematic prioritization** - Focus on high-impact secrets first 2. **Context reconstruction** - Investigate purpose and current usage 3. **Stakeholder identification** - Find current owners/users 4. **Phased remediation** - Address in priority order **Timeline:** Hours to days per incident **Success factors:** Good investigation tools, clear prioritization criteria [Detailed workflow →](./historical-incidents.md) ### Scenario 4: Bulk remediation (post-historical scan) **Use for:** Large volumes of historical incidents requiring systematic approach. **Approach:** 1. **Automated triage** - Use filters and automation to categorize 2. **Batch processing** - Group similar incidents for efficiency 3. **Team coordination** - Distribute work across teams 4. **Progress tracking** - Monitor completion rates and blockers **Timeline:** Weeks to months **Success factors:** Automation tools, team coordination, management support ## Workflow selection guide | Situation | Primary Scenario | Secondary Considerations | |-----------|------------------|-------------------------| | New commit detected with secret | Real-time with active developer | Check if public repository | | Historical scan reveals 500+ incidents | Bulk remediation | Prioritize by criticality first | | Secret found in public GitHub | Emergency response | May also need bulk approach if widespread | | Valid secret, unknown usage | Historical investigation | Consider developer engagement if possible | | Test/dummy secret | Quick resolution | May use bulk processing | ## Platform features supporting scenarios Our platform comes with several integrated features which can help you in addressing these different scenarios: ### Emergency response - **Integrated revocation** - Disable secrets directly from GitGuardian - **Public leak detection** - Identify external exposure - **Priority alerts** - Escalate critical incidents immediately ### Real-time workflow - **Instant notifications** - Alert relevant stakeholders immediately - **Developer sharing** - Provide direct access to incident details - **Feedback collection** - Gather developer input on false positives - **Auto-healing** - Allow developers to resolve incidents independently ### Historical workflow - **Bulk operations** - Process multiple incidents efficiently - **Advanced filtering** - Find high-priority incidents quickly - **Presence checking** - Verify if secrets still exist in repositories - **Validity checking** - Test if secrets are still active ## Next steps Choose the detailed workflow that matches your situation: - **[Real-time incidents](./realtime-incidents.md)** - Handle new detections with developer engagement - **[Historical incidents](./historical-incidents.md)** - Systematic approach for existing secrets - **[Platform features](../remediate-incidents.md)** - Deep dive into GitGuardian capabilities - **[Investigation guide](../investigate-incidents.md)** - Thorough analysis techniques --- ## Real-time incidents After adding automated secrets detection to your repositories, you need to establish precise remediation processes for the real-time incidents that the GitGuardian Internal Monitoring platform will raise. At this stage, you will have to determine: - Which team/role is responsible for remediating the incidents. Which team/role will be held accountable for the open incidents. - Which team/role to consult during the remediation process (e.g. DevOps engineers might have to intervene to avoid service outages while rotating secrets). - How much autonomy/trust you are willing to give developers for incident remediation. At GitGuardian, we believe developers should be front-and-center when it comes to remediating incidents they are responsible for. To bring your security teams and developers together, GitGuardian Internal Monitoring suggests two options: - The first one is to provide external access to incidents a developer is involved in. - The second one requires the developer to sign up to GitGuardian and join your workspace to view their incidents in-app. Both options can be automated with what we call [Playbooks](../../../platform/automate-with-playbooks/playbooks-overview.md). These are process flows running a series of automated jobs without the manual intervention of your security or software engineers. ### Option 1. Using the dev-in-the-loop feature to provide external access You can automate the incident sharing process with the developers involved using the "Auto-share incident access to the author of the leak" playbook. Whenever a new incident is detected, GitGuardian will send an email with a unique link to the developer to view the incident details on a standalone (external) page. You can also choose which options to apply to the sharing link: - Feedback collection option: the ability for the developer to submit feedback on the incident on the external page. - Resolution capability option: the ability for the developer to resolve or ignore the incident on the external page. In the early stages of the rollout, security teams will likely have to go all out when it comes to verifying the progress of developers on remediation – the feedback collection option is helpful here. This option provides security teams with more context about incidents but leaves taking care of the resolution to their members. As both teams advance and become more comfortable with their collaboration and remediation processes, we recommend security teams embrace the trust but verify principle. In the long run, we advise that developers are empowered to resolve their incidents with as little intervention as possible from security teams – the auto-share with resolution capability option is useful here. ### Option 2. Inviting developers to join your workspace :::caution [SSO authentication](../../../platform/enterprise-administration/saml-sso-configuration.md) needs to be activated on your workspace for this scenario to function. You are also responsible for sending the SSO login URL to your team members ahead of the rollout. ::: You can automate the process of giving access to incident details in the GitGuardian dashboard for members with a Restricted access level (usually reserved for developers) thanks to the auto-access granting playbook. GitGuardian will automatically give the Restricted user access to the incident details page in the dashboard by matching the commit author email against the dashboard user email. To abide by the principle of least privileges, Restricted users can only get access to their incidents in the dashboard. Restricted users cannot view the incidents of their teammates unless they are given access by a workspace Manager (usually reserved for technical security leads or development leads). Going with one or another depends on how close you want to pull your developers towards the remediation process. You can start with the external access option to explore how security and development teams should work together. Over time, you should consider migrating to the second option, where developers are part of your GitGuardian workspace. We believe this option is more valuable for the following reasons: - The auto-access granting playbook is not only for real-time incidents. It also applies to all historical incidents the developer committed before implementing GitGuardian. This playbook will be practical for Step 3. Remediating historical incidents (see below). - Technical Security Leads will be able to track the progress of each developer on their incidents’ remediation and notify them directly in the dashboard when needed. - Developers with access to the dashboard can generate Personal Access Tokens to use ggshield CLI and implement secret scanning at the pre-commit level. --- ## AWS IAM Integration The AWS IAM integration provides comprehensive visibility into your AWS Identity and Access Management infrastructure, enriching your NHI governance with detailed permission context and security insights. ## Overview This integration is provided directly in **Gitguardian platform** and does not require to install GitGuardian Scout. It fetches comprehensive AWS IAM data, including all permissions tied to users, roles and groups, and link all those permissions to AWS API keys. This enriches your security graph with detailed context about credential sensitivity and potential blast radius in case of a leak. ## Key Features - **Comprehensive Permission Analysis**: Fetches all AWS IAM data including policies, roles, users, and groups - **API Key Context**: Analyzes permissions tied to AWS API keys to understand their potential impact - **Security Graph Enrichment**: Provides detailed context about credential sensitivity and blast radius - **Secure Authentication**: Uses OIDC authentication, eliminating the need for long-lived credentials ## Getting Started Follow these steps to configure the AWS IAM integration: ### Step 1: Configure OIDC Provider in AWS Add your GitGuardian instance as an OIDC provider in your AWS account, using these values: - **Provider URL**: - GitGuardian SaaS: `https://api.gitguardian.com` - Self-hosted: `https:///exposed` (keep the `/exposed` path) - **Audience**: `sts.amazonaws.com` To confirm the exact Provider URL for your instance, open `/.well-known/openid-configuration` in a browser. The `issuer` field is the value to use. ![AWS IAM Base Configuration](/img/nhi-governance/iam/aws_iam_base.png) ![Create OIDC Provider](/img/nhi-governance/iam/create_oidc.png) When AWS asks for a certificate thumbprint, use the **Get thumbprint** button in the console. AWS retrieves the fingerprint from the Provider URL's TLS certificate, so there is nothing to copy from GitGuardian. If you create the provider through the AWS CLI, CloudFormation, or Terraform, supply the thumbprint of the certificate authority for your Provider URL, following [AWS's guide on obtaining the thumbprint](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html). :::note Self-hosted reachability AWS validates tokens by fetching `/.well-known/openid-configuration` and the public keys at `/v1/auth/jwks`. Both endpoints must be reachable from the public internet. If your GitGuardian instance is only reachable inside your network, the role assumption fails until you expose them to AWS. ::: ### Step 2: Create AWS IAM Role Create an AWS role that trusts the GitGuardian OIDC provider. This involves setting up both a trust policy and permission policy. #### Trust Policy Configure the trust policy to allow the GitGuardian OIDC provider to assume the role. For enhanced security, include a condition that restricts access to your specific GitGuardian account: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::{your-aws-account-id}:oidc-provider/{your-gitguardian-oidc-provider}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "{your-gitguardian-oidc-provider}:sub": "gitguardian-account-id:{your-gitguardian-account-id}" } } } ] } ``` **Note**: Replace the placeholders: - `{your-aws-account-id}`: Your AWS account ID - `{your-gitguardian-oidc-provider}`: The OIDC provider URL from Step 1, without the `https://` prefix. For GitGuardian SaaS, use `api.gitguardian.com`. For self-hosted, keep the `/exposed` path, for example `gitguardian.example.com/exposed`. - `{your-gitguardian-account-id}`: Your GitGuardian account ID. Find it in your GitGuardian dashboard URL, as the number after `/workspace/`. On self-hosted instances the default account ID is `1`. **Example**: If your dashboard URL is `https://dashboard.gitguardian.com/workspace/123456/`, then your GitGuardian account ID is `123456`. The `sub` condition (`gitguardian-account-id:{your-gitguardian-account-id}`) ensures that only your specific GitGuardian account can assume this role, providing an additional layer of security. This can also be done from the UI, by selecting `Web Identity` when creating the AWS IAM Role. #### Permission Policy Attach the following permission policy to grant the necessary IAM read permissions: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:GetAccessKeyLastUsed", "iam:GetGroup", "iam:GetGroupPolicy", "iam:GetPolicy", "iam:GetPolicyVersion", "iam:GetRolePolicy", "iam:GetUserPolicy", "iam:ListAccessKeys", "iam:ListAttachedGroupPolicies", "iam:ListAttachedRolePolicies", "iam:ListAttachedUserPolicies", "iam:ListGroups", "iam:ListPolicies", "iam:ListRolePolicies", "iam:ListRoles", "iam:ListUserPolicies", "iam:ListUsers" ], "Resource": "*" } ] } ``` ### Step 3: Access GitGuardian Integration Settings In GitGuardian platform, navigate to **Settings > Sources** to access the integration configuration page. ![GIM Source Integration](/img/nhi-governance/iam/gim_source_integration.png) ### Step 4: Add AWS IAM Integration Configure the new AWS IAM integration by providing: - **AWS Account ID**: Your AWS account identifier - **Role ARN**: The ARN of the role created in Step 2 ![GIM Add Integration](/img/nhi-governance/iam/gim_add_integration.png) ### Completion You're all set! GitGuardian will start fetching AWS IAM data from your account, enriching your security graph with comprehensive permission context for discovered AWS credentials. Once the integration is active, you'll be able to view the enriched AWS data in your GitGuardian platform. The NHI inventory will display all discovered AWS API keys with comprehensive metadata: ![AWS NHI Inventory](/img/nhi-governance/iam/aws_nhi_inventory.png) Each AWS API key will have an enriched security graph showing detailed permission analysis: ![AWS API Key Graph Resources](/img/nhi-governance/iam/aws_api_key_graph_resources.png) ## Other Integrations For information about other integrations including secrets managers, CI/CD systems, and infrastructure sources, please refer to the **[ggscout documentation](/ggscout-docs/integrations)**. --- ## Microsoft Entra Integration The Microsoft Entra integration provides comprehensive visibility into your Microsoft Entra ID (formerly Azure Active Directory) and Azure RBAC infrastructure, enriching your NHI governance with detailed identity, permission, and credential context. ## Overview This integration is provided directly in **GitGuardian platform** and does not require to install GitGuardian Scout. It fetches comprehensive identity data from Microsoft Entra ID using Microsoft Graph API and collects Azure RBAC (Role-Based Access Control) data for specified Azure subscriptions. This enriches your security graph with detailed context about service principal credentials, their permissions, and potential blast radius in case of a leak. ## Key Features - **Comprehensive Identity Discovery**: Fetches all Microsoft Entra data including users, groups, service principals, managed identities, and applications - **Credential Tracking**: Discovers and tracks service principal credentials (client secrets and certificates) - **Permission Analysis**: Maps directory roles and Azure RBAC permissions to service principals - **Security Graph Enrichment**: Provides detailed context about credential sensitivity and blast radius - **Secure Authentication**: Uses Workload Identity Federation (OIDC), eliminating the need for long-lived credentials ## Data Collected ### Microsoft Graph API Data (Identity Layer) The integration collects the following identity information: - **Users**: User profiles, account status, and metadata - **Groups**: Group information, types, and memberships - **Service Principals**: Service principal metadata and associations - **Managed Identities**: System-assigned and user-assigned managed identities - **Applications**: Application registrations and metadata - **Client Secrets**: Metadata for service principal client secrets (values are never accessible) - **Certificates**: Certificate metadata for service principals - **Directory Roles**: Microsoft Entra directory role assignments ### Azure Management API Data (RBAC Layer) When Azure subscription IDs are configured, the integration also collects: - **Role Definitions**: Built-in and custom Azure RBAC role definitions with permission details - **Role Assignments**: Role assignments for subscriptions and resources - **Subscriptions**: List of accessible Azure subscriptions ## Required Permissions ### Microsoft Graph API Permissions The following **Application permissions** are required for the registered application: - `Application.Read.All` - `Directory.Read.All` - `Group.Read.All` - `GroupMember.Read.All` - `User.Read.All` - `AdministrativeUnit.Read.All` **Note**: These are **Application permissions** (not Delegated permissions), which work without a signed-in user and require admin consent. ### Azure Management API Permissions For Azure RBAC data collection (optional but recommended): - **Reader** role on each Azure subscription you want to monitor This can be assigned at subscription level or management group level for multiple subscriptions. ## Getting Started Follow these steps to configure the Microsoft Entra integration: ### Step 1: Register Application in Azure Entra 1. Sign in to the [Azure Portal](https://portal.azure.com) 2. Navigate to **Azure Active Directory** → **App registrations** → **New registration** 3. Provide a name (e.g., "GitGuardian NHI Integration") 4. Select **Accounts in this organizational directory only** 5. Click **Register** 6. **Save the following values:** - **Application (client) ID** - You'll need this for GitGuardian configuration - **Directory (tenant) ID** - You'll need this for GitGuardian configuration ### Step 2: Grant API Permissions 1. In your app registration, go to **API permissions** 2. Click **Add a permission** 3. Select **Microsoft Graph** → **Application permissions** 4. Add the following permissions: - `Application.Read.All` - `Directory.Read.All` - `Group.Read.All` - `GroupMember.Read.All` - `User.Read.All` - `AdministrativeUnit.Read.All` 5. Click **Grant admin consent** for your organization **Important**: Application permissions require admin consent and work without a signed-in user. ### Step 3: Configure Workload Identity Federation (OIDC) 1. In your app registration, go to **Certificates & secrets** 2. Click the **Federated credentials** tab 3. Click **Add credential** 4. Select **Other issuer** as the federated credential scenario 5. Fill in the following fields: - **Issuer**: `https://api.gitguardian.com` (for SaaS) or your self-hosted instance URL - **Subject identifier**: `gitguardian-account-id:{your-gitguardian-account-id}` - **Name**: A descriptive name (e.g., "gitguardian-federation") - **Description**: Optional description - **Audience**: Leave as default (`api://AzureADTokenExchange`) 6. Click **Add** ![Configure Federated Credential](/img/nhi-governance/entra/entra_oidc_declaration.png) **Finding your GitGuardian Account ID**: Your account ID can be found in your GitGuardian dashboard URL: `https://dashboard.gitguardian.com/workspace/{your-gitguardian-account-id}/` **Example**: If your dashboard URL is `https://dashboard.gitguardian.com/workspace/123456/`, then your GitGuardian account ID is `123456`. ### Step 4: Assign Azure RBAC Permissions (Optional) If you want to collect Azure RBAC data: 1. Navigate to **Subscriptions** in the Azure Portal 2. Select each subscription you want to monitor 3. Go to **Access control (IAM)** → **Add role assignment** 4. Select the **Reader** role 5. Assign it to your registered application (search by application name) 6. Save the **Subscription ID(s)** for GitGuardian configuration ### Step 5: Configure Integration in GitGuardian 1. In GitGuardian platform, navigate to **Settings > Sources** 2. Click **Add Integration** 3. Select **Microsoft Entra** 4. Provide the following information: - **Integration Name**: A friendly name for this integration instance - **Tenant ID**: Your Azure AD Directory (tenant) ID from Step 1 - **Client ID**: Your Application (client) ID from Step 1 - **Subscription IDs** (optional): Comma-separated list of Azure subscription IDs for RBAC data collection 5. Click **Save** ### Completion You're all set! GitGuardian will start fetching Microsoft Entra data from your tenant, enriching your security graph with comprehensive identity and permission context. Once the integration is active, you'll be able to view the enriched Microsoft Entra data in your GitGuardian platform. The NHI inventory will display all discovered entities including service principals, managed identities, client secrets, and certificates with comprehensive metadata. ![Microsoft Entra Identities in GitGuardian Inventory](/img/nhi-governance/entra/entra_dashboard.png) Each service principal credential will have an enriched security graph showing: - Which service principal owns the credential - What directory roles and RBAC roles are assigned to that service principal - Which groups the service principal belongs to (if any) - Permission statements from Azure RBAC roles - Credential validity period and expiration status ## Integration Instances This integration supports **multiple instances**, allowing you to: - Monitor multiple Azure AD tenants from a single GitGuardian account - Separate production and development environments - Track different organizational units with different tenant configurations Each integration instance is configured independently with its own tenant ID, client ID, and subscription list. ## Security Considerations - **No Long-Lived Secrets**: The integration uses Workload Identity Federation, eliminating the need for client secrets - **Read-Only Access**: All permissions are read-only; the integration cannot modify your Azure environment - **Short-Lived Tokens**: Access tokens are automatically managed and expire within 1 hour - **Credential Metadata Only**: Secret values are never accessible through Microsoft Graph API - **Least Privilege**: Only the minimum required permissions are requested ## Troubleshooting ### Common Issues **"Insufficient privileges" error:** - Ensure all required Microsoft Graph API permissions are granted - Verify admin consent has been granted for application permissions **"Invalid federated credential" error:** - Verify the Issuer URL matches your GitGuardian instance (SaaS vs. self-hosted) - Confirm the Subject identifier format: `gitguardian-account-id:{your-account-id}` - Check that your GitGuardian account ID is correct **RBAC data not appearing:** - Verify Subscription IDs are correctly entered in the integration configuration - Confirm the Reader role is assigned to your application on each subscription - Check that the subscriptions are active **Federated credential not working:** - Ensure you're using Application permissions (not Delegated permissions) - Verify the federated credential is added under "Certificates & secrets" → "Federated credentials" - Check that the credential hasn't expired (federated credentials can have expiration dates) ## Additional Resources - [Microsoft Entra Workload Identity Federation](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation) - [Microsoft Graph API Permissions Reference](https://learn.microsoft.com/en-us/graph/permissions-reference) - [Azure RBAC Documentation](https://learn.microsoft.com/en-us/azure/role-based-access-control/) ## Other Integrations For information about other integrations including secrets managers, CI/CD systems, and infrastructure sources, please refer to the **[ggscout documentation](/ggscout-docs/integrations)**. --- ## Core concepts(Nhi-governance) ## What are non-human identities? Non-Human Identities (NHIs) are digital identities designed for machine-to-machine interactions, enabling automated systems, applications, services, and APIs to securely access resources without human intervention. Unlike user accounts tied to individuals, NHIs are created and managed by systems and are typically used by scripts or backend processes. They authenticate using secrets such as tokens, keys, certificates, or service account credentials. NHIs are essential for enabling secure automation in modern, interconnected software environments—facilitating tasks like backend communication, cloud resource access, and third-party service integration. Because they lack direct human oversight, understanding the context in which NHIs operate is critical for managing their access and ensuring security. ## Why should you address your NHI security posture? Addressing the security posture of Non-Human Identities is critical because they represent a rapidly growing and often overlooked attack surface in modern IT environments. For every human identity, there can be hundreds of NHIs—a 100:1 ratio, making them far more numerous and difficult to manage. NHIs are highly distributed across systems, frequently overprivileged, and commonly lack clear ownership, defined usage, or scoped access, leading to significant blind spots. These gaps make it challenging to monitor and enforce security controls effectively. As a result, NHIs have become prime targets for attackers, who exploit them to gain unauthorized access to sensitive systems and data. Without a proactive approach to NHI security—covering visibility, least privilege enforcement, and lifecycle management—organizations risk exposing critical infrastructure to breaches. --- ## Discover your NHIs ## NHI Inventory The inventory provides a centralized, searchable table listing all Non-Human Identities discovered across your perimeter. This dynamic view helps you monitor, audit, and triage NHIs efficiently across various environments and sources. **Inventory table overview** Each row in the inventory represents a unique NHI and displays the following key attributes: - **Secret name** – The identifier of the associated secret. - **Detector**: The [Secrets Detection Engine](/secrets-detection/secrets-detection-engine/detectors/introduction) detector that classified the secret, or **Unknown** if none matched. - **Source** – The integration where the NHI was discovered (e.g., the name of the secret manager or Kubernetes cluster). - **Path** – The exact path or location of the secret within the source. - **Environment** – The associated environment tag (e.g., `prod`, `staging`, `dev`). [Learn how to categorize environments](/nhi-governance/integrate-your-sources#contextualize-your-nhi-sources) - **Breached policies** – Any detected misconfigurations or violations of security best practices. [Learn more about breached policies](nhi-governance/improve-your-posture.md) - **Identity level** – Whether the NHI holds admin-level permissions on its source (e.g. an AWS IAM principal with `AdministratorAccess`, a Microsoft Entra Global Administrator, or an Okta Super Admin). Admin identities are marked with a dedicated badge in the detail view. [Learn more](nhi-governance/improve-your-posture.md#identify-admin-identities) - **Risk criticality** – An aggregated level (low, medium, high, critical) combining the highest-risk policy breach on the identity with modifiers for admin status and production exposure. [Learn more](nhi-governance/improve-your-posture.md#risk-criticality) - **Owners** – The person(s) responsible for the NHI. See [NHI Ownership](#nhi-ownership) below. ![NHI Inventory](/img/nhi-governance/nhi-inventory.png) The inventory supports filtering based on: - Detector: any detector, or **Unknown** - Detector type: **Generic**, **Specific**, or **Unknown** - Secret family - Secret category - Secret provider - Breached policy - Environment - Source - Identity level: **Admin** or **Non-admin** - Risk criticality: **Critical**, **High**, **Medium**, or **Low** - Owner: by specific owner, **No owner**, or **Current user** The detector-linked filters (detector, detector type, secret family, category, and provider) are the same facets used on secret incidents, so you can ask the same questions of vaulted secrets as of leaks. [Learn more about categories and providers](/secrets-detection/secrets-detection-engine/gse-categories-providers-reference). :::warning Upgrade ggscout to 0.32.0 or later Detector classification requires [ggscout](/ggscout-docs/configure-ggscout) **0.32.0** or later. Until you upgrade, collected secrets stay unclassified (**Unknown**). After you upgrade, the next fetch classifies the existing inventory. No extra configuration is required. ::: Clicking into an NHI opens a detailed view that includes the detector, policy breaches, secret version, and a visual map of the NHI’s relationships and context. Note that if a version is deleted, metadata remains but the graph is empty and marked as deleted, while fully destroyed secrets disappear from the inventory. ### NHI Ownership Ownership assigns accountability for each NHI to one or more people in your organization: you can see who is responsible for an identity, filter the inventory by owner, and add or change owners manually. **Suggested vs manual owners** - **Suggested owners** – GitGuardian can automatically suggest owners using data from your integrated sources and from secret incidents. Suggested owners are labeled as *Set automatically by GitGuardian* in the NHI detail view. You can keep them, remove them, or add other owners. - **Manual owners** – Any owner you add or confirm yourself is labeled *Set manually*. Manual assignments are never overwritten by automatic suggestions. **How owners are suggested** Suggestions are based on several signals, in order of confidence (highest first): 1. **Direct owner field** – The NHI source exposes an explicit owner for the identity (e.g. IAM or IdP owner field). 2. **Metadata tags** – A tag on the resource contains an owner (e.g. an AWS IAM or Azure tag with an email). 3. **Source-level owner** – The integration has a declared owner (e.g. the user who configured the integration). 4. **Last editor or creator** – The person who last modified or created the resource, when provided by the source. 5. **Incident committer** – A developer who committed a secret that led to an incident tied to this NHI (private or public). 6. **Public secrets scan** – The user whose scan detected the secret associated with this NHI. When several candidates exist, the system keeps only those with the highest confidence. You can have up to **5 owners** per NHI. **Who can be an owner** - A **workspace member** (linked to their GitGuardian user). - An **external user** identified by email (e.g. a contractor or someone in another team). No GitGuardian account is required. **Managing owners** - In the **inventory**, the Owner column shows up to two owners per NHI; use the **Owner** filter to narrow the list (e.g. *No owner*, *Current user*, or a specific person). - In an **NHI’s detail view**, use the **Owners** section to add, remove, or replace owners. You can type a workspace member or any valid email to add an external owner. Removing a suggested owner discards that suggestion so it is not re-applied automatically. **API** Ownership can be managed via the public API using the `nhi:ownership:read` and `nhi:ownership:write` scopes. Endpoints allow you to list owners for an identity, add owners, remove an owner, or replace the full list of owners. ### Exploration map The Exploration map gives you a visual, end-to-end view of an NHI, helping you understand its connections, usage, and potential impact across your environment. The map is composed of: - **Secrets managers** – Where the NHI's secrets are safely stored. - **Consumers** – Entities (such as services, scripts, or jobs) that use the secret to authenticate and access other systems. - **Accessed resources** – The targets accessed by the consumers, along with their permissions, based on [Secret Analyzers](/secrets-detection/secrets-detection-engine/secrets_analyzer). - **Incidents** – Both **public** and **private** secret incidents associated with the NHI. ![Exploration Map](/img/nhi-governance/exploration-map.png) You can access the map from an NHI’s detail view or directly from a secret incident, enabling fast, contextual navigation between detection and analysis. **Use cases** While the primary goal is to visualize and contextualize NHIs, the map also helps to: - **Streamline remediation** – Quickly assess the impact of revoking a secret and identify all affected systems. - **Investigate leaks** – Trace which consumers and resources may have been compromised. - **Improve secret hygiene** – Spot stale or overprivileged secrets, unused consumers, and other hygiene issues across your perimeter. --- ## Assess and improve your NHI security posture Our security policies are informed by the **[OWASP Top 10 for NHIs](https://owasp.org/www-project-non-human-identities-top-10/2025/)**, a comprehensive framework that highlights the most critical security risks they pose. We support the following policies: - **Publicly Leaked Secrets**: These are secrets that have been exposed publicly, identified through our public monitoring services. Such exposure can allow unauthorized parties to access sensitive systems, posing significant security threats. - **Internally Leaked Secrets**: Secrets that have been inadvertently exposed within your internal perimeter can be detected through our private monitoring services. These internal leaks can be just as harmful as public ones, especially if internal defenses are breached. - **Cross-Environment Secrets**: A secret that is found in multiple environments, like both production and staging, can risk exposing sensitive production-level access to less secure environments. Ensuring each environment has distinct secrets helps maintain security boundaries. - **Reused Secrets**: When a secret is used by multiple entities, it increases the risk of compromise. If one entity is breached, others using the same secret can also be jeopardized. Ensuring unique secrets for each use case reduces this risk. - **Duplicated Secrets**: Having the same secret stored in multiple vaults or paths can complicate management and increase the chance of using outdated or unrevoked credentials. It is crucial to maintain a single source of truth to manage secrets effectively. - **Long-Lived Secrets**: Secrets that exist beyond a given lifespan (by default one year) without renewal are vulnerable to misuse. Regularly updating these secrets helps minimize the risk of prolonged exposure to potential threats. - **Overprivileged Identity**: An identity that has been granted broader permissions than it actually needs. Overprivileged NHIs widen the blast radius if their secret is compromised, so trimming entitlements back to least privilege is key to reducing risk. Evaluation is available for AWS IAM, Microsoft Entra, and Okta identities. In the inventory details, selecting a breach policy will visually highlight the locations of the issues on the exploration map. ![Breached Policies](/img/nhi-governance/breached-policies.png) ## Identify admin identities {#identify-admin-identities} In addition to policy breaches, GitGuardian flags identities that hold **admin-level permissions** on your infrastructure or identity provider. Admin NHIs are surfaced in the inventory with an **Identity level: Admin** badge and can be isolated with the dedicated **Identity level** filter (Admin / Non-admin). Admin detection is available for: - **AWS IAM**: principals attached to `AdministratorAccess` or `IAMFullAccess`, or holding custom policies with wildcard actions on IAM or AWS Organizations. - **Microsoft Entra**: principals with high-impact directory roles (e.g. Global Administrator, Privileged Role Administrator, Application Administrator), admin-equivalent Azure RBAC roles (Owner, User Access Administrator), or tier-1 Microsoft Graph permissions (e.g. `RoleManagement.ReadWrite.Directory`). - **Okta**: principals with built-in admin roles (Super, Org, App, Group, User, API Access Management Admin) or custom roles granting admin-equivalent permissions. Use this signal to focus remediation on the identities with the greatest blast radius, independently of whether they currently breach a policy. ## Risk criticality {#risk-criticality} Each NHI in the inventory is assigned a **Risk criticality** level (low, medium, high, critical) derived from two layers: 1. **Base severity** from the highest-risk active policy breach on the identity. For example, a publicly leaked secret rates critical, internally leaked rates high, overprivileged rates medium, long-lived rates low. 2. **Modifiers** that bump the score by +1 level each, capped at critical: - **Admin identity**: any breach on an admin NHI is one level more severe. - **Cross-environment with production**: a cross-environment breach that touches production environment is one level more severe. This means a leaked secret on an admin identity is surfaced as critical even if the leak itself is internal, letting you sort the inventory by risk and focus on the NHIs where an attacker would do the most damage first. Note that new policies will be supported shortly. --- ## Integrate your NHI sources ## Monitor your perimeter NHI Governance supports a range of integrations that connect to your existing systems where NHIs are created, stored, or used. These integrations enable the platform to automatically inventory NHIs, capture key metadata (such as context, usage, and scope), and provide continuous visibility into their lifecycle and security posture. ## Supported integrations NHI Governance offers native support for widely-used secrets managers and infrastructure components where NHIs typically reside or operate. GitGuardian integrates with a set of sources across your infrastructure through **[ggscout](/ggscout-docs/home)** a lightweight, auditable application that safely collects secrets and their metadata from your configured secret managers, without exposing secret values. It hashes the data locally before securely sending it to your GitGuardian workspace. To classify collected secrets against the Secrets Detection Engine, run [ggscout 0.32.0 or later](/ggscout-docs/configure-ggscout). Until you upgrade, those secrets stay **Unknown** in the inventory. ![Scout Flow](/img/ggscout/scout-flow.png) ### Secrets Managers GitGuardian integrates with Secrets Managers as a primary source of truth for secrets and tied NHIs. Supported Secrets Managers: - HashiCorp Vault - CyberArk Secrets Manager SaaS - CyberArk Secrets Manager Self-Hosted - Akeyless Secrets Management Platform - AWS Secrets Manager - Google Cloud Secret Manager - Azure Key Vault - Delinea Secret Server Learn more on [Secrets managers integrations](/ggscout-docs/integrations/secret-managers). ### CI and Infrastructure sources GitGuardian also integrates with CI and Infrastructure sources to collect additional NHIs and provide additional insights to those already collected, such as understanding where NHIs are used and consumed. Supported sources: - [GitHub Actions](/ggscout-docs/integrations/github-actions) - [GitLab CI](/ggscout-docs/integrations/gitlab-ci) - [Kubernetes clusters](/ggscout-docs/integrations/infrastructure/kubernetes) ### Cloud IAM integrations GitGuardian also integrates with Cloud Identity and Access Management systems to provide comprehensive context about NHI permissions and potential impact. These integrations analyze the permissions and policies associated with discovered credentials, offering deeper insight into the sensitivity and blast radius of exposed secrets. Supported Cloud IAM systems: - [AWS IAM](./aws-iam-integration) - Comprehensive AWS Identity and Access Management integration - [Azure Entra ID](./azure-entra-integration) - Comprehensive Microsoft Entra ID integration ### Other identity providers - Auth0 - Okta ### SaaS providers GitGuardian can also integrate with popular SaaS platforms to provide visibility on NHI usage and potential exposure. Supported providers: - Airbyte - Anthropic - Datadog - N8n - OpenAI - Slack - Snowflake ## Contextualize your NHI sources {#contextualize-your-nhi-sources} When configuring your integrations, you can manually assign an environment category to each data source (e.g., a specific vault or Kubernetes cluster) directly in the ggscout configuration file. This helps you contextualize NHIs based on their operational scope—such as distinguishing between production and development identities. Supported categories: - ```prod``` - Production - ```preprod``` - Pre-production - ```staging``` - Staging - ```testing``` - Testing - ```dev``` - Development --- ## Track your performance Your dashboard provides data-driven insights into how well your organization is managing its NHIs. This section is divided into three main areas: Posture Management, Secret Hygiene, and Secrets Incidents. ### Posture Management ![Posture Management](/img/nhi-governance/posture-management-analytics.png) - **Breached Policies Over Time**: The first graph displays the evolution of breached policies over time. By tracking these trends, you can evaluate the effectiveness of your remediation efforts and overall security measures. - **Distribution of Breached Policies**: The second graph shows the distribution of breached policies across your environment, highlighting which risk types occur most frequently. Clicking on any specific breach category will take you to an inventory view filtered by that policy, enabling you to quickly identify and address areas that require attention. ### Secret Hygiene ![Secret Hygiene](/img/nhi-governance/secret-hygiene-analytics.png) - **Vault Coverage**: Monitor what percentage of your secrets are stored in designated secret managers. This metric reflects how consistently your organization is adopting secure storage practices. - **Integration Overview**: Get a snapshot of your NHI integrations. This overview lets you assess whether all relevant systems communicate properly with NHI Governance, ensuring comprehensive coverage. - **Secrets Age Distribution**: Review the age of your active secrets. Older secrets—especially those nearing or exceeding the recommended lifespan may require rotation to reduce the risk of exposure. ![Secrets Age](/img/nhi-governance/secrets-age-analytics.png) ### Secrets Incidents ![Compromised Secrets](/img/nhi-governance/compromised-secrets-analytics.png) - **Public Incidents**: These secrets are detected by GitGuardian in publicly accessible GitHub repositories, making them potentially visible to anyone, including malicious actors. These incidents can occur through direct commits to public repositories or when private repositories are accidentally made public. You need to have Public Monitoring to access this data. - **Private Incidents**: These secrets are discovered through GitGuardian's internal monitoring of private code repositories, CI/CD pipelines, and developer productivity tools. --- ## AI Management Policy :::info **This document describes GitGuardian's AI systems and the governance, security measures, and ethical standards we implement to ensure their safe and responsible use.** ::: ## Overview - **Secret values are redacted:** We use GitGuardian's cutting-edge detection engine to identify and redact secrets before any data is sent to external AI models. - **Minimal context exposure:** When context is required for certain AI features, only an excerpt around the detection location is sent, with secrets redacted by GitGuardian's detection engine. - **Secure, regional data transmission:** All data is transmitted securely over encrypted connections and remains within your region (EU or US): external AI providers process requests in the same geographic region as your GitGuardian instance. - **Limited metadata:** When metadata is required, we send incident characteristics such as detector type, severity, validity status, and other non-sensitive attributes: no secret values. - **No training, no retention by AI providers:** Your data is not used to train models and is not retained by any external AI provider apart from the minimum necessary to answer the request. - **Declared sub-processors:** All AI providers (AWS Bedrock, Google Cloud Vertex AI, OpenAI) are formally declared sub-processors. Full list: [gitguardian.com/legal/subprocessors](https://www.gitguardian.com/legal/subprocessors) - **You are in control:** You can route LLM calls through your own cloud ([BYOC](./ai-settings.md)), or [disable external LLM calls entirely](./ai-settings.md). ## GitGuardian's AI core principles ### AI ethics principles GitGuardian complies with all applicable AI laws and regulations and adheres to the following ethical principles: - **Data protection and privacy:** AI systems respect user privacy and comply with data protection regulations. - **Accountability and responsibility:** Clear ownership over AI outcomes with human-in-the-loop approvals and traceability. - **Trustworthiness and integrity:** Reliable systems with continuous improvement. GitGuardian also respects all standard GitGuardian Security Policies, available on our [Trust Center](https://trust.gitguardian.com/). ### Protection of your data Secret security is a **core mission** of GitGuardian. Every model and AI feature is designed, trained, evaluated, and maintained on internal benchmarks before rollout, then subject to manual validation. GitGuardian uses a mix of proprietary, self-hosted models and, in some cases, validated third-party large language models. Our systems are resilient to prompt injection by design. Most AI features implement one or more of the following safeguards: - **Input/output separation:** Input producers and output receivers are separated. An attacker cannot confirm whether their malicious input produced an effect, nor influence other users' responses. - **Constrained and validated inputs and outputs:** Models respond only within a predefined scope (e.g., Yes/No classification), preventing unintended actions or uncontrolled content. - **Free-form context limited to the requester's allowed scope:** RBAC and least-privilege by design guarantee strict tenant isolation. - **Guardrails and monitoring:** Defenses block injection attempts before they reach the model and catch unsafe behaviors after generation. These safeguards are complemented by sensitive data redaction, safety filters (moderation on inputs/outputs), and input/output validators (schema and policy checks). ### Compliance with the EU AI Act GitGuardian does not develop general-purpose AI, and all AI implementations are purpose-built to improve Secrets and Non-Human Identity detection, classification, prioritization, and remediation — always with strict safeguards to protect customer data. These implementations fall under a **minimal-risk AI system according to the EU AI Act nomenclature**. In practice, this means they present very limited or no risk to fundamental privacy, rights or safety, and therefore are permitted without additional compliance obligations beyond transparency. GitGuardian provides assurances with respect to its services' compliance with applicable laws and regulations through contractual protection. ## Data usage & protection To continuously improve secret detection, prioritization, and remediation, GitGuardian may use: 1. **Customer data** for service improvement only, not training. 2. **Performance data** for model and algorithm training. ### Customer data for service improvement A typical example is a support ticket for a false positive that shares the affected incident. Our detection team reviews it and improves the corresponding detection logic. ### Performance data for training GitGuardian may use anonymized Performance Data to train and evaluate internal models. These are for small internal models, not "General Purpose AI". **For avoidance of doubt: Performance Data does not identify any customer, and only includes feedback and metadata generated by the service, but not repository content, source code, company names, PII.** The goal is to learn general patterns, for example that an AWS credential linked to a production environment is usually more critical than a lower-impact credential in a test environment. - **Scope:** Data is used exclusively for GitGuardian's internal model improvement. It is never used to train third-party models. Most data types can exist in two forms: - Public: already accessible to anyone on the internet (e.g., public GitHub or DockerHub files) - Internal: only accessible through access granted by Customer. - **Data transformation:** Before inclusion in training sets, data undergoes redaction of sensitive content (secrets, credentials, personal information). - **Security practices:** Data handling follows all GitGuardian security standards, including access controls and retention policies. Data from one customer cannot be exposed to another customer through model outputs. *(\*) **"Performance Data"** means, where applicable, usage data and information compiled by GitGuardian on Customer's use of the Services, including Service Data, and statistical and performance information related to the provision and operation of the Services. Performance Data includes information concerning Customers' and Users' use of the various features and functionality of the Services and analytics and statistical data derived there from, and aggregated and anonymized data derived from Customer Data (where such data is processed in connection with the Services) so that such data does not identify a person.* ### Input and output usage & ownership GitGuardian shall ensure that your inputs or outputs are not: - Available to other customers - Sent outside your data residency region (US or EU) during its processing by AI system - Sent to any third-party LLM provider other than our standard LLM Providers - Stored by any third-party LLM provider - Used to train or improve any third-party models GitGuardian does not claim ownership of AI-generated output but retains a license right to inputs and outputs to improve the corresponding features. Customers retain full rights to use, modify, and distribute the output at their discretion. GitGuardian shall indemnify customers against third-party intellectual property claims related to the use of AI-generated output, provided that the Customer: (i) has a valid right to use their inputs; (ii) has an active, paid subscription for the relevant AI feature; (iii) had no prior knowledge of the alleged infringement; (iv) The output has not been materially altered before the claim. ## AI models & deployment strategies GitGuardian uses a multi-tiered approach to balance performance and privacy: - **Proprietary / Self-Hosted Models:** Custom models for secret detection and prioritization, hosted entirely within GitGuardian's infrastructure. - **Hybrid Models:** Combining proprietary models with open-source LLMs hosted in our secure environment. - **Third-Party LLMs:** For specific features (e.g., chat, explanations), we integrate with trusted providers like AWS Bedrock and OpenAI via secure APIs with Zero Data Retention. ## GitGuardian's AI system details AI Processing Purposes Securing Secrets and NHI and helping with remediation. Proprietary or Third-Party AI System(s) Hybrid use of proprietary models and third-party LLMs (AWS Bedrock, Gemini, OpenAI). AI Input Depending on the AI Features (please refer to the AI Features Catalog below), AI Input may be: Limited Secret Context (Public or Internal) — a snippet or document portion centered on the detected secret, with limited metadata (e.g., date, filename). Performance Data — non-sensitive incident attributes such as whether the secret is valid, how many times it has leaked, its type/category, and severity classification (does not include the secret value, repository content, or context and feedback from user interaction). User Input — only the text entered by the user in chat or queries. Company description and keywords — high-level description and keywords describing the company (e.g., company name, domain), typically from OSINT sources. Source Data (Public or Internal) — full access to current repository, project, or channel content (e.g., Git repos) and related metadata (descriptions, anonymized users, interactions). GitGuardian Dashboard — information available in the Dashboard to the authenticated user, respecting RBAC and permissions. AI Output Type Text and classification labels. AI Output Disclaimers/Watermarks AI features are labelled as powered by AI in our docs but also when meaningful in the display. ## GitGuardian's AI features catalog For a detailed breakdown of each AI-powered capability, see [AI-powered features](./ai-powered-features.md). ## Continuous improvement and monitoring As our AI evolves, so will these principles. We'll keep reviewing and improving them to reflect the latest best practices in responsible AI. --- ## AI-Powered Features GitGuardian uses AI to enhance its detection engine with capabilities that go beyond what rule-based systems can achieve. :::note This list is not exhaustive. AI and LLMs are used broadly across the GitGuardian platform, and capabilities continue to evolve. ::: ## False positive detection **What it does:** Catches the complex edge cases of false positives that rule-based detection cannot resolve on its own — ambiguous patterns, test credentials mixed with production ones, revoked tokens still present in code. **Why it matters:** Rule-based detection inevitably encounters ambiguous patterns: credentials that look real but aren't, test keys mixed with production ones, revoked tokens still in code. AI adds a second layer of judgment to catch these cases. Coverage now extends beyond code repositories to non-code sources such as Confluence, Jira, Slack, and Microsoft Teams, so generic secrets can be detected on these sources without flooding your dashboard with false positives. Learn more: [Machine learning — False Positive Remover](../../secrets-detection/secrets-detection-engine/machine_learning.md#false-positive-remover) ## Incident prioritization (risk score) **What it does:** Assigns a risk score from 0 to 100 to every incident, with a human-readable explanation. **Why it matters:** Without prioritization, security teams either treat everything as high-priority or rely on coarse severity buckets. Risk scoring turns the incident queue into a ranked list that reflects actual business impact. Learn more: [Prioritize incidents — Risk score](../../internal-monitoring/remediate/prioritize-incidents.md) On public incidents, this ML-powered score is being replaced by the agents analysis described below. ## Agents analysis on public incidents (beta) **What it does:** Runs AI agents over public secret incidents to determine whether a leak found on public sources is actually related to your company, and how much it matters. Each incident gets a Company-related verdict and a risk score set by the agents, with the reasoning exposed in an Analysis tab. **Why it matters:** On public sources, the expensive question is not whether something is a secret but whether it is yours. A leak can come from a developer's personal project, a contractor, or an unrelated third party. Deterministic rules can only say "this matched your perimeter", which leaves analysts reading commits by hand. The agents make that judgment and explain it, so teams spend their time on leaks that genuinely belong to them. Learn more: [Agents analysis](../../public-monitoring/remediate/agents-analysis.md) ## Secret enrichment **What it does:** Adds provider, service category, and company context to generic secret detections. A generic "high-entropy string" becomes "Stripe API key" or "internal database credential" — with enough context to act immediately. **Why it matters:** A large portion of detected secrets are generic — high-entropy strings, connection URIs, unknown tokens. Without enrichment, these incidents are opaque: something was found, but nobody knows what service it belongs to, who owns it, or how critical it is. AI-powered enrichment reads the surrounding code context and infers the provider, category, and usage pattern — bringing generic secrets close to the quality level of specific detections. Learn more: [Machine learning — Secret Enricher](../../secrets-detection/secrets-detection-engine/machine_learning.md#secret-enricher) ## Similar issues **What it does:** Automatically groups related incidents so teams can remediate recurring patterns in batches instead of handling each incident individually. **Why it matters:** In large organizations, the same secret often appears in many places. Without grouping, each occurrence requires separate triage. With grouping, a team can remediate the entire pattern at once. Learn more: [Investigate incidents — Similar incident grouping](../../internal-monitoring/remediate/investigate-incidents.md) ## GitGuardian Assistant (alpha) **What it does:** A conversational AI assistant that helps analysts investigate incidents interactively — explaining risk, providing context, and suggesting next steps. **Why it matters:** Investigation is the most time-consuming part of remediation. Analysts need to understand what a secret is, where it's used, who committed it, and what the blast radius is. The assistant puts that context at their fingertips through natural conversation. For full details on the assistant, see the [GitGuardian Assistant documentation](../assistant/overview.md). For details on how your data is handled and which AI models are used, see the [AI Management Policy](./ai-management-policy.md). To control which AI features are active, see [AI settings](./ai-settings.md). --- ## AI Settings Workspace administrators have two controls in **Settings > Workspace > AI**: 1. **External LLM toggle** — enable or disable all calls to external large language models. When off, no data is sent to any third-party AI provider. Internal ML models continue to run. 2. **BYOC provider configuration** — route LLM calls through your own cloud provider account instead of GitGuardian's sub-processors. **AWS Bedrock is the first supported provider**, with more to follow. ## Customer options | Option | External LLM calls | What you get | |--------|-------------------|--------------| | **Default** (GitGuardian sub-processors) | Yes — via declared sub-processors | Full LLM-powered features. See the [AI Management Policy](./ai-management-policy.md). | | **BYOC** (Bring Your Own Cloud) | Yes — via your own cloud account | Full LLM-powered features, routed through your own infrastructure. At launch: AWS Bedrock only. | | **External LLM off** | No | External LLM features are disabled. Internal ML models remain active. | ## What the toggle controls "AI features" is an umbrella term that covers two distinct layers: - **Internal ML models** — run entirely on GitGuardian infrastructure. No data leaves. These currently power false positive detection, prioritization scoring on internal incidents, and similar issues grouping. - **External LLM calls** — calls to third-party large language models via GitGuardian's sub-processors (or your own cloud account with BYOC). The workspace toggle **only controls external LLM calls**. Internal ML models are unaffected by the toggle and continue to run. :::info Public Monitoring The [agents analysis](/public-monitoring/remediate/agents-analysis) on public incidents is outside the scope of this toggle. The agents analyze publicly available data in a shared pipeline rather than per workspace, so their output is unaffected when external LLM calls are disabled. ::: ## Bring Your Own Cloud (BYOC) :::info **At launch, the only supported BYOC provider is AWS Bedrock.** Other cloud providers will follow. ::: BYOC lets you route LLM calls through your own cloud provider account, giving your security team full control over the infrastructure that processes AI requests while keeping all LLM-powered features. GitGuardian offers BYOC (Cloud), not BYOK (Key). BYOC is a stronger guarantee because LLM calls go through your infrastructure. ### Supported providers: - [AWS Bedrock](./byoc-aws-bedrock.md) --- ## BYOC: AWS Bedrock GitGuardian authenticates to your AWS account using **OpenID Connect (OIDC)** federation — no long-lived AWS credentials are stored. When an LLM call is needed, GitGuardian: 1. Signs a short-lived JWT token identifying your GitGuardian workspace 2. Calls AWS STS `AssumeRoleWithWebIdentity` to exchange the JWT for temporary AWS credentials 3. Uses those credentials to invoke models on your Bedrock endpoint This mechanism is used for both **SaaS** and **Self-Hosted** deployments. ## Prerequisites - **Owner** or **Manager** role on your GitGuardian workspace - **AWS IAM permissions** to create OIDC providers, roles, and policies in your AWS account - **Amazon Bedrock model access** enabled in the target AWS region (see [AWS documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html)) ## Step 1: Add GitGuardian as an OIDC provider in AWS 1. Open the [IAM Console → Identity providers](https://console.aws.amazon.com/iam/home#/providers) 2. Click **Add provider** 3. Select **OpenID Connect** 4. Configure the provider: | Field | SaaS | Self-Hosted | |-------|------|-------------| | **Provider URL** | `https://api.gitguardian.com` | `https:///exposed` | | **Audience** | `sts.amazonaws.com` | `sts.amazonaws.com` | 5. Click **Add provider** ## Step 2: Create an IAM role 1. In the [IAM Console → Roles](https://console.aws.amazon.com/iam/home#/roles), click **Create role** 2. Select **Web Identity** as the trusted entity type 3. Choose the OIDC provider you just created 4. Select `sts.amazonaws.com` as the **Audience** ### Trust policy Add a condition on the `sub` claim to restrict role assumption to your specific GitGuardian workspace: 5. Click **Add condition**: - **Key**: `:sub` (e.g. `api.gitguardian.com:sub`) - **Condition**: `StringEquals` - **Value**: `gitguardian-account-id:` :::tip Finding your GitGuardian account ID Your account ID is visible in your GitGuardian dashboard URL: `https://dashboard.gitguardian.com/workspace//` ::: The resulting trust policy should look like this: **For SaaS users:** ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRoleWithWebIdentity", "Principal": { "Federated": "arn:aws:iam:::oidc-provider/api.gitguardian.com" }, "Condition": { "StringEquals": { "api.gitguardian.com:sub": "gitguardian-account-id:", "api.gitguardian.com:aud": "sts.amazonaws.com" } } } ] } ``` **For Self-Hosted users:** ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRoleWithWebIdentity", "Principal": { "Federated": "arn:aws:iam:::oidc-provider//exposed" }, "Condition": { "StringEquals": { "/exposed:sub": "gitguardian-account-id:", "/exposed:aud": "sts.amazonaws.com" } } } ] } ``` ### Permission policy 6. Click **Next** 7. Attach a policy granting Bedrock invoke access. You can use the AWS managed policy `AmazonBedrockFullAccess`, or create a more restrictive custom policy: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream" ], "Resource": [ "arn:aws:bedrock:*::foundation-model/anthropic.*", "arn:aws:bedrock:*:*:inference-profile/us.anthropic.*", "arn:aws:bedrock:*::foundation-model/amazon.nova-*", "arn:aws:bedrock:*:*:inference-profile/us.amazon.nova-*" ] } ] } ``` :::note GitGuardian uses [cross-region inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html) to invoke models as most modern models require it. Include the inference profile ARN matching the AWS region of your Bedrock: `us.anthropic.*`, `eu.anthropic.*`. The cross-region inference profile is mandatory: the Anthropic models GitGuardian relies on are mostly not available in Region mode. See [Anthropic model region compatibility](https://docs.aws.amazon.com/bedrock/latest/userguide/models-region-compatibility.html#model-regions-anthropic). ::: 8. Click **Next** 9. Name the role (e.g. `GitGuardianBedrockAccess`) and click **Create Role** ## Step 3: Configure the integration in GitGuardian 1. In the GitGuardian platform, navigate to **Settings → Workspace → AI** 2. Click **Edit** button 3. Select **Custom AWS Bedrock** as the provider 4. Enter: - **AWS Account ID**: Your AWS account identifier - **Role ARN**: The ARN of the role created in Step 2 (e.g. `arn:aws:iam::123456789012:role/GitGuardianBedrockAccess`) - **Region**: The AWS region where you have Bedrock model access enabled (e.g. `us-west-2`) 5. Click **Install** — GitGuardian will perform a connectivity check to verify the configuration That's it! GitGuardian will now use your AWS Bedrock account for LLM-powered features. --- ## Why enable third-party LLMs AI has been part of GitGuardian from the start. We built and hosted our own machine-learning models to power capabilities like false positive detection, risk scoring, incident enrichment, and guided remediation. These internal models served us well, but the landscape has changed. Third-party large language models (LLMs) now deliver a quality leap that is transformational, not incremental. They understand code and context with a depth that purpose-built internal models cannot match, and they improve at a pace we could not sustain alone. We are progressively replacing our internal models with third-party LLMs to bring that value to every customer. We will rely on third-party LLMs more and more to bring value to the platform. The improvements they deliver to false positive reduction, contextual analysis, and guided remediation are too significant to withhold from our customers. Adopting third-party LLMs does not mean compromising on security: our secrets detection engine scans and redacts any secret it finds before data is sent to an external model. Customer data is never used for training and is never retained by any AI provider. For full details, see our [AI management policy](ai-management-policy). To control how AI features operate in your workspace, see [AI settings](ai-settings). --- ## Internal Monitoring GitGuardian's Analytics offers robust data visualization and actionable insights, empowering you to monitor your security posture, track performance trends, and make informed decisions. :::info Analytics are only accessible to: - Workspace **Owner** and **Managers**. - **Members** with `Full access` incident permissions on the **All-incidents** team. Analytics are computed once daily. Data may take up to 24 hours to appear for new self-hosted installations or new SaaS workspaces. ::: ## Monitor your security posture across 4 dimensions The Internal Monitoring Analytics is structured to deliver clear, in-depth insights across four key security areas: 1. **"Protect"** section provides an overview of your current monitoring coverage Once you have enabled full-breadth coverage on your sources, your focus shifts to two main objectives: stopping new leaks and resolving existing incidents. 2. **"Detect"** section helps you identify the sources and teams involved in leaks, including recurring issues, so you can plan training or actions to reduce and prevent them. 3. **"Remediate"** section guides you in addressing existing incidents, prioritizing the most critical cases, and leveraging GitGuardian’s automated remediation tools. 4. **"Prevent"** section helps you track and assess whether your prevention strategy is effective, and ensures that appropriate measures are in place to prevent future problems. ![Dimensions tabs](/img/analytics/anaytics-pages.png) ### Protect Navigate to the **Analytics** page in your GitGuardian dashboard, select **Internal Monitoring**, and then click on the **[Protect tab](https://dashboard.gitguardian.com/analytics/internal-monitoring/protect)**. **Purpose:** These analytics indicates how healthy your sources are regarding coverage. Are they monitored effectively? Do you have any gaps? How many commits are scanned, and how many secrets are found? 1. **Count of Sources**: Displays the percentage of monitored sources over time, helping identify whether all sources are properly monitored and highlighting discrepancies between total sources and those eligible for historical scanning. 2. **Count of Sources by Category**: Shows the percentage of monitored sources by category (e.g., code repositories), providing insight into which source types are monitored and identifying any under-monitored categories. 3. **Percentage of Blocked GitHub PRs**: Illustrates the percentage of GitHub pull requests blocked from merging due to detected secrets, indicating the effectiveness of secret detection in preventing sensitive data leaks via PRs. 4. **GitHub PRs with Check Runs**: Shows the total number of GitHub PRs scanned by GitGuardian, tracking coverage and integration of secret scanning in the PR workflow. 5. **Percentage of Commits Containing Secrets**: Displays the percentage of commits containing secrets out of the total commits scanned, helping assess the prevalence of hardcoded secrets codebases over time. 6. **Commits Scanned**: Shows the total number of commits scanned for secrets, regardless of whether secrets were found, indicating overall scanning activity and coverage. ### Detect Navigate to the **Analytics** page in your GitGuardian dashboard, select **Internal Monitoring**, and then click on the **[Detect tab](https://dashboard.gitguardian.com/analytics/internal-monitoring/detect)**. **Purpose:** These analytics offers insights into where and how secrets are detected, highlighting incident creation. These help you understand where and how secrets are being detected in your organization, which types of secrets are most problematic, and which sources and teams are most frequently involved. This allow you to understand where the leaks come from and how important they are. 1. **New incidents created**: Shows the number of newly created incidents over time, categorized by severity (Critical, High, Medium, Low, Info, Unknown) or validity. Helps prioritize remediation efforts by visualizing when and how many incidents of each severity occur. 2. **Most detected secrets**: Displays the most frequently detected secret types (e.g., generic high entropy secrets, passwords, API keys, credentials). Useful for identifying which kinds of secrets are most commonly leaked and may require targeted prevention or education. 3. **Top sources by incident count**: Lists the sources (repositories, etc.) responsible for the most incidents, broken down by severity or validity. Helps pinpoint where secret leaks are originating, so you can focus remediation and exclusion efforts on problematic sources. 4. **Top teams by incident count**: Shows which teams are responsible for the most incidents, broken down by severity or validity. Useful for identifying teams that may need additional training, support, or process improvements to reduce secret leaks. ### Remediate Navigate to the **Analytics** page in your GitGuardian dashboard, select **Internal Monitoring**, and then click on the **[Remediate tab](https://dashboard.gitguardian.com/analytics/internal-monitoring/remediate)**. **Purpose:** These analytics help you track and prioritize the most critical cases, monitor the status of open and closed incidents, and measure the effectiveness of your remediation efforts. By leveraging GitGuardian’s automated remediation tools, you can streamline incident resolution, reduce backlog, and continuously improve your incident response processes. 1. **Average open incidents per source (code repositories only)**: Tracks the average number of unresolved incidents per code repository over time. Helps monitor whether remediation efforts are keeping pace with incident creation and highlights trends in backlog. 2. **Open incidents**: Shows the total number of incidents that are currently unresolved and require attention. Useful for understanding the current workload and prioritizing remediation. 3. **Closed incidents**: Displays the total number of incidents that have been resolved and closed over time. Indicates remediation progress and effectiveness. 4. **Auto-closed by GitGuardian automations**: Shows incidents that were automatically closed by system automations. Highlights the efficiency and impact of automated remediation. 5. **Top teams by closed incidents**: Lists teams that closed the most incidents during the selected period. Helps identify high-performing teams and distribute workload insights. 6. **Top sources by closed incidents**: Identifies sources (repositories, directories, etc.) with the most incidents closed during the selected period. Useful for prioritizing remediation efforts and understanding which sources are being effectively managed. 7. **Median time to remediate**: Displays the median time taken to resolve incidents each month. Helps monitor changes in response times, identify trends, and pinpoint areas for improvement in remediation processes. ### Prevent or "Shift Left" protection Navigate to the **Analytics** page in your GitGuardian dashboard, select **Internal Monitoring**, and then click on the **[Prevent tab](https://dashboard.gitguardian.com/analytics/internal-monitoring/prevent)**. **Purpose:** These analytics help you measure the effectiveness and adoption of your secret leaks prevention strategies through GGShield. Here, you can track incidents avoided, scan activity, and developer engagement, helping you ensure that preventive measures are in place and effective. These insights empower you to assess the impact of your preventive controls and continuously improve your organization’s secret management practices. 1. **New incidents found in realtime** : Shows the number of new incidents detected in real time. Helps monitor immediate risk and the effectiveness of real-time secret detection. 2. **Total count of incidents avoided by GGShield** :Tracks the number of incidents prevented by GGShield scans (e.g., pre-commit, path, pre-push, etc.), demonstrating the tool’s effectiveness in stopping hardcoded secrets before they become security incidents. 3. **GGShield scans over time** : Shows the total number of GGShield CLI scans executed during the selected period, broken down by scan mode (e.g., pre-commit, path, pre-push, etc.). Indicates adoption, usage patterns, and coverage of secret scanning across workflows. 4. **Active GGShield users** : Displays the number of unique developers actively using GGShield, counted by Personal Access Token usage in the last 30 days. Helps track engagement and adoption of secret prevention tools among developers. ## Analytics Tools ### Page level filters ![Analytics - Page levels Tools tabs](/img/analytics/page-level-tools.png) With page-level tools, you can filter the entire page by: - A specific time period (e.g., "Last 3 months", "All time") - Custom time intervals ("buckets") such as day, week, month, or year - A particular team :::warning - Not all charts support team-based filtering. If a chart does not support team filtering, a specific warning will appear. - Certain filter selections (such as "all time" combined with "group by day") may not be rendered due to data volume limitations. In these cases, a warning will also be displayed. ::: ### Chart level tools At the chart level, you have several tools to help you customize and analyze your data: #### Filters Apply filters directly to individual charts to focus on specific data segments ![Analytics - Chart levels Tools Filters](/img/analytics/analytics-chart-filters.png) #### CSV export You can export the data from any chart as a CSV file for use in external analysis or reporting tools. :::info The exported CSV reflects any breakdowns you have applied. ::: ![Analytics - Chart levels Tools Filters](/img/analytics/analytics-chart-csv-export.png) #### Breakdowns Break down your chart data by various dimensions (such as severity, validity, etc.) to uncover deeper insights and make comparisons across different categories. :::info Table charts automatically adjust their columns based on the selected breakdown. ::: ![Analytics - Chart levels Tools Breakdowns](/img/analytics/analytics-chart-breakdown.png) #### Display options: Show/Hide specific breakdown values Easily display or hide specific breakdown categories in your chart to concentrate on the data that matters most to you. ![Analytics - Chart levels Tools Labels Filters](/img/analytics/analytics-chart-label-filters.gif) #### Display options: Show/Hide values or percentages Easily switch between displaying absolute values and percentages on your charts to tailor data visualization to your preferences and analysis needs. ![Analytics - Chart levels Tools Show Hide Percentage and Values](/img/analytics/analytics-chart-show-hide-percentage-values.gif) --- ## Overview(Analytics) The Analytics Overview page provides executives and security leaders with an instant pulse on your organization's security posture. It aggregates key performance indicators (KPIs) from across the GitGuardian platform into a single, streamlined dashboard designed for leadership reviews and status reporting. :::info Analytics are computed once daily. Data may take up to 24 hours to appear for new self-hosted installations or new SaaS workspaces. ::: ## Access the Overview dashboard Navigate to **[Analytics > Overview](https://dashboard.gitguardian.com/analytics/overview)** in your GitGuardian dashboard. Use the time period selector in the top-right corner to adjust the reporting window (e.g., "Last quarter", "Last month"). ![Analytics Overview dashboard](/img/analytics/analytics-overview.png) ## Unified KPI strip At the top of the page, four KPIs provide a quick status check across all security dimensions: | KPI | Description | |-----|-------------| | **Protect** | Number of internal repositories currently monitored, with trend indicator showing coverage changes | | **Detect** | Count of critical incidents detected, with trend indicator | | **Remediate** | Median time to remediate critical incidents | | **Govern** | NHI governance metrics (coming soon) | Each KPI includes a trend indicator showing percentage change, helping you quickly identify improvements or areas needing attention. **How trend percentages are calculated:** The trend percentage compares today's value to the value from the start of your selected time period: - **Last month**: Compares today's data to the value from 30 days ago - **Last quarter**: Compares today's data to the value from 90 days ago For example, if you select "Last quarter" and your monitored repositories increased from 500 to 713, the trend indicator shows +42.6%. ## Protect section The Protect section focuses on your monitoring coverage: ### Monitored perimeter A bar chart showing the evolution of your monitored source count over time. Use this to: - Track how your coverage grows month over month - Identify drops in coverage that may indicate configuration issues ### Top data sources with critical or high incidents A horizontal bar chart highlighting which repositories generate the most critical and high-severity incidents. This helps you: - Identify where risk concentrates in your organization - Prioritize remediation efforts on high-risk repositories - Focus developer training on teams owning problematic sources ## Sources summary At the bottom of the page, a summary card displays your connected sources: - **Code repositories**: Total count with breakdown by provider (GitHub, GitLab, etc.) - **Documentation**: Confluence, SharePoint, and other documentation sources - **File storage**: OneDrive, Google Drive, and similar services - **Docker**: Container registry sources - **Custom sources**: Any custom integrations Use the **Add** buttons to quickly expand your monitoring perimeter to new source types. ## Use cases ### Leadership reviews Use the Overview dashboard for weekly or monthly security reviews: 1. Check the KPI strip for a quick status assessment 2. Review trend indicators to validate progress against goals ### Status reporting Generate executive summaries by: 1. Selecting the appropriate time period 2. Capturing the KPI strip for high-level metrics 3. Highlighting top risky data sources that need attention ## Related documentation - [Internal Monitoring Analytics](/platform/analytics/internal-monitoring) - Detailed analytics across Protect, Detect, Remediate, and Prevent dimensions --- ## GitGuardian Assistant :::info This feature is only available for workspaces with a Business plan. ::: :::warning[Alpha] The GitGuardian Assistant is currently in **private alpha**. Features and behavior may change as we iterate based on user feedback. Interested in trying the assistant? Contact us at [support@gitguardian.com](mailto:support@gitguardian.com) or reach out to your CSM or account manager to request access. ::: The GitGuardian Assistant helps you investigate, understand, and remediate secret incidents directly from the [internal monitoring](../../internal-monitoring/home.mdx) dashboard. It works alongside you in a conversational interface: it can execute actions on your behalf (such as assigning incidents or updating tags), but only after you explicitly approve them. :::note We use our industry leading detection engine to detect and redact secrets before we send data to the AI model. For more details, see [Data security and privacy](./security.md). ::: ## Key capabilities - **Incident investigation**: Explain threat patterns, analyze scope and impact, and identify related incidents. - **Remediation planning**: Get tailored remediation steps and prioritization guidance grounded in GitGuardian documentation and security best practices. - **Incident management**: Assign incidents, manage tags, update incident details, and explore monitored sources — all through natural language. The assistant proposes each action and waits for your confirmation before executing. ## How it works The assistant is available from the incident detail page. When you ask a question or make a request, it: 1. **Understands your intent** using the context of the incident you are viewing and your conversation history. 2. **Gathers information** by querying your incident data, workspace details, or GitGuardian documentation as needed. 3. **Responds or proposes an action** — for read-only queries it answers directly; for write actions (assigning, tagging, updating) it presents the proposed change and waits for your approval. The assistant does not operate autonomously or run tasks in the background. Every interaction is initiated by you and requires your presence in the conversation. ## Getting started 1. Navigate to an incident detail page in the [internal monitoring](../../internal-monitoring/home.mdx) dashboard 2. Open the assistant interface in the sidebar 3. Type your question or request in natural language 4. Review the response and approve any proposed actions ## Providing feedback Your feedback is especially valuable during the private alpha. After each response, you can rate it, add comments, or report issues. This feedback directly shapes how we improve the assistant. ## Limitations - **Internal monitoring only**: The assistant is currently available only in the [internal monitoring](../../internal-monitoring/home.mdx) product. - **Human oversight required**: All write actions require your explicit approval. Critical security decisions should always be reviewed by your team. - **Private alpha**: As a private alpha feature, you may encounter rough edges. Your [feedback](#providing-feedback) helps us improve. ## Next steps - [Learn about assistant tools](./tools-reference.md) - Explore the specific tools the assistant uses to help you - [GitGuardian MCP Server](https://github.com/GitGuardian/ggmcp) - Bring GitGuardian secret detection and incident management to your IDE or CLI using the Model Context Protocol --- ## Data security and privacy :::warning[Alpha] The GitGuardian Assistant is currently in **private alpha**. Features and behavior may change. Contact us at [support@gitguardian.com](mailto:support@gitguardian.com) or reach out to your CSM or account manager to request access. ::: The GitGuardian Assistant is designed with security and privacy as core principles. This page explains how your data is handled when interacting with the assistant. - **We use our industry leading detection engine to redact secret values** before any data reaches the AI model — only metadata (type, severity, location, status) is shared - **Workspace boundaries respected** — the assistant operates with the user's own permissions, never exceeding their access level - **No model-provider training** — prompts and responses are never shared with model providers; powered by Amazon Bedrock with strict data controls - **Zero data retention** — data passes through for inference only, nothing is stored by Bedrock or the model provider ## Secret redaction Sensitive values such as the secret itself are always **redacted** before being sent to the AI model. The assistant does not need to see the actual secret to provide threat analysis or remediation guidance. Only metadata about the incident (type, severity, locations, status) is shared with the model. ## AI infrastructure The GitGuardian Assistant is powered by [Amazon Bedrock](https://aws.amazon.com/bedrock/), a fully managed AI service provided by AWS. Amazon Bedrock allows GitGuardian to leverage large language models while maintaining strict control over your data. ### Your data is never used for model training Inputs and outputs sent through Amazon Bedrock are **never used to train or improve** the underlying AI models. This is a core guarantee of the Amazon Bedrock service: - No customer data is used to train, retrain, or improve base models. - Model providers have no access to your data at any point. See [Amazon Bedrock Data Protection](https://docs.aws.amazon.com/bedrock/latest/userguide/data-protection.html) for details. ### Your data is not persisted by the model provider Amazon Bedrock does not store or log your prompts and responses. Your data passes through the model for inference and is not retained by Amazon Bedrock or the model provider after the response is generated. See [Security, Privacy, and Responsible AI — Amazon Bedrock](https://aws.amazon.com/bedrock/security-privacy-responsible-ai/) for details. ### Encryption All data exchanged with Amazon Bedrock is encrypted: - **In transit**: All communications between GitGuardian and Amazon Bedrock are encrypted using TLS. - **At rest**: Any data stored on the GitGuardian side is encrypted at rest using industry-standard encryption. Amazon Bedrock supports customer-managed encryption keys through [AWS Key Management Service (KMS)](https://docs.aws.amazon.com/bedrock/latest/userguide/encryption-at-rest.html). See [Amazon Bedrock Data Protection](https://docs.aws.amazon.com/bedrock/latest/userguide/data-protection.html) for details on encryption guarantees. ## What data is sent to the model When you interact with the assistant, the following data may be sent to the AI model for processing: - **Your message**: The question or request you type in the assistant interface. - **Incident context**: Details about the incident you are viewing, such as the secret type, severity, locations, and status. This context allows the assistant to provide relevant and tailored responses. - **Conversation history**: Previous messages in the current conversation, so the assistant can maintain context across follow-up questions. As described in [Secret redaction](#secret-redaction) above, actual secret values are always redacted before being sent to the model. --- ## Assistant tools reference :::warning[Alpha] The GitGuardian Assistant is currently in **private alpha**. Features and behavior may change. Contact us at [support@gitguardian.com](mailto:support@gitguardian.com) or reach out to your CSM or account manager to request access. ::: The GitGuardian Assistant uses a collection of specialized tools to help you manage secret incidents. Each tool is designed for a specific purpose and operates within your workspace's security context. ## Understanding assistant tools When you ask the assistant a question or make a request, it automatically selects the appropriate tool(s) to fulfill your needs. You don't need to specify which tool to use - simply describe what you want to accomplish in natural language. ### Tool approval Some tools that modify your data require your explicit approval before executing. When the assistant needs to perform a write action (such as assigning an incident or updating tags), it will present the action and its parameters for your review. You can then approve or reject the action before it is carried out. Read-only tools (such as listing incidents or searching documentation) are executed automatically without requiring approval. ## Available tools | Tool | Description | Approval required | |------|-------------|:-----------------:| | [List Incidents](#list-incidents) | Search and filter incidents in your workspace | No | | [Get Incident](#get-incident) | Get full details for a specific incident | No | | [List Repo Occurrences](#list-repo-occurrences) | View where a secret appears across repositories | No | | [List Users](#list-users) | Browse workspace members | No | | [Get Member](#get-member) | Get details about a specific workspace member | No | | [List Sources](#list-sources) | View monitored repositories and integrations | No | | [List Detectors](#list-detectors) | View available secret detectors | No | | [Read Custom Tags](#read-custom-tags) | View tags applied to an incident | No | | [Write Custom Tags](#write-custom-tags) | Set custom tags on an incident | Yes | | [Update Or Create Incident Custom Tags](#update-or-create-incident-custom-tags) | Batch add or update tags across incidents | Yes | | [Manage Private Incident](#manage-private-incident) | Update incident status or properties | Yes | | [Assign Incident](#assign-incident) | Assign an incident to a team member | Yes | | [Get Attack Pattern Guidance](#get-attack-pattern-guidance) | Understand why a secret exposure is risky | No | | [Get Remediation Plan Guidance](#get-remediation-plan-guidance) | Get a step-by-step remediation plan | No | | [Search GitGuardian Documentation](#search-gitguardian-documentation) | Search GitGuardian docs and knowledge base | No | --- ## Tool details ### List Incidents Searches for incidents matching your criteria and returns incident details including status, severity, metadata, detection date, source, and associated tags. **Example questions:** - "Show me all open incidents from last week" - "Find incidents related to AWS credentials" - "List high-severity incidents assigned to my team" :::note By default, the assistant filters out low-severity incidents, false positives, and test files to focus on the most relevant results. You can ask for specific filters to override this behavior. ::: --- ### Get Incident Fetches comprehensive details for a single incident, including all occurrences and their locations, validity and presence check results, tags, and assignments. **Example questions:** - "Tell me more about incident #12345" - "What's the status of this incident?" - "Show me the details of the current incident" --- ### List Repo Occurrences Lists all locations where a secret has been found, including which repositories, branches, and commits are affected. Helps assess the exposure scope of an incident. **Example questions:** - "Where does this secret appear in our codebase?" - "Show me all occurrences for this incident" - "Which repositories contain this leaked credential?" --- ### List Users Returns a list of workspace members. Useful for identifying who to assign incidents to. **Example questions:** - "Who are the members of my workspace?" - "List all users" --- ### Get Member Retrieves detailed information about a specific member of your workspace, such as their role and permissions. **Example questions:** - "Show me details about John" - "What role does Sarah have?" - "Who is the owner of this workspace?" --- ### List Sources Shows which repositories and integrations are monitored by GitGuardian in your workspace. **Example questions:** - "What sources are being monitored?" - "Show me the list of connected repositories" --- ### List Detectors Shows which types of secrets GitGuardian can detect and provides information about detector categories. **Example questions:** - "What types of secrets can GitGuardian detect?" - "Show me available detectors" --- ### Read Custom Tags Returns the custom tags currently applied to an incident. Useful for understanding how an incident has been categorized before making changes. **Example questions:** - "What tags are on this incident?" - "Show me the tags for incident #12345" - "Is this incident tagged as high-priority?" --- ### Write Custom Tags Sets custom tags on a specific incident. Creates new tags if they don't already exist in your workspace. **Example requests:** - "Tag this as 'reviewed-by-security-team'" - "Set the tags to 'production' and 'database-access'" - "Replace the tags on this incident with 'urgent'" :::note This action requires your approval before executing. ::: --- ### Update Or Create Incident Custom Tags Adds or updates custom tags across one or more incidents. Supports batch operations for organizing multiple incidents at once. **Example requests:** - "Add the 'high-priority' tag to all open AWS incidents" - "Tag these three incidents with 'sprint-42'" - "Add 'needs-rotation' to all critical incidents from last week" **Common tagging strategies:** - **By team**: `frontend-team`, `backend-team`, `infra-team` - **By project**: `project-alpha`, `payment-service`, `user-auth` - **By status**: `needs-review`, `in-progress`, `waiting-rotation` - **By priority**: `urgent`, `high-priority`, `can-wait` :::note This action requires your approval before executing. ::: --- ### Manage Private Incident Updates incident properties such as status through natural language commands. All changes are logged for audit purposes. **Example requests:** - "Mark this incident as resolved" - "Ignore this incident - it's a false positive" - "Reopen incident #12345" :::note This action requires your approval before executing. The assistant will show you the proposed changes for confirmation. ::: --- ### Assign Incident Assigns one or more incidents to a user in your workspace. Helps distribute remediation work across the team. All assignments are logged for tracking purposes. **Example requests:** - "Assign this incident to John" - "Who can handle this? Assign it to someone from the backend team" - "Assign all open AWS incidents to me" :::note This action requires your approval before executing. ::: --- ### Get Attack Pattern Guidance Analyzes the type of secret exposed and provides a detailed explanation of potential attack vectors, impact of unauthorized access, risk factors specific to your incident, and references to relevant security resources. **Example questions:** - "Why is this AWS key dangerous?" - "Explain the threat posed by this incident" - "What could an attacker do with this secret?" --- ### Get Remediation Plan Guidance Generates a step-by-step remediation plan tailored to a specific incident, including guidance on secret rotation, best practices for secure storage, recommendations for preventing future exposures, and integration suggestions. **Example questions:** - "How should I remediate this incident?" - "Create a remediation plan for this AWS key exposure" - "What steps should I take to fix this?" --- ### Search GitGuardian Documentation Searches GitGuardian documentation and knowledge base to find relevant articles, best practice guidance, and product feature information. **Example questions:** - "How do I set up Slack notifications?" - "What is validity checking?" - "How do Secret Manager integrations work?" ## Tool permissions The assistant executes all actions using your own permissions. It can only read and modify data that you have access to in the GitGuardian dashboard. If you don't have permission to perform an action manually, the assistant won't be able to do it on your behalf either. Write actions (such as assigning incidents, updating status, or managing tags) additionally require your explicit approval before the assistant executes them. ## Best practices ### Be specific The more specific your request, the better the assistant can help: - "Show me open AWS credential incidents from the last 30 days" - Avoid: "Show me some incidents" ### Use natural language You don't need to know technical details - just describe what you need: - "Help me understand why this database password is risky" - Avoid: "Execute explain_threat tool with incident_id parameter" ### Review write actions carefully When the assistant asks for approval on a write action: - Review the proposed changes and their parameters - Verify the target incidents are correct, especially for bulk operations - Reject and clarify if the action doesn't match your intent ## Feedback and improvements If a tool doesn't work as expected: 1. Rate the response to indicate the issue 2. Provide specific feedback on what went wrong 3. Include details about what you expected Your feedback helps improve tool accuracy and reliability. --- ## Available playbooks GitGuardian provides several built-in playbooks that can be applied to internal incidents, public incidents, or both. ### Auto-share incident public link to involved developer :::info This playbook is available only for Internal Monitoring. ::: Automates sharing incidents with involved developers via email with public share links. **Trigger**: Incident created by non-workspace member **Action**: Creates public share link and emails developer **Requirements**: Public sharing must be enabled in workspace settings **Options:** - **Feedback collection**: Developer can submit feedback via the link - **Resolution capability**: Developer can resolve/ignore incident via the link > If the incident is triggered by a workspace member, this playbook won't apply as they can access the incident through the authenticated dashboard. ![Auto-share incident link playbook](/img/platform/playbooks/playbook-auto-share-incident-link.png) ### Auto-grant access to involved developer (in-app) :::info This playbook is available for both Internal Monitoring and Public Monitoring. ::: Automatically grants incident access to workspace members with Restricted or Member access levels when they are involved in the incident. **Trigger**: The playbook grants access in three situations: - *New incidents* — when a new incident is detected involving a workspace member, that member is granted access automatically. - *On activation (historical incidents)* — when the playbook is first enabled, GitGuardian runs a one-time backfill that grants access to **all existing incidents** where a current workspace member is the author. Enabling the playbook therefore applies retroactively, not only to incidents detected afterwards. - *When a member joins* — when a new member is added to the workspace while the playbook is active, they are granted access to the existing incidents they are involved in. **Action**: Grants the involved user access to view this specific incident. This is done by matching the commit author email against the dashboard user email. ![Auto-grant access playbook](/img/platform/playbooks/playbook-auto-grant-access.png) ### Auto-resolve revoked secrets :::info This playbook is available for both Internal Monitoring and Public Monitoring. It is activated by default for Internal Monitoring. ::: Automatically resolves incidents when previously valid secrets are revoked. **Trigger**: A secret previously checked as valid by GitGuardian becomes invalid. **Action**: Automatically close the incident as "Resolved", with reason "Secret was revoked" Activating this playbook applies to both real-time detection (when an incident is re-checked and found invalid) and all historical incidents that became invalid in the past. Upon activation, you will see a confirmation prompt indicating how many historical incidents will be automatically resolved. ![Auto-resolve revoked secrets playbook](/img/platform/playbooks/playbook-auto-resolve-revoked.png) ### Auto-ignore invalid secrets :::info This playbook is available for both Internal Monitoring and Public Monitoring. It is activated by default for Internal Monitoring. ::: Automatically ignores open incidents whose secret is known to be invalid. **Trigger**: GitGuardian learns that the secret of an open incident is invalid. This happens in four situations: - *New incidents*: an incident is created with a secret that is already checked as invalid. - *Validity re-checks*: a periodic re-check, an on-demand re-check, an endpoint validity refresh, or a manual validity override reports the secret as invalid. - *Regressions*: an incident re-opens while its secret is still invalid. - *On activation (historical incidents)*: when the playbook is first enabled, GitGuardian applies it to the existing incidents of your workspace. **Action**: Automatically close the incident as "Ignored", with reason "Invalid secret". Upon activation, you will see a confirmation prompt indicating how many historical incidents will be automatically ignored. **Precedence with Auto-resolve revoked secrets**: both playbooks react to the same signal. Auto-resolve revoked secrets runs first and takes the incidents whose secret was checked as valid at least once. Auto-ignore invalid secrets then takes the incidents still open. | Secret validity history | Auto-resolve revoked secrets | Outcome | | ------------------------------ | ---------------------------- | ------------------------------------------ | | Was checked as valid at least once | Active | Resolved, with reason "Secret was revoked" | | Was checked as valid at least once | Inactive | Ignored, with reason "Invalid secret" | | Was never checked as valid | Active or inactive | Ignored, with reason "Invalid secret" | :::note This playbook does not apply to detectors that support custom hosts. For those detectors, validity depends on which host the secret is checked against. See [Customize validity checks](../../secrets-detection/customize-detection/validity-checks.md#customize-validity-checks). ::: ![Auto-ignore invalid secrets playbook](/img/platform/playbooks/playbook-auto-ignore-invalid.png) ### Auto-ignore false positives :::info This playbook is available and enabled by default for both Internal Monitoring and Public Monitoring. ::: Automatically ignores incidents that have been tagged as false positives by GitGuardian's internal machine learning model. **Trigger**: An incident is identified as a false positive by the ML model **Action**: Automatically close the incident as "Ignored", with reason "False positive (not a secret)" This playbook works exclusively with generic secrets, as the machine learning model only analyzes this secret type. It applies to real-time detection whenever an incident is identified as a false positive, and can also be applied to historical incidents by launching a historical scan on your perimeter. Activating this playbook applies to both real-time incidents and historical incidents that were already invalid when detected. Upon activation, you will see a confirmation prompt indicating how many historical incidents will be automatically resolved. ![Auto-ignore false positive playbook](/img/platform/playbooks/playbook-auto-ignore-false-positive.png) --- ## Automate with playbooks Playbooks enable you to **automate some remediation behaviors** across your workspace. They are process flows that run a series of automated jobs without manual intervention from security or software engineers. Playbooks are accessible in [your workspace settings](https://dashboard.gitguardian.com/settings/workspace/playbooks). :::info Playbooks is a business feature. Only managers can activate/deactivate playbooks. ::: ## How playbooks work Playbooks operate through **event-driven automation**: 1. **Trigger event**: Something happens in your GitGuardian workspace (e.g., new incident detected) 2. **Condition check**: The playbook evaluates if its conditions are met 3. **Automated action**: If conditions match, the playbook executes its configured actions 4. **Audit trail**: All actions are logged with "GitGuardian Bot" attribution ## Apply to Internal and/or Public Monitoring Playbooks can be configured to work with: - **Internal incidents** (from [Internal Monitoring](../../internal-monitoring/home)) - **Public incidents** (from [Public Monitoring](../../public-monitoring/home) - if this product is enabled for your workspace) Each playbook shows an "Apply to" section where you can toggle support for internal incidents and/or public incidents. Learn more about [available playbooks](./available-playbooks.md). --- ## Custom tags ## Using custom tags Custom tags offer a flexible way to organize and manage objects such as incidents and honeytokens within your workspace. Unlike GitGuardian tags, which are predefined and automatically applied to objects, custom tags allow you to define your own labels in the form of keys and values. You can assign these custom tags to incidents and honeytokens, enabling you to filter and search for them based on specific characteristics relevant to your organization. For more information on GitGuardian tags for incidents, refer to the [GitGuardian tags](../../internal-monitoring/remediate/prioritize-incidents#gitguardian-tags) documentation. Limitations apply to custom tags, depending on your plan: - **Personal**: Max tags per workspace: 100 (10 keys × 10 values), Max tags per resource: 1 - **Business and Trial**: Max tags per workspace: 2,500 (50 keys × 50 values), Max tags per resource: 10 - **Character limit per tag**: 100 (50 for key, 50 for value) ### Categorize your incidents Custom tags provide a flexible way to organize incidents. You can create your own custom tags in the form of keys and values, assign them to incidents, and use them to filter and search for incidents based on specific characteristics. Note that you must have ["Can edit" permissions](./teams#define-their-incident-permissions) or be a manager to assign or remove custom tags from incidents. ### Categorize your honeytokens Custom tags provide a flexible way to organize honeytokens. You can create your own custom tags in the form of keys and values, assign them to honeytokens, and use them to filter and search for honeytokens based on specific characteristics. ### Manage custom tags Go to **Settings > Workspace > [Tags](https://dashboard.gitguardian.com/settings/workspace/tags)** to access the Tags settings page. From here, you can view the existing tags and see how many incidents or honeytokens are categorized under them. Note that you must be a manager to manage custom tags. ![Tags settings](/img/platform/collaboration-and-sharing/custom-tags/custom-tags-settings.png) #### Create custom tags You can create new keys and values from the [Tags settings page](https://dashboard.gitguardian.com/settings/workspace/tags). Note that you can create a single-word tag. #### Edit or delete custom tags On the [Tags settings page](https://dashboard.gitguardian.com/settings/workspace/tags), to the right of the tag's name, click the ![platform icon](/img/icons/three-dots-menu.svg) menu, then select **Edit** or **Delete** to bring up the option to edit or delete the tag. Note that deleting a tag is not reversible, even if it is used in incidents or honeytokens. However, it is still possible to delete it, which will remove it from any incident and honeytoken. Similarly, if you edit a tag, the modification will be applied to all incidents and honeytokens that use that tag. ### Examples of use - Create an `env` key with values such as `prod`, `test`, `staging`, etc. - Create a `place` key with values such as `codebase`, `docker`, `jenkins`, `jira`, `slack`, etc., to represent the location where the honeytoken is deployed. - Create a `team` key with values representing your teams and indicating which scope is covered by a honeytoken. - Create a single `reviewed` tag to indicate that closed incidents have been reviewed and validated after resolution. ### Python3 example Here is a Python3 example of how to automate applying a custom tag from a custom webhook: 1. **Create a Service Account Token** in GitGuardian with custom tag and incidents read and write permissions. 2. **Receive a new occurrence** via a [custom webhook](../configure-alerting/notifiers-integrations/custom-webhook):
Example of the webhook payload ```json { "source": "GitGuardian", "timestamp": "2025-03-23T09:10:24.594597Z", "action": "new_occurrence", "message": "A new occurrence has been detected for this incident.", "target_user": "GitGuardian", "incident": { "id": 31605, "date": "2025-03-16T08:23:40Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "Api", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "secret_revoked": false, "occurrence_count": 5, "status": "assigned", "regression": false, "assignee_email": "bruce.wayne@charadriidae.org", "severity": "high", "validity": "not_checked", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null }, "occurrence": { "id": 1234, "incident_id": 1243, "kind": "RLTM", "sha": "xxx", "author_name": "GitHub", "author_info": "noreply@github.com", "date": "2025-03-23T09:10:23.529812Z", "presence": "visible", "url": "https://github.com/charadriidae/wrybill-new-zealand/commit/123#diff-xxx", "matches": [], "filepath": "TestJS.js", "change_type": "addition", "source": { "id": 710, "url": "https://github.com/charadriidae/wrybill-new-zealand", "type": "github", "full_name": "wrybill", "health": "at_risk", "open_incidents_count": 5, "closed_incidents_count": 0, "visibility": "private", "last_scan": { "status": "finished", "date": "2025-02-18T17:07:59.079520Z" }, "external_id": "github_id" } } } ```
3. **Apply a custom tag** depending on the source URL (e.g., if it contains `"wrybill"`, apply the custom tag `bird:wrybill`). Refer to the [GitGuardian API documentation for incidents](https://api.gitguardian.com/docs#tag/Secret-Incidents/operation/retrieve-incidents).
Example of the API call to apply a custom tag ```http PATCH https://api.gitguardian.com/v1/incidents/secrets/31605 ``` ```json { "custom_tags": [ { "key": "bird", "value": "wrybill" } ] } ```
Example of the python script ```python # Set the GitGuardian service account token and API base URL outside the function GITGUARDIAN_API_KEY = os.getenv("GITGUARDIAN_API_KEY") GITGUARDIAN_API_BASE_URL = os.getenv("GITGUARDIAN_API_BASE_URL", "https://api.gitguardian.com") # Default to the main GitGuardian API URL, use https://my-gg-instance.com/exposed/v1 for self-hosted # Function to apply a custom tag based on the incident_id def apply_custom_tag(incident_id, tag_key, tag_value): url = f"{GITGUARDIAN_API_BASE_URL}/v1/incidents/secrets/{incident_id}" headers = { "Authorization": f"Token {GITGUARDIAN_API_KEY}", "Content-Type": "application/json" } data = { "custom_tags": [ { "key": tag_key, "value": tag_value } ] } # Send the PATCH request to apply the custom tag response = requests.patch(url, json=data, headers=headers) if response.status_code == 200: print(f"Successfully applied custom tag: {tag_key}:{tag_value}") else: print(f"Failed to apply custom tag. Status code: {response.status_code}, {response.text}") # Function to process and extract data from the webhook payload def process_webhook(webhook_payload): # Extract incident ID and URL from the webhook payload incident_id = webhook_payload.get('incident', {}).get('id') secret_url = webhook_payload.get('occurrence', {}).get('url') if incident_id and secret_url: return incident_id, secret_url else: print("Error: Missing incident ID or URL in the webhook.") return None, None def main(webhook_payload): # Retrieve the incident_id and secret_url from the webhook payload incident_id, secret_url = process_webhook(webhook_payload) if incident_id and secret_url: # Check if the secret_url contains the string "wrybill" if "wrybill" in secret_url: # Apply the custom tag "bird:wrybill" apply_custom_tag(incident_id, "bird", "wrybill") else: print("No matching URL found for tag application.") else: print("Invalid webhook payload.") ```
--- ## Incident permissions and sharing GitGuardian is designed to be super collaborative yet very secure. Learn how to use incident permission levels and our sharing capability to do so, so users only access and do what you want them to access and do. ## What are incident permissions Incident permissions define the set of actions that users can perform on the incident in question: - **Can view**: they can view the incident and be assigned to it. - **Can edit**: they have the "Can edit" permissions, plus the ability to resolve, ignore, change severity and custom tags, comment and provide feedback on an incident. - **Full access**: they have the "Can edit" permissions, plus the ability to share the incident within the workspace or publicly. Any time you manually grant someone access to an incident, you will need to set their incident permissions. The default incident permission is `Can edit`. ![Incident permissions dropdown in the share modal](/img/platform/collaboration-and-sharing/incident-permissions-dropdown-share-modal.png) Those advanced granular incident permissions are only allowed in the Business plan, thus: - **any workspace under the Free plan works as if only the `Full access` incident permission was present**. - when switching from the Business plan to the Free plan (eg: end of contract or end of business trial), **all people who do not have `Full access` incident permission are considered deactivated**. ## Granting access to incidents GitGuardian has a sharing capability internal to the workspace: this is called the "Grant Access" feature. This makes it possible to share an incident with a person registered on the workspace or even a team. :::info The "Grant access" capability is a feature reserved for workspaces under the Business plan. Only people with `Full access` incident permissions can use the "Grant access" feature. ::: ### Granting access to individuals Sometimes you will want to share an incident only with certain other members of your workspace to gain their expertise or knowledge. 1. Click on **Share** at the top-right-hand corner of the incident you want to share. 2. Search for the people you want by typing in their name or email address. Since workspace Managers have access to all incidents of the workspaces, **only Members and Restricted are eligible to be selected**. 3. You can set their incident permission from the dropdown in the input. 4. Click on **Grant access**. 5. An email is then sent to these people to notify them of their new access. ![Grant access to individuals](/img/platform/collaboration-and-sharing/grant-access-to-individuals.png) By default, users with `Member` or `Restricted` access level and `Full access` incident permission can enter the email address of someone who is not yet registered in the workspace. This behavior can be deactivated via a workspace setting. Please refer to [this page](../enterprise-administration/workspace-settings.md) for more details. #### How can I automate this incident workflow? If you are under our Business plan (or in Business trial), you can automate this entire process with our [Auto-access granting playbook](../automate-with-playbooks/available-playbooks.md#auto-grant-access-to-involved-developer-in-app) ### Granting access to entire teams Sometimes you will want to share an incident with an entire team to better collaborate on an incident. 1. Click on **Share** at the top-right-hand corner of the incident you want to share. 2. Search for the teams you want by typing in their name. 3. You can set the incident permission of those teams from the dropdown in the input. 4. Click on **Grant access**. 5. An email is then sent to all teammates belonging to the teams to notify them of their new access. ![Grant access to teams](/img/platform/collaboration-and-sharing/grant-access-to-teams.png) ## Revoking access If you want to revoke access to the incident for a specific person or team. 1. Click on **Share** at the top-right-hand corner of the incident. 2. To the right of the team's name or the individual's name, click on the bin icon.You can use the search bar at the top of the modal if needed. ![Revoke access](/img/platform/collaboration-and-sharing/revoke-access.png) If a team has access to an incident because it occurred on their perimeter, access cannot be revoked. ![Revoke access not Authorized for team with perimeter involved](/img/platform/collaboration-and-sharing/revoke-access-not-authorize-for-team-with-perimeter-involved.png) If a user is assigned to an incident, access cannot be revoked. The assignment needs to be changed first for access to be revoked. ## Sharing incidents publicly GitGuardian has a sharing capability external to the workspace. This allows you to share an incident on the web via a single link accessible to everyone, even those who are not registered in your workspace. Public sharing can be deactivated via a workspace setting. Please refer to [this page](../enterprise-administration/workspace-settings.md) for more details. :::info Under Business plan, only people with `Full access` incident permissions can share the incident publicly. Under Free plan, every user can share the incident publicly. ::: ### Creating the public share link You can share any incident by turning on the sharing switch. Such action will **generate a unique link** containing by default: - the **incident** with the secret visible, - its **occurrences** with links to their locations on the VCS and the resulting check of their presence in the git history, - the resulting check of the secret's **validity**, - **"How to remediate"** guidelines. This link will automatically expire either 30 days after its creation or 5 days after the incident is closed, whichever of the two dates is earlier. A new link can be generated at any time after the expiration of the previous one. ![Incident public sharing](/img/platform/collaboration-and-sharing/public-sharing.png) The publicly accessible page of the incident via the unique share link looks like this: ![Public share page](/img/platform/collaboration-and-sharing/public-share-page.png) ### Enabling feedback collection The feedback collection process can be achieved via this link. The sharing link of an incident has a **"Feedback collection" option**. When this option is on, an entire section becomes available in the shared page where **the person having access to it can submit their feedback**. ![Public share page feedback panel](/img/platform/collaboration-and-sharing/public-share-page-feedback-panel.png) When the feedback is submitted, it will be **directly visible on the incident page of your GitGuardian dashboard** under the **"Feedback" section**. ![Incident feedback panel](/img/internal-monitoring/remediate/incident-detail/feedback-panel.png) :::info This "Feedback collection" option is ON by default whenever a share link is generated manually. The feedback form is not customizable yet. ::: ### Allowing auto-healing The share link also provides a **"Resolve or ignore via link" option**. When turned on, you enable the **auto-healing of the incident**: the person who has access to the link can close the incident themselves. An entire section becomes accessible within the shared page to enable "Resolve" and "Ignore" actions. ![Public share page auto healing panel](/img/platform/collaboration-and-sharing/public-share-page-auto-healing-panel.png) This is particularly useful if **you want to reduce your workload and if you trust members of your team external to your dashboard**, namely the developer responsible for the leak, to properly remediate the incident. :::info This "Auto-healing" option is OFF by default whenever a share link is generated manually as GitGuardian considers closing an incident as a sensitive action. ::: --- ## Saved views Saved views allow users to save and share customized filter sets, making it easier to collaborate and maintain consistent views across teams. ## Key benefits - Shared views: Workspace managers can create shared views accessible to all team members, enabling smoother workflows and reducing the time spent configuring filters. - Personalized experience: While the primary focus is on sharing, members can also create private views tailored to their individual needs. Each user can then customize their session by adding or hiding views according to their preferences. - Dynamic filtering: The "Current user" filter enables views to dynamically adjust and display relevant data for each user, such as "My Incidents," providing a personalized and relevant experience even in shared views. ![Filter on current user](/img/platform/collaboration-and-sharing/saved-views/current-user-filter.png) ## How to create a new view 1. Set your desired filters in an existing view. 2. Click "Save" > "Save as new view." 3. Enter a name for the view and save. :::info If you’re a workspace manager, choose whether it should be available to everyone or just to you. Members can only create private views. ::: ![Save as new view](/img/platform/collaboration-and-sharing/saved-views/save-as-new-view.png) ![Create view modal for manager](/img/platform/collaboration-and-sharing/saved-views/create-new-view-manager.png) ## GitGuardian views In addition to user-created views, GitGuardian provides pre-configured views with recommended filter sets. These views help users quickly access common data configurations. While these views can be hidden, they cannot be edited or deleted. Learn more about: - [Views for the incidents page](../../internal-monitoring/remediate/prioritize-incidents.md#1-prioritize-with-the-incidents-table) - [Views for the perimeter page](../../internal-monitoring/integrate-sources/monitored-perimeter.md) ## Save what you searched for The [search bar](./search-and-filter.md) is the entry point for every view. Build a combination of filters, raw text searches, secret-value lookups, or natural-language prompts (when AI Filters are enabled), then save the result as a view to share with your team. --- ## Search and filter The search bar at the top of every listing page (Incidents, Public incidents, Perimeter, Audit logs, and most settings tables) is the single entry point for finding what you need. It supports four search modes that you can mix and match in the same query: 1. **Structured filters** — pick a filter, choose a value. 2. **Raw text search** — type any text to match across file paths, commit authors, and source names. 3. **Search by secret value** — paste a secret to check whether GitGuardian has already detected it. 4. **Natural language search (AI Filters)** — describe what you want in plain English. Available only when AI Filters are enabled. ![Searching the incidents page in natural language and with structured filters](/img/platform/collaboration-and-sharing/search-and-filter/search-bar-demo.gif) ## 1. Build filters with the dropdown Click the search bar to see all available filters for the current page. Type the start of a filter name (`severity`, `assignee`, `integration`, etc.) and pick a value from the suggestions. You can also type values directly without naming the filter — the search bar matches the most likely filter: | Type this | Result | | ---------------- | ----------------------------------------------------- | | `critical` | Suggests `Severity: Critical` or `Source criticality: Critical` | | `integration : github` | Applies the GitHub integration filter | | `vaul : azu` | Partial matches work — suggests `Vault: Azure Key Vault` | | `occurrence = 5` | Use `>`, `<`, `=` operators on numeric filters | | `occurrence > 5` | Filter incidents with more than 5 occurrences | :::info Syntax Use `:` or `=` to separate the filter name from its value (e.g. `severity : critical` or `severity = critical`). Spaces around the separator are optional. The same syntax works with operators (`>`, `<`, `=`) for numeric filters. ::: ![Typing "vaul : azu" suggests Vault › Azure Key Vault](/img/platform/collaboration-and-sharing/search-and-filter/partial-match-vault-azure.png) ## 2. Search by raw text When you type free text that doesn't match a filter name, the search bar searches across **three** properties of every incident at once: - **Occurrence file path** — the file where the secret was found. - **Occurrence author** — the developer (git committer name) who introduced the secret. - **Source name** — the repository, channel, drive, or project name where the leak was detected. This is the fastest way to answer questions like "did anything leak in our config files?" or "what's on John's plate?" without picking a specific filter. ### By file path Type any portion of a file path. The matching incidents have at least one occurrence whose path contains the text. | Prompt | What it matches | | ------------------------------------- | ------------------------------------------------ | | `Occurrence path : .env` | Incidents with an occurrence in any `.env` file | | `Occurrence path : docker-compose.yml`| Incidents from a `docker-compose.yml` file | | `Occurrence path : config/secrets` | Incidents under the `config/secrets` folder | ### By commit author Type a developer name (or email fragment). The matching incidents have at least one occurrence introduced by that author. | Prompt | What it matches | | ------------------------------------- | ----------------------------------------------------------------- | | `Occurrence author : john` | Every leak introduced by an author whose git name contains "john" | | `Occurrence author : @contractor.com` | All commits made by contractors with that email domain | ### By source name Type any portion of a source name. The matching incidents come from a source whose display name contains the text. | Prompt | What it matches | | ----------------------------------- | -------------------------------------------- | | `Source name : main-business-app` | Incidents in repositories matching that name | | `Source name : backend` | Incidents from every backend service | :::tip Raw text search and structured filters compose. `Severity: Critical occurrence path : .env` returns critical incidents that leaked through a `.env` file. ::: ## 3. Search by secret value If you want to verify whether a specific secret value is already known to GitGuardian, paste it into the **Secret value** filter (or as raw text after selecting that filter). :::info Your secrets never leave your browser The value is **hashed locally in your browser** before being sent to the server. The plaintext secret is never transmitted, never stored, and never sent to any AI model. The search is performed against hashed secrets only. ::: Use this when: - A developer reports a leaked credential and you want to check if GitGuardian already raised an incident for it. - You want to confirm that a rotated secret no longer appears in your monitored perimeter. - You need to correlate a third-party alert with an existing incident. ## 4. Natural language search (AI Filters) :::note Requires AI Filters to be enabled Natural language search is part of the **AI Filters** feature and shows up in the search bar only when AI Filters are activated for your workspace. See [AI settings](../ai/ai-settings) for the workspace toggle and self-hosted prerequisites (a configured LLM provider, either GitGuardian-managed or your own Amazon Bedrock setup). ::: When AI Filters are enabled, you can type a full sentence directly in the search bar and GitGuardian translates it into the right combination of filters — no special mode to activate. ### How to use it 1. Click the search bar on any supported page. 2. Type a sentence in plain English and press Enter, for example: - `Open critical unassigned incidents related to cloud providers` - `Valid AWS keys introduced by contractors under infra/ since January` - `Sources with open incidents and no honeytoken` 3. Review the applied filters in the filter bar. You can keep, adjust, or remove any filter just like manual ones. Natural language also covers the same dimensions as raw text search — file paths, commit authors, and source names — and combines them with any other filter on the page: - `Critical incidents in .env files committed by Alice in the last month` - `Incidents in the backend repos introduced by anyone on the data team` ### Suggestions and history While you're typing in the search bar, GitGuardian shows: - **Suggestions** — curated example prompts for the current page, useful when you're getting started. - **History** — your most recent prompts, so you can re-run a successful query in one click. You can clear the history at any time. ### Date presets When your prompt refers to a familiar time range, the AI maps it to the same named preset you would pick manually — so the filter shows as a pill labelled `Last week` rather than as a custom range. Supported phrasings include `yesterday`, `last week`, `last month`, `last 3 months`, `last 6 months`, `last year`, and `current year`. ### Operators On surfaces that support filter operators, AI Filters can return comparison operators (`>`, `<`, `=`, `contains`) so prompts like `more than 5 occurrences` or `path contains .env` resolve to the right filter expression. ### Provide feedback Each AI result has thumbs-up and thumbs-down buttons. Use them to tell us whether the filters matched your intent. You can add a short comment to explain what worked or what was off — that feedback helps us improve the suggestions and prompt examples. ## Examples Common triage and investigation workflows, expressed both with structured filters and with natural language (when AI Filters are enabled). ### Find critical leaks introduced by contractors - **Filters**: `Severity: Critical` + `Occurrence author : @contractor.com` - **Natural language**: `Critical incidents introduced by anyone with a @contractor.com email` ### Triage what leaked in `.env` files this week - **Filters**: `Occurrence path : .env` + `Date: Last week` - **Natural language**: `Incidents found in .env files in the last 7 days` ### Check whether a specific token is already known - **Filters**: `Secret value: ` (hashed locally before search) - **Natural language**: `Find incidents with this token: ghp_xxxxxxxxxxxxxxxxxxxx` ### List open incidents in a specific repository - **Filters**: `Source name : main-business-app` + `Status: Triggered` + `Status: Assigned` - **Natural language**: `Open incidents in the main-business-app repository` ### Focus on unassigned high and critical incidents - **Filters**: `Assignee: No assignee` + `Severity: High` + `Severity: Critical` - **Natural language**: `Unassigned high and critical incidents` ### Investigate AWS leaks under a specific folder - **Filters**: `Detector: Amazon AWS` + `Occurrence path : infra/` - **Natural language**: `AWS keys leaked under the infra/ folder` ### Audit one developer's incidents over a period - **Filters**: `Occurrence author : alice` + `Date: Last 3 months` - **Natural language**: `Incidents introduced by Alice in the last 3 months` :::tip Save the queries you reuse Whenever an example combination matches your team's recurring workflow, save it as a [view](./saved-views). Views always run the same deterministic filter set, no AI prompt required. ::: ## AI Filters limits - **Languages** — optimized for English. Other languages may work but with reduced accuracy. - **Coverage** — the AI can only return filters that exist on the current page. If a concept has no matching filter, it is ignored. - **Failures** — if the AI cannot interpret your prompt, the page returns an error and your existing filters are unchanged. Rephrase the request or use the standard filter menu. :::note Self-hosted instances On self-hosted, AI Filters require an LLM provider to be configured by your administrator. GitGuardian supports a managed inference profile or your own Amazon Bedrock setup. See [AI settings](../ai/ai-settings) and [Bring Your Own Cloud — AWS Bedrock](../ai/byoc-aws-bedrock) for configuration. ::: For details on which data is sent to the model and how it is handled, see the [AI Management Policy](../ai/ai-management-policy). --- ## Create and manage teams Teams allow you to organize security responsibilities by ensuring team members only receive alerts and access incidents from sources within their area of responsibility. :::info Only workspaces under Business plan can create and use teams. ::: ## Creating a team Only Managers can create teams within the workspace. 1. Navigate to Settings > User management > [Teams](https://dashboard.gitguardian.com/settings/user/teams). 2. In the top-right corner of the page, click **Create team**. 3. Enter the team name and description. ![Create a team](/img/platform/collaboration-and-sharing/create-team-form.png) ## Add teammates to your team You can add as many teammates as you want to a team. Note that users with Restricted access level cannot be added to teams. 1. On your team page, go to the Teammates section. 2. Click **Add teammates**. ![Team addition modal](/img/platform/collaboration-and-sharing/teammate-addition-modal.png) ### Define their incident permissions For each teammate, you can set their default incident permissions. These permissions automatically apply to all incidents (past and future) within the team's perimeter. - **Can view**: they can view the incident and be assigned to it. When enabled by [workspace settings](../enterprise-administration/workspace-settings#enable-comments-and-feedback-for-can-view-permission), they can also comment and provide feedback on an incident. - **Can edit**: they have the "Can edit" permissions, plus the ability to resolve, ignore, change severity and custom tags, comment and provide feedback on an incident. - **Full access**: they have the "Can edit" permissions, plus the ability to share the incident within the workspace or publicly. :::info When added to a team, workspace Managers automatically receive unmodifiable `Full access` incident permissions by default. ::: ![Incident permissions selection](/img/platform/collaboration-and-sharing/teammate-incident-permissions-dropdown.png) > For more details about incident permissions, read the [dedicated documentation](./incident-permissions-and-sharing). ### Define team leaders You can designate team leaders for each team. Team leaders can: - Manage team members (add/remove/accept or decline requests) - Rename the team and update its description - Configure alert settings - Delete the team Workspace Managers added to a team automatically have the same rights as team leaders. ![Team leader definition selection](/img/platform/collaboration-and-sharing/team_leader_definition.png) By default, team leaders can invite new users to the workspace by adding them to their team. This behavior can be disabled via workspace settings. For more details, refer to [this page](../enterprise-administration/workspace-settings.md). :::info Team leaders cannot configure the team perimeter. For security reasons, only workspace Managers can configure team perimeters. ::: ## Configure team perimeter The team perimeter defines the products and sources that the team can access. Team members will have access to all incidents (past and future) from these sources. :::info For workspaces with access to Public Monitoring, sources are distributed across both products: [Internal Monitoring](../../internal-monitoring/home) and [Public Monitoring](../../public-monitoring/home). ::: ### Adding sources to the perimeter On your team page, go to the Perimeter section and click **Add sources**. **For Internal Monitoring access:** 1. Select the integration you want to add sources from. 2. Choose the sources you want to add to the team perimeter and click **Add sources**. 3. Repeat these steps to add sources from different integrations if needed. **For Public Monitoring access:** (only for workspaces with access to Public Monitoring) In the Public Monitoring section, click **Public GitHub**. ![Team perimeter modal VCS selection](/img/platform/collaboration-and-sharing/team-perimeter-modal-vcs-selection.png) ![Team perimeter modal adding GitHub repositories](/img/platform/collaboration-and-sharing/team-perimeter-modal-add-github-repositories.png) :::info For security reasons, configuration of the team perimeter can only be done by a workspace Manager. Indeed, the addition of new sources to the perimeter of the team has very significant implications since it allows access to all the incidents that have occurred on these new sources. This is why only people with the highest privileges, workspace managers, can perform this action. ::: ### About source nodes addition and other important things to know Keep these key points in mind when configuring your team perimeter: - **Selecting an entire node** (e.g., a GitHub organization, GitLab group, or Bitbucket project): - All existing sources within the node are added to the team perimeter - **Future sources within this node are automatically added** to the team perimeter - **Selecting all nodes of a VCS integration** (e.g., all GitHub organizations you have integrated): - GitGuardian assumes you want to monitor the entire VCS integration - **Future nodes are automatically added** to the team perimeter (e.g., future GitHub organizations you integrate) - A source can belong to multiple teams ### Removing sources from the perimeter 1. On your team page, go to the Perimeter section. 2. Click the bin icon and confirm your action. ![Team perimeter deletion](/img/platform/collaboration-and-sharing/team-perimeter-deletion.png) For more granular control on Internal Monitoring sources, click the ![platform icon](/img/icons/three-dots-menu.svg) menu to open the configuration modal. Here you can add or remove specific sources by checking or unchecking them, then confirm your changes. ## Requesting access to a team People with the `Member` access level must request access to join a team. In order to request access: 1. Navigate to Settings > User management > [Teams](https://dashboard.gitguardian.com/settings/user/members). 2. To the right of the team's name, click **Request access**. 3. An email is then sent to teammates with `Can manage` team permissions notifying this new request. If there are no teammates with `Can manage` team permissions, the email is sent to workspace managers. ![Request access](/img/platform/collaboration-and-sharing/team-request-access.png) Members can cancel their own team requests at any time. Teammates with `Can manage` team permissions can review team requests on the team page and decide whether to accept or decline them. The Member who made the request will be informed by email of the decision. ![Pending requests table](/img/platform/collaboration-and-sharing/team-pending-requests-table.png) :::info Workspace Managers have the ability to visit, join, accept or decline team requests, and leave any teams present on the Workspace, even if they are not part of it. ::: ## Add alerting integrations to a team As a workspace Manager you can manage alerting integrations for any team from the Integration section. ![Manage integrations from workspace](/img/platform/collaboration-and-sharing/team-notifiers-workspaceconf.png) As a Member with `Can manage` team permissions, you can create and modify alerting integration for your specific team. ![Manage integrations from team](/img/platform/collaboration-and-sharing/team-notifiers-fromteam.png) Team-level alerting enables you to send alerts directly to each team's preferred communication channel, reducing unnecessary distractions for other team members. Team members will only receive alerts for incidents that require their attention and remediation. If an incident already exists in another team, and a new occurrence of this incident occurs in a repository attached to your team, you'll receive an alert - even if you've asked to be alerted only by new incident and not occurrences. This ensures you won't overlook any incident. :::info Each workspace has a default limitation of 1000 integrations for all the teams. If you need to increase this quota, please get in touch with your account manager. ::: ## Deleting a team As a workspace Manager or a teammate with `Can manage` team permission, you can delete a team. 1. Navigate to Settings > User management > [Teams](https://dashboard.gitguardian.com/settings/user/members). 2. Visit the page of the team you want to delete and scroll down to the "Danger zone". 3. Click **Delete team** and confirm your action by typing the name of the team. This action cannot be undone. All teammates will instantly lose access to incidents they were able to access because those incidents occurred within the team perimeter. ![Deleting a team](/img/platform/collaboration-and-sharing/team-deletion-modal.png) ## A specific team: The "All-incidents" team ### What is the "All-incidents" team In the team management feature within a GitGuardian workspace there is a particularity: **the "All-incidents" team**. The "All-incidents" team is a team that **exists by default on the workspace** and which **gives access to all the incidents** of the workspace to the people who compose it. Consequently, there is no notion of perimeter within the "All-Incidents" team. This team will usually bring together the people responsible for security at the global level of your organization (eg: CISOs). ![All-incidents team](/img/platform/collaboration-and-sharing/all-incidents-team.png) :::info The "All-incidents" team cannot be deleted. ::: ### How the "All-incidents" team articulates in with access levels and plans About access levels: - By default, **all Managers in your workspace are part of the "All-incidents" team and cannot be withdrawn from it**. - That said, people with the **Member access level can also be part of the "All-Incidents" team** (ex: security auditors). - People with the Member access level who are not part of the "All incidents" team cannot see it in the list of teams and therefore **cannot request access** to it. A Member can only be part of the "All-incident" team if added manually by a Manager. About plans: - As the team management feature - and therefore the ability to have siloed views on incidents - is only allowed in the Business plan, **any workspace under the Free plan works as if only the team "All-Incidents" was present**. - Thus, when switching from the Business plan to the Free plan (eg: end of contract or end of business trial), **all people who are not part of the "All-incidents" team are considered deactivated**. --- ## Add and manage users :::info In addition to inviting users via email or SSO Just-In-Time (JIT) provisioning, you can now automatically provision users via SCIM if your workspace has SCIM enabled. When SCIM is configured, users added in your Identity Provider (IdP) will be automatically created in your GitGuardian workspace. Learn more and see setup instructions in the [SCIM documentation](../enterprise-administration/scim-configuration). ::: ## Adding new users ### Inviting via email As a workspace Owner or Manager, you can invite via email other users to join your GitGuardian workspace. 1. Navigate to Settings > User management > [Members](https://dashboard.gitguardian.com/settings/user/members) 2. Simply submit the email address of the person you want to invite. If you are under a Business plan, you will be able to specify the teams of your new invitee. 3. The invited user will receive and email with an invitation link. If you have performed an SSO integration, the invitation link will redirect to your dedicated SSO login URL. ![Invitation form](/img/platform/collaboration-and-sharing/invitation-via-email-form.png) There is no limit to the number of users on your workspace. ### Pointing to SSO login URL If you have configured SSO, you can simply let the Just-In-Time provisioning do the work. 1. Make sure the people you want to add to your GitGuardian workspace are part of the allowed IdP group 2. Point those people to the SSO login URL dedicated to your workspace. This URL is accessible by workspace Manager in the [Authentication settings section](https://dashboard.gitguardian.com/settings/workspace/auth/saml). ![SSO login url](/img/platform/enterprise-administration/sso_login_url.png) ### Manage pending invitations Once invited, the new user appears in the "Pending" list in the [Members section](https://dashboard.gitguardian.com/settings/user/members) of your workspace. There, you can choose the access level they will be attributed upon sign up. You can delete a pending invitation, which invalidates the sent invitation link. ## Access levels Each user has its own user account and can be member of one or multiple workspaces. Thus, user membership is handled at the workspace level. Each member is assigned a access level that defines its privileges on the workspace at stake. | Action | Owner | Manager | Member | Restricted | | :--------------------------------------------------------------------------------------------------------------------------------- | :----------------: | :----------------: | :----------------: | :------------------------------------------------------------: | | Can access incidents and act on them according to their incident permissions (share, assign, resolve, ignore, export) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark:, only to incidents they are given access to | | Can create/delete API personal access tokens | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark:, only with `scan` scope | | Can create/delete API service accounts (Business only) | :white_check_mark: | :white_check_mark: | :x: | :x: | | Can launch historical scans | :white_check_mark: | :white_check_mark: | :white_check_mark:, based on team perimeter assignments | :x: | | Can [manage the perimeter](../../internal-monitoring/integrate-sources/monitored-perimeter#bulk-actions-on-perimeter-sources) (monitor/unmonitor sources, assign sources to teams, set source criticality) | :white_check_mark: | :white_check_mark: | :x: | :x: | | Can add/remove/change members | :white_check_mark: | :white_check_mark: | :x: | :x: | | Can join/leave/request access to teams | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | | Can see [workspace settings](../enterprise-administration/workspace-settings) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | | Can change workspace settings (SSO, detection capabilities,...) | :white_check_mark: | :white_check_mark: | :x: | :x: | | Can configure integrations (VCS and notifiers) | :white_check_mark: | :white_check_mark: | :x: | :x: | | Can access [analytics](../analytics/overview) | :white_check_mark: | :white_check_mark: | :white_check_mark:, only with `Full access` on the All-incidents team | :x: | | Can delete workspace | :white_check_mark: | :x: | :x: | :x: | | Can change [secret occurrences grouping](../../internal-monitoring/detect/secrets-occurrences#grouping-of-occurrences-into-secret-incidents) | :white_check_mark: | :x: | :x: | :x: | ### Owner - The Owner has unrestricted access and all rights over the entire workspace. - Each workspace must have one and only one Owner. - When the Owner deletes their user account, it also deletes their workspace and members. ### Manager - A Manager has the same level of access as the Owner except they cannot delete the workspace. - A Manager can manage workspace settings and fellow members of the workspace. - A Manager can access all the incidents. Managers are the people responsible for managing the GitGuardian workspace. These may be security or technology managers, depending on your own organization. ### Member - A Member can view the workspace settings but cannot act on them. - A Member can access the incidents. - A Member can be part of teams. Members are people in your organization (Developers, Ops, Security) that you want to collaborate to remediate incidents. :::info Memberships with Viewers have been migrated to access level Member with [`Can view`](./teams#define-their-incident-permissions) incident permissions on all the incidents. ::: ### Restricted - A Restricted can only access a certain set of incidents defined by the Manager or the Member on an ad-hoc basis. - A Restricted cannot be part of a team. - A Restricted can list members and teams to assign or share incidents they have access to. Restricted are typically people outside of your organization who you want to allow access only to very specific incidents. #### Promote a Restricted to Member When promoting a Restricted to Member access level: 1. They have read access to the workspace settings 2. They are able to request to join teams in the workspace #### Demote a Member to Restricted When demoting a Member (or a Manager) to Restricted access level: 1. They are removed from all the teams they belong to 2. Only incidents to which they are granted access to manually are accessible. 3. All open incidents they were assigned to are unassigned :::info The Restricted access level is only accessible to workspaces under the Business plan. ::: ## Delete or deactivate members As a workspace Owner or Manager, you can remove or deactivate a member from the workspace. Deactivating a member temporarily restricts their access to the workspace without permanently deleting their account or data, allowing you to reactivate them later if needed. In contrast, removing a member permanently revokes their access and deletes their association with the workspace. However, note that the Owner of the workspace cannot be removed or deactivated by any user. 1. Navigate to Settings > User management > [Members](https://dashboard.gitguardian.com/settings/user/members) 2. To the right of the person's name, click the ![platform icon](/img/icons/three-dots-menu.svg) menu, then select Delete or Deactivate. 3. Confirm your action. This person will instantly lose access to your workspace and all of its data. Personal access tokens belonging to that person will also be revoked. ![Removing a member](/img/platform/collaboration-and-sharing/removing-a-member.png) ## [Self-hosting] Access to the Admin Area If you are using GitGuardian in a self-hosted environment, you will have access to the Admin Area for managing your system. For additional information, please refer to the [Admin Area User Management](/self-hosting/management/application-management/admin-area) page. --- ## Configure real-time alerting and notifications for your perimeter GitGuardian's real-time monitoring allows alerts to be sent immediately when an incident is detected or updated. Configuring a notifier from your GitGuardian workspace allows you to push incident alerts to the channel of your choice (e.g Slack, PagerDuty...). These alerts will contain details about the incident such as the triggered detector and location (org and repository) without revealing the secrets detected or any other sensitive data, avoiding any further contribution to sprawling of secrets. ## Incident types and integration scope Most GitGuardian's alerting integrations are designed to handle **internal secret incidents** detected within your integrated sources. This includes all the notification channels and issue tracking integrations listed below. **Custom webhooks** and **Slack** are the exceptions: if your workspace and team have access to **[Public Monitoring](../../public-monitoring/home)**, these integrations can also be configured to receive events related to **public secret incidents** detected on public repositories. ## Available integrations By default, GitGuardian will notify dashboard users via email for every incident. You can [read more about email alerting here](./notifiers-integrations/email-alerting.md). You can also choose to integrate with other notification channels, GitGuardian currently supports: - [Custom webhooks](./notifiers-integrations/custom-webhook) Custom services can be written to listen in on GitGuardian's detection engine and programmatically treat detected incidents. Can handle internal and/or public secret incidents. - [Slack](./notifiers-integrations/slack) The Slack integration provides comprehensive notification coverage for internal and/or public secret incident lifecycle events. Configure which events to receive in your team's workspace channels, with an incoming webhook or the GitGuardian Slack App for threaded notifications. - [Microsoft Teams](./notifiers-integrations/microsoft-teams) The Microsoft Teams integration allows you to be notified on your team's workspace in a channel of your choice. - [Discord](./notifiers-integrations/discord) The Discord integration allows you to be notified on your team's discord server of your choice. - [PagerDuty](./notifiers-integrations/pagerduty) Send incidents as PagerDuty event notifications with the PagerDuty Integration. - [Splunk](./notifiers-integrations/splunk) Treat incidents as data with the Splunk Integration. ## Filter notifications by incident criteria By default, every new and updated incident generates a notification, regardless of how critical it is. To cut down on noise and focus your team on what matters, you can define **filtering rules** so a notification is only sent for incidents that match the criteria you choose. Rules are configured **per channel**, directly on each integration's settings page, and can combine any of the following incident criteria: - **Severity** - **ML risk score** (Business plans). Not available on public incidents if the [agents analysis](../../public-monitoring/remediate/agents-analysis.md) is enabled for the workspace. - **Validity** - **Secret type** (detector) - **GitGuardian tags** (e.g. _Publicly leaked_, _Default branch_, _Test files_) Filtering applies to both **internal** and **public monitoring** incidents. If you don't set any rule, the channel keeps receiving notifications for every incident (full coverage), which is the default behavior. **Availability** - **Destinations** — filtering on internal and public monitoring incidents is available for [custom webhooks](./notifiers-integrations/custom-webhook), [Slack](./notifiers-integrations/slack), [Microsoft Teams](./notifiers-integrations/microsoft-teams), and [ServiceNow](./issue-tracking-integrations/servicenow). Other channels are rolling out progressively. - **Email** — public monitoring incidents can be [filtered by severity](./notifiers-integrations/email-alerting). Additional criteria and internal monitoring support are planned. --- ## Wiz :::warning Not available yet The Wiz integration is not available yet. Early access is planned for September 2026. If you are interested, reach out to your Customer Success Manager or [support@gitguardian.com](mailto:support@gitguardian.com). ::: GitGuardian integrates with [Wiz](https://www.wiz.io/) to push the secret incidents detected in your version control sources to Wiz as native secret findings. Security teams get a single view of secrets risk and cloud risk, and can prioritize and remediate leaked credentials directly from Wiz. ## How it works Once a day, GitGuardian sends your active secret incidents to Wiz: - **Scope**: incidents detected in your version control sources (GitHub, GitLab, Bitbucket, Azure DevOps) with an open status (triggered or assigned). - **Granularity**: one finding per incident and per repository. An incident groups all the [occurrences](../../../internal-monitoring/detect/secrets-occurrences.md) of the same secret: when an incident has several occurrences in the same repository, only the most recently detected one is sent to Wiz, and the full list remains available in GitGuardian. Each finding carries the detection context: repository, file path, commit, detector, severity, and a link back to the GitGuardian incident. - **Privacy**: GitGuardian never sends secret values to Wiz. Findings contain a SHA-256 hash of the secret and its metadata only. Each sync sends the full list of active incidents. Wiz keeps findings open as long as they are present in the latest upload: when you resolve or ignore an incident in GitGuardian, it is dropped from the next sync and Wiz removes the finding automatically. ### Severity mapping The severity of the GitGuardian incident sets the severity of the finding in Wiz: | GitGuardian severity | Wiz severity | | -------------------- | ------------ | | Critical | Critical | | High | High | | Medium | Medium | | Low | Low | | Info | Low | | Unknown | None | ## Configure the integration :::info Prerequisites You need a Wiz service account with the required permissions to upload findings. See the [Wiz documentation on prerequisites](https://docs.wiz.io/dev/prerequisites#active-wiz-service-account) to create one. ::: 1. In Wiz, retrieve your service account **Client ID** and **Client secret**, along with your tenant **Authentication URL** and **API endpoint URL**. 2. In GitGuardian, go to **Settings > Integrations > [Wiz](https://dashboard.gitguardian.com/settings/integrations/wiz)** and click **Configure**. 3. Paste the four values from Wiz into the form. 4. Click **Add integration**. ![New Wiz integration configuration](/img/platform/configure-alerting/aspm-integrations/wiz/new-wiz-integration.png) You can pause or resume the sync at any time from the integration settings page. :::caution Coming soon The **Automatic incident resolution** option is not active yet. Once available, enabling it will let GitGuardian periodically resolve incidents that have been ignored in Wiz. Until then, GitGuardian is the source of truth: a finding ignored or resolved in Wiz is recreated at the next sync as long as the corresponding incident is still open in GitGuardian. ::: ## Limitations - Only incidents from version control sources are sent. Secrets detected in other sources (Slack, Jira, Confluence, and others) are not pushed to Wiz. Gerrit sources are not supported. - Incidents detected by custom detectors are not sent. - Occurrences without a file path are skipped. - Wiz ingests uploads in batches: new findings can take up to 24 hours to appear in Wiz. - After an incident is resolved or ignored in GitGuardian, its finding can remain visible in Wiz for up to 7 days before Wiz removes it. --- ## Jira Cloud GitGuardian provides an integration with Jira Cloud to empower users to synchronize their GitGuardian incidents with Jira Cloud issues. This integration aims to streamline incident remediation processes and strengthen alignment with your Software Development Lifecycle (SDLC). ## Benefits This feature streamlines the process of creating issues from GitGuardian incidents: - Supports both manual and automatic issue creation upon incident detection. - Enables issue creation directly in the Jira project linked to the GitGuardian Team. - Provides customizable templates that utilize Jira custom fields and GitGuardian variables for tailored issue descriptions. - Includes an auto-resolve feature that automatically closes GitGuardian incidents when the corresponding Jira issues are resolved. ## Requirements The Jira integration uses Jira OAuth and requires installation with a Jira user account possessing these permissions across all projects: - **Manage:** Jira-configuration, Jira-webhook - **View:** Jira-user, Jira-work - **Update:** Jira-work :::info We recommend creating a dedicated Jira user, `GitGuardian`, for the integration. This prevents issues if the user who set up the integration leaves the company or loses Jira admin access. The reporter for issues in Jira will be the account name used during setup. ::: ## Installation The integration is available on the Integrations > [Destinations](https://dashboard.gitguardian.com/settings/integrations/destinations) page, under the Issue Tracking section. Do not confuse it with the Jira Cloud integration for secret scanning. ![Integration Setup Step 1](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_cloud_integration_1.png) ### Authentication with Jira ![Authentication](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_cloud_integration_2.png) 1. Ensure you're logged into Jira with a user account that meets the [requirements](#requirements). 2. Click **Install your first site**. 3. If multiple Jira Cloud sites are available, select the desired one for integration. ![OAuth Selection](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_cloud_oauth.png) Repeat this process for multiple Jira sites, if needed. Note that the same Jira site cannot be installed on multiple GitGuardian workspaces. :::caution If you had installed the initial version of our integration (without auto-creation and auto-resolve features), you will need to reinstall to meet additional scope requirements. ::: ### Project selection Select Jira projects for synchronization. ![Project Selection](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_projects.png) - Choose only projects necessary for GitGuardian. - Avoid creating overly long project lists to simplify selection during manual issue creation. - Prevent issues in unrelated projects by refining project choices. ### Creating templates and configuring Jira for teams The integration allows you to create templates for automatic issue creation, tailored to your workspace plan: - **Free Plan Users:** One template applicable to all incidents. - **Business Plan Users:** Create multiple templates, each assigned to specific teams. Templates automatically apply to new incidents. A team-specific template is used only for incidents linked to that team. To apply a template across all incidents, associate it with the "All-incidents team". #### Template functionality The templates are automatically generated based on the Jira template defined for the selected issue type. - **Required fields:** Clearly marked as mandatory in the GitGuardian template. - **Optional fields:** Can be added as needed. - **Dynamic UI:** Automatically adjusts based on the type of each field. :::tip **Best practice:** Set the default assignee in each Jira project to the team lead or security champion. This ensures tickets from GitGuardian go straight to the right person, who can then reassign them to the right developer during sprint planning or triage. You can configure this in **Project settings > Details** in Jira. Learn more about [setting default assignees](https://support.atlassian.com/jira-software-cloud/docs/who-does-the-automatic-assignee-option-assign-an-issue-to/) in the official Jira documentation. ::: #### GitGuardian variables When configuring templates, you can insert GitGuardian variables into the **Title** and **Description** fields. These variables are dynamically replaced with incident-specific values when a Jira issue is created. ![Template Variables](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_template_variables.png) **Variables available in the Title field:** | Variable | Description | |----------|-------------| | `{sourceName}` | Name of the source where the secret was detected | | `{sourceType}` | Type of source (e.g., Git repository, Jira, Confluence) | | `{secretType}` | Type of secret detected (e.g., AWS Keys, GitHub Token) | | `{incidentId}` | Unique identifier of the GitGuardian incident | | `{fileName}` | Name of the file containing the secret | | `{lineNumber}` | Line number where the secret was found | **Variables available in the Description field:** | Variable | Description | |----------|-------------| | `{sourceName}` | Name of the source where the secret was detected | | `{sourceType}` | Type of source (e.g., Git repository, Jira, Confluence) | | `{secretType}` | Type of secret detected (e.g., AWS Keys, GitHub Token) | | `{locationUrl}` | Direct URL to the location of the secret in the source | | `{incidentUrl}` | URL to the incident page in the GitGuardian dashboard | | `{incidentId}` | Unique identifier of the GitGuardian incident | | `{fileName}` | Name of the file containing the secret | | `{lineNumber}` | Line number where the secret was found | :::tip Use variables to create informative templates. For example: - **Title:** `A new {secretType} vulnerability has been found` - **Description:** `A secret of type {secretType} has been detected in your {sourceType} "{sourceName}". Link to the secret: {locationUrl}` ::: #### Supported Jira custom fields The integration supports the following Jira custom fields: - **Selection Fields:** Single/multiple choice, Radio Buttons, Checkboxes - **Date & Labels:** Date Picker, Labels - **Text Fields:** Single-line, Multi-line - **Number Fields:** Numbers (or float) - **Special Fields:** URL Field, User Picker (single user), Group Pickers (single group), Priority For unsupported fields, contact our **[support team](mailto:support@gitguardian.com)**. #### Steps to create a template 1. Begin by adding an integration to the desired team. ![Template Creation Step 1](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team1.png) 1. Choose the Jira project and the corresponding issue type for the template. ![Template Creation Step 2](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team2.png) 1. Adjust fields as needed and save the template by clicking **Add Integration**. ![Template Creation Step 3](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team3.png) 1. View the configured template under the selected team, including its association with the chosen Jira project. ![Template Visualization](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team4_cloud.png) ## Additional features ### Issue update By default, updates from GitGuardian incidents (e.g., status changes, comments, severity changes) are added as comments in Jira issues. This feature can be disabled. ### Automatic assignment When enabled, tickets are automatically assigned to the incident author if their email matches a Jira user. If no match is found, the ticket remains unassigned. This feature only works for automatic ticket creation. Assignee manually set in templates take precedence over this auto-assignment feature. If neither applies, Jira's project default assignee will be used. ### Auto-resolve When enabled, specify the Jira status that triggers automatic closure of associated incidents. The incident will be marked as resolved when the Jira issue reaches the defined status. ![Auto-Resolve](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_autoclose.png) Note: Reopening Jira issues will not reopen incidents. ## Manual issue creation It is possible to manually create Jira tickets for incidents that were created **before the Jira/GitGuardian integration was configured** to automatically create tickets for new incidents. Users can do this from either the **incident page** or the **incident list page**, provided that a template is assigned to the user's team. ![Issue Creation](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_create_issue.png) The Jira issue will be accessible from the incident page. :::caution Bulk issue creation is not supported. ::: ## Unlink a ticket You can remove the link between a GitGuardian incident and its Jira ticket. This is useful when a ticket was linked by mistake or is no longer relevant to the incident. 1. On the incident page, locate the linked Jira ticket under **Issue tracking** and click the unlink icon next to it. ![Issue tracking links](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/snow-issue-tracking.png) 2. Confirm by clicking **Unlink ticket** in the dialog. :::note Unlinking only removes the association in GitGuardian. The Jira ticket itself is not deleted. ::: ## Uninstallation 1. Navigate to Settings > Integrations > Destinations > [Jira Cloud](https://dashboard.gitguardian.com/settings/integrations/jira_cloud_notifier). 2. Click **Delete** in the site configuration panel. 3. Remove the GitGuardian application from your Jira site's profile. ![Uninstallation Step](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_cloud_delete.png) 4. Remove access for the GitGuardian app under _Apps with access to your accounts_. 5. Confirm removal in GitGuardian. :::caution Warning The GitGuardian app is shared across integrations. Ensure no Jira Cloud site is installed on the platform before removing the app. ::: ## Troubleshooting If issue creation fails, verify: - Jira integration user permissions. - Existence of project/issue types in templates. - Mandatory fields added to Jira projects after template creation. - Fields in templates that were deleted from Jira. For assistance, contact **[support](mailto:support@gitguardian.com)**. --- ## Jira Data Center GitGuardian provides an integration with Jira Data Center to empower users to synchronize their GitGuardian incidents with Jira Data Center issues. This integration aims to streamline incident remediation processes and strengthen alignment with your Software Development Lifecycle (SDLC). ## Benefits This feature streamlines the process of creating issues from GitGuardian incidents: - Supports both manual and automatic issue creation upon incident detection. - Enables issue creation directly in the Jira project linked to the GitGuardian Team. - Provides customizable templates that utilize Jira custom fields and GitGuardian variables for tailored issue descriptions. - Includes an auto-resolve feature that automatically closes GitGuardian incidents when the corresponding Jira issues are resolved. ## Requirements To create Jira tickets, regular user permissions are sufficient. **Administrator** privileges on the Jira Data Center site are only required when setting up the two-way synchronization [Auto-resolve](#auto-resolve) feature. The minimum supported version is **Jira Data Center 9.1**. ## Installation 1. Make sure you're signed in as an administrator in the Jira Data Center site you want to install 2. Go to the **Profile** page ![Jira Data Center profile](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-profile.png) 3. Go to the **Personal Access Tokens** section and click **Create token** to create a new PAT ![Jira Data Center PAT](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-pat.png) 4. Provide a **Token Name**, an optional **Expiry date** and click **Create** ![Jira Data Center PAT form](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-pat-form.png) 5. Copy your new PAT and click **Close** ![Jira Data Center PAT copy](/img/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center/jira-data-center-pat-copy.png) 6. The integration is available in the settings under [Integrations > Destinations](https://dashboard.gitguardian.com/settings/integrations/destinations). It's located in the Issue Tracking section at the bottom of the page. Be careful not to confuse it with the Jira Data Center integration for secret scanning. ![Install1](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_data_center_integration_1.png) 7. Paste your **Jira Data Center site URL**, your **Administrator Personal Access Token** and click **Add** ![Install2](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_data_center_integration_2.png) :::info GitGuardian no longer renews PATs. See the [customer notice](/support/customer-notices/jira-confluence-data-center-token-renewal). ::: ### Project selection Select Jira projects for synchronization. ![Project Selection](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_projects.png) - Choose only projects necessary for GitGuardian. - Avoid creating overly long project lists to simplify selection during manual issue creation. - Prevent issues in unrelated projects by refining project choices. ### Creating templates and configuring Jira for teams The integration allows you to create templates for automatic issue creation, tailored to your workspace plan: - **Free Plan Users:** One template applicable to all incidents. - **Business Plan Users:** Create multiple templates, each assigned to specific teams. Templates automatically apply to new incidents. A team-specific template is used only for incidents linked to that team. To apply a template across all incidents, associate it with the "All-incidents team." #### Template functionality The templates are automatically generated based on the Jira template defined for the selected issue type. - **Required fields:** Clearly marked as mandatory in the GitGuardian template. - **Optional fields:** Can be added as needed. - **Dynamic UI:** Automatically adjusts based on the type of each field. :::tip **Best practice:** Set the default assignee in each Jira project to the team lead or security champion. This ensures tickets from GitGuardian go straight to the right person, who can then reassign them to the right developer during sprint planning or triage. You can configure this in **Project settings > Details** in Jira. Learn more about [setting default assignees](https://support.atlassian.com/jira-software-cloud/docs/who-does-the-automatic-assignee-option-assign-an-issue-to/) in the official Jira documentation. ::: #### GitGuardian variables When configuring templates, you can insert GitGuardian variables into the **Title** and **Description** fields. These variables are dynamically replaced with incident-specific values when a Jira issue is created. ![Template Variables](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_template_variables.png) **Variables available in the Title field:** | Variable | Description | |----------|-------------| | `{sourceName}` | Name of the source where the secret was detected | | `{sourceType}` | Type of source (e.g., Git repository, Jira, Confluence) | | `{secretType}` | Type of secret detected (e.g., AWS Keys, GitHub Token) | | `{incidentId}` | Unique identifier of the GitGuardian incident | | `{fileName}` | Name of the file containing the secret | | `{lineNumber}` | Line number where the secret was found | **Variables available in the Description field:** | Variable | Description | |----------|-------------| | `{sourceName}` | Name of the source where the secret was detected | | `{sourceType}` | Type of source (e.g., Git repository, Jira, Confluence) | | `{secretType}` | Type of secret detected (e.g., AWS Keys, GitHub Token) | | `{locationUrl}` | Direct URL to the location of the secret in the source | | `{incidentUrl}` | URL to the incident page in the GitGuardian dashboard | | `{incidentId}` | Unique identifier of the GitGuardian incident | | `{fileName}` | Name of the file containing the secret | | `{lineNumber}` | Line number where the secret was found | :::tip Use variables to create informative templates. For example: - **Title:** `A new {secretType} vulnerability has been found` - **Description:** `A secret of type {secretType} has been detected in your {sourceType} "{sourceName}". Link to the secret: {locationUrl}` ::: #### Supported Jira custom fields The integration supports the following Jira custom fields: - **Selection Fields:** Single/multiple choice, Radio Buttons, Checkboxes - **Date & Labels:** Date Picker, Labels - **Text Fields:** Single-line, Multi-line - **Number Fields:** Numbers (or float) - **Special Fields:** URL Field, User Picker (single user), Group Pickers (single group), Priority For unsupported fields, contact our **[support team](mailto:support@gitguardian.com)**. #### Steps to create a template 1. Begin by adding an integration to the desired team. ![Template Creation Step 1](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team1.png) 2. Choose the Jira project and the corresponding issue type for the template. ![Template Creation Step 2](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team2.png) 3. Adjust fields as needed and save the template by clicking **Add Integration**. ![Template Creation Step 3](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team3.png) 4. View the configured template under the selected team, including its association with the chosen Jira project. ![Template Visualization](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_add_integration_team4_data_center.png) ## Additional features ### Issue update By default, updates from GitGuardian incidents (e.g., status changes, comments, severity changes) are added as comments in Jira issues. This feature can be disabled. ### Automatic assignment When enabled, tickets are automatically assigned to the incident author if their email matches a Jira user. If no match is found, the ticket remains unassigned. This feature only works for automatic ticket creation. Assignee manually set in templates take precedence over this auto-assignment feature. If neither applies, Jira's project default assignee will be used. ### Auto-resolve When enabled, specify the Jira status that triggers automatic closure of associated incidents. The incident will be marked as resolved when the Jira issue reaches the defined status. ![Auto-Resolve](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_autoclose.png) Note: Reopening Jira issues will not reopen incidents. ## Manual issue creation It is possible to manually create Jira tickets for incidents that were created **before the Jira/GitGuardian integration was configured** to automatically create tickets for new incidents. Users can do this from either the **incident page** or the **incident list page**, provided that a template is assigned to the user's team. ![Issue Creation](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_create_issue.png) The Jira issue will be accessible from the incident page. :::caution Bulk issue creation is not supported. ::: ## Unlink a ticket You can remove the link between a GitGuardian incident and its Jira ticket. This is useful when a ticket was linked by mistake or is no longer relevant to the incident. 1. On the incident page, locate the linked Jira ticket under **Issue tracking** and click the unlink icon next to it. ![Issue tracking links](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/snow-issue-tracking.png) 2. Confirm by clicking **Unlink ticket** in the dialog. :::note Unlinking only removes the association in GitGuardian. The Jira ticket itself is not deleted. ::: ## Update your Personal Access Token You can replace the PAT used by the integration at any time, for example before it expires or after rotating it. Updating the token in place keeps your configuration intact, so there is no need to reinstall. 1. Create a new PAT in Jira Data Center, following steps 1 to 5 above 2. Navigate to Settings > Integrations > Destinations > [Jira Data Center](https://dashboard.gitguardian.com/settings/integrations/jira_data_center_notifier) 3. Update the token of the site with your new PAT If you also use the Jira Data Center source integration for secrets scanning, update its token separately. ## Uninstallation 1. Navigate to Settings > Integrations > Destinations > [Jira Data Center](https://dashboard.gitguardian.com/settings/integrations/jira_data_center_notifier). 2. Click **Delete** in the site configuration panel. ![Uninstallation Step](/img/platform/configure-alerting/issue-tracking-integrations/jira/jira_data_center_delete.png) 3. Confirm removal in GitGuardian. ## Troubleshooting If issue creation fails, verify: - Jira integration user permissions. - Existence of project/issue types in templates. - Mandatory fields added to Jira projects after template creation. - Fields in templates that were deleted from Jira. For assistance, contact **[support](mailto:support@gitguardian.com)**. --- ## ServiceNow GitGuardian offers an integration with ServiceNow, enabling users to synchronize their GitGuardian incidents with ServiceNow issues. This integration helps streamline incident remediation processes and align them with the Software Development Lifecycle (SDLC). ## Benefits This feature streamlines the process of creating ServiceNow issues from GitGuardian incidents: - Supports both manual and automatic issue creation upon incident detection. - Provides customizable templates that utilize GitGuardian variables for tailored issue descriptions. - Includes an auto-resolve feature that automatically closes GitGuardian incidents when the corresponding ServiceNow issues are resolved. ## Integration configuration To enable GitGuardian to create and manage issues in your ServiceNow instance, you need to set up a dedicated user, create a web service, and finalize the configuration in GitGuardian. ### Step A: Create the ServiceNow User In this section, we create a dedicated user in ServiceNow to authenticate and authorize GitGuardian's access to create and update incidents. 1. **Open ServiceNow**: In the web interface of your ServiceNow instance, search for "Users" in the search bar and click on "Users" under **System Security > Users and Groups**. ![Click Users](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/1-click-users.png) 2. **Create new user**: Click the "New" button. ![New user](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/2-new-user.png) 3. **Configure user ID**: Enter a username in the "User ID" field and check "Web service access only". Click "Submit". - **Tip**: We recommend using a dedicated username for GitGuardian notifications. ![User config](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/3-user-config.png) 4. **Set the password**: Click on the newly created user and set a password. Ensure the changes are saved. ![Click user](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/4-click-user.png) ![Set password](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/5-set-password.png) The user ID and password will be later used for [configuring the integration in the GitGuardian settings](#step-c-finalize-the-configuration-in-gitguardian). 5. **Assign roles**: Under the "Roles" tab, click "Edit..." and add the roles `import_set_loader` and `import_transformer`. Save the changes. ![Edit roles](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/6-edit-roles.png) ![Select roles](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/7-select-roles.png) :::info Ensure access to target table: If your target table is restricted by roles, you must assign those roles to the user you're creating.
How to check and add required roles Navigate to the table's definition by going to System Definition > Tables in the navigation pane. Open the desired table (e.g., Incident), and scroll down to the Controls section. Here, you can view the roles required to access the table. Ensure that the user created for the GitGuardian integration is assigned these roles, in addition to the roles already specified (import_set_loader and import_transformer).
::: ### Step B: Set up the web service for GitGuardian notifications In this section, we create and configure a custom web service in ServiceNow to receive incident data from GitGuardian and map it to ServiceNow records. 6. **Create the web service**: - In the ServiceNow search bar, search for "Web Services" and select "Create New" under **System Web Services > Inbound**. ![Click create new web service](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/8-click-create-new-web-service.png) - Label the web service identifying it for GitGuardian notifications. - Select the target table as "Incident" (or any custom table used for incidents). - Add seven fields (rows) for the web service, filling out the labels for each. The "Name" and "Length" fields will auto-populate. - Ensure the length of the `description`, `comments`, and `short description` fields is adjusted (to avoid data cropping in ServiceNow tickets). ![Web service config](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/9-web-service-config.png) 7. **Finalize the transform map** The Transform Map links fields from the GitGuardian notification to the corresponding fields in your ServiceNow table. Coalesce fields ensure that records are either updated if a match is found or created if no match exists. - After creating the web service, select **Use Coalesce Field for Record Matching** to designate the coalesce setting for the appropriate field and click Submit. - In the "Related Links" section, click **Auto Map Matching Fields** to automatically map fields from GitGuardian to your ServiceNow table. ![Transform map config](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/10-transform-map-config.png) - Review the mapped fields and **create any missing correspondences**: ![New map](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/11-new-map.png) - For the `Sys ID` field, manually map it to `u_sys_id` and ensure it is set to **coalesce**. This ensures that updates are applied to existing records. ![Sys ID map](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/12-sys-id.png) - For the other fields, do **not** set them to coalesce to avoid unintended overwriting of records. ![Timestamp](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/13-timestamp.png) ![Source](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/14-source.png) - For the `u_timestamp` field, do not change the date format - it must be `yyyy-MM-dd HH:mm:ss` for the mapping to work. The transform map should look like this: ![Back](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/15-back.png) 8. **Additional fields for custom tables** (Optional):
If you're not using the default Incident table, know that the following fields are accessible and can be mapped for more detailed context on the detected secrets. (These will be empty if the issue is created manually from a GitGuardian incident u_source_name u_source_type u_location_url u_author_name u_author_email u_secret_type u_occurrence_id u_triggered_on (do not change the format - it should be yyyy-MM-dd HH:mm:ss)
9. **Retrieve the web service URL**: - Under the web service's "Related Links," click on **Explore REST API**. ![Explore REST API](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/16-explore-rest-api.png) - Copy the link to the API, replacing `{stagingTableName}` with the name of your web service. This URL will be used in GitGuardian's settings. ![Webservice URL](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/17-webservice-url.png) :::info The URL should follow this format: https://xxxxx.service-now.com/api/now/import/gitguardian_notification (where xxxxx is your ServiceNow instance ID). ::: ### Step C: Finalize the configuration in GitGuardian In this section, we finalize the integration in GitGuardian by using the credentials and web service setup created in the previous sections. In GitGuardian, go to **Settings > Integration > Destination > Issue Tracking > [ServiceNow](https://dashboard.gitguardian.com/settings/integrations/servicenow)**, then click **Add Integration** for the team where you want the integration to apply (choose "All incidents" if it's not team-specific). The configuration is then set up through a four-step wizard. 1. **Select the events** (Step 1 of 4): - Give the configuration a name in the **Events name** field. - Under **Event subscription**, choose which events ServiceNow should create incidents for. Toggle the event group you want to monitor: **Internal monitoring**, **Public monitoring**, or **Honeytoken**. Only one event group can be active at a time. - In the **Notify when** section, select the specific events that should trigger an incident creation or update in ServiceNow. Use **Filters** and **Presets** to refine the selection, or **Unselect all** to start from scratch. The "New incident detected" event is always selected. ![Select events](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/snow-step1-events.png) 2. **Connect to your ServiceNow instance** (Step 2 of 4): - Use the URL obtained in Step 9 for the **API endpoint URL**. - For **Username** and **Password**, input the credentials created in Steps 3 and 4. Leave the password blank to keep the current one when editing an existing configuration. ![Connect to ServiceNow](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/snow-step2-connection.png) 3. **Define issue content** (Step 3 of 4): - Customize the content of the ServiceNow issue (title and description), using the available variables. ![Define issue content](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/snow-step3-template.png) 4. **Define automation parameters** (Step 4 of 4): - You can configure the following automation options: - **Auto-create**: Automatically creates a ServiceNow issue for each new incident detected in GitGuardian - in the team perimeter. (If left unchecked, it is still possible to create ServiceNow issues from existing GitGuardian incident). - **Auto-update**: Sends updates from GitGuardian to the associated ServiceNow issue in the form of comments whenever the GitGuardian incident changes. - **Auto-resolve**: When the linked ServiceNow issue is marked as closed, the related GitGuardian incident will be automatically marked as Resolved. - Click **Save** to finalize the configuration. ![Define automation parameters](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/snow-step4-automation.png) If you've selected the **Auto-resolve** option, additional fields appear so you can define how the status of a ServiceNow issue triggers the closure of the corresponding GitGuardian incident: - **Target table name**: the target table from ServiceNow (the value between brackets from Step 6, for example `incident`). - **ServiceNow field for the issue status**: the name of the field in your ServiceNow table that reflects the issue's status (in the Incident table, this field is typically called `state`). - **ServiceNow value(s) for the resolved status**: the value(s) of the status field that should trigger the closure of the corresponding GitGuardian incident. Separate values with a comma if there are several. The default ServiceNow incident states are: New=1, In Progress=2, On Hold=3, Resolved=6, Closed=7, Canceled=8 (these may differ on a customized instance). You can retrieve them by going to System Definition > Tables, and exploring the table name, columns, and choices. :::note Resolving the linked ServiceNow issue triggers the GitGuardian incident closure with a 30-minute delay. ::: Once the configuration is saved, send a test notification and confirm the creation of an incident in ServiceNow. ![Test integration](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/21-snow-test-integration.png) ## Manual creation of issues from GitGuardian Once a ServiceNow integration is configured, issues can be created from the incident page or incidents list page. ![Create manually](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/22-create-manually-1.png) The creation form is initialized from the integration configuration and template. Note that the auto-update and the auto-resolve parameters are inherited from the configuration and cannot be manually updated. ![Creation form](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/23-create-manually-2.png) After creation, the ServiceNow issue becomes visible on the incident page for quick access. :::caution Bulk issue creation from the incidents table is not supported. ::: ### Unlink a ticket You can remove the link between a GitGuardian incident and its ServiceNow ticket. This is useful when a ticket was linked by mistake or is no longer relevant to the incident. 1. On the incident page, locate the linked ServiceNow ticket under **Issue tracking** and click the unlink icon next to it. ![Issue tracking links](/img/platform/configure-alerting/issue-tracking-integrations/servicenow/snow-issue-tracking.png) 2. Confirm by clicking **Unlink ticket** in the dialog. :::note Unlinking only removes the association in GitGuardian. The ServiceNow ticket itself is not deleted. ::: --- ## Custom webhook Custom webhooks allow you to receive GitGuardian notifications on any server that accepts incoming json-encoded HTTP "POST" requests. We use HMAC with sha256 as a hash function to sign the payload of our requests. The key used is a string concatenation of the timestamp and the signature token. This allows you to check that requests are coming from GitGuardian and that the payload was not altered during transport. See below how to implement the verification procedure. You can set the signature token in your settings. The “Timestamp” field in the header counters replay attacks. If your current timestamp differs from our sending “Timestamp” by more than a few seconds, it is safer to drop the request. A custom header can also be added to the requests from your settings to specify, for example, the environment or service. ## How to create a custom webhook endpoint 1. Navigate to Settings > Workspace > Integrations > Destinations > [Custom webhook](https://dashboard.gitguardian.com/settings/integrations/custom_webhook) ### For a personal workspace 2. Create a new custom webhook with the name of your webhook and the URL where you want to receive GitGuardian notifications. GitGuardian generates a default signature token for you to verify the authenticity of the webhook. The signature token can be edited, make sure to store it in a safe place as you won't be able to access it again after creating the webhook. ![Custom webhook form](/img/platform/configure-alerting/notifiers-integrations/custom-webhook/custom_webhook_form.png) 3. Select the events you would like to subscribe to and receive. 4. Configure the endpoint on your side to verify the incoming request and handle GitGuardian alerts. ### For a business workspace 2. Create a new custom webhook at team level. - If you intend to activate the custom webhook for ALL incidents within the workspace, you should create it within the 'All-incidents team'. - If you intend to activate the custom webhook for incidents within a particular team, you should create it within that team. This can be done directly from the integration page: ![Manage integrations](/img/platform/collaboration-and-sharing/team-notifiers-workspaceconf.png) or from the team page: ![Custom webhook form team](/img/platform/configure-alerting/notifiers-integrations/custom-webhook/custom-webhook-team.png) 3. Select the events you would like to subscribe to and receive. 4. Configure the endpoint on your side to verify the incoming request and handle GitGuardian alerts. ### Events You can subscribe to the following events from **GitGuardian Internal Monitoring** and/or **GitGuardian Public Monitoring** (if your workspace and team have access to Public Monitoring): | Name | Description | |----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **New incident detected** | A new incident has been detected. | | **New occurrence detected** | A new occurrence has been detected for this incident. | | **Incident Validity changed** | The validity has been updated for this incident. | | **Incident status change** | Triggered when the status of an incident is updated. | |     **Incident resolved** | This incident has been resolved. | |     **Incident ignored** | This incident has been ignored. | |     **Incident reopened** | This incident has been reopened. | |     **Incident regression** | A new occurrence has been detected by real-time scanning of a connected source for an incident previously marked as resolved (manually or by the auto-resolver). | |     **Incident Severity changed** | The severity has been updated for this incident. | | **Risk score updated** _(Business plan)_ | The risk score has been updated for this incident. Not sent for public incidents on workspaces where the [agents analysis](/public-monitoring/remediate/agents-analysis) is enabled. | | **Incident assignments** | Triggered when an incident is assigned, reassigned, or unassigned. | |     **Incident assigned** | This incident has been assigned to a user. | |     **Incident reassigned** | This incident has been reassigned to a different user. | |     **Incident unassigned** | A user was unassigned from this incident. | | **Incident access** | Triggered when a user's access to an incident changes. | |     **Incident access granted** | A user has been granted access to this incident. | |     **Incident access revoked** | Access to this incident has been revoked for a user. | | **Publicly shared** | Triggered when the public sharing link of an incident changes. | |     **Incident shared publicly** | A user has generated a public sharing link for this incident. | |     **Incident unshared publicly** | A user has deactivated the public sharing link for this incident. | | **Messages** | Triggered when a new message is added to an incident. | |     **Feedback submitted** | A feedback has been submitted for this incident. | |     **New comment on an incident** | A new note has been created for this incident. | ## Filter notifications by incident criteria You can define **filtering rules** so this notifier only sends notifications for incidents that match the criteria you choose — by **severity**, **ML risk score**, **validity**, **secret type**, or **GitGuardian tags**, on both internal and public monitoring incidents. The risk score is the exception: it is not available on public incidents if the [agents analysis](/public-monitoring/remediate/agents-analysis) is enabled for the workspace. If you don't set any rule, every incident is notified (the default). See [Filter notifications by incident criteria](/platform/configure-alerting/alerting-and-notifications#filter-notifications-by-incident-criteria) for the full list of criteria and important notes on notification timing. ## How to test the webhook You can send a test message from the GitGuardian workspace in order to check that your webhook is operational. Here is a sample payload of the test message you will receive: ```json { "author": { "info": "sample@sample.sample", "name": "Sample Sample" }, "origin": "GitGuardian", "date": "2042-10-10 04:00:00 PM", "type": "Welcome Message Token", "policy": "Secrets detection", "gitguardian_link": "http://dashboard.gitguardian.com/workspace/34123/incidents/8213", "break_url": "github.com/sample_user/sample_repo/compare#ae32df", "severity": "unknown", "validity": "invalid", "matches": [ { "type": "client_id", "match": "--censored--", "index_start": 74, "index_end": 86, "pre_line_start": 2, "pre_line_end": 2, "post_line_start": 3, "post_line_end": 3 }, { "type": "client_secret", "match": "--censored--", "index_start": 30, "index_end": 44, "pre_line_start": 1, "pre_line_end": 1, "post_line_start": 2, "post_line_end": 2 } ] } ``` > Note: your response message will contain the matched secret in plain text and will not show as `--censored--` as shown above. ## How to verify the payload signature We use HMAC with SHA256 as a hash function to sign the payload of our requests. The key used is a string concatenation of the timestamp and the signature token. This allows you to check that requests are coming from GitGuardian and that the payload was not altered during transport. See below how to implement the verification procedure. You can set the signature token in your settings. The `Timestamp` field in the header counters replay attacks. If your current timestamp differs from our sending `Timestamp` by more than a few seconds, it is safer to drop the request. The `Gitguardian-Signature` replaces the old header `X-GitGuardian-Signature`, which is still available but deprecated as we switch to the new. #### Python3 example Here is a python3 example of how to verify the signature of our notifications: - **signature** is from our request's headers - **timestamp** is from our request's headers - **signature_token** is the token that you have specified in the settings - **payload** is our request body, decoded from “utf-8” (i.e. string representing our json) ```python def verify_signature(signature: str, timestamp: str, signature_token: str, payload: str) -> bool: if not signature.startswith("sha256="): return False signature = signature.split("sha256=")[-1] hmac_digest = hmac.new(key=bytes(timestamp + signature_token, "utf-8"), msg=bytes(payload, "utf-8"), digestmod=hashlib.sha256).hexdigest() return hmac.compare_digest(signature, hmac_digest) ``` Here is a very basic unit test that lets you check that your implementation is correct: ```python assert verify_signature_gitguardian( signature="sha256=172fe3d694b734aa53dc892fd3b8d62163fc240064de570ba006900bb54a0fc2", timestamp="0", signature_token="foo", payload="bar" ) ``` #### AWS Lambda example When using AWS lambda, a **HTTP API Gateway** must be used as trigger. ![HTTP API Gateway](/img/platform/configure-alerting/notifiers-integrations/custom-webhook/lambda.png) Below are two examples, respectively in Javascript and Python, on how to validate the payload received from the dashboard. ##### Javascript ```js const { createHmac } = require('crypto') function verifySignature(signature, timestamp, signatureToken, payload) { var signatureHeader = signature.substring(0, 7) if (signatureHeader !== 'sha256=') { return false } var signatureActual = signature.split('=')[1] var hmac = createHmac( 'sha256', Buffer.from(timestamp + signatureToken, 'utf8') ) hmac.update(payload) var result = hmac.digest('hex') if (result === signatureActual) { return true } else { return false } } exports.handler = async (event) => { const payload_signature = event.headers['gitguardian-signature'] const timestamp = event.headers['timestamp'] const webhook_token = '' const payload = event.body let statusCode if (verifySignature(payload_signature, timestamp, webhook_token, payload)) { console.log('OK') statusCode = 200 } else { statusCode = 400 throw new Error() } const response = { statusCode, } return response } ``` ##### Python ```python def verify_signature(signature: str, timestamp: str, signature_token: str, payload: str) -> bool: if not signature.startswith("sha256="): return False signature = signature.split("sha256=")[-1] hmac_digest = hmac.new(key=bytes(timestamp + signature_token, "utf-8"), msg=bytes(payload, "utf-8"), digestmod=hashlib.sha256).hexdigest() return hmac.compare_digest(signature, hmac_digest) def lambda_handler(event, context): payload_dump = event["body"] timestamp = event["headers"]["timestamp"] payload_signature = event["headers"]["gitguardian-signature"] webhook_token = "" if verify_signature(payload_signature, timestamp, webhook_token, payload_dump): return {'statusCode': 200, 'body': json.dumps('Success') } return {'statusCode': 400, 'body': json.dumps('Failed to verify') } ``` ## Payload structure :::caution Please be aware that webhook delivery is not guaranteed and is best effort. When a webhook event is triggered, GitGuardian sends a single HTTP POST request to your defined webhook endpoint. However, if your endpoint is unreachable or there are network issues between GitGuardian and your server, the webhook event may not be received. While webhooks are generally reliable, it's important to remember that delivery cannot be guaranteed. ::: The payloads are described by the OpenAPI specification. Below are a few examples for the different events you can subscribe to. :::note Public incidents and the risk score On public incidents, the risk score is produced by the agents that analyze them, and that changes two things for notifications: - **You cannot filter notifications on the risk score.** The agents' analysis is asynchronous and may be completed several hours after the incident is detected, so waiting for a score before notifying would delay alerts. - **There is no "Risk score updated" event.** Unlike the ML score it replaces, the agents' score does not evolve on its own once the incident has been analyzed, so there is nothing to notify about. Internal Monitoring incidents are not affected: their risk score, events and filters are unchanged. :::
New incident ```json { "source": "GitGuardian", "timestamp": "2022-06-20T07:45:32.930965Z", "action": "incident_triggered", "message": "A new incident has been detected.", "target_user": "GitGuardian", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31542, "date": "2022-06-20T07:45:31.666462Z", "detector": { "name": "generic_password", "display_name": "Generic Password", "nature": "generic", "family": "Other", "detector_group_name": "generic_password", "detector_group_display_name": "Generic Password" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "no_checker", "occurrence_count": 0, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "unknown", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Assign event ```json { "source": "GitGuardian", "timestamp": "2022-06-17T12:18:41.917977Z", "action": "incident_assigned", "message": "This incident has been assigned to a user.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31450, "date": "2022-06-15T09:16:42.378417Z", "detector": { "name": "generic_password", "display_name": "Generic Password", "nature": "generic", "family": "Other", "detector_group_name": "generic_password", "detector_group_display_name": "Generic Password" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "no_checker", "occurrence_count": 1, "status": "assigned", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": "bruce.wayne@gitguardian.com", "severity": "medium", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Re-assign event ```json { "source": "GitGuardian", "timestamp": "2022-06-17T12:18:41.917977Z", "action": "incident_reassigned", "message": "This incident has been reassigned to a different user.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31450, "date": "2022-06-15T09:16:42.378417Z", "detector": { "name": "generic_password", "display_name": "Generic Password", "nature": "generic", "family": "Other", "detector_group_name": "generic_password", "detector_group_display_name": "Generic Password" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "no_checker", "occurrence_count": 1, "status": "assigned", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": "bruce.wayne@gitguardian.com", "severity": "medium", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Unassign event ```json { "source": "GitGuardian", "timestamp": "2022-06-17T12:20:10.500000Z", "action": "incident_unassigned", "message": "A user was unassigned from this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31450, "date": "2022-06-15T09:16:42.378417Z", "detector": { "name": "generic_password", "display_name": "Generic Password", "nature": "generic", "family": "Other", "detector_group_name": "generic_password", "detector_group_display_name": "Generic Password" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "no_checker", "occurrence_count": 1, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "medium", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [], "risk_score": null } } ```
Risk score updated This event is only sent to workspaces on a Business plan. ```json { "source": "GitGuardian", "timestamp": "2022-06-17T12:25:00.000000Z", "action": "incident_risk_score_updated", "message": "The risk score has been updated for this incident.", "target_user": "GitGuardian", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31450, "date": "2022-06-15T09:16:42.378417Z", "detector": { "name": "generic_password", "display_name": "Generic Password", "nature": "generic", "family": "Other", "detector_group_name": "generic_password", "detector_group_display_name": "Generic Password" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "no_checker", "occurrence_count": 1, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "high", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [], "risk_score": 350 } } ``` > Note: every `incident` object also carries an optional `risk_score` integer field (populated on Business plans only). It is omitted from the other examples for brevity.
Severity change ```json { "source": "GitGuardian", "timestamp": "2022-06-17T12:18:22.220508Z", "action": "incident_severity_changed", "message": "The severity has been updated for this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31450, "date": "2022-06-15T09:16:42.378417Z", "detector": { "name": "generic_password", "display_name": "Generic Password", "nature": "generic", "family": "Other", "detector_group_name": "generic_password", "detector_group_display_name": "Generic Password" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "no_checker", "occurrence_count": 1, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "medium", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Validity change ```json { "source": "GitGuardian", "timestamp": "2022-06-17T12:18:22.220508Z", "action": "incident_validity_changed", "message": "The validity has been updated for this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31450, "date": "2022-06-15T09:16:42.378417Z", "detector": { "name": "generic_password", "display_name": "Generic Password", "nature": "generic", "family": "Other", "detector_group_name": "generic_password", "detector_group_display_name": "Generic Password" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "invalid", "occurrence_count": 1, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "medium", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Incident resolved ```json { "source": "GitGuardian", "timestamp": "2022-06-22T09:00:16.143457Z", "action": "incident_resolved", "message": "This incident has been resolved.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31605, "date": "2022-06-16T08:23:40Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": true, "validity": "not_checked", "occurrence_count": 1, "status": "resolved", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "high", "ignored_at": null, "ignore_reason": null, "resolved_at": "2022-06-22T09:00:16.038050Z", "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Incident ignored ```json { "source": "GitGuardian", "timestamp": "2022-06-22T09:02:57.377837Z", "action": "incident_ignored", "message": "This incident has been ignored.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31605, "date": "2022-06-16T08:23:40Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "not_checked", "occurrence_count": 1, "status": "ignored", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "high", "ignored_at": "2022-06-22T09:02:57.292217Z", "ignore_reason": "low_risk", "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Incident reopened ```json { "source": "GitGuardian", "timestamp": "2022-06-22T09:03:10.775369Z", "action": "incident_reopened", "message": "This incident has been reopened.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31605, "date": "2022-06-16T08:23:40Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "not_checked", "occurrence_count": 1, "status": "ignored", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "high", "ignored_at": "2022-06-22T09:02:57.292217Z", "ignore_reason": "low_risk", "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Incident regression ```json { "source": "GitGuardian", "timestamp": "2022-06-28T09:10:19.966461Z", "action": "incident_regression", "message": "A new regression was found for this incident.", "target_user": "GitGuardian", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 1234, "date": "2022-06-28T09:10:18.613418Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": true, "validity": "invalid", "occurrence_count": 4, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "high", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Incident access granted ```json { "source": "GitGuardian", "timestamp": "2022-06-28T09:15:55.682589Z", "action": "incident_access_granted", "message": "A user has been granted access to this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 3831600, "date": "2022-06-28T00:03:46.110078Z", "detector": { "name": "stripe", "display_name": "Stripe Keys", "nature": "specific", "family": "token", "detector_group_name": "stripe_keys", "detector_group_display_name": "Stripe Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "invalid", "occurrence_count": 2, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "unknown", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/8/incidents/xxx", "share_url": "https://dashboard.gitguardian.com/share/incidents/xxx", "feedbacks": [] }, "member": { "id": 3252, "name": "John Smith", "email": "john.smith@example.org", "access_level": "owner" } } ``` `member` provides details about the member who have been granted access during this event. If multiple members were granted access, there will be one event for each access granted.
Incident access revoked ```json { "source": "GitGuardian", "timestamp": "2022-06-28T09:17:01.353280Z", "action": "incident_access_revoked", "message": "Access to this incident has been revoked for a user.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 3831600, "date": "2022-06-28T00:03:46.110078Z", "detector": { "name": "stripe", "display_name": "Stripe Keys", "nature": "specific", "family": "token", "detector_group_name": "stripe_keys", "detector_group_display_name": "Stripe Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "invalid", "occurrence_count": 2, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "unknown", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/8/incidents/xxx", "share_url": "https://dashboard.gitguardian.com/share/incidents/xxx", "feedbacks": [] }, "member": { "id": 3252, "name": "John Smith", "email": "john.smith@example.org", "access_level": "owner" } } ``` `member` provides details about the member who have been revoked access during this event. If multiple members were granted access, there will be one event for each access granted.
Incident shared publicly ```json { "source": "GitGuardian", "timestamp": "2022-06-28T08:48:49.290758Z", "action": "incident_shared_publicly", "message": "A user has generated a public sharing link for this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 3827964, "date": "2022-06-23T14:34:11Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "invalid", "occurrence_count": 1, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "unknown", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xx", "share_url": "https://dashboard.gitguardian.com/share/incidents/xxx", "feedbacks": [] } } ```
Incident publicly unshared ```json { "source": "GitGuardian", "timestamp": "2022-06-28T08:49:56.806741Z", "action": "incident_unshared_publicly", "message": "A user has deactivated the public sharing link for this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 3827964, "date": "2022-06-23T14:34:11Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "invalid", "occurrence_count": 2, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "unknown", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] } } ```
Incident feedback received ```json { "source": "GitGuardian", "timestamp": "2022-06-28T08:49:56.806741Z", "action": "incident_feedback_received", "message": "A feedback has been submitted for this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 3827964, "date": "2022-06-23T14:34:11Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "invalid", "occurrence_count": 2, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "unknown", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [ { "id": 1, "date": "2022-06-28T08:49:56.806741Z", "updated_at": "2022-06-28T08:49:56.806741Z", "revoked": false, "remarks": "This secret is no longer valid.", "member": { "id": 1, "role": "owner", "name": "John Doe", "email": "john.doe@gitguardian.com" }, "real_secret": false, "sensitive": false } ] } } ```
New occurrence ```json { "source": "GitGuardian", "timestamp": "2022-06-23T09:10:24.594597Z", "action": "new_occurrence", "message": "A new occurrence has been detected for this incident.", "target_user": "GitGuardian", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31605, "date": "2022-06-16T08:23:40Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "not_checked", "occurrence_count": 5, "status": "assigned", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": "bruce.wayne@gitguardian.com", "severity": "high", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] }, "occurrence": { "id": 1234, "incident_id": 1243, "kind": "RLTM", "sha": "xxx", // only for internal monitoring incidents. "element_type": "GIT_COMMIT", // only for public monitoring incidents. "element": "xxx", // only for public monitoring incidents. "actors": [ // actors section only for public monitoring incidents. { "id": 1234, "type": "github_user", "name": "xxx", "email": "xxx@yy.com", "primary": true, "url": "https://github.com/xxx" } ], "author_name": "GitHub", // only for internal monitoring incidents. "author_info": "noreply@github.com", // only for internal monitoring incidents. "date": "2022-06-23T09:10:23.529812Z", "presence": "visible", "url": "https://github.com/user/repo/commit/123#diff-xxx", "filepath": "my/path/TestJS.js", "change_type": "addition", // only for VCS sources, null otherwise. "filename": "TestJS.js", // only for public monitoring incidents. "source": { "id": 710, "url": "https://github.com/user/repo", "type": "github", "full_name": "name of repository", // only for internal monitoring incidents. "name": "name of repository", // only for public monitoring incidents. "health": "at_risk", // only for internal monitoring incidents. "open_incidents_count": 5, // only for internal monitoring incidents. "closed_incidents_count": 0, // only for internal monitoring incidents. "visibility": "private", // only for internal monitoring incidents. "last_scan": { // only for internal monitoring incidents. "status": "finished", "date": "2022-11-18T17:07:59.079520Z" }, "external_id": "github_id", "metadata": {} // only for public monitoring incidents. } } } ```
New incident note ```json { "source": "GitGuardian", "timestamp": "2022-06-22T09:11:02.733441Z", "action": "incident_note_created", "message": "A new note has been created for this incident.", "target_user": "John Doe john.doe@gitguardian.com", "target_team": "My team", "custom_webhook_name": "My custom webhook name", "incident": { "id": 31605, "date": "2022-06-16T08:23:40Z", "detector": { "name": "aws_iam", "display_name": "AWS Keys", "nature": "specific", "family": "credentials", "detector_group_name": "aws_iam", "detector_group_display_name": "AWS Keys" }, "secret_hash": "xxx", "hmsl_hash": "xxx", "secret_revoked": false, "validity": "not_checked", "occurrence_count": 1, "status": "triggered", "declarative_secret_status": "active", // only for public monitoring incidents. "regression": false, // only for internal monitoring incidents. "assignee_email": null, "severity": "high", "ignored_at": null, "ignore_reason": null, "resolved_at": null, "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/incidents/xxx", "share_url": null, "feedbacks": [] }, "incident_note": { "id": 46389, "api_token": null, "created_at": "2022-06-22T09:11:02.683727Z", "updated_at": null, "comment": "This is not a test" } } ```
These events are sent for workspaces with Honeytoken enabled. They are emitted at the workspace level, so `target_user` is always `null`.
New honeytoken event ```json { "source": "GitGuardian", "timestamp": "2022-06-28T09:10:19.966461Z", "action": "new_honeytoken_event", "message": "A new honeytoken event has been received.", "target_user": null, "target_team": "My team", "custom_webhook_name": "My custom webhook name", "honeytoken_event": { "id": "a1b2c3d4-0000-0000-0000-000000000000", "honeytoken_id": "f9e8d7c6-0000-0000-0000-000000000000", "triggered_at": "2022-06-28T09:10:18.613418Z", "status": "open", // "open" or "closed". "ip_address": "1.2.3.4", "action": "GetCallerIdentity", "data": { "user_agent": "aws-cli/2.0.0 Python/3.9", "region": "us-east-1" }, "tags": ["production"] } } ```
Honeytoken triggered ```json { "source": "GitGuardian", "timestamp": "2022-06-28T09:10:19.966461Z", "action": "honeytoken_triggered", "message": "This honeytoken has been triggered.", "target_user": null, "target_team": "My team", "custom_webhook_name": "My custom webhook name", "honeytoken": { "id": "f9e8d7c6-0000-0000-0000-000000000000", "name": "My AWS honeytoken", "description": "Deployed in CI config", "created_at": "2022-06-01T08:00:00Z", "gitguardian_url": "https://dashboard.gitguardian.com/workspace/1/honeytokens/xxx", "status": "triggered", // "active", "revoked" or "triggered". "triggered_at": "2022-06-28T09:10:18.613418Z", "revoked_at": null, "open_events_count": 1, "type": "AWS", "creator_id": 3252, "creator_api_token_id": null, "revoker_id": null, "revoker_api_token_id": null } } ```
--- ## Discord To set up your Discord integration, provide a Discord Webhook URL in the Discord integration section. ### How to integrate 1. Open the Discord app and go to the **channel settings** (click the gear icon in the upper left corner). ![0](/img/platform/configure-alerting/notifiers-integrations/discord/0.png) 2. In the **Integrations** tab, create a **New Webhook**. ![1](/img/platform/configure-alerting/notifiers-integrations/discord/1.png) 3. Click **Copy Webhook URL**. ![2](/img/platform/configure-alerting/notifiers-integrations/discord/2.png) 4. Paste the webhook URL into the [Discord integration section](https://dashboard.gitguardian.com/settings/integrations/discord) of your dashboard settings. --- ## Email alerting GitGuardian sends an email to all members of the affected team anytime it detects an incident. To prevent alert fatigue, only one email is sent for multiple occurrences of the same incident. The members of a team will only receive emails for incidents within their team(s). If you want to receive emails for all the incidents of your workspace, make sure you're a member of the `all-incidents` team. ## Email alerts Email alerts include: - Details of the incident (secret detector, repository and commit involved) - Date of the incident - A link to view the offending file directly on the source - A link to the incident in the GitGuardian dashboard > You can configure your email alerts in your [personal settings](https://dashboard.gitguardian.com/settings/personal/notifications). Read [our dedicated documentation on email preferences](../../user-account/email-preferences.md). ## Filter email alerts by incident criteria For **public monitoring** incidents, you can filter email alerts by **severity** so you only receive emails for the incidents that meet your threshold. Support for additional criteria (ML risk score, validity, secret type, GitGuardian tags) and for internal monitoring incidents is planned. See [Filter notifications by incident criteria](../alerting-and-notifications#filter-notifications-by-incident-criteria) for an overview. ## FAQ **I just received an alert email on which I did not install GitGuardian. Why did this happen?** **Public Alerts** are another type of GitGuardian alert that you may encounter. They originate from our pro-bono public alerting service, which is not related to this application. When GitGuardian detects a secret on a public GitHub repository, it alerts the developer responsible for the incident through their commit email. If you have received an alert email, please see our [remediation guide for leaks on public GitHub](../../../secrets-detection/secrets-detection-engine/leaks_remediation.mdx) --- ## Microsoft Teams This notifier can send messages to a Microsoft Teams channel for incident lifecycle events (from Internal and/or Public Monitoring), honeytoken alerts. To set up your Microsoft Teams integration, provide a Microsoft Teams channel link in the Teams settings section and configure which events you want to receive notifications for. ### How to integrate 1. Go to the [Microsoft Teams app store](https://teams.microsoft.com/l/app/61d2bd20-544a-4dff-854d-9b2f6e1c774d?source=app-details-dialog) and add the **GitGuardian app**. ![1](/img/platform/configure-alerting/notifiers-integrations/ms-team/1.png) 2. Select the channel where you want to send alerts. ![2](/img/platform/configure-alerting/notifiers-integrations/ms-team/2.png) A welcome message is sent to your channel: ![3](/img/platform/configure-alerting/notifiers-integrations/ms-team/3.png) 3. Copy the link to the channel: - Right-click the channel name. ![4](/img/platform/configure-alerting/notifiers-integrations/ms-team/4.png) - Select **Get link to channel**. ![5](/img/platform/configure-alerting/notifiers-integrations/ms-team/5.png) 4. Add the integration to your team in the [Microsoft Teams integration section](https://dashboard.gitguardian.com/settings/integrations/alert_ms_teams) of your dashboard settings. ![6](/img/platform/configure-alerting/notifiers-integrations/ms-team/6.png) **Team-level configuration:** - **Personal workspace**: You can only configure alerting on the 'All-incidents team'. - **Business workspace**: You can configure the integration on any team: - Create it within the 'All-incidents team' to receive notifications for all workspace incidents. - Create it within a specific team to receive notifications only for that team's incidents. This can be done directly from the integration page or from the team page. 5. Paste the copied link. ![7](/img/platform/configure-alerting/notifiers-integrations/ms-team/7.png) 6. Select the events you would like to subscribe to and receive. 7. Your integration is now successfully configured. ![8](/img/platform/configure-alerting/notifiers-integrations/ms-team/8.png) ### Events You can subscribe to the following events from **GitGuardian Internal Monitoring** and/or **GitGuardian Public Monitoring** (if your workspace and team have access to Public Monitoring): | Name | Description | |----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **New incident detected** | A new incident has been detected. | | **New occurrence detected** | A new occurrence has been detected for this incident. | | **Incident Validity changed** | The validity has been updated for this incident. | | **Incident status change** | Triggered when the status of an incident is updated. | |     **Incident resolved** | This incident has been resolved. | |     **Incident ignored** | This incident has been ignored. | |     **Incident reopened** | This incident has been reopened. | |     **Incident regression** | A new occurrence has been detected by real-time scanning of a connected source for an incident previously marked as resolved (manually or by the auto-resolver). | |     **Incident Severity changed** | The severity has been updated for this incident. | | **Risk score updated** _(Business plan)_ | The risk score has been updated for this incident. Not sent for public incidents on workspaces where the [agents analysis](/public-monitoring/remediate/agents-analysis) is enabled. | | **Incident assignments** | Triggered when an incident is assigned, reassigned, or unassigned. | |     **Incident assigned** | This incident has been assigned to a user. | |     **Incident reassigned** | This incident has been reassigned to a different user. | |     **Incident unassigned** | A user was unassigned from this incident. | | **Incident access** | Triggered when a user's access to an incident changes. | |     **Incident access granted** | A user has been granted access to this incident. | |     **Incident access revoked** | Access to this incident has been revoked for a user. | | **Publicly shared** | Triggered when the public sharing link of an incident changes. | |     **Incident shared publicly** | A user has generated a public sharing link for this incident. | |     **Incident unshared publicly** | A user has deactivated the public sharing link for this incident. | | **Messages** | Triggered when a new message is added to an incident. | |     **Feedback submitted** | A feedback has been submitted for this incident. | |     **New comment on an incident** | A new note has been created for this incident. | ## Filter notifications by incident criteria You can define **filtering rules** so this notifier only sends notifications for incidents that match the criteria you choose — by **severity**, **ML risk score**, **validity**, **secret type**, or **GitGuardian tags**, on both internal and public monitoring incidents. The risk score is the exception: it is not available on public incidents if the [agents analysis](/public-monitoring/remediate/agents-analysis) is enabled for the workspace. If you don't set any rule, every incident is notified (the default). See [Filter notifications by incident criteria](/platform/configure-alerting/alerting-and-notifications#filter-notifications-by-incident-criteria) for the full list of criteria and important notes on notification timing. ## Setup MS Teams for self-hosted GitGuardian 1. Configure Your Microsoft Teams App ![9](/img/platform/configure-alerting/notifiers-integrations/ms-team/9.png) To integrate Microsoft Teams with the Self-Hosted GitGuardian platform, you must create your own Microsoft Teams app. This app will serve as the interface for sending notifications via a bot. Follow these steps: a. Why Do We Need a Bot? - The bot acts as the interface for sending messages in Microsoft Teams and will serve as the sender of all GitGuardian notifications. - Users can add the bot to their preferred Teams channels via the Microsoft Teams Store and link it to GitGuardian Platform to enable team notifications. b. Use the Microsoft Teams Developer Portal - Access the [Microsoft Teams Developer Portal](https://dev.teams.microsoft.com/apps). - Create your app by following these steps: - Click **New app**. - Complete the `Basic Information` section with the required details: - Name, Display Name, Description (short and long). - Developer/Company Name. - Terms of Service and Privacy Policy links. c. Add a Bot - Navigate to the **Add Features** section and add a bot: - Create a new Entra identity for the bot or link it to an existing bot identity. - Under `What can your bot do?`, select **Only send notifications**. - Set the scope to **Team** and **Group Chat** for maximum flexibility. d. Publish the App - Navigate to the **Publish to org** section to publish the app privately within your organization. - Once published, the app will be available in the Microsoft Teams Store for your organization. - If the app is blocked by IT admins or requires approval, complete the validation steps in the [Microsoft Teams Admin Portal](https://admin.teams.microsoft.com/). e. Copy your bot's **Client ID** and **Client Secret** from your Microsoft Teams app into GitGuardian to complete the integration: - In the [Azure portal](https://portal.azure.com/#home), search for your app and select **Microsoft Entra ID**. - Find the **Application ID** (Client ID) in the **Overview** section. - Generate a **Client Secret** in **Certificates & Secrets** and copy it immediately (it’s only shown once). 2. Select the channel where you want to send alerts. ![2](/img/platform/configure-alerting/notifiers-integrations/ms-team/2.png) A welcome message is sent to your channel: ![3](/img/platform/configure-alerting/notifiers-integrations/ms-team/3.png) 3. Copy the link to the channel: - Right-click the channel name. ![4](/img/platform/configure-alerting/notifiers-integrations/ms-team/4.png) - Select **Get link to channel**. ![5](/img/platform/configure-alerting/notifiers-integrations/ms-team/5.png) 4. Add the integration to your team in the [Microsoft Teams integration section](https://dashboard.gitguardian.com/settings/integrations/alert_ms_teams) of your dashboard settings. ![6](/img/platform/configure-alerting/notifiers-integrations/ms-team/6.png) 5. Paste the copied link. ![10](/img/platform/configure-alerting/notifiers-integrations/ms-team/10.png) 6. Select the events you would like to subscribe to and receive (see the [Events](#events) table above). 7. Your integration is now successfully configured. ![8](/img/platform/configure-alerting/notifiers-integrations/ms-team/8.png) --- ## PagerDuty PagerDuty is an incident management platform that provides notifications, automatic escalations, on-call scheduling, and other functionality to help teams detect and fix infrastructure problems quickly. GitGuardian is natively integrated with PagerDuty so all alerts sent by GitGuardian can be disseminated through PagerDuty flows. ### PagerDuty + GitGuardian integration benefits - Receive PagerDuty notifications for GitGuardian alerts - GitGuardian groups occurrences of the same secret under one single secret incident. Set the frequency of your notifications: either all occurrences of each secret incident, or only at the first occurrence (only when the incident is newly created). ### How it works When GitGuardian detects a secret in your source code, GitGuardian will send an event to a service in PagerDuty. Events from GitGuardian will trigger a new incident on the corresponding PagerDuty service, or group as alerts logs into an existing incident. ![GG PagerDuty incident](/img/platform/configure-alerting/notifiers-integrations/pagerduty/Pagerduty_occurences.png) ### Requirements PagerDuty integrations require Admin rights on the PagerDuty service you want to receive notifications on (to create routing integration key needed for the integration on GitGuardian side). If it is not your case, please reach out to a PagerDuty Admin of your service to configure the integration. ### Integration walkthrough #### In PagerDuty **Integrating with a PagerDuty service** 1. From the Configuration menu, select Services. 2. There are two ways to add an integration to a service: - **If you are adding your integration to an existing service**: click the name of the service you want to add the integration to. Then, select the **Integrations** tab and click the **New Integration** button. - If you are creating a new service for your integration: Please read PagerDuty documentation in section [Configuring Services and Integrations](https://support.pagerduty.com/docs/services-and-integrations#section-configuring-services-and-integrations) and follow the steps outlined in the [Create a New Service](https://support.pagerduty.com/docs/services-and-integrations#section-create-a-new-service) section, selecting GitGuardian as the Integration Type. Continue with the In GitGuardian section (below) once you have finished these steps. 3. Select GitGuardian from the Integration Type menu (if you cannot find GitGuardian, please fallback on "Events API v2" type). 4. Click the **Add Integration** button to save your new integration. You will be redirected to the Integrations tab for your service. 5. An **Integration Key** will be generated on this screen. Keep this key saved in a safe place, as it will be used when you configure the integration with GitGuardian in the next section. #### In GitGuardian 1. Navigate to Settings > Integrations > Destinations > [PagerDuty](https://dashboard.gitguardian.com/settings/integrations/pagerduty) 2. Provide your newly created integration key 3. Select the frequency of notifications 4. Submit For business workspace, the PagerDuty integration configuration is done per team. You can either create a single configuration within the `All-incidents` team to send all GitGuardian incidents to the same PagerDuty project or create separate configurations for each team to send their incidents to specific projects. ![GG PagerDuty integration form](/img/platform/configure-alerting/notifiers-integrations/pagerduty/new_integration_form.png) ### How to uninstall 1. Navigate to Settings > Integrations > Destinations > [PagerDuty](https://dashboard.gitguardian.com/settings/integrations/pagerduty) 2. Delete your integration key on GitGuardian 3. Revoke your key on PagerDuty ![PagerDuty integration keys table](/img/platform/configure-alerting/notifiers-integrations/pagerduty/integration_keys_table.png) --- ## Slack This notifier can send messages to a Slack channel for incident lifecycle events (from Internal and/or Public Monitoring) and honeytoken alerts. You can connect Slack in two modes: - **Incident thread** _(Recommended)_: installs the GitGuardian Slack app on your workspace via OAuth. Every event about an incident is grouped into a single thread, so your channel doesn't get flooded and the full history of an incident stays in one place. ⚠️ Not available yet, coming soon. - **Webhook**: quick to set up. Each event is posted as a new, separate message. ## Set up with Incident thread mode 1. Open the Slack notifier configuration, select your **Team**, then choose **Incident thread** instead of **Webhook**. ![1](/img/platform/configure-alerting/notifiers-integrations/slack/slack-app/1-mode.png) 2. Under **Workspace**, select **Add new** to connect a Slack workspace. If a workspace is already connected, skip to step 4. ![2](/img/platform/configure-alerting/notifiers-integrations/slack/slack-app/2-add-workspace.png) 3. You're redirected to Slack to install the GitGuardian Notifier app. Review the requested permissions, viewing your channels and workspace info, and posting messages in the channels you choose, then select **Allow**. ![3](/img/platform/configure-alerting/notifiers-integrations/slack/slack-app/3-oauth-consent.png) 4. Back in GitGuardian, select the **Workspace** you just connected and the **Channel** where you want alerts posted, then select **Next**. ![4](/img/platform/configure-alerting/notifiers-integrations/slack/slack-app/4-workspace-channel.png) 5. On the **Events** tab, name the notifier and select which **Internal monitoring**, **Public monitoring**, and **Honeytoken** events to subscribe to, then select **Submit**. ![5](/img/platform/configure-alerting/notifiers-integrations/slack/slack-app/5-events.png) 6. Once the notifier is saved, open its row menu (⋮) and select **Send test message** to confirm the app can post to the channel before relying on it. ![6](/img/platform/configure-alerting/notifiers-integrations/slack/slack-app/6-test-notification.png) :::note Uninstalling the GitGuardian app from your Slack workspace (from Slack's own app settings) also breaks the integration on GitGuardian's side. Your notifier configuration flags the workspace as disconnected, repeat the connection steps above to reconnect it. ::: ## Set up with Webhook mode 1. Visit [Slack API: Create an App](https://api.slack.com/apps?new_app=1). 2. Create a new application for **GitGuardian**. ![1](/img/platform/configure-alerting/notifiers-integrations/slack/1.png) 3. Enable the **Incoming Webhooks** feature. ![2](/img/platform/configure-alerting/notifiers-integrations/slack/2.png) 4. Generate a new webhook. ![3](/img/platform/configure-alerting/notifiers-integrations/slack/3.png) 5. Copy the generated webhook URL. ![4](/img/platform/configure-alerting/notifiers-integrations/slack/4.png) 6. Paste the webhook URL in the [Slack integration section](https://dashboard.gitguardian.com/settings/integrations/alert_slack) of your GitGuardian dashboard settings. ![5](/img/platform/configure-alerting/notifiers-integrations/slack/slack_form.png) **Team-level configuration:** - **Personal workspace**: You can only configure alerting on the 'All-incidents team'. - **Business workspace**: You can configure the integration on any team: - Create it within the 'All-incidents team' to receive notifications for all workspace incidents. - Create it within a specific team to receive notifications only for that team's incidents. This can be done directly from the integration page or from the team page. 7. Select the events you would like to subscribe to and receive. ### Events You can subscribe to the following events from **GitGuardian Internal Monitoring** and/or **GitGuardian Public Monitoring** (if your workspace and team have access to Public Monitoring): | Name | Description | |----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **New incident detected** | A new incident has been detected. | | **New occurrence detected** | A new occurrence has been detected for this incident. | | **Incident Validity changed** | The validity has been updated for this incident. | | **Incident status change** | Triggered when the status of an incident is updated. | |     **Incident resolved** | This incident has been resolved. | |     **Incident ignored** | This incident has been ignored. | |     **Incident reopened** | This incident has been reopened. | |     **Incident regression** | A new occurrence has been detected by real-time scanning of a connected source for an incident previously marked as resolved (manually or by the auto-resolver). | |     **Incident Severity changed** | The severity has been updated for this incident. | | **Risk score updated** _(Business plan)_ | The risk score has been updated for this incident. Not sent for public incidents on workspaces where the [agents analysis](/public-monitoring/remediate/agents-analysis) is enabled. | | **Incident assignments** | Triggered when an incident is assigned, reassigned, or unassigned. | |     **Incident assigned** | This incident has been assigned to a user. | |     **Incident reassigned** | This incident has been reassigned to a different user. | |     **Incident unassigned** | A user was unassigned from this incident. | | **Incident access** | Triggered when a user's access to an incident changes. | |     **Incident access granted** | A user has been granted access to this incident. | |     **Incident access revoked** | Access to this incident has been revoked for a user. | | **Publicly shared** | Triggered when the public sharing link of an incident changes. | |     **Incident shared publicly** | A user has generated a public sharing link for this incident. | |     **Incident unshared publicly** | A user has deactivated the public sharing link for this incident. | | **Messages** | Triggered when a new message is added to an incident. | |     **Feedback submitted** | A feedback has been submitted for this incident. | |     **New comment on an incident** | A new note has been created for this incident. | ## Filter notifications by incident criteria You can define **filtering rules** so this notifier only sends notifications for incidents that match the criteria you choose — by **severity**, **ML risk score**, **validity**, **secret type**, or **GitGuardian tags**, on both internal and public monitoring incidents. The risk score is the exception: it is not available on public incidents if the [agents analysis](/public-monitoring/remediate/agents-analysis) is enabled for the workspace. If you don't set any rule, every incident is notified (the default). See [Filter notifications by incident criteria](/platform/configure-alerting/alerting-and-notifications#filter-notifications-by-incident-criteria) for the full list of criteria and important notes on notification timing. --- ## Splunk To receive GitGuardian notifications on Splunk, you need a Splunk instance and must generate an HTTP Event Collector (HEC) token. Follow the instructions below to set it up. Once you have your webhook URL and token, enter them on the Integrations page. :::caution This integration works with all paid Splunk plans but is not supported on the free plan. ::: ### How to integrate 1. Open the Splunk web interface and navigate to **Settings** > **Data inputs**. ![splunk1](/img/platform/configure-alerting/notifiers-integrations/splunk/1.png) ![splunk2](/img/platform/configure-alerting/notifiers-integrations/splunk/2.png) 2. Add a new **HTTP Event Collector** and click the button to create a new token. ![splunk3](/img/platform/configure-alerting/notifiers-integrations/splunk/3.png) ![splunk4](/img/platform/configure-alerting/notifiers-integrations/splunk/4.png) 3. Provide a name (and optionally a description) for your Event Collector, then click **Next**. ![splunk5](/img/platform/configure-alerting/notifiers-integrations/splunk/5.png) 4. Select an existing index or create a new one, then click **Review**. ![splunk6](/img/platform/configure-alerting/notifiers-integrations/splunk/6.png) ![splunk6.1](/img/platform/configure-alerting/notifiers-integrations/splunk/6bis.png) 5. Verify the settings and click **Submit** to create your token. ![splunk7](/img/platform/configure-alerting/notifiers-integrations/splunk/7.png) 6. Go back to **Settings** > **Data inputs**. Tokens are disabled by default, so click **Global Settings** to enable it. ![splunk8](/img/platform/configure-alerting/notifiers-integrations/splunk/8.png) ![splunk9](/img/platform/configure-alerting/notifiers-integrations/splunk/9.png) ![splunk10](/img/platform/configure-alerting/notifiers-integrations/splunk/10.png) 7. If your instance URL is `https://prd-p-xxxxxxxxxxxx.cloud.splunk.com/`, your webhook URL will be: `https://input-prd-p-xxxxxxxxxxxx.cloud.splunk.com:8088/services/collector/event`. ![splunk11](/img/platform/configure-alerting/notifiers-integrations/splunk/11.png) 8. Enter your webhook URL and token into the [Splunk integration section](https://dashboard.gitguardian.com/settings/integrations/splunk) of your dashboard settings. 9. **Team Configurations:** For business workspaces, you can configure the Splunk integration per team: - Create a single configuration under the `All-incidents` team to send all GitGuardian incidents to the same Splunk project. - Alternatively, create separate configurations for each team to send incidents to specific projects. ![Splunk team](/img/platform/configure-alerting/notifiers-integrations/splunk/team-notifiers-splunk.png) --- ## Overview(Deployment-model) # GitGuardian Deployment Models GitGuardian offers flexible deployment options to meet diverse organizational needs, from cloud-first companies to enterprises with strict security and compliance requirements. Choose the deployment model that best fits your infrastructure, security posture, and operational preferences. ## Available deployment models ### GitGuardian SaaS **Fully managed cloud solution** GitGuardian SaaS is our cloud-hosted platform that provides immediate access to all GitGuardian features without any infrastructure management overhead. **Best for Organizations:** - Requiring faster time-to-value - Without dedicated DevOps or Infrastructure resources - Comfortable with SaaS infrastructure **Key Benefits:** - Instant setup and deployment - Automatic updates and maintenance - Global availability and performance - No infrastructure costs or management - Access to latest features first - [Service status monitoring](https://status.gitguardian.com) **Available Regions:** - **USA**: us-west-2 (Oregon) - Available for all plans - **Europe**: eu-central-1 (Frankfurt) - Available for [Business and Enterprise customers](https://www.gitguardian.com/pricing#plan-details) [**Get started with SaaS →**](../getting-started/account-creation.md) --- ### GitGuardian Bridge **SaaS with secure private network access** GitGuardian Bridge extends GitGuardian SaaS with secure, encrypted tunnels to your private infrastructure, enabling you to scan and monitor self-hosted services without exposing them to the internet. **Best for:** - Organizations using both cloud and on-premise infrastructure - Companies wanting SaaS benefits while accessing private systems - Teams with mixed infrastructure environments - Enterprises requiring secure private network integration **Key Benefits:** - Full SaaS platform benefits with private network access - Secure, outbound-only connections - Scan private repositories and services - No inbound firewall rules required - Multiple network support [**Learn about GitGuardian Bridge →**](./ggbridge.md) --- ### GitGuardian Self-Hosted **Complete control in your environment** GitGuardian Self-Hosted runs entirely within your infrastructure, giving you complete control over data, security, and compliance while maintaining all core platform capabilities. **Best for:** - Organizations with strict data residency requirements - Enterprises with custom compliance frameworks - Companies requiring air-gapped environments - Teams with existing Kubernetes/container infrastructure **Key Benefits:** - Complete data control and residency - Custom security and compliance configurations - Integration with existing infrastructure - Air-gap deployment support [**Explore self-hosted option →**](./self-hosted.md) ## Comparison matrix | Feature | SaaS | SaaS + GG Bridge | Self-Hosted | |---------|------|------------------|-------------| | **Setup Time** | Minutes | Hours | Hours to Days | | **Infrastructure Management** | None | Minimal | Full | | **Data Location** | GitGuardian Cloud | GitGuardian Cloud | Your Infrastructure | | **Firewall Requirements** | Inbound/Outbound | Outbound only | N/A | | **Maintenance** | Automatic | Minimal | Manual | | **Feature Access** | Latest | Latest | Monthly | ## Need help deciding? Our team can help you evaluate the best deployment model for your specific requirements: [Contact our team](https://www.gitguardian.com/contact-us) for personalized guidance. --- ## GitGuardian Bridge GitGuardian Bridge extends GitGuardian SaaS with secure access to your private infrastructure through encrypted tunnels. This approach allows you to leverage the full benefits of GitGuardian's cloud platform while maintaining secure access to your internal resources. Built with security at its core, GitGuardian Bridge uses outbound-only connections, mutual TLS authentication, end-to-end encryption, minimal attack surface with distroless container images, and provides complete audit logging for full compliance. :::info GG Bridge is only available for: - Workspaces under Enterprise plan - US and EU SaaS customers ::: ## What is GitGuardian Bridge? GitGuardian Bridge creates an encrypted, outbound-only tunnel from your private network to GitGuardian SaaS, allowing you to: - **Scan private repositories** without exposing them to the internet - **Monitor self-hosted services** while maintaining network isolation - **Meet compliance requirements** by keeping sensitive infrastructure private - **Support multiple networks** with separate bridge configurations ## Cost considerations GitGuardian Bridge has the same egress cost implications as direct GitGuardian SaaS access. Consider data volume when scanning large datasets, and deploy your bridge close to data sources to minimize network transfer costs. ## Supported integrations GitGuardian Bridge works with: | Service | Type | |---------|------| | [GitHub Enterprise Server](../../internal-monitoring/integrate-sources/vcs-integrations/github-enterprise) | Version Control | | [GitLab Enterprise Edition](../../internal-monitoring/integrate-sources/vcs-integrations/gitlab) | Version Control | | [Bitbucket Data Center](../../internal-monitoring/integrate-sources/vcs-integrations/bitbucket) | Version Control | | [Azure DevOps Server](../../internal-monitoring/integrate-sources/vcs-integrations/azure-repos) | Version Control | | [JFrog Artifactory](../../internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry) | Container Registry | | [Azure Container Registry](../../internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry) | Container Registry | | [Confluence Data Center](../../internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center) | Documentation | | [Microsoft OneDrive](../../internal-monitoring/integrate-sources/file-storage-integrations/microsoft-onedrive) | File Storage | | [Microsoft SharePoint Online](../../internal-monitoring/integrate-sources/file-storage-integrations/microsoft-sharepoint-online) | File Storage | | [Jira Data Center](../../internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center) | Ticketing | | [ServiceNow (on-premise)](../../internal-monitoring/integrate-sources/ticketing-integrations/servicenow) | Ticketing | | [Bring Your Own Sources](../../internal-monitoring/integrate-sources/bring-your-own-sources) | Custom Sources | | [Custom webhooks](../configure-alerting/notifiers-integrations/custom-webhook) | Notifications | | [Splunk Enterprise](../configure-alerting/notifiers-integrations/splunk) | Notifications | | [Custom validity endpoints](../../secrets-detection/customize-detection/validity-checks#customize-validity-checks) | Secret Validation | | [Secrets Analyzers](../../secrets-detection/secrets-detection-engine/secrets_analyzer) | Secret Analyzers | | [ggscout](https://github.com/GitGuardian/ggbridge/tree/main/examples/ggscout) | NHI Governance | :::info Validity Checks Support GitGuardian Bridge currently supports validity checks for detectors that allow you to configure custom hosts (such as GitLab instances). However, validity checks are not yet supported for detectors where GitGuardian automatically extracts the host information from the location where the secret is discovered (such as PostgreSQL connection strings). Reach out to [support@gitguardian.com](mailto:support@gitguardian.com) if you have any questions. ::: ## How to set up GitGuardian Bridge ### Step 1: Request bridge access Contact [support@gitguardian.com](mailto:support@gitguardian.com) to request bridge functionality for your account. Specify how many bridges you need (typically one per isolated network segment). ### Step 2: Create your bridge 1. Log into GitGuardian Dashboard and navigate to **Settings > Security > [GitGuardian Bridge](https://dashboard.gitguardian.com/settings/workspace/security#gg_bridge)** 2. Click **"Create Bridge"** ![Create GG Bridge](/img/platform/enterprise-administration/ggbridge/create_ggbridge.png) 3. **Configure your bridge**: Name your bridge (e.g., "Production Network", "Dev Environment"), optionally add a Custom CA if your internal services use custom certificates, and add domain names of internal services (you can also do this later). Then download the certificate bundle and copy the bridge URL. ![Configure GG Bridge](/img/platform/enterprise-administration/ggbridge/configure_ggbridge.png) :::warning Custom CA Configuration The Custom CA field is **required** when your target services use certificates signed by a custom Certificate Authority (CA). You must provide the complete certificate chain in PEM format, including: - The Root CA certificate - All intermediate CA certificates (if any) **To export the certificate chain from your service:** ```bash openssl s_client -showcerts -connect your-internal-service.com:443 -servername your-internal-service.com /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > bundle.pem ``` **Example PEM format:** ``` -----BEGIN CERTIFICATE----- MIIDXTCCAkWgAwIBAgIJAKoK/OvD... (Root CA) ...certificate content... -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIJAKoK/OvD... (Intermediate CA) ...certificate content... -----END CERTIFICATE----- ``` Alternatively, you can export the Root CA and Intermediate CA certificates from your browser and concatenate them into a single file: ![Export CA from browser](/img/platform/enterprise-administration/ggbridge/export-custom-ca.png) Without proper Custom CA configuration, GitGuardian Bridge will be unable to establish secure connections to your internal services and will fail with SSL verification errors. ::: ### Step 3: Configure bridge client Deploy the bridge client in your private network using the certificate bundle and bridge URL from Step 2. 📋 **Follow the detailed installation guide**: [github.com/GitGuardian/ggbridge](https://github.com/GitGuardian/ggbridge) The repository provides complete instructions for: - VM deployment (via k3s) - Kubernetes/Helm deployment - OpenShift configurations - Troubleshooting guides :::tip Important Make sure to whitelist the bridge URL in your network security settings to allow outbound connections from your private network to GitGuardian SaaS. ::: ### Step 4: Configure URL mapping (if not done during creation) If you didn't add domain names during bridge creation, go to your [bridge settings](https://dashboard.gitguardian.com/settings/workspace/security#gg_bridge) and add the domain names of internal services that should route through the bridge: - `gitlab.internal.company.com` - `bitbucket.team.local` - `artifactory.dev.internal` ![Configure URL Mapping](/img/platform/enterprise-administration/ggbridge/configure_url_mapping.png) GitGuardian will automatically route traffic to these URLs through your bridge. ### Step 5: Configure your integrations Set up your self-hosted services in GitGuardian Dashboard: 1. **Sources**: Navigate to **Settings > Integrations > [Sources](https://dashboard.gitguardian.com/settings/integrations/sources)** 2. **Destinations**: Navigate to **Settings > Integrations > [Destinations](https://dashboard.gitguardian.com/settings/integrations/destinations)** 3. **Custom Hosts**: Navigate to **Settings > Secrets > [Detectors](https://dashboard.gitguardian.com/settings/secrets/detectors?sd_validity_check=y%2Cc_set%2Cc_none%2Boperator__in)**. Example with GitHub Enterprise: ![Example Sources Integration Settings](/img/platform/enterprise-administration/ggbridge/example_sources_integration_settings.png) When you enter URLs that match your bridge configuration, GitGuardian automatically uses the bridge connection. ## Verify everything works - **Bridge Status**: Check **Settings > Security > [GitGuardian Bridge](https://dashboard.gitguardian.com/settings/workspace/security#gg_bridge)** for connection status - **Integration Health**: Monitor your source/destination health checks - **Test Scans**: Run a test scan on a private repository :::tip Start Small **Before launching full-scale scans**, we recommend starting with a small batch of repositories/sources to confirm the bridge is working correctly. This approach helps: - Verify connectivity and authentication - Validate certificate configurations - Test integration health without overwhelming your network - Identify and resolve any configuration issues early Once you've confirmed everything works smoothly with the small batch, you can proceed with larger-scale scanning operations. ::: For assistance, contact **[support](mailto:support@gitguardian.com)**. --- ## Self-Hosted # Self-Hosted Deployment GitGuardian Self-Hosted runs entirely within your infrastructure, giving you complete control over data, security, and compliance while maintaining all core platform capabilities. ## Overview Self-hosted deployment provides: - Complete data control and residency - Custom security and compliance configurations - Air-gap deployment support - Integration with existing infrastructure ## Deployment options ### Existing cluster with Helm (recommended) Deploy on your existing Kubernetes cluster for production environments with full control and advanced features. ### Embedded cluster with KOTS All-in-one installation with built-in Kubernetes cluster and web-based management interface, ideal for trials and PoC environments. ## Key benefits - **Data Residency**: All data remains within your jurisdiction - **Custom Security**: Adapt to your specific security policies and compliance requirements - **Air-Gap Support**: Deploy in completely isolated environments - **Infrastructure Control**: Full control over scaling, monitoring, and operations ## Getting started 1. **Check Requirements**: Review [system requirements](../../self-hosting/system-requirements.md) and [network requirements](../../self-hosting/network-requirements.md) 2. **Choose Installation Method**: [Compare Helm vs KOTS options](../../self-hosting/installation/choose-embedded-existing.md) 3. **Follow Installation Guide**: Complete setup with detailed installation instructions 4. **Configure Security**: Implement [security recommendations](../../self-hosting/security/recommendations.md) --- ## Audit log The audit log is **the centralized stream of user activity which occurs on your workspace**. It allows the workspace Managers to investigate for potential suspicious behavior and security issues by reviewing the actions performed by users of their workspace. The following information is included in each event recorded: - **Actor**: the GitGuardian user who performed the event. - **Event**: the event recorded. - **Date**: the date when the event happened. - **IP address**: the IP address of the actor who performed the event. ### Accessing the audit log 1. Navigate to Settings > Workspace > [Audit log](https://dashboard.gitguardian.com/settings/workspace/audit-logs). 2. Search for logs. ![Audit log table](/img/platform/enterprise-administration/audit-log-table.png) :::info Only the Owner and Managers have access to the workspace's audit log. ::: ### Email Alerts for Audit Log Failures For self-hosted, owners and managers can receive email alerts for audit log failures. These alerts will provide details about the issue. To enable this feature, run the following command: ```bash kubectl exec --namespace deployments/webapp-internal-api -c app -- python manage.py set_preferences --general__is_audit_log_failure_triggers_mail=True ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). --- ## Manage email domain ## How to reserve an email domain Once an SAML SSO integration is completed, the users of your GitGuardian workspace (usually the Owner or a Manager) can request to **reserve one or several specific email domains that belong to them or your company**. This feature goes one step further in the authentication/security aspect. It is independent from the “force SSO” feature. - When you reserve a domain `company.com`, you **restrict users with an email address "xxxx@company.com" from signing up to GitGuardian and creating their own workspace**. It is a guarantee that there will only be one workspace for users having an email address “xxx@company.com”. - When users try to sign up with a reserved email domain address, they are alerted that **they are required to sign up via SSO**. - Also, reserving an email domain will allow users to **find your custom SSO page just by filling in their email**. Without this option you would need to bookmark your SSO login url. ![SSO reserved email domain](/img/platform/enterprise-administration/sso_reserved_email_domain.png) Users who already have a workspace and are impacted by a newly reserved email domain will not be affected. They will be able to join the workspace that requested these domains be reserved for SSO. :::info This feature is reserved to workspaces with Business access (Business or Business trial plans). After the end of a Business trial, the email domains will no longer be reserved. This feature is not accessible with GitGuardian self-hosted instances. ::: ## Domain synchronization between regions Reserved domains are synchronized between the EU and US regions. This ensures that once a domain is reserved in either region, users are prevented from signing up in one region if they already have an account in the other. --- ## IP allowlist for workspace access The IP Allowlist enables customers to restrict access to their workspace, including both the dashboard and the public API, to trusted IP addresses or IP ranges. This feature is designed to enhance security by ensuring that only approved IPs can interact with your GitGuardian resources. :::info Business accounts only This feature is reserved to workspaces with Business access (Business or Business trial plans). After the end of a Business trial, any IP restriction will be lifted. ::: :::info Not available on self-hosted environments This feature is not supported on self-hosted environments, as there are alternative methods to restrict access in those scenarios. ::: ## Configuring the IP allowlist Configuring and enabling the allowlist can be done only by workspace managers. 1. Navigate to Settings > Authentication > IP allowlist 2. Add IP addresses or ranges: in the IP Allowlist management section, enter the IP addresses or IP ranges (in CIDR notation) that you wish to allow, and enter a description. Note that only IPv4 addresses are supported. 3. Enable IP Allowlist: once the necessary IP addresses or ranges are added, toggle the IP restriction option to enable it. Workspace managers can subsequently edit or delete IP addresses or IP ranges through the same settings section. ![ip-allowlist-setting](/img/platform/enterprise-administration/auth-ip-allowlist.png) ## Blocked Resources Once the IP Allowlist is enabled, the restriction applies to all resources within your GitGuardian workspace: - **UI:** Users without an allowed IP address will be blocked from accessing the dashboard. - **API and ggshield:** The API, and as a consequence the ggshield cli that relies on it, will be subject to the same IP restrictions. :::caution If you are using ggshield in CI/CD pipelines or in pre-receive hooks, you must ensure that the IPs from your version control system (VCS) or CI/CD runners are added to the allowlist to avoid any disruptions. ::: --- ## Configure SAML SSO Single Sign-On (or SSO) allows you to manage your organization's entire membership via a third-party provider. GitGuardian supports the SAML2 standard for SSO which allows the Owner or any Manager of the workspace to configure any SAML2-enabled Identity Provider (IdP) system. ## Set up SSO To configure your SSO, navigate to Settings > [Authentication](https://dashboard.gitguardian.com/settings/workspace/auth). Detailed set up procedures are available for the following IdP: - [Google](./sso-providers/google) - [Okta](./sso-providers/okta) - [Auth0](./sso-providers/auth0) - [Microsoft Entra ID](./sso-providers/entra-id) - [Duo](./sso-providers/duo) - [Keycloak](./sso-providers/keycloak) - [JumpCloud](./sso-providers/jumpcloud) For all other SAML2-enabled IdP, you can follow the [generic procedure](./sso-providers/generic). ## Just-In-Time (JIT) provisioning GitGuardian supports Just-In-Time (JIT) provisioning. **New members of your workspace are automatically registered with GitGuardian on their first login attempt with SAML2 SSO** if they are authorized on the IdP side. You don't need to invite users manually. You just need to authorize them **on the IdP's side** by being part of the "GitGuardian group". Users who are not part of the GitGuardian group on the IdP side will be rejected during their attempt to sign in via SSO. :::info GitGuardian does not support JIT deprovisioning yet but you can use [SCIM](./scim-configuration) to automatically deprovision your users. ::: ## Default access level Because GitGuardian uses Just-In-Time (JIT) provisioning, new members will be given **a default access level upon their first login**. "Member" is the default setting. You can modify this default in your [Authentication settings page](https://dashboard.gitguardian.com/settings/workspace/auth/saml). ![SSO default access level](/img/platform/enterprise-administration/sso_default_access_level.png) If you selected "Member" as the default access level and your workspace is under the Business plan, you must also configure whether new Members will be part of the ["All-incidents" team](../collaboration-and-sharing/teams#a-specific-team-the-all-incidents-team) or not upon sign up. ![SSO All-incidents team default membership setting](/img/platform/collaboration-and-sharing/sso-all-incidents-team-default-membership-setting.png) ## Force SSO Once you have successfully set up an SAML2 SSO integration, in your [Authentication settings page](https://dashboard.gitguardian.com/settings/workspace/auth/saml), you have the option to **force the SSO**: - If the option is turned ON, **all the members of your workspace will have to go through your IdP in order to be able to access your GitGuardian workspace**. Only the users you have authorized on your IdP's side will be able to sign into your GitGuardian workspace. - If the option is turned OFF, members of your workspace can still login via SSO, going through your IdP, but they can also sign up via email. ![SSO force sso](/img/platform/enterprise-administration/sso_force_sso.png) :::warning Once SSO is forced, all the members of the workspace, including the owner, will have to connect using SSO. If the owner has never connected with SSO, you will not be able to activate the option. Make sure that your SSO connection works before enforcing SSO. In case of issues, you can contact the [support team](mailto:support@gitguardian.com) for assistance. ::: ## SCIM-related settings If you have [SCIM](./scim-configuration) enabled, additional settings appear in the Authentication settings page: - **Default team membership permission**: Controls the incident permission level given to members synchronized via SCIM (Can view or Can edit). - **Enable notifications for SCIM operations**: Sends notifications when SCIM updates affect users or teams. Learn more in the [SCIM settings section](./scim-configuration#scim-settings). ## Email domain reservation :::tip Essential Step: Reserve Your Email Domain After configuring SSO, you must **reserve your email domain** to enable the full SSO experience. This critical step: - **Enables automatic SSO discovery** - Users can log in from the main login page by entering their email; GitGuardian automatically redirects them to your SSO provider - **Prevents workspace fragmentation** - Users cannot create separate workspaces with their company email, ensuring everyone joins the same workspace - **Simplifies user experience** - Without domain reservation, users must bookmark and use the dedicated SSO login URL **To reserve your domain:** 1. Navigate to Settings > [Email Domain Management](https://dashboard.gitguardian.com/settings/workspace/auth) 2. Follow the instructions to reserve your organization's email domain Learn more about [email domain management](./email-domain-management). ::: ## FAQ **How to verify that my SSO connection is working?** If you have not reserved [an email domain](./email-domain-management#how-to-reserve-an-email-domain), please remember your SSO login URL. 1. Make sure to know your login credentials, i.e., your `email` and `password`. 2. Log out of the application. 3. Go to the SSO login URL, and log in by selecting the SSO option. For additional security purpose, GitGuardian will ask you to submit your email and password to confirm your identity. **My Identity Provider (IdP) does not support "emailAddress" as the Name ID format. What do I do?** If your IdP does not support `emailAddress` as the Name ID format, please [contact us](mailto:support@gitguardian.com). We will allow you to use `unspecified` as the Name ID format. :::caution When using `unspecified` as the Name ID format, you must ensure that you send the email addresses of your IdP users as an `email_address` attribute. This is mandatory, as email is the unique identifier that GitGuardian uses for its users. ::: ![SSO NameId unspecified and email_address attribute](/img/platform/enterprise-administration/sso_nameid_unspecified_and_email_address_attribute.png) **I want to configure MFA for GitGuardian. What do I do?** GitGuardian now provides native [MFA via email verification](../user-account/account-settings#email-verification-mfa) for users who sign in with email and password. Verification is required at login and before performing sensitive actions in the dashboard. For SSO users, MFA is handled by your identity provider. We strongly advise that you enable the [Force SSO setting](#force-sso) and configure MFA on your IdP to ensure all users authenticating to GitGuardian are covered. --- ## Configure SCIM System for Cross-domain Identity Management (SCIM) lets you manage GitGuardian users and teams directly from your Identity Provider (IdP). Based on changes in your IdP, SCIM automatically creates, updates, deactivates, and deletes users, and creates/manages teams from IdP groups. :::info SCIM supports user and team provisioning/deprovisioning for Okta, Microsoft Entra ID, and JumpCloud. ::: ## Prerequisites - SCIM requires [Single Sign-On (SSO)](./saml-sso-configuration) to be configured first. - SCIM requires a [Service Account Token](/api-docs/service-accounts) with `members:write`, and `teams:write` access. ## SCIM Features GitGuardian supports: - Manage the full user lifecycle: provision, activate, deactivate, and delete based on your IdP. - Provision and manage teams from IdP groups. ## Prepare for SCIM Setup ### Generate API Token in GitGuardian Before configuring SCIM in Okta, you need to create a service account token in GitGuardian: 1. In your GitGuardian dashboard, navigate to **API > [Service accounts](https://dashboard.gitguardian.com/api/service-accounts)**. 2. Click **Create service account**. 3. Enter a name (e.g., "IdP SCIM") and select the following permissions: - `members:write` - `teams:write` 4. Click **Create** and copy the generated token. This will be used in the IdP setup steps. ![GitGuardian service account token](/img/platform/enterprise-administration/scim-providers/api_token_scim.png) ### Enable SCIM in GitGuardian 1. Navigate to **Settings > [Authentication](https://dashboard.gitguardian.com/settings/workspace/auth)** in your GitGuardian workspace. 2. Under **SCIM**, toggle the option to enable SCIM integration. ![gitguardian scim enable](/img/platform/enterprise-administration/scim_enable.png) 3. Follow the instructions in the **Set up SCIM in your IdP** section. Once SCIM is enabled, your users can be synchronized with your IdP, and user deprovisioning can occur automatically. :::info Unlinked Members You may see a message indicating that some users are **not linked to your IdP**. These users won't be managed by SCIM. - **Review the Members List**: Check the unlinked users. - **Deactivate if Necessary**: Manually deactivate any users who shouldn't have access. This typically happens for users added before SCIM was enabled or not assigned in your IdP. SCIM only manages linked users. ::: ## Set up SCIM in your IdP To configure SCIM, you will need to provide the SCIM endpoint and configure the corresponding SCIM settings in your IdP. Here's a high-level overview for common IdPs: Follow the specific steps for your IdP to enable SCIM integration. Most IdPs provide an option to configure SCIM via their API or dashboard settings. You will need to provide: - **GitGuardian SCIM Endpoint**: `https://api.gitguardian.com/v1/scim/v2` (or `https://gitguardian.mycorp.local/exposed/v1/scim/v2` for self-hosted) - **API Token**: Use a GitGuardian [service account](https://dashboard.gitguardian.com/api/service-accounts) token with `members:write` and `teams:write` permissions. Each IdP's SCIM configuration page will have specific instructions. Refer to the documentation for your IdP for details on how to enter the SCIM endpoint and configure API credentials. :::info Keycloak Users The [scim-for-keycloak plugin](https://scim-for-keycloak.de/) has a bug that causes confusion with the `externalId` value, which is used for making SCIM requests to GitGuardian, so it won't work with our SCIM integration. For more details, see the issue [here](https://github.com/Captain-P-Goldfish/scim-for-keycloak/issues/126). ::: ## Set up procedures ### Okta You can configure SCIM using either the [GitGuardian app from the Okta Integration Network](#okta-oin-app) (recommended) or a [custom SAML app](#okta-custom-scim). :::info Important Note If users are assigned to the Okta app before SCIM is enabled, they won't be deactivated in GitGuardian when later unassigned. To ensure proper deactivation: 1. Duplicate the original Okta group (same members). 2. Assign the duplicate group to the app. 3. Unassign the original group from the app. ::: #### Okta OIN app If you've installed the GitGuardian app from the [Okta Integration Network](https://www.okta.com/integrations/gitguardian/), SCIM provisioning is built-in and Okta Verified. ##### Supported features - **Create users**: Provision new users from Okta to GitGuardian - **Update user attributes**: Sync user profile changes from Okta - **Deactivate users**: Deactivate users when unassigned or disabled in Okta - **Import users**: Import existing GitGuardian users into Okta - **Push groups**: Sync Okta groups as GitGuardian teams ##### Configuration steps 1. In Okta, navigate to your GitGuardian application and go to the **Provisioning** tab. 2. Under **Settings > Integration**, you will see that the provisioning integration is partner-built by GitGuardian. ![okta app provisioning tab](/img/platform/enterprise-administration/scim-providers/okta_app_provisioning_tab.png) 3. Click **Configure API Integration**. 4. Check the box for **Enable API integration**. 5. Enter your GitGuardian SCIM credentials: - **API Token**: Paste the service account token generated above. - **Import Groups**: Check this option if you want to sync groups as teams. 6. Click **Test API Credentials** to verify the connection. You should see "GitGuardian SCIM was verified successfully!". ![okta app api integration](/img/platform/enterprise-administration/scim-providers/okta_app_api_integration.png) 7. Click **Save**. 8. Go to **Settings > To App** and enable **Create Users**, **Update User Attributes**, and **Deactivate Users**. :::caution Make sure to disable **Set password when creating new users** (enabled by default). ::: ![okta app provisioning to app](/img/platform/enterprise-administration/scim-providers/okta_app_provisioning_to_app.png) 9. Click **Save**. 10. Go to the **Assignments** tab to assign users. 11. Go to the **Push Groups** tab to sync Okta groups as GitGuardian teams. #### Okta custom SCIM If you're using a custom SAML application, follow these steps to enable SCIM: 1. In **Okta**, navigate to the **General** settings of your GitGuardian app and check the box for **Enable SCIM provisioning**. ![okta scim enable](/img/platform/enterprise-administration/scim-providers/okta_enable_scim.png) 2. In the **Provisioning** settings of your Okta app, configure the following: - Set the **SCIM Connector Base URL** to: `https://api.gitguardian.com/v1/scim/v2` (or `https://gitguardian.mycorp.local/exposed/v1/scim/v2` for self-hosted). - Use **email** as the unique identifier field for users. Username field must be an email. - Enable the **Push New Users**, **Push Profile Updates** and **Push Groups** settings. - Select **HTTP Header** for authentication mode and add the **service account token** in the **Authorization HTTP header**. ![okta scim connection](/img/platform/enterprise-administration/scim-providers/okta_scim_connection.png) 3. Check the **Create Users**, **Update User Attributes** and **Deactivate Users** options under the **Provisioning to app** settings. ![okta scim provisioning](/img/platform/enterprise-administration/scim-providers/okta_scim_provisioning.png) 4. Finally, in **Assignments**, assign the users. In **Push Groups**, assign the groups you want to sync with GitGuardian. ### Microsoft Entra ID :::info important note When a user is unassigned from the GitGuardian app in Entra ID, no deactivation request is sent. To deactivate, the user must be disabled in Entra ID. ::: #### Configuration steps 1. In **Microsoft Entra ID** (formerly Azure Active Directory), navigate to the **Enterprise Applications** section. 2. Select your GitGuardian app, then go to **Provisioning** and set the **Provisioning Mode** to **Automatic**. 3. Enter the following credentials: - **Secret Token**: Paste the service account token generated above. - **Tenant URL**: `https://api.gitguardian.com/v1/scim/v2` (or `https://gitguardian.mycorp.local/exposed/v1/scim/v2` for self-hosted). 4. In the **Attribute Mappings** section under **Provision Microsoft Entra ID Users**, configure the following mappings to match GitGuardian's SCIM requirements: - Target Object Actions: Set actions to `Create`, `Update` and `Delete` for the target object. - Attribute Mappings: - `userName`: Map this to `userPrincipalName` - `active`: Map this to `Switch([IsSoftDeleted], , "False", "True", "True", "False")` - `name.givenName`: Map this to `givenName` - `name.familyName`: Map this to `surname` - `externalId`: Map this to `email` ![ms intra scim attribute](/img/platform/enterprise-administration/scim-providers/ms_entra_id_attribute_mappings_users.png) 5. In the **Attribute Mappings** section under **Provision Microsoft Entra ID Groups**, configure the following mappings to match GitGuardian's SCIM requirements: - Target Object Actions: Set actions to `Create`, `Update` and `Delete` for the target object. - Attribute Mappings: - `displayName`: Map this to `displayName` - `externalId`: Map this to `objectId` - `members`: Map this to `members` ![ms intra scim attribute](/img/platform/enterprise-administration/scim-providers/ms_entra_id_attribute_mappings_teams.png) 6. Save the mapping and sync the users and teams. ### JumpCloud SCIM :::info important note Auto-adding users to the All-incidents team does not function with JumpCloud SCIM. To include users in this team you will need to create a JumpCLoud Group named "All-incidents team" and assign users to this group within JumpCloud. ::: #### Configure JumpCloud SCIM Settings 1. Enable the SCIM toggle in the GitGuardian Authentication page. 2. Open the SSO Application for GitGuardian in JumpCloud 3. Select the Identity Management tab. 4. Verify API Type "SCIM API" is set. 5. Verify Authentication Method is set to "Bearer Token" 6. Copy the SCIM Service Provider Endpoint value to the Base URL field in JumpCloud. 7. Place the Service Account Token you generated above into the Token Key field in JumpCloud. 8. Place a testable email in the Test User Email field. 9. Remove ALL the default Export Attribute Mappings, and replace them with the following | JumpCloud Attribute | SCIM Attribute | Type | | ------------------- | --------------- | ------ | | email | userName | Direct | | email | externalId | Direct | | firstname | name.givenName | Direct | | lastname | name.familyName | Direct | 10. Save and Sync the mappings. 11. Click "Test" 12. Click "Apply" to activate SCIM. ## SCIM settings Once SCIM is enabled, additional settings are available in your [Authentication settings page](https://dashboard.gitguardian.com/settings/workspace/auth/saml) to control the behavior of SCIM-provisioned members. ### Default team membership permission This setting controls the **incident permission level** assigned to members synchronized via SCIM when they are added to a team. The available options are: - **Can view**: Members can view incidents assigned to their team. - **Can edit**: Members can view and edit incidents assigned to their team. By default, this is set to **Can edit**. You can change this at any time from the Authentication settings page. ### Enable notifications for SCIM operations When enabled, GitGuardian sends **notifications whenever SCIM updates affect users or teams** in your workspace. This includes events such as: - User provisioning or deactivation - Team creation, update, or deletion - Membership changes This setting is **disabled by default**. Toggle it on if you want members to stay informed about SCIM-driven changes. ## FAQ **Can I use SCIM for provisioning teams?** Yes, SCIM supports team provisioning for Okta, Microsoft Entra ID, and JumpCloud. Teams are automatically created and managed in your workspace when groups are added or updated in your IdP. Ensure your service account token has `teams:write` permissions. **How do I link GitGuardian to my IdP for SCIM?** You will need to configure SCIM in your IdP by entering the provided SCIM endpoint and API token. Each IdP has its own process for linking SCIM integrations. Follow the relevant setup instructions for your IdP. **Does GitGuardian support Just-In-Time (JIT) provisioning with SCIM?** SCIM now supports user provisioning, activation, deactivation, and deletion. JIT provisioning via SSO is also available, while SCIM gives you more control over the user lifecycle for provisioning, activation, deactivation, and deletion. --- ## User and Team mapping scripts ## Overview For efficient and secure user and team management, we **strongly recommend** configuring **SSO** and enabling **SCIM** on GitGuardian: - **SSO:** Ensures secure access, user provisioning (via Just-In-Time (JIT)) and centralized management ([SAML SSO Configuration](./saml-sso-configuration)). - **SCIM:** Automates user provisioning and deprovisioning ([SCIM Configuration](./scim-configuration)). These features streamline integration with your identity provider and enhance overall efficiency. However, for customers who prefer to map their team structures directly to their version control systems (VCS), such as GitHub and GitLab, we provide **User and Team Mapping Scripts**. These scripts automate user and team synchronization at scale, ensuring consistency across platforms while leveraging the GitGuardian API client library, [py-gitguardian](https://pypi.org/project/pygitguardian/). This solution caters to enterprise customers who require direct alignment between their VCS and GitGuardian environments. ## Key Features ### 1. **User and Team Mapping** - **Mapping**: Automatically maps GitLab groups or GitHub teams, along with the repositories they own and the users associated with them, to GitGuardian Teams and their respective perimeters. For GitHub, this is achieved by leveraging IDP users when GitHub Enterprise Server is utilized, or alternatively, by analyzing the Organization members as a fallback. However, for Organization members, synchronization will be skipped if their email addresses are hidden by default, as these are required for mapping. - **Platform Support**: GitHub, GitLab. - **Automated User Management**: Invites new users and syncs memberships. Does not handle inactive users or their removal— for this, please use [SCIM](./scim-configuration), which now supports both user provisioning and deprovisioning. For GitHub, the script only maps users who have an email address on their profile or if SAML is configured on GitHub with an Enterprise plan. ### 2. **Permission Handling** - **Selective Permissions**: Excludes elevated roles (e.g., managers, owners) to prevent over-permissioning. ### 3. **Notifications** - **Email Alerts**: Option to notify users of changes, invitations, or removal from teams. ### 4. **Logging and Error Handling** - **Detailed Logs**: Tracks success, failure, and error details using the Python `logging` module. - **Error Handling**: Provides graceful handling of API errors with appropriate logging. ### 5. **Scalability** - **Large Dataset Support**: Handles large datasets (1000+ users and teams) with pagination. ### 6. **Customization** - **Authentication**: Easily configurable using tokens for GitHub. - **Script Modifications**: Designed for modularity, allowing easy customization to extend functionality. ## Getting Started Refer to the repository's README file for detailed instructions on configuring and running the script for your platform: - **GitHub**: [team-mapping-github-gitguardian](https://github.com/GitGuardian/ggtools/tree/main/team-mapping-github-gitguardian) - **GitLab**: [team-mapping-gitlab-gitguardian](https://github.com/GitGuardian/ggtools/tree/main/team-mapping-gitlab-gitguardian) ## Support For further assistance, reach out at [support@gitguardian.com](mailto:support@gitguardian.com). --- ## Auth0 1. First, go to your dashboard, select "Application", and click on "Create Application" 2. Choose "Regular Web Applications" as type and a name. ![auth0 create app](/img/platform/enterprise-administration/sso-providers/auth0_create_app.png) 3. Go to your application addons. Click on "SAML2 Web App" and then on "Settings" 4. Fill the `Application Callback URL` with the `ACS URL` provided in GitGuardian dashboard. ![auth0 setup acs](/img/platform/enterprise-administration/sso-providers/auth0_setup_acs.png) 5. Then, copy-paste these settings to configure mappings, name identifier and message signatures: ```json { "mappings": { "given_name": "first_name", "family_name": "last_name" }, "signatureAlgorithm": "rsa-sha256", "digestAlgorithm": "sha256", "signResponse": true, "nameIdentifierFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", "nameIdentifierProbes": [ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ], "includeAttributeNameFormat": "false" } ``` 6. Finally, we need to configure the Identity Provider in GitGuardian dashboard. First, click on "Usage", then use these values: - `Entity id` field is filled with the `Issuer` value - `Single Sign-On URL` field is filled with the `Identity Provider Login URL` value - `X509 Cert` field is filled with the plain text value of the Identity Provider Certificate - Ensure that the checkbox **I have mapped the attributes first_name and last_name in my IdP** is checked - Ensure that the checkbox **I have specified that the response assertions with RSA_SHA256 as signature algorithm and SHA256 as digest algorithm** is unchecked ![auth0 idp settings](/img/platform/enterprise-administration/sso-providers/auth0_idp_settings.png) 7. **Important:** Don't forget to [reserve your email domain](../saml-sso-configuration#email-domain-reservation) to enable automatic SSO discovery. --- ## Duo 1. Configure an Authentication Source for Single Sign-On in the Duo Dashboard. Ensure that `FirstName` and `LastName` are provided as attributes as described in the [Duo documentation](https://duo.com/docs/sso#configure-your-authentication-source). 2. From the "Applications" tab, click on "Protect an Application", and choose to protect a "Generic Service Provider" with "2FA with SSO hosted by Duo (Single Sign-On)" ![duo create app](/img/platform/enterprise-administration/sso-providers/duo_create_app.png) 3. Map the following from the Duo Generic Service Provider values into the GitGuardian dashboard: | Duo values | GitGuardian configuration | | -------------------- | ------------------------- | | Entity ID | Entity ID | | Single Sign-On URL | Single Sign On URL | | Certificate contents | X509 Cert | Also ensure that the checkbox **I have mapped the attributes first_name and last_name in my IdP** is checked. 4. Map the following from the GitGuardian dashboard into the Duo Generic Service Provider configuration: | Duo Service Provider configuration | GitGuardian values | | ---------------------------------- | ------------------ | | Service Provider Entity ID | SP Entity id | | Assertion Consumer Service | ACS URL | 5. In the SAML Response section, add the following mapping in "Map attributes" | IdP Attribute | SAML Response Attribute | | ------------- | ----------------------- | | First Name | first_name | | Last Name | last_name | ![duo attribute mapping](/img/platform/enterprise-administration/sso-providers/duo_attribute_mapping.png) 6. Give the Service Provider configuration a recognizable name, such as "GitGuardian". 7. Save. 8. **Important:** Don't forget to [reserve your email domain](../saml-sso-configuration#email-domain-reservation) to enable automatic SSO discovery. --- ## Microsoft Entra ID :::tip GitGuardian also supports SCIM provisioning for Microsoft Entra ID. See the [SCIM configuration guide](../scim-configuration) for setup instructions. ::: 1. First, go to the [Microsoft Entra admin center](https://entra.microsoft.com/), click on "Add enterprise application" at the bottom of the page, then "Create your own application". 2. In the new panel that appears on the right, provide a name (e.g. "GitGuardian") and select "Integrate any other application you don't find in the gallery (Non-gallery)". Finally, click on the "Create" button. ![entra-id start](/img/platform/enterprise-administration/sso-providers/entra_id_start.png) 3. After a few seconds, you will be redirected to your newly created application. Click on "Set up single sign on" and choose the SAML sign-on method. ![entra-id select sso](/img/platform/enterprise-administration/sso-providers/entra_id_select_sso.png) 4. Now, you need to configure the Service Provider in Microsoft Entra ID. Click on Edit in the "Basic SAML Configuration" box. Use these values: - `Identifier (Entity Id)` field is filled with the `SP Entity ID` value on GitGuardian dashboard. - `Reply URL (Assertion Consumer Service URL)` field is filled with the `ACS URL` value on GitGuardian dashboard. Don't forget to click on "Save". ![entra-id setup sp](/img/platform/enterprise-administration/sso-providers/entra_id_setup_sp.png) 5. Now, some mappings need to be done. Select 'Edit' on the 'Attributes & Claims' box. Click on 'Add new claim'. Leave 'Namespace' empty and use these values: - Name: `first_name` + Source attribute: `user.givenname` Don't forget to click on "Save". ![entra-id mapping first_name](/img/platform/enterprise-administration/sso-providers/entra_id_mapping_first_name.png) - Name: `last_name` + Source attribute: `user.surname` Don't forget to click on "Save". ![entra-id mapping last_name](/img/platform/enterprise-administration/sso-providers/entra_id_mapping_last_name.png) 6. You also need to make sure that the Unique User Identifier (Name ID) claim is set to user.mail. ![entra-id userid](/img/platform/enterprise-administration/sso-providers/entra_id_userid.png) 7. Then, setup how responses and assertions are signed: Select 'Edit' on the 'SAML Certificates' box and choose 'Sign SAML response and assertion' as Signing Option and 'SHA-256' as Signing Algorithm: ![entra-id signature](/img/platform/enterprise-administration/sso-providers/entra_id_signature.png) 8. Now, you need to configure the Identity Provider in GitGuardian dashboard. Use these values: - `Entity Id` field is filled with the `Microsoft Entra Identifier` - `Single Sign-On URL` field is filled with the `Login URL` - `X509 Cert` field is filled with the certificate. Download the Base64 certificate, use `cat` and copy/paste the plaintext value. - Ensure that the checkbox **I have mapped the attributes first_name and last_name in my IdP** is checked ![entra-id idp config](/img/platform/enterprise-administration/sso-providers/entra_id_idp_config.png) 9. Test your app configuration by clicking on "Test". 10. **Important:** Don't forget to [reserve your email domain](../saml-sso-configuration#email-domain-reservation) to enable automatic SSO discovery. --- ## Generic SAML2 IdP For SAML2-enabled Identity Providers not listed in our specific guides, follow this generic procedure. ## 1. Register GitGuardian on your Identity provider In order to integrate GitGuardian with your Identity Provider, you must first register GitGuardian (Service Provider) as an application on the IdP's side. Follow these steps carefully: 1. Navigate to Settings > [Authentication](https://dashboard.gitguardian.com/settings/workspace/auth) 2. Click on "Configure" ![SSO Service provider info configure](/img/platform/enterprise-administration/sso_sp_info_configure.png) 3. On your IdP: 1. Fill in the SAML endpoint provided by GitGuardian (ACS url, SP Entity id) 2. Fill in Email or EmailAddress as the primary identifier (Name ID format). Refer to our [FAQ](../saml-sso-configuration#faq) if this Name ID format is not available in your IdP. 3. Set RSA_SHA256 for the signature algorithm, and SHA256 for the digest algorithm for your response. Some Identity Providers (IdPs) may require you to sign either the response message or the response assertions. GitGuardian provides the ability to specify this IdP behavior. Note that at least one of these, either the response message or the response assertions, must be signed. 4. Configure `first_name` and `last_name` mapped attributes. ![SSO Service provider info](/img/platform/enterprise-administration/sso_sp_info.png) ## 2. Register your IdP on GitGuardian's side Once GitGuardian is registered as an application on your IdP's side, you need to provide your IdP metadata fields on GitGuardian (Service Provider side) in order to complete the integration: 1. While still on the [Authentication config page](https://dashboard.gitguardian.com/settings/workspace/auth/saml/setup) of your workspace settings, complete the form with: - Entity Id [required] - Single Sign On Url [required] - Single Log Out Url [optional] - X509 certificate [required] - Ensure that the checkbox **I have mapped the attributes first_name and last_name in my IdP** is checked 2. Submit the form to fully register the SAML integration. ![SSO IdP info](/img/platform/enterprise-administration/sso_idp_info.png) 3. The setup is complete. Your workspace will have **a dedicated SSO login url for your collaborators to sign in using your IdP**. ![SSO login url](/img/platform/enterprise-administration/sso_login_url.png) > You can register this SSO login url on the IdP side to enable the SSO flow with one click directly in the IdP interface. However this IdP-Initiated flow carries a security risk and is therefore NOT recommended. Make sure you understand the risks before enabling IdP-initiated SSO. :::info Next Step Don't forget to complete the [Email domain reservation](../saml-sso-configuration#email-domain-reservation) step to enable automatic SSO discovery and prevent workspace fragmentation. ::: --- ## Google 1. First, go to the Google Admin Console, and create a new custom SAML app. 2. You will land on this page, where you can set your app name and general information for your SAML app that users will see when logging in. ![google start](/img/platform/enterprise-administration/sso-providers/google_start.jpeg) 3. Click on "Continue". Now, you need to configure the Identity Provider in your GitGuardian dashboard. Use these values provided by Google: - `Entity Id` field is filled with the `Entity ID` - `Single Sign-On URL` field is filled with the `SSO URL` - `X509 Cert` field is filled with the certificate from Google. Download it, use `cat` and copy/paste the plaintext value. - On the GitGuardian dashboard, ensure that the checkbox "I have specified that the response assertions with RSA_SHA256 as signature algorithm and SHA256 as digest algorithm" is **unchecked**. ![google idp config](/img/platform/enterprise-administration/sso-providers/google_idp_info.jpeg) 4. Click on "Continue". You can now configure the Service Provider details provided by GitGuardian within Google: - `ACS URL` field is filled with the `ACS URL` value. - `Entity ID` field is filled with the `SP Entity id` value. - `Signed Response` must be checked - `Name ID format` must be set to `EMAIL` - `Name ID` must be set to `Basic Information > Primary Email` ![google config sp](/img/platform/enterprise-administration/sso-providers/google_config_sp.jpeg) 5. Now, some mappings need to be done, they are quite straightforward: - `first_name` is mapped to the user first name - `last_name` is mapped to the user last name ![google mappings](/img/platform/enterprise-administration/sso-providers/google_mappings.jpeg) 6. Finish your app configuration by clicking on "Finish". You might need to modify the SAML app user access, which is OFF for everyone by default. 7. **Important:** Don't forget to [reserve your email domain](../saml-sso-configuration#email-domain-reservation) to enable automatic SSO discovery. --- ## JumpCloud :::tip GitGuardian also supports SCIM provisioning for JumpCloud. See the [SCIM configuration guide](../scim-configuration) for setup instructions. ::: 1. Log into your [JumpCloud Portal](https://console.jumpcloud.com/login/admin) as an admin. 2. Select Access -> SSO Applications 3. Click "+ Add New Application" 4. Type "GitGuardian" in the search pane, and select "Create a Custom Integration" 5. Click "Next" 6. Select "Manage Single Sign-on (SSO) and ensure the SAML option is selected 7. Optional: Select "Export users to this app (Identity Management)" if you intend to set up SCIM 8. Click "Next" 9. Add a display label, description, and upload a logo like the one [here](/img/gg_owl.png) 10. Click "Save Application" 11. Click "Configure Application" 12. Scroll Down to the IdP Entity ID field and enter a unique string. (E.G.: use `uuidgen` to make a UUID and use that) 13. Log into GitGuardian as a Manager and navigate to the [SSO Setup Page](https://dashboard.gitguardian.com/settings/workspace/auth/setup) 14. Copy the value of the Service Provider Entity ID field from GitGuardian to the SP Entity ID field in JumpCloud. 15. Copy the value of the Assertion Consumer Service URL field from GitGuardian to the ACS URLs field in JumpCloud. 16. Select `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` as the value for the SAML Subject NameID Format in JumpCloud. 17. Ensure the Signature Algorithm in JumpCloud is set to RSA-SHA256. 18. Ensure the Sign option in JumpCloud is set to "Assertion and Response" 19. In JumpCloud, map the User Attributes as follows: | Service Provider Attribute Name | JumpCloud Attribute Name | | ------------------------------- | -------------------------| | first_name | firstname | | last_name | lastname | 20. Click "Save" 21. Select "Download Certificate" from the Actions menu. 22. In GitGuardian, check the box verifying you have mapped first_name and last_name. 23. In GitGuardian, place the Entity ID you generated in step 12 in the Entity ID field. 24. Copy the IdP URL from JumpCloud to the Single-Sign-On URL in GitGuardian 25. Upload the text of the certificate you downloaded in step 22 to the X 509 Cert field in GitGuardian. 26. Click Configure in GitGuardian. 27. Optionally: Copy the Login URL from GitGuardian to the Login URL field in JumpCloud and save the change. :::warning You can register this SSO login url on the IdP side to enable the SSO flow with one click directly in the IdP interface. However this IdP-Initiated flow carries a security risk and is therefore NOT recommended. Make sure you understand the risks before enabling IdP-initiated SSO. ::: 28. Create a JumpCloud User Group named "All-incidents team" and map your users and SSO application together. 29. SaaS Only: [Reserve your SSO Domain](../saml-sso-configuration#email-domain-reservation). :::tip If you are a SaaS client, don't forget to complete the [Email domain reservation](../saml-sso-configuration#email-domain-reservation) step to enable automatic SSO discovery and prevent workspace fragmentation. ::: --- ## Keycloak 1. Navigate to "Realm Settings" under the "General" tab in Keycloak, and copy the 'SAML 2.0 Identity Provider Metadata'. For example: `https://$YOUR_KEYCLOAK_DOMAIN/realms/master/protocol/saml/descriptor`. ![keycloak realm endpoint](/img/platform/enterprise-administration/sso-providers/keycloak_realm_endpoint.png) 2. Go to the "Keys" tab, and click on the 'Certificate' button next to the RS256 algorithm. Copy the displayed certificate. ![keycloak realm certificate](/img/platform/enterprise-administration/sso-providers/keycloak_realm_certificate.png) 3. To configure the Identity Provider in the GitGuardian dashboard, use the following values: - The `Entity Id` field should be filled with the Keycloak SAML 2.0 Identity Provider Metadata URL, excluding `/protocol/saml/descriptor` from the end. Example: `https://$YOUR_KEYCLOAK_DOMAIN/realms/master`. - The `Single Sign-On URL` field should include the Keycloak SAML 2.0 Identity Provider URL, excluding `/descriptor` from the end. Example: `https://$YOUR_KEYCLOAK_DOMAIN/realms/master/protocol/saml`. - In the `X509 Cert` field, paste the certificate copied in the previous step. - Ensure that the checkbox **I have mapped the attributes first_name and last_name in my IdP** is checked. 4. To configure the "Client" (Service Provider) in Keycloak: - Navigate to the Clients menu and click on 'Create client'. Use the following values: - Set the `Client type` field to `SAML`. - Fill the `Client ID` field with the `SP Entity ID` from the GitGuardian dashboard. - Click on 'Next', then: - Fill the `Home URL` field with the URL of your GitGuardian dashboard. For example: `https://dashboard.gitguardian.com` (SaaS) or `https://gitguardian.mycorp.local` (Self-Hosted). - Fill the `Valid Redirect URIs` and `Master SAML Processing URL` fields with the `ACS URL`. 5. Click on 'Save', then configure these settings on the newly created client: - In 'SAML capabilities', set the `Name ID Format` to `email`. - Set `Force POST Binding` and `Include AuthnStatement` to `ON`. - In 'Signature and Encryption', set `Sign documents` and `Sign assertions` fields to `ON`. - `Signature algorithm` should be `RSA_SHA256`. - Set `SAML signature key name` to `NONE`. - In 'Logout settings', set `Front Channel Logout` to `ON`. - Click on 'Save'. - In the 'Keys' tab, set `Client signature required` to `OFF`. ![keycloak clients](/img/platform/enterprise-administration/sso-providers/keycloak_clients.png) 6. Still in the same client, under the 'Client scopes' tab, edit the 'Dedicated scope and mappers for this client' and configure a new mapper for the first name: - Choose `User Property` as the `Mapper Type`. - The `Name` field should be `firstName`. - The `Property` field should be `firstName`. - Set the `SAML Attribute Name` to `first_name` and the `SAML Attribute NameFormat` to `Basic`. 7. For the last name, create a second mapper: - Again, select `User Property` for the `Mapper Type`. - The `Name` field should be `lastName`. - The `Property` field should be `lastName`. - Set the `SAML Attribute Name` to `last_name` and the `SAML Attribute NameFormat` to `Basic`. ![keycloak mappers](/img/platform/enterprise-administration/sso-providers/keycloak_mappers.png) 8. In the "Client Scopes" tab, note the 'Assigned Default Client Scopes'. For example, `role_list`. ![keycloak client scopes](/img/platform/enterprise-administration/sso-providers/keycloak_client_scopes.png) 9. Edit the client scope(s) listed in the previous step by navigating to the "Client Scopes" menu. Go to the "Mappers" tab, edit the Role list mapper, and ensure the `Single Role Attribute` field is set to `ON`. ![keycloak client scopes Single Role Attribute](/img/platform/enterprise-administration/sso-providers/keycloak_client_scopes_single_role_attribute.png) 10. Finalize your setup by testing the SSO authentication using the `Login URL` provided in the GitGuardian dashboard [SAML configuration page](https://dashboard.gitguardian.com/settings/workspace/auth/saml). 11. **Important:** Don't forget to [reserve your email domain](../saml-sso-configuration#email-domain-reservation) to enable automatic SSO discovery. --- ## Okta You can configure SSO using either the [GitGuardian app from the Okta Integration Network](#okta-oin-app) (recommended) or a [custom SAML app](#okta-custom-saml-app). ## Prerequisites - An Okta account with administrator privileges - A GitGuardian workspace with Owner or Manager role - Your GitGuardian Workspace ID (found in your dashboard URL or workspace settings) ## Supported features - **SP-initiated SSO**: Users can sign in to GitGuardian directly from the application URL - **IdP-initiated SSO**: Users can sign in to GitGuardian from the Okta dashboard - **Just-in-Time (JIT) provisioning**: New users are automatically created in GitGuardian on first login :::tip GitGuardian also supports SCIM provisioning for Okta. See the [SCIM configuration guide](../scim-configuration) for setup instructions. ::: ## SP-initiated SSO Users can sign in directly to GitGuardian without going through Okta first: 1. Navigate to your GitGuardian dashboard URL (e.g., `https://dashboard.gitguardian.com`). 2. Enter your email address. 3. If your email domain is reserved, you will be automatically redirected to Okta for authentication. 4. After authenticating with Okta, you will be redirected back to GitGuardian. ## Okta OIN app The GitGuardian app is available in the [Okta Integration Network](https://www.okta.com/integrations/gitguardian/). 1. In Okta, go to **Applications > Applications** and click **Browse App Catalog**. 2. Search for "GitGuardian" and select the GitGuardian app. 3. Click **Add Integration**. 4. On the **General Settings** page, configure the following: - **Application label**: Enter a name for the app (e.g., "GitGuardian"). - **GitGuardian Workspace ID**: Enter your GitGuardian workspace ID. - **GitGuardian API FQDN**: Enter `api.gitguardian.com` or `api.eu1.gitguardian.com` (or your self-hosted API domain). - **GitGuardian Dashboard FQDN**: Enter `dashboard.gitguardian.com` or `dashboard.eu1.gitguardian.com` (or your self-hosted dashboard domain). ![okta app general settings](/img/platform/enterprise-administration/sso-providers/okta_app_general_settings.png) 5. Click **Done** to create the application. 6. Go to the **Sign On** tab to view the SAML configuration. ![okta app sign on](/img/platform/enterprise-administration/sso-providers/okta_app_sign_on.png) 7. Scroll down to find the SAML metadata and copy the following values: - **Sign on URL** - **Issuer** - **Signing Certificate** (download or copy) ![okta app saml metadata](/img/platform/enterprise-administration/sso-providers/okta_app_saml_metadata.png) 8. In your GitGuardian dashboard, navigate to **Settings > [Authentication](https://dashboard.gitguardian.com/settings/workspace/auth)** and click **Configure**. ![GitGuardian Authentication settings](/img/platform/enterprise-administration/sso-providers/okta_app_gg_auth_settings.png) 9. Configure the Identity Provider with the values from the previous step: - **Entity Id**: paste the **Issuer** value - **Single Sign-On URL**: paste the **Sign on URL** value - **X509 Cert**: paste the **Signing Certificate** content - Ensure that the checkbox **I have mapped the attributes first_name and last_name in my IdP** is checked ![GitGuardian IdP configuration](/img/platform/enterprise-administration/sso-providers/okta_app_gg_idp_config.png) 10. Assign users to the app in the **Assignments** tab. 11. **Important:** [Reserve your email domain](../saml-sso-configuration#email-domain-reservation) to enable automatic SSO discovery. ## Okta custom SAML app If you prefer to create a custom SAML application, follow these steps: 1. In Okta, go to **Applications > Applications** and click **Create New App**. ![okta create new app](/img/platform/enterprise-administration/sso-providers/okta_create_new_app.png) 2. Set the general information for your SAML app (name, logo) that users will see when logging in. ![okta general](/img/platform/enterprise-administration/sso-providers/okta_general.png) 3. Click **Next** and configure the basic SAML settings: - **Single sign on URL**: paste the **ACS URL** value from the GitGuardian dashboard. - **Audience URI (SP Entity ID)**: paste the **SP Entity ID** value from the GitGuardian dashboard. - **Default RelayState**: leave blank. - **Name ID format**: set to **EmailAddress**. ![okta basic settings](/img/platform/enterprise-administration/sso-providers/okta_basic_settings.png) 4. Click **Show Advanced Settings** and verify the following: - Both **Response** and **Assertion Signature** are set to **Signed**. - **Signature Algorithm** is set to **RSA-SHA256**. - **Digest Algorithm** is set to **SHA256**. - Assertions are not encrypted. ![okta advanced settings](/img/platform/enterprise-administration/sso-providers/okta_advanced_settings.png) 5. Complete the remaining app configuration steps. ![okta config end](/img/platform/enterprise-administration/sso-providers/okta_config_end.png) 6. Go to the **Sign On** tab and configure attribute mappings: - `first_name` is mapped to the user's first name. - `last_name` is mapped to the user's last name. ![okta mappings](/img/platform/enterprise-administration/sso-providers/okta_mappings.png) 7. Still on the **Sign On** tab, click **View Setup Instructions** and use the provided values to configure the Identity Provider in the GitGuardian dashboard: - **Entity Id**: paste the **Identity Provider Issuer** value. - **Single Sign-On URL**: paste the **Identity Provider Single Sign-On URL** value. - **X509 Cert**: paste the **X.509 Certificate** content. - Ensure that the checkbox **I have mapped the attributes first_name and last_name in my IdP** is checked. ![okta setup instructions](/img/platform/enterprise-administration/sso-providers/okta_setup_instructions.png) ![okta idp_settings](/img/platform/enterprise-administration/sso-providers/okta_idp_settings.png) 8. **Important:** Don't forget to [reserve your email domain](../saml-sso-configuration#email-domain-reservation) to enable automatic SSO discovery. --- ## Transfer workspace ownership As a workspace Owner, you can transfer your ownership to any users of your workspace. 1. Go to Settings > User management > [Members](https://dashboard.gitguardian.com/settings/user/members). 2. Find the user you want to transfer the ownership to. 3. Click on the "access level" dropdown and choose Owner. 4. You will be prompted for a confirmation. The former owner will automatically be demoted to `Manager` access level. The new owner will receive a notification email. --- ## Workspace settings ## Collaboration and sharing options ### Team leaders can invite workspace users :::info This feature is only available for workspaces with a Business plan. ::: These settings are designed to give non-manager users the ability to onboard new users onto the platform, reducing the administrative burden on workspace managers. Enabling this setting allows users with the `Member` access level to invite people to the teams they lead. Team leaders can only invite new users by adding them to their teams and cannot invite new users to the workspace via the Settings > Members page. Newly added users will be assigned the `Member` access level. Upon signing up, they will automatically be added to the team from which they were invited. This setting is `ON` by default. Deactivate it [in your workspace settings](https://dashboard.gitguardian.com/settings/workspace/general) if you want the privilege of adding new users to your workspace to remain exclusive to `Managers`. ### “Full access” incident permissions allow to invite users :::info This feature is only available for workspaces with a Business plan. ::: Similarly, this setting allows non-manager users who belong to a team and have [`Full access`](../collaboration-and-sharing/incident-permissions-and-sharing) incident permission to invite new users to the workspace. The goal is to enable trusted team members to take an active role in onboarding new users, without requiring manager-level access. Users with `Full access` incident permission can only invite new users by granting them access to the incident where they have `Full access` permission, and cannot invite new users to the workspace via the Settings > Members page. Upon signup: - the newly added user will only have access to the incident they have been invited from - to prevent privilege escalation, the access level of the new user will be the same as the person who granted them access to the incident: - If granted access by a `Restricted` user, the new user will have the `Restricted` access level. - If granted access by a `Member` user, the new user will have the `Member` access level. - If granted access by a `Manager` user, the new user will have the `Member` access level since we consider the highly privileged `Manager` access level can only be given specifically on the Settings > Members page. This setting is `ON` by default. Deactivate it [in your workspace settings](https://dashboard.gitguardian.com/settings/workspace/general) if you want the privilege of adding new users to your workspace to remain exclusive to `Managers`. ### Public sharing In the [workspace settings](https://dashboard.gitguardian.com/settings/workspace/general), Managers can activate or deactivate public sharing across the entire workspace. Enabling public sharing allows users to access an incident without needing to be registered. For more details about public sharing, please refer to our [Collaboration and sharing section](../collaboration-and-sharing/incident-permissions-and-sharing). Public sharing is available in all plans: - in the `Free` plan, both Managers and Members can perform public sharing. - in the `Business` plan, only users with `Full_access` incident permission can perform public sharing. Public sharing is `OFF` by default. ### By default, users are notified by email when a new incident is detected :::info This feature is only available for workspaces with a Business plan. ::: When this setting is enabled, users will automatically receive email notifications whenever a new incident is detected within a member's team perimeter. This notification can be modified by users in their personal settings under [Secrets detection > Incident alerting](https://dashboard.gitguardian.com/settings/personal/notifications), overriding the workspace setting if needed. Workspace Managers can adjust the default notification setting for all users via the workspace settings. If email notifications for new incidents are disabled, users should rely on the notifier configured at the team level. For further details on configuring alerting and notifications, please refer to the [Alerting and Notifications](../configure-alerting/alerting-and-notifications) page. This setting is `ON` by default. To disable email notifications for new incidents by default for both new and existing users, deactivate it in your [workspace settings](https://dashboard.gitguardian.com/settings/workspace/general). ### Enable comments and feedback for "Can view" permission Managers can allow team members with the `Can view` incident permission to provide comments and feedback on incidents. Enable or disable this option in your [workspace settings](https://dashboard.gitguardian.com/settings/workspace/general) to broaden collaboration without granting edit rights. This setting is `OFF` by default. ## Incidents lifecycle ### Regression When the **Regression** setting is enabled and GitGuardian detects a new occurrence on an incident previously marked as resolved (manually or by the auto-resolver), the incident is reopened, its status changes back to **Triggered**, and a notification is raised. Regression only applies to occurrences detected through real-time scanning of connected sources: a resolved incident won't be reopened if a new occurrence is uncovered by a historical scan. When turned `Off`, GitGuardian silently attaches the new occurrence to the existing resolved incident without sending any notification. Configure this behavior in your [workspace General settings](https://dashboard.gitguardian.com/settings/workspace/general). This setting is `ON` by default. For more context on how regression fits into the incident lifecycle, see the [Internal Monitoring](../../internal-monitoring/detect/incident-statuses) and [Public Monitoring](../../public-monitoring/detect-public-secret-incidents/incident-statuses) incident status pages. ## Security options ### Maximum lifetime of API personal access tokens :::info This feature is only available for workspaces with a Business plan. ::: In [the workspace settings](https://dashboard.gitguardian.com/settings/workspace/security), Managers can enforce a maximum lifetime for API personal access tokens created within their workspace. This applies whether the creation happens via [the API > Personal access tokens page](https://dashboard.gitguardian.com/api/personal-access-tokens) or via ggshield using the `ggshield auth login` command. If existing personal access tokens exceed the new maximum lifetime at the time of the setting modification, GitGuardian will force their lifetime to fit the new setting, starting from the time of the setting modification. By default, there is no enforced maximum lifetime for API personal access tokens. ### Restrict git patch visibility :::info This feature is only available for workspaces with a Business plan. ::: In [the workspace settings](https://dashboard.gitguardian.com/settings/workspace/security), Managers can activate the restriction for git patch visibility. When the restriction is activated, the git patch of an occurrence will be visible to a user if either of the following conditions are met: - **The user is a member of a team that includes the repository where the occurrence took place**. It's worth noting that since workspace Managers are automatically part of the "All-incidents" team, they will always have access to all the git patches. - **The user is directly involved in the occurrence**, meaning their email matches the committer email of the occurrence. It is important to note that while the restriction on git patch visibility is in effect, the metadata of an occurrence will still be visible to users. Only the git patch of the occurrence will be impacted by the restriction. This means that there may be instances where a user has access to a secret incident that contains multiple occurrences. The user will be able to view the metadata of all occurrences, but only a subset of them will have visible git patches. This distinction is critical to ensure an effective remediation when multiple teams are involved and collaboration is necessary. By restricting access to the code (git patch) of each other's occurrences, teams can maintain the necessary level of confidentiality while still working together to resolve the incident. When the restriction on git patch visibility is enabled, the git patches of occurrences are hidden on the public share page of an incident. ### Enable API endpoint to retrieve detected secrets in clear text for each incident :::info This feature is only available for workspaces with a Business plan. ::: In [the workspace settings](https://dashboard.gitguardian.com/settings/workspace/security), Managers can control access to secret values through the API endpoint `/v1/secrets/{secret_id}`. This endpoint allows users to securely retrieve secret values directly via the API, enabling enhanced security automation and integration with existing security workflows. The secret access API provides several layers of security controls that must be properly configured: - **Personal Access Token (PAT) permissions**: Users must have appropriate PAT permissions (`secret:read`) to access secret values. SAT are not allowed. - **Workspace settings**: Managers must first activate the setting to enable API access to secrets at the workspace level. - **IP allowlisting**: Workspace owners need to configure [IP-based access controls to allow access from authorized sources](./ip-allowlist). - **Complete secret context**: Once properly configured, the API returns both the secret value and detector information for comprehensive remediation. For more information about using this API endpoint, please refer to the [API documentation](https://api.gitguardian.com/docs#tag/Secret-Incidents/operation/get-secret-detail). ### Session duration In [the workspace settings](https://dashboard.gitguardian.com/settings/workspace/security), Managers can customize how long a dashboard session lasts before users are automatically logged out. Choose from one of the preset durations or select **Custom** to specify a session duration in minutes. Leave the custom duration field empty to reset to GitGuardian defaults. :::warning Changing the session duration requires all users to log in again once the change is applied. ::: ### Restrict Personal Access Token scopes :::info This feature is only available for workspaces with a Business plan. ::: In [the workspace settings](https://dashboard.gitguardian.com/settings/workspace/security), Managers can restrict the scopes available to Members when creating Personal Access Tokens (PATs). This allows Managers to enforce the principle of least privilege by limiting what Members can do with their tokens. This restriction does not apply to Managers. By default, there is no restriction on PAT scopes for Members. ### Privacy mode enforcement {#privacy-mode-enforcement} :::info This feature is only available for workspaces with a Business plan. ::: In [the workspace settings](https://dashboard.gitguardian.com/settings/workspace/security), the workspace owner can enforce [privacy mode](/platform/security-data-privacy/privacy-mode) for some or all users, preventing them from toggling it off. This is useful for organizations that require secrets to always be obfuscated as a security policy. This setting is only editable by the workspace owner. Managers and members can see it but cannot change it. Four enforcement levels are available: - **All users** (default): no enforcement — every user controls their own privacy mode toggle. - **Managers and owner only**: members and restricted users have privacy mode enforced ON and cannot disable it. Managers and the owner retain control of their own toggle. - **Owner only**: managers, members, and restricted users have privacy mode enforced ON and cannot disable it. Only the owner retains control. - **No one**: privacy mode is permanently ON for everyone, including the owner. When enforcement applies to a user, the privacy mode toggle in the navigation bar is disabled and shows a tooltip explaining that it is controlled by the workspace settings. --- ## RSS & Atom feeds Stay up to date with the latest GitGuardian product updates through our ![feed icon](/img/icons/feed-icon.svg) RSS and Atom feeds! We provide dedicated feeds for different product components to help you track the changes that matter most to you. ## SaaS Platform Track updates to GitGuardian's cloud-based platform: - **RSS Feed**: [https://docs.gitguardian.com/releases/saas/rss.xml](https://docs.gitguardian.com/releases/saas/rss.xml) - **Atom Feed**: [https://docs.gitguardian.com/releases/saas/atom.xml](https://docs.gitguardian.com/releases/saas/atom.xml) ## Self-Hosted Platform Follow changes to GitGuardian's self-hosted solution: - **RSS Feed**: [https://docs.gitguardian.com/releases/self-hosted/rss.xml](https://docs.gitguardian.com/releases/self-hosted/rss.xml) - **Atom Feed**: [https://docs.gitguardian.com/releases/self-hosted/atom.xml](https://docs.gitguardian.com/releases/self-hosted/atom.xml) ## Detection engine Stay informed about updates to our secrets detection capabilities: - **RSS Feed**: [https://docs.gitguardian.com/releases/detection-engine/rss.xml](https://docs.gitguardian.com/releases/detection-engine/rss.xml) - **Atom Feed**: [https://docs.gitguardian.com/releases/detection-engine/atom.xml](https://docs.gitguardian.com/releases/detection-engine/atom.xml) ## ggshield Monitor updates to our CLI tool: - **Atom Feed**: [https://github.com/GitGuardian/ggshield/releases.atom](https://github.com/GitGuardian/ggshield/releases.atom) ## Py-GitGuardian Track changes to our Python SDK: - **Atom Feed**: [https://github.com/GitGuardian/py-gitguardian/releases.atom](https://github.com/GitGuardian/py-gitguardian/releases.atom) ## GitGuardian VSCode Extension Stay updated with our Visual Studio Code extension: - **Atom Feed**: [https://github.com/GitGuardian/gitguardian-vscode/releases.atom](https://github.com/GitGuardian/gitguardian-vscode/releases.atom) ## ggscout helm charts Track updates to our ggscout Helm charts: - **Atom Feed**: [https://github.com/GitGuardian/ggscout-helm-charts/releases.atom](https://github.com/GitGuardian/ggscout-helm-charts/releases.atom) --- ## Create your GitGuardian account Getting started with GitGuardian Internal Monitoring is easy. All you need is a GitGuardian account and repositories to scan for hardcoded secrets. ## Step 1. Create your account Go to [https://dashboard.gitguardian.com](https://dashboard.gitguardian.com/auth/signup?utm_source=website&utm_medium=docs&utm_campaign=getting-started) and choose one of the following options. ![Sign up page](/img/platform/getting-started/create_account.png) ### Option 1. Using GitHub's social login Signing up via your GitHub account is the fastest way to get started with GitGuardian. 1. Click `Sign up with GitHub` 2. Follow the instructions on GitHub to set up the [GitGuardian GitHub App](https://github.com/marketplace/gitguardian). You can choose to give GitGuardian access to all your repositories or to a selection of repositories, this can be modified later from your GitHub account. ### Option 2. Using email and password 1. Fill the sign up form 2. You will receive an email in order to confirm your email address. Follow the instructions in this email to finish creating your account. ### Option 3. Using SSO If you are joining an existing workspace managed by your organization, you can also create an account and sign in using SSO. Go to [https://dashboard.gitguardian.com/auth/sso](https://dashboard.gitguardian.com/auth/sso?utm_source=website&utm_medium=docs&utm_campaign=getting-started) and complete the form with your **professional email address** or **company domain** to be redirected to your organization's workspace. --- ## Assess your repositories' health ## How do I launch a historical scan of my repositories? Now that you have integrated your first repositories, it's time to check if they contain any secrets! GitGuardian gives you the ability to scan the entire commit history, across all branches, of your repositories to check if they are safe. > ## Understanding your perimeter > > Your perimeter is simply anywhere you are storing your shared code repositories. This includes shared repository hosting like GitHub, GitLab, Bitbucket or Azure Repos. > > ## Your perimeter view Simply go to the [**Perimeter view**](https://dashboard.gitguardian.com/perimeter) and launch your first historical scan! ![perimeter historical scanning](/img/internal-monitoring/integrate-sources/perimeter/historical_scanning_highlighted.png) ## How do I read the results of my scan? The [Perimeter view](https://dashboard.gitguardian.com/perimeter) contains a table listing the sources of your monitored perimeter. After running your first historical scan, GitGuardian will update the `Health` status of each repository, it will be set to `AT RISK` if a repository contains at least one hard-coded secret or `SAFE` if it doesn't contain any. The total number of unique secrets found will also be displayed in the `Secret incidents` column. If your repositories contain any hardcoded secrets, click on the Open secrets incidents link. It will take you to the `Incidents view` and display all the secret incidents found in a particular source. --- ## Investigate and remediate your first open incident ## What is a secret incident? What are its implications? Secret incidents are open issues that need your attention to be resolved. They are created by [our secrets detection engine](../../secrets-detection/home) that continuously scans your monitored repositories for hardcoded secrets and displays them in your GitGuardian dashboard. Leaving a secret in plain text in source control represents a threat for the security of the resources that are protected by that secret. To learn more about why hardcoded secrets are a vulnerability that needs your Application or Product Security teams' attention, read the related paragraph in our [Core Concepts](../../secrets-detection/core-concepts/what-is-a-secret) section of Secrets Detection. ## What are the occurrences of an incident? The **same secret can be seen multiple times** in your VCS. They are referred to as occurrences. GitGuardian streamlines the remediation process by automatically **grouping multiple occurrences of the same secret into a single secret incident**. Thus, an occurrence of a secret incident is uniquely identified by the combination of the following parameters: - the source (for instance: a GitHub repository or a GitLab project) impacted by the secret occurrence, - the commit in which we detected the secret occurrence, - the commit file containing the secret occurrence, - the line within the commit file where the secret occurred. Alerts are sent only when a new incident is created or reopened because of a regression. A new occurrence attached to an already-existing open secret incident won't raise any alerts. > GitGuardian sets a maximum limit of 1,000 occurrences for a single secret incident (this does not apply to the self-hosted platform). ## What are the critical steps to remediating a compromised secret? The **most important step is to revoke the secret**. Once a secret is exposed, it should be considered compromised and potentially exploited by attackers. But to prevent operational disruption, always assess the impact of a revocation first. GitGuardian provides you with a lot of context and insights to [assess the impact of the exposure](../../internal-monitoring/remediate/investigate-incidents), but more importantly, [measure the impact of the revocation](/nhi-governance/discover-your-nhis#exploration-map), thanks to the identification of the workloads using these credentials. ### Recommended remediation workflow: 1. **Secure storage:** Store the secret properly in a secret manager or secure vault. 2. **Update code:** Fix your application code to retrieve the secret from the secure storage location. 3. **Test and deploy:** Perform non-regression testing, deploy to production, and monitor that your application works as expected. 4. **Rotate and revoke:** Generate new credentials, update them in your secret manager, and revoke/deactivate the compromised secret to ensure no attacker can access the involved service. 5. **Check for unauthorized access:** Review logs to see if the secret was used maliciously, and proceed with mitigation process in case a breach is confirmed. This approach ensures your systems remain operational throughout the remediation process while implementing secure secret management practices. ### Detailed remediation guides: Choose the guide that matches your situation: - **For internal incidents** (secrets in your monitored repositories): [Remediation scenarios](../../internal-monitoring/remediate/remediation-scenarios/overview.md) - **For public incidents** (secrets found on public GitHub): [Remediate public incidents](../../public-monitoring/remediate/remediate-incidents.md) - **For public GitHub leaks** (comprehensive step-by-step guide): [Public GitHub leak remediation](../../secrets-detection/secrets-detection-engine/leaks_remediation.mdx) ## What if I don't have all the information I need? ### Getting more context: - **Involve the developer** who committed the secret - they have the most knowledge about what the secret accesses - **Check the detector documentation** - Each secret type has specific revocation instructions - **Use the incident timeline** - Review all related commits and files - **Follow the investigation process** - Use our [incident investigation guide](../../internal-monitoring/remediate/investigate-incidents.md) for thorough analysis ### Need help with the remediation process? - **Contact your security team** if you don't have permission to revoke the secret - **Use GitGuardian's sharing features** to collaborate with the right stakeholders - **Check our [detector documentation](../../secrets-detection/secrets-detection-engine/detectors/supported_credentials.md)** for specific guidance on revoking different types of secrets ### Prevention for the future: Now that you've handled your first incident, consider implementing these preventive measures to catch secrets before they enter your repositories: - **Install [GitGuardian CLI (ggshield)](../../ggshield-docs/getting-started.md)** - Scan for secrets locally and in CI/CD pipelines before code is committed - **Set up [pre-commit hooks](../../ggshield-docs/integrations/git-hooks/pre-commit.md)** - Automatically prevent secrets from being committed to your repositories - **Adopt [secure secrets management practices](https://blog.gitguardian.com/secrets-api-management/)** - Use proper secret management solutions instead of hardcoding credentials. --- ## Integrate your first repositories To get started with Internal Monitoring for secrets, you need to add an integration with a source like a Version Control System (VCS). ![Get started page - connect a source](/img/platform/getting-started/connect-source.png) ![Sources integrations](/img/platform/getting-started/sources-integrations.png) :::tip If you want to try GitGuardian Internal Monitoring out on a test repository, go ahead and clone our [**sample_secrets repo**](https://github.com/GitGuardian/sample_secrets). It contains 8 unique secrets our detection engine will find during the scans. ::: ## Integrate with GitHub 1. From the VCS integrations page, select GitHub ![GitHub integration](/img/platform/getting-started/vcs_integrations-github-1.png) 2. Confirm access to your GitHub account ![GitHub integration](/img/platform/getting-started/vcs_integrations-github-2.png) 3. Choose whether you want GitGuardian to monitor all your repositories or a selection of repositories. This can be changed later from your GitHub account. ![GitHub integration](/img/platform/getting-started/vcs_integrations-github-3.png) ![GitHub integration](/img/platform/getting-started/vcs_integrations-github-4.png) 4. Go back to your GitGuardian dashboard to see your added user or organization and its repositories. ![GitHub integration](/img/platform/getting-started/vcs_integrations-github-5.png) Once installed, GitGuardian will also give you the option to add or remove repositories from the monitored perimeter directly from your workspace. ## Integrate with other VCS platforms ### Integrate with GitLab When integrating GitGuardian with GitLab, you can choose to monitor an entire instance or certain groups only. In both cases, you will need to generate a personal access token with admin permissions for the chosen perimeter. Once installed, GitGuardian will also give you the option to add or remove repositories from the monitored perimeter directly from your workspace. #### Step 1. Create a personal access token 1. Go to your **User Settings** on GitLab 2. View the **Access Tokens** section 3. Choose a name (for example “gitguardian-secrets-scanning”) 4. IMPORTANT: Select the **API** scope If you need to, visit the [GitLab documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) for more details on how to create personal access tokens. #### Step 2. Configure your GitLab integration via a system hook or a group hook There are two ways to configure your GitLab integration, using system hooks or group hooks. Now that you have your personal access token ready, follow one of these guides depending on your preference: - [setup a system hooks type integration](../../internal-monitoring/integrate-sources/vcs-integrations/gitlab.md#integrate-your-gitlab-instance-with-system-hooks), - [setup a group hooks type integration](../../internal-monitoring/integrate-sources/vcs-integrations/gitlab.md#integrate-your-gitlab-groups-with-group-hooks). ### Integrate with Bitbucket server/data center :::warning This integration does not support projects and repositories hosted on Bitbucket Cloud (bitbucket.org). Check out our Bitbucket Pipelines integration to keep your Bitbucket Cloud workspace secure. ::: #### Step 1. Create a personal access token 1. In your Bitbucket workspace, navigate to your Bitbucket user settings (typically on your upper right hand corner, under Manage Account) 2. Go to the Personal access tokens section 3. Create a personal access token with a simple name such as "GitGuardian" and Read permissions on projects and Admin permissions on repositories. Set the "Automatic Expiry" option to "No". #### Step 2. Configure your Bitbucket integration via a system hook or a group hook There are two ways to configure your Bitbucket integration, at the instance-level or at the project-level. Follow one of these guides depending on your preference: - [setup an instance-level integration](../../internal-monitoring/integrate-sources/vcs-integrations/bitbucket.md#instance-level-integration), - [setup a project-level integration](../../internal-monitoring/integrate-sources/vcs-integrations/bitbucket.md#project-level-integration). --- ## Navigate with quick access Quick access is a unified search feature that enhances user navigation and productivity within the GitGuardian platform. This feature provides a centralized interface to quickly access different sections of the application, or search within our public documentation. ## Key features ### Unified search interface - **Application navigation**: Quickly jump to any section or page within GitGuardian. - **Documentation search**: Find relevant documentation and help articles. ### Enhanced productivity - **Faster navigation**: Reduce time spent navigating through complex menu structures. - **Context-aware results**: Search results adapt based on your current location and permissions. - **Keyboard shortcuts**: Navigate efficiently using keyboard interactions. ## Using quick access - Use the keyboard shortcut `Ctrl+K` (or `Cmd+K` on Mac) from anywhere in the platform. Alternatively, click the search icon in the main navigation bar. - The Quick access modal will appear with a search input field where you can enter your search keyword. - You can thus search for pages or sections within the dashboard, or use the prefix "Doc" to search within the product documentation. ![Quick access](/img/platform/getting-started/quick-access.png) ### Tips for effective use - **Use specific keywords**: More specific terms yield better results. - **Try different variations**: If you don't find what you're looking for, try synonyms or related terms. ### Keyboard shortcuts | Shortcut | Action | | --- | --- | | `Ctrl+K` / `Cmd+K` | Open Quick access | | `↑` / `↓` | Navigate through results | | `Enter` | Select highlighted result | | `Escape` | Close Quick access modal | | `Tab` | Navigate between result categories | ### Permissions and access Quick access respects your user permissions and workspace access: - Only shows pages and features you have permission to access. - Filters results based on your role. - Adapts to your workspace configuration and enabled features. ## Feedback and improvements Quick access is continuously improved based on user feedback and usage patterns. To suggest improvements or report issues, please refer to our [Support Page](/support/home). --- ## API GitGuardian Internal Monitoring has a public API for teams to: - Programmatically manage their GitGuardian workspace and handle their incidents lifecycle - Scan additional data sources for hardcoded secrets (e.g., Slack, MS Teams, Jira, Confluence by Atlassian) ## Resources - [**API documentation**](../../api-docs/introduction.md) - [**API reference**](https://api.gitguardian.com/docs) > Please note that if you are using a GitGuardian self-hosted instance, the base url of the API routes will be `https://dashboard.gitguardian.mycorp.local/exposed/` instead of `https://api.gitguardian.com/`. For example, the scan route will be: `https://dashboard.gitguardian.mycorp.local/exposed/v1/scan` Examples are provided in all supported programming languages (e.g. Python and Go). --- ## Dashboard GitGuardian Internal Monitoring comes with a dashboard for security and development teams to: - Configure their perimeter of monitored code repositories - Centralize their incidents in one area - Manage the incident lifecycle and coordinate remediation requiring cross-functional effort - Integrate with other platforms like SIEMs and ITSMs to forward GitGuardian alerts - Deploy secrets scanning in developer workflows (using the GitGuardian CLI or API) ## Resources - [**Dashboard**](https://dashboard.gitguardian.com) - [**Documentation**](../home.mdx) --- ## GitGuardian CLI (ggshield) ![](https://cdn.jsdelivr.net/gh/gitguardian/ggshield/doc/logo.svg) **ggshield** is an open-source command-line interface application (CLI) for secrets scanning in developer workflows. `ggshield` can run: - **in your local environment** to scan local files and repositories or as a pre-commit hook. - **in a CI environment**, - **in a pre-receive hook**, if you have a self-managed VCS instance ## Resources - [**Quick-reference guide**](../../ggshield-docs/getting-started.md) - [**Integrations guide**](../../ggshield-docs/integrations/overview.md) - [**CLI command reference**](../../ggshield-docs/reference/overview.md) - [**GitHub repository**](https://github.com/GitGuardian/ggshield) --- ## Python SDK ![](https://cdn.jsdelivr.net/gh/gitguardian/py-gitguardian/doc/logo.svg) **py-gitguardian** is the official python client for GitGuardian's public API. It can be used to create ad-hoc integrations to scan various data sources, from your workstation's filesystem to your favorite ChatOps tools like Slack, MS Teams, or developer wikis and ticketing systems like Confluence and Jira by Atlassian. ## Resources - [**GitHub repository**](https://github.com/GitGuardian/py-gitguardian) --- ## Glossary Here you can find a list of some Git, GitHub and GitGuardian specific terms and concepts that we use across our documentation. ### Author vs Committer [From Git definitions](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History): - The author is the person who originally wrote the work - The committer is the person who most recently applied a set of changes, for example by using commands such as `rebase` or `cherry-pick` ### Commit A commit is a Git object. It "is an individual change to a file (or set of files)". See the [GitHub glossary](https://help.github.com/en/github/getting-started-with-github/github-glossary#commit) for a more precise definition. Commits typically include a commit message, which provides a brief description of the changes made, the date of the commit, and the **author** and **committer** of the commit, who can be two distinct users. ### Commit author The Git user who makes the commit. ### Commit SHA Unique identifier of a commit created by Git. It is a 40-character checksum hash. For the sake of convenience, only the first 7 characters are usually displayed. ### Custom webhooks Custom webhooks allow you to build dedicated integration to receive different type of events (like incidents) from GitGuardian. It provides a way to integrate your different services with the GitGuardian alerting pipeline. ### GitHub contributor A contributor is a GitHub user who does not have collaborator access to a repository but has contributed to a project and had a pull request they opened merged into the repository. ### GitHub events Every interaction between a user and GitHub is logged in a GitHub Event. The complete list of event types is available [here](https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/github-event-types) It contains useful information, such as: - the **actor**, the GitHub user who triggered the event (in the case of a `PushEvent`, i.e when pushing several commits on GitHub, the actor is also referred to as the **pusher**) - the **organization** id, if the event occurred on a GitHub organization - the **payload** which depend on the event's type - the **repo** on which the event happened - the **type** ### GitHub organization GitHub organizations are a group of multiple users that typically mirror the structure of your real-world organization. GitGuardian can monitor as many GitHub organizations and scan their associated activity. ### Git users vs GitHub Users A commit as defined in the Git protocol, contains both an `author` and `committer`, defined by their email address and name. For example `"Author Name "` is a valid git user (either a committer or an author). This email is configured at the git protocol level, on your developers’ computers, using the commands: ```bash git config --global user.name "FIRST_NAME LAST_NAME" ``` ```bash git config --global user.email "MY_NAME@MY_DOMAIN.com" ``` On top of that, GitHub **sometimes** adds a GitHub author and / or committer, if it managed to link the git user to an existing GitHub user, based on the **email addresses**. In that case, the commit also contains a GitHub login as the author and / or the committer. ### Patch and diff A patch/diff is a git concept that represents the difference in changes between two commits, or saved changes. The diff will visually describe what was added or removed from a file since its last commit. ### Push event A Push Event is triggered whenever several commits are pushed on GitHub, from a local repository, and therefore its payload contains a list of commits. That is the main type of event we monitor, since it is the one containing commits, reflecting changes in code. ### Repository Following [GitHub's definition](https://help.github.com/en/github/getting-started-with-github/github-glossary#repository), a repository is the most basic element of GitHub. They are the easiest to imagine as a project's folder. A repository contains all of the project files (including documentation), and stores each file's revision history. Repositories can have multiple collaborators and can be either public or private. ### Secret A secret is any of the following: API keys, database connection strings, certificates. --- ## Data retention GitGuardian takes data collection and privacy very seriously. In order to perform monitoring effectively, GitGuardian needs to process multiple data and collects only what is actually needed for the product to meet the monitoring and remediation expectations. ### Commits with incidents only As explained in the [How Internal Monitoring works section](../../internal-monitoring/core-concepts/how-internal-monitoring-works.md), GitGuardian integrates with your VCS on the server side. Therefore, every commit reaching the server and belonging to the perimeter will be scanned for secrets. A commit consists of: - its actual content: the patches containing the additions and/or deletions of code in the different files. A commit can have several patches. - its metadata: - commit date - author date - committer email - committer name - author email - [author name](../glossary#author-vs-committer) - commit SHA GitGuardian collects: - The metadata of all the events including mostly push events. Push events metadata contains commits metadata. We do this in order to keep track of all the activity and compute analytics. - The precise patch of the commits for which GitGuardian has detected secrets This in order for the secret to be displayed in the dashboard to help with remediation. Plus if the git history is overwritten by the developer, GitGuardian becomes the only place where the security team can access the secret in order to perform the remediation and access logs checking. #### What happens during historical scans? During a historical scan, GitGuardian goes through all existing commits on the repository across all branches. The patches containing secrets are collected for the same reasons as mentioned above. The other commits are not collected. We also collect some metadata about the historical scan performed in order to compute analytics and improve the robustness of the algorithms: - Number of commits scanned - Number of branches scanned ### Perimeter sources’ metadata When integrating with GitGuardian, you allow the monitoring of specific GitHub repositories or GitLab projects you own. They constitute the sources of your perimeter. GitGuardian collects the metadata of those sources: - Name - Size (in bytes) - Visibility (public/private) - VCS unique identifier - Number of stars - Number of forks - Number of watchers We use such information to give you an overview of your entire perimeter analytics and the ability to filter the secret incidents by sources. Metadata are also crucial to allow seamless integration between GitGuardian and your VCS. ### VCS members basic information GitGuardian has read-access to your VCS members: - Members of your GitHub organization (private and public members) - Members of your GitLab instance in case of an instance-level integration. It is necessary for GitGuardian to compute the number of seats for billing purposes. If you would rather have your data completely isolated, you might want to self-host GitGuardian. ### SaaS Europe: GDPR Compliance For customers in the European Union, GitGuardian offers a SaaS solution that is fully compliant with the [General Data Protection Regulation (GDPR)](https://gdpr.eu/what-is-gdpr/). This ensures that all data processing and retention adhere to the strict privacy and data protection regulations mandated by GDPR. Data is stored and processed within the EU, providing peace of mind and compliance assurance for EU-based organizations. If you are interested, please reach out to the GitGuardian team at [support@gitguardian.com](mailto:support@gitguardian.com). Please note that we do not support migration of existing workspace from our US platform to the EU platform at this time. --- ## Privacy mode Protecting sensitive information from unauthorized access is crucial for maintaining data privacy. The privacy mode enables you to control sensitive information's visibility, preventing unauthorized viewing and aligning with privacy-by-design principles. ## What sensitive information can be obfuscated? To enable you to use GitGuardian in the best possible conditions, you can choose to show or hide sensitive information at any time from the application. The obfuscated sensitive information are: - The secrets themselves with [their multiple matches](../../secrets-detection/secrets-detection-engine/quick_start#detecting-secrets-with-multiple-matches-and-multi-line-secrets). - The honeytokens and the IP addresses that triggered the honeytokens. ## How to use privacy mode - You can activate or deactivate this mode from the top navigation bar. - When activated, all the workspace's secrets are obfuscated. It is not possible to deactivate the privacy mode for a single secret. - This mode is a setting available to every user, regardless of their access level or workspace plan. ![privacy mode](/img/platform/security-data-privacy/privacy-mode.png) > Please note that its activation does not affect other users in the same workspace. ## Workspace-level enforcement Workspace owners can enforce privacy mode for some or all users, preventing them from toggling it off. See [Privacy mode enforcement](/platform/enterprise-administration/workspace-settings#privacy-mode-enforcement) for details. --- ## Account settings ## Change your theme Customize GitGuardian's appearance to suit your preferences. You can choose between Light and Dark themes. To change your theme: 1. Navigate to Settings > Personal > [Account](https://dashboard.gitguardian.com/settings/personal/account) 2. In the **Interface** section, select your preferred theme from the **Theme** dropdown 3. Your selection is saved automatically Your theme preference is stored in your profile and persists across sessions. ## Change your first and last name If you sign up via email / password, GitGuardian would have asked you to submit your first and last names upon registration. If you have signed up through GitHub, GitGuardian infers your first and last name from the name indicated on GitHub. But if a name is not indicated on GitHub, GitGuardian will consider your GitHub login as your first name. In such cases, we recommend that you change your first and last name in order to facilitate collaboration with other members of your workspace. To change your first name and last name: 1. Navigate to Settings > Personal > [Account](https://dashboard.gitguardian.com/settings/personal/account) 2. Enter a new `First name` and `Last name` 3. Submit the form ## Change your email address We currently do not support email address modification. If you want to use another email address on GitGuardian, you would need to create another workspace. ## Change your GitHub login If you registered to GitGuardian using GitHub, your GitHub login will be visible in the Settings page. Since your GitGuardian and GitHub identities are intertwined, we do not allow you to edit your GitHub login within GitGuardian. ## Email verification (MFA) If you sign in with **email and password**, GitGuardian requires a one-time verification code sent to your email to confirm your identity. This applies at login and before performing sensitive actions in the dashboard. :::info Users who authenticate via **SAML SSO** or **GitHub** are not prompted — MFA is handled by your identity provider. ::: ### Sensitive actions Verification is required when you add or modify settings such as SSO configuration, API tokens (PAT/SAT), member invitations, user role promotions, source and destination integrations, alerting integrations in teams, password changes, account deletion, or GitGuardian Bridge configuration. After a successful verification, you can perform additional sensitive actions **without re-verifying for 30 minutes**. Each action resets the timer. ### Troubleshooting - **Didn't receive the code?** Check your spam/junk folder, then use the "Resend code" button. - **Locked out after failed attempts?** Wait for the cooldown period and try again. If you suspect unauthorized access, change your password immediately. - **Lost access to your email?** Contact [GitGuardian support](mailto:support@gitguardian.com) for identity verification and account recovery. ## Change your password 1. Navigate to Settings > Personal > [Account](https://dashboard.gitguardian.com/settings/personal/account) 2. Scroll to the `Password` section 3. Enter your current password in the `Current password` field. 4. Enter your desired new password twice, once in the `New password` field and once in the `Confirm new password` field. 5. Submit the form **Current password policy**: - your password must be at least 12 characters long - your password must contain at least 1 letter, 1 numeric character and 1 special character :::info I signed up through SSO and, now I don't have any password. Whenever you register through SSO, GitGuardian lets the IdP handle the authentication, therefore you don't need a password. However, we do let you configure a password if you want. This password will be associated with the email address you are using on GitGuardian. If the SSO is disabled, you will then be able to sign in via email / password submission. ::: ## Belong to multiple workspaces GitGuardian allows you to be member of several workspaces. Thus, your email address can be associated to multiple workspaces. However, GitGuardian allows you to create only one workspace yourself. In order to be member of other workspaces, you must receive an invitation. You can be a member of **at most 5 workspaces**. If you are member of several workspaces and you want to switch the workspace you are currently viewing, click on the first tab of the sidebar and then select the workspace to switch to. --- ## Delete your account ## Overview Users can be deleted from GitGuardian, either by: - the users themselves - the owner of the workspace ### By the user themselves As a user, you can delete your own GitGuardian account by: 1. Navigating to Settings > Personal > [Account](https://dashboard.gitguardian.com/1/settings/personal/account) 2. Clicking on **Delete my account** and confirming your action. ![delete account](/img/platform/user-account/delete_account.png) > Please note that if you are the Owner of the GitGuardian workspace, this workspace will also be deleted automatically. ### By the owner of the workspace If the owner of a workspace to which you belong as a member decides to delete their account and therefore his workspace, your membership to this account will also be automatically deleted. > Please note that if you only belong to this workspace, your user account will also be deleted. --- ## Configure email preferences You can configure the email notifications you want to receive from GitGuardian in [your personal settings](https://dashboard.gitguardian.com/settings/personal/notifications). By default, GitGuardian notifies you by email for any important events that occur on your dashboard. You can customize the email notifications for each workspace you are a member of. The available notifications are grouped into different categories: - **Workspace notifications** - **Team notifications**: Receive email notifications about your teams. - **Health Checks**: Receive email notifications about the health of your integrations. - **Mentioned in an incident note**: Receive email notifications when you, or a team you belong to, are mentioned in an incident note or feedback. - **Internal Monitoring** - **Incident alerting**: Receive email notifications upon new internal incidents from your teams.:warning: Turning off these notifications will require confirmation, as you may miss future important security-related notifications. This setting may be automatically disabled by default at the [workspace level](../enterprise-administration/workspace-settings#by-default-users-are-notified-by-email-when-a-new-incident-is-detected)). You have two options for receiving notifications: - All internal incidents (default) - Only internal incident involving yourself (based on git commit email) - **Historical scan notifications**: Receive email notifications upon completion of historical scans. - **Feedback submission notifications**: Receive email notifications upon feedback submission on an internal incident. - **Access granting notifications**: Receive email notifications when granted access to an internal incident. - **Weekly recap**: Receive a weekly email to keep track of the evolution of your internal incidents. - **Incident ignored with a valid secret**: Receive email notification when an internal incident is ignored with a valid secret based on the teams(s) you manage. _This option is available in the business plan_ - **Honeytokens** - **Trigger notifications**: Receive email notifications when an active token is triggered. Find more information about those alerts [here](../../honeytoken/configure-alerts). - **Public Monitoring** (if your workspace and team have access to Public Monitoring) - **Incident alerting**: Receive email notifications upon new public incidents - **Historical scan notifications**: Receive email notifications upon completion of historical scans of your public perimeter. - **Feedback submission notifications**: Receive email notifications upon feedback submission on a public incident. - **Access granting notifications**: Receive email notifications when granted access to a public incident. ![email preferences](/img/platform/user-account/email_preferences.png) > If you are a member of multiple workspaces, you can tailor your email notifications for each separate workspace. --- ## Plan and usage ## Overview You can find more information about your plan and usage in your workspace settings. Visit the [Plan & usage section](https://dashboard.gitguardian.com/settings/workspace/plan). :::info **What is a private collaborative repository?** A private collaborative repository is a private repository belonging to a VCS organization, representing a business entity, and to which multiple developers can be contributing. **What is a contributing developer?** We define a contributing developer as a commit author email address. A contributing developer is a developer who made at least one commit to a private collaborative repository within the last 90 days. ::: ## Plan There are three types of plan: - Free - Business - Enterprise You can benefit from all Business plan features with a 30-day free trial of the plan. | Plan / Contributing developers | Free | Trial | Business & Enterprise | | :----------------------------- | :-------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | | **< 25 devs** | :white_check_mark: **All** repositories monitored :x: No Business features | :white_check_mark: **All** repositories monitored :white_check_mark: Business features | :white_check_mark: **All** repositories monitored :white_check_mark: Business features | | **> 25 devs** | :x: Private collaborative repositories **NOT** monitored :x: No Business features | :white_check_mark: **All** repositories monitored :white_check_mark: Business features | :white_check_mark: **All** repositories monitored :white_check_mark: Business features | If you want additional information about our different plans, please visit the [pricing page on our website](https://www.gitguardian.com/pricing?utm_source=documentation). ## Usage ### Free plan You can monitor your private collaborative repositories within a **limit of 25 contributing developers**. Only workspace Managers and Owners can view the total number of contributing developers. If you have more than 25 contributing developers, there are two possibilities: - Your trial will start automatically if you reach the limit of 25 contributing developers (happens after adding new repositories to your perimeter for example). - Your free trial has been redeemed and expired, meaning your private collaborative repositories are no longer monitored. We invite you to contact our sales team via [email](mailto:sales@gitguardian.com) to upgrade your plan. ### Business & Enterprise plan You can monitor your private collaborative repositories, in respect with the number of contributing developer licenses you have acquired. --- ## Core concepts(Public-monitoring) GitGuardian's Public Monitoring continuously scans [public sources](./sources/overview.md) like GitHub to detect exposed secrets related to your organization and developers. This proactive monitoring helps you identify and remediate security risks before they can be exploited by malicious actors. :::info Public Monitoring is a business feature that requires a specific license. [Contact us](https://www.gitguardian.com/contact-us) for availability and pricing information. ::: :::info Public Monitoring complements [Internal Monitoring](../internal-monitoring/home.mdx) by extending your security coverage to developer activity outside your direct control. ::: ## How Public Monitoring works Public Monitoring operates through the following approach: ### 1. Define your company's public perimeter GitGuardian maps your attack surface on public GitHub by defining exactly where to monitor for leaked secrets. Your [company public perimeter](./perimeter/overview.md) includes: - **Monitored GitHub developers** attached to your company - **Company-owned GitHub organizations** - **Secret graspers** - company-specific keywords that help identify relevant secrets ### 2. Continuous secret scanning Using our [Secret Detection Engine](../secrets-detection/secrets-detection-engine/quick_start), GitGuardian scans all activity within your defined perimeter to detect any occurrence of secrets and alerts you as soon as it is detected. This monitoring covers public GitHub as well as additional [public sources](./sources/overview.md) such as DockerHub. ### 3. Incident management and remediation When secrets are detected, GitGuardian creates [public secret incidents](./detect-public-secret-incidents/incidents-occurrences.md) that provide detailed context for investigation and remediation. ## Getting started 1. **Review your perimeter**: Navigate to [Perimeter > Public monitoring](https://dashboard.gitguardian.com/perimeter/public-monitoring) to review your monitored perimeter 2. **Configure detection settings**: Customize which secret types to monitor and set up custom hosts for validity checking 3. **Explore incidents**: Visit [Public Monitoring > Public secret incidents](https://dashboard.gitguardian.com/public-incidents/secrets) to see detected issues ## Key benefits - **Proactive risk detection**: Identify exposed secrets before they can be exploited - **Comprehensive coverage**: Monitor both current and former employees' public activity - **Contextual intelligence**: Understand the scope and severity of each incident - **Streamlined remediation**: Get actionable insights to quickly resolve security issues --- ## Incident lifecycle ## Incident statuses :::info A public secret incident can be in one of two overall states: - **Open**: including Triggered and Assigned statuses - **Closed**: including Resolved and Ignored statuses ::: ### Triggered A triggered incident is an incident detected and stored by GitGuardian but not yet investigated by a member of your workspace. ### Assigned An assigned incident is being investigated by a specific member of the workspace. It is not resolved or ignored yet. ### Resolved A resolved incident is an incident considered as remediated. In the case of a public secret incident related to your company, you must typically ensure that the secret is revoked, and optionally that the evidence is removed from Public GitHub. :::info Regression setting for resolved incidents - If you consider a new occurrence of an incident that has already been resolved to be problematic, you will want the regression behavior enabled. When the regression behavior is turned `On` and a new occurrence of this secret is detected in real-time (regardless of whether it has been revoked or not), GitGuardian reopens the incident, changes its status back to **Triggered**, and raises a notification. - If the exposure of the secret is not important to you and only revocation matters, you can turn `Off` the regression behavior and GitGuardian will silently add the occurrence to the existing resolved incident without delivering any notifications. The regression behavior can be configured in the [Incidents lifecycle section of your workspace General settings](https://dashboard.gitguardian.com/settings/workspace/general). ![Regression setting](/img/internal-monitoring/remediate/incidents/regression_setting.png) ::: ### Ignored An ignored incident is an incident not considered as such by a member of your team and does not require remediation. For public secrets incidents, a typical reason for ignoring a secret is that the secret is a personal credential from a developer, and not actually related to your company ("Credential is not related to the company"). However, several other ignore reasons are possible: - this is a test credential - this is a low risk secret - this is not a secret (false positive) - developer is not connected to the company - credential is not related to the company > Ignoring an incident means that you don't want GitGuardian to consider it anymore. If a new occurrence appears for an ignored incident, GitGuardian will not reopen it or alert you. ```mermaid graph LR Triggered --> Assigned Assigned --> Resolved Assigned --> Ignored Ignored -.->|Reopen| Triggered Resolved -.->|Reopen or regression| Triggered ``` ## Lifecycle of an incident ### 1. Receiving incidents alerts GitGuardian can send an alert **upon detection of a new incident**. All members with access to Public Monitoring can be alerted by email, and/or on their [alerting integrations](../../platform/configure-alerting/alerting-and-notifications.md), in order to tackle the new incident as quickly as possible. > Note that for incidents detected thanks to historical scanning, we do not send an alert per incident but rather an email recap with all the incidents discovered on a given historical scan. Members will also receive similar alerts upon regression of an already-resolved incident. ### 2. Assigning incidents Investigation and remediation of an incident can take some time. So let your teammates know that you are **currently working on a given incident**, by declaring the assignee, in order not to duplicate work within your team. **Prioritizing and knowing which incident is more severe than another can be very challenging**, especially when you are dealing with a large number of incidents. Have a look at our [Prioritize guide](../remediate/prioritize-incidents.md) to read our good practices for identifying the incidents you need to tackle first. ### 3. Collaborate and remediate Once you decide which incident you want to work on, a new phase of collaboration and remediation starts. GitGuardian helps you by providing as much as **contextual information** as possible and features that help you **get in touch with the appropriate stakeholders** and **check that the incident has been properly remediated**. Read more about this topic in our [Remediating incidents](../remediate/remediate-incidents.md) section. Ultimately, you can resolve or ignore the incident. You will always have the possibility to reopen it manually. In the specific case of resolved incidents for which new occurrences are detected again, you can configure GitGuardian to automatically re-open incidents and receive alerts or not by choosing your preferred [Regression setting.](https://dashboard.gitguardian.com/settings/workspace/general) All user activity and team notes attached to a given incident can be found in the **Activity section** of the incident page. ![Incident timeline](/img/internal-monitoring/remediate/incident-detail/timeline.png) --- ## Incidents and occurrences ## What is a public secret incident? Public secret incidents are open issues created when GitGuardian detects secrets within your Public Perimeter. When secrets are leaked publicly within your company perimeter, they are likely related to your organization and require your attention to assess their impact, and resolve the incident accordingly. ## What are the occurrences of a public secret incident? The **same secret can be detected multiple times** across different public sources. These individual detections are called **occurrences**. GitGuardian streamlines the remediation process by automatically **grouping multiple occurrences of the same secret into a single public secret incident**. A public secret occurrence is uniquely identified by the combination of the following parameters: - The public source where the secret was detected (typically a GitHub repository) - The commit or content in which the secret was found - The file or content containing the secret occurrence - The specific location within the content where the secret occurred (for example, the line within a commit, or the file within a DockerHub image layer) :::info Each occurrence may have been detected through different [attachment reasons](../remediate/understand-incident-properties.md#attachment-reasons). For example, the same incident may group: - An occurrence leaked 'By dev from perimeter' (a developer from your monitored perimeter was involved) - Another occurrence leaked 'On organization from perimeter' (the secret was found in a repository belonging to one of your monitored GitHub organizations). As a result, a single public secret incident may have multiple attachment reasons. ::: --- ## Detect public secret incidents GitGuardian continuously monitors public sources to detect exposed secrets related to your organization. When secrets are found within your [company public perimeter](../perimeter/overview.md), GitGuardian creates public secret incidents that require investigation and remediation. ## How detection works ### Real-time monitoring GitGuardian scans public commits on GitHub continuously using our [Secret Detection Engine](/secrets-detection/secrets-detection-engine/quick_start). When a commit matches your company perimeter, GitGuardian analyzes it for 600+ types of secrets. **Response time**: most incidents are created and alerted within about **10 minutes** of the commit. Some commits are detected later. Each incident carries two dates: the occurred date, when the commit was pushed to GitHub, and the detected date, when GitGuardian detected the secret and created the incident. **What's monitored in real-time:** - Activity from developers in your perimeter - Commits in your monitored GitHub organizations - Content matching your [secret graspers](../perimeter/secret-graspers.md). ### Historical scanning GitGuardian also performs historical scans to detect secrets that were exposed before your monitoring was established. A historical scan is performed at initialization of your Public Monitoring dashboard. **What's covered by historical scans:** - Past activity from monitored developers - Historical commits in monitored GitHub organizations :::info Secret graspers limitation [Secret graspers](../perimeter/secret-graspers.md) only work for real-time monitoring and do not apply to historical scans. They are monitored from the moment they are created, without retroactive scanning of past activity. ::: ## How incidents are created A public secret incident is created when all of the following conditions are met: 1. A secret is detected in a [monitored public source](../sources/overview.md) - for example, a public GitHub commit 2. The detection is attached to your company through your [perimeter definition](../perimeter/overview.md) 3. The secret detector is enabled in your detection settings Each incident provides [detailed information](../remediate/understand-incident-properties.md) like secret type, validity status, attachment reasons, and complete context for investigation and remediation. ## Expanding detection with Explore While perimeter-based monitoring provides comprehensive coverage of known organization's and developers' activity, the [Explore](../explore/overview.md) feature extends your detection capabilities by enabling proactive searches across public GitHub for secrets that might fall outside your defined perimeter. You can use Explore to complement your perimeter monitoring with targeted searches for company-specific terms, domains, and technologies. ## Customizing detection You can customize which secrets to detect and how validity is checked. For detailed configuration options, see [Customize detection](/secrets-detection/customize-detection/detector-settings) and [Validity checks](/secrets-detection/customize-detection/validity-checks). --- ## Explore Explore enables you to proactively search for secrets that may have been leaked in public GitHub repositories related to your organization. By expanding your secret detection beyond your defined perimeter, Explore helps you discover exposures that traditional perimeter-based monitoring might miss. :::info Explore is designed to help you find secrets related to your company's infrastructure, domains, and technologies. Focus your searches on company-specific terms for the most relevant and actionable results. ::: ## How Explore works Explore allows you to search through public GitHub commits and patches using sophisticated query capabilities, then scan the results for secrets using GitGuardian's detection engine. ### 1. Search for relevant commits Use targeted search queries to find public commits that might contain secrets related to your organization: - Search for your company domains, API endpoints, or infrastructure - Look for commits from current or former employees - Find references to your internal systems or technologies ![Explore search](/img/public-monitoring/explore/explore-search.png) ### 2. Scan results for secrets Once you've identified potentially relevant commits, scan them for actual secrets, using GitGuardian's comprehensive detector library. ![Explore scan](/img/public-monitoring/explore/explore-scan-for-secrets.png) ### 3. Create incidents and monitor Transform discovered secrets into actionable security incidents: - Create public secret incidents directly from scan results - Set up automated incident creation with scheduled scans - Track and remediate exposures through your standard incident workflow ## Getting started and best practices 1. **Use company-specific searches**: Focus on terms directly related to your organization (domains, infrastructure, technologies) rather than generic keywords. This ensures relevant, actionable results and stays within the 10,000 result limit required for scanning. 2. **Scan results**: Use the search interface to find relevant commits, then scan the results to identify actual secret exposures 3. **Create incidents**: Convert findings into trackable security incidents through your standard workflow 4. **Set up monitoring**: Schedule regular scans for critical search queries to maintain ongoing monitoring 5. **Regular review**: Monitor the quality of results and refine queries to reduce false positives and improve detection effectiveness ## Next steps - Learn the [search syntax](./search-syntax.md) for building effective queries - Understand how to [scan and monitor](./scan-and-monitor.md) search results --- ## Scan and monitor search results After running a search query in Explore, you can scan the results for secrets and set up ongoing monitoring to catch new exposures automatically. ## Scanning search results ### Running a scan 1. Execute your search query to find relevant commits 2. Review the number of results - **scanning is only possible with 10,000 commits or fewer** 3. If results exceed 10,000, refine your search query to reduce the number of matches 4. Click **Scan for secrets** to analyze the commits with GitGuardian's detection engine 5. Wait for the scan to complete - processing time depends on the number of results ## Viewing scan results ### Secret findings Scan results show: - **Detected secrets**: Type, severity, and confidence level - **Source context**: Repository, commit, and file information - **Patch details**: Exact location and surrounding code - **Metadata**: Author, date, and commit message ![Explore scan results](/img/public-monitoring/explore/explore-scan-results.png) ### Creating incidents For each detected secret, you can: - **Review context**: Examine the full commit and file details - **Assess impact**: Determine if the secret poses a real risk to your organization - **Create incident**: Convert the finding into a public secret incident :::info Incidents created from Explore will have the attachment reason "From Explore" to help you track their origin in your incident management workflow. ::: ![Create incident from Explore](/img/public-monitoring/explore/explore-create-incident.png) ## Scheduled monitoring ### Setting up automated scans You can transform any relevant search into ongoing monitoring: 1. **Name the scan** (optional): After running a search and scan, you can give it a descriptive name 2. **Set frequency**: Choose daily or weekly automated scanning 3. **Automatic incident creation**: New secrets found in subsequent scans automatically become incidents 4. **Continuous protection**: Stay protected as new commits matching your criteria appear ## Next step - Review [incident remediation](../remediate/remediate-incidents.md) for handling Explore findings --- ## Search syntax Explore uses a powerful query language to search through public GitHub commits and patches. This guide covers the essential syntax for building effective searches to find secrets related to your organization. ## Basic search concepts ### Simple term search Enter a term in the search bar to search across all indexed fields: ```query yourcompany ``` ### Boolean operators Combine terms using boolean operators: - **AND** - Both terms must be present - **OR** - At least one term must be present - **NOT** - Exclude a term **⚠️ Boolean operators MUST be in CAPITAL LETTERS.** ```query yourcompany AND database yourcompany OR yourdomain yourcompany AND NOT test ``` For complex queries mixing operators, use parentheses: ```query (yourcompany OR yourdomain.com) AND database AND NOT test ``` ## Field-specific searches Target specific types of information by specifying which field to search: ### Common search fields | Field | Query term | Description | |-------|-----------|-------------| | Patch content | `file.patch` | Search within the actual code changes | | Author email | `commit.author.email` | Email of the code author | | Author name | `commit.author.name` | Name of the code author | | Author GitHub username | `author.login` | GitHub username of author | | Committer email | `commit.committer.email` | Email of the person who committed | | Committer name | `commit.committer.name` | Name of the person who committed | | Committer GitHub username | `committer.login` | GitHub username of committer | | Filename | `file.filename` | Name of the changed file | | File extension | `file.file_extension` | Extension of the changed file | ### Basic field search examples ```query # Search for patches from a specific email commit.author.email: john@yourcompany.com # Search patch content file.patch: database # Search across multiple fields commit.author.email: @yourcompany.com OR file.patch: yourcompany ``` ### Searching for multiple words Use quotes to search for plain words that appear near each other: ```query file.patch: "production database" ``` ### Exact keyword matching For exact matches (case-sensitive), add `.keyword` suffix, without quotes: ```query source_metadata.repo_name.keyword: yourcompany/api-service ``` :::caution Do not use quotes A quoted value containing `/` returns no results: `source_metadata.repo_name.keyword: "yourcompany/api-service"` matches no repository. ::: ## Practical search examples | What you're looking for | Query to use | |------------------------|-------------| | Patches containing a term | `file.patch: yourcompany` | | Patches with multiple terms (OR) | `file.patch: yourcompany OR file.patch: yourdomain` | | Patches with multiple terms (AND) | `file.patch: yourcompany AND file.patch: database` | | Patches from a GitHub username | `author.login: username OR committer.login: username` | | Patches from an email domain | `commit.author.email: @yourcompany.com OR commit.committer.email: @yourcompany.com` | | Patches from a specific person | `(commit.author.name: "John Doe") OR (commit.committer.name: "John Doe")` | | Patches from a user after a date | `(author.login: username OR committer.login: username) AND commit.committer.date:{2024-01-01 TO *}` | | Patches from a user in date range | `(author.login: username OR committer.login: username) AND (commit.committer.date:{2024-01-01 TO 2024-03-31})` | | Patches from multiple users | `(author.login: (user1 OR user2) OR committer.login: (user1 OR user2))` | | Patches in specific repository | `source_metadata.repo_name: yourrepo` |
Advanced search capabilities ## Field types and advanced searching Different field types support different search methods: ### Date fields Use range operators with ISO 8601 format dates. All dates are stored in UTC. ```query # After a date (inclusive) source_metadata.created_at:[2024-01-01 TO *] # Between dates (exclusive start, inclusive end) commit.author.date:{2024-01-01 TO 2024-03-31] # Before a date (exclusive) commit.committer.date:[* TO 2024-01-01} ``` - Square brackets `[]` = inclusive - Curly brackets `{}` = exclusive - Asterisk `*` = wildcard for open-ended ranges ### Integer fields Search numeric fields with exact values or ranges: ```query # Exactly 10 additions file.additions: 10 # At least 100 additions file.additions: [100 TO *] # Between 50 and 200 additions file.additions: [50 TO 200] ``` ### Text fields vs Keyword fields - **Text fields** (e.g., `file.patch`): Tokenized and analyzed for flexible searching - **Keyword fields** (e.g., `source_metadata.repo_name.keyword`): Exact match, case-sensitive ### Text field processing Text fields like `file.patch` undergo complex processing: - Split on special characters (/, :, =, etc.) - Extract camelCase terms: `GitGuardian` → `git`, `guardian`, `gitguardian` - Extract email parts: `user@company.com` → `user`, `company.com`, `user@company.com` - Extract domain components and IP address parts - Convert to lowercase - Remove terms shorter than 3 characters ## Complete field reference | Field | Type | Description | |-------|------|-------------| | `sha` | keyword | Commit SHA | | `html_url` | path | GitHub commit URL | | `author.id` | keyword | GitHub author ID | | `author.login` | keyword | GitHub author username | | `committer.id` | keyword | GitHub committer ID | | `committer.login` | keyword | GitHub committer username | | `commit.message` | text | Git commit message | | `commit.author.email` | text | Git author email | | `commit.author.name` | text | Git author name | | `commit.author.date` | date | Git author date | | `commit.committer.email` | text | Git committer email | | `commit.committer.name` | text | Git committer name | | `commit.committer.date` | date | Git committer date | | `file.filename` | path | Patch filename | | `file.patch` | text | Patch content | | `file.file_extension` | keyword | File extension | | `file.sha` | keyword | File SHA | | `file.additions` | int | Lines added | | `file.deletions` | int | Lines deleted | | `file.changes` | int | Lines changed | | `source_metadata.created_at` | date | GitHub processing date | | `source_metadata.repo_id` | keyword | Repository ID | | `source_metadata.repo_name` | text | Repository name | **Note**: Many fields have both text and keyword versions (e.g., `commit.author.name` vs `commit.author.name.keyword`). ## Search limitations ### Text field limitations - Cannot search terms shorter than 3 characters - Cannot search numbers smaller than 10,000 - Cannot search special characters directly: `; , " ' ` = : / \ $ # & ~ | ^ < > { } [ ] ( ) ? ! § * °` - Cannot perform exact substring matching ### Subdomain searching Domain searching has specific behavior: - Domains with 3 or fewer levels: `file.patch: company.com` matches `api.company.com` - Domains with more than 3 levels: requires exact match or middle subdomain search
## Building effective searches Focus your searches on terms most likely to appear near secrets: - **Company domains**: `yourcompany.com`, `api.yourcompany.com` - **Email patterns**: `@yourcompany.com`, specific employee emails - **Internal services**: database names, API endpoints, service identifiers - **Repository names**: company-owned repositories - **User activity**: current or former employee usernames Use quotes only for plain words. On values containing characters such as `/`, `-` or `_`, quotes widen the search instead of narrowing it: `file.patch: "payment-service"` also matches `auth-service`, `payment-gateway`, and anything else containing `payment` or `service`. **Remember**: More specific searches yield more actionable results and help stay within the 10,000 result limit required for scanning. ## Search scope options - **Entire Public GitHub**: Search across all public GitHub repositories (default) - **Company perimeter**: Restrict searches to within your [company's public perimeter](../perimeter/overview.md) --- ## Developers :::tip Why monitor developers? Any developer who is—or was—an employee of your company may leak secrets or sensitive data that could be damaging to your organization. This includes activities in personal projects, contributions to open-source repositories, and testing activities. ::: ## Developers attached to the company GitGuardian automatically links GitHub profiles to your company based on several criteria. The list of developers attached to your company is visible in your [public perimeter](https://dashboard.gitguardian.com/perimeter/public-monitoring/developers). The "Why in perimeter" column explains why each developer is included in your monitoring scope. ## Managing your developer perimeter To view and manage the developers in your perimeter: 1. Navigate to [Perimeter > Public monitoring > GitHub developers](https://dashboard.gitguardian.com/perimeter/public-monitoring/developers) 2. Review the list of automatically detected developers 3. Contact our **[support team](mailto:support@gitguardian.com)** to manually add additional developers if needed --- ## GitHub organizations GitGuardian can monitor multiple GitHub organizations that belong to your company. Once configured, GitGuardian will: - scan every commit on each repository of the GitHub organization, - add the organization’s *members* to the list of monitored developers, and scan any of their public activity. ## Adding organizations to your perimeter To add GitHub organizations to your monitored list, GitGuardian needs the GitHub ID of each organization. Contact our **[support team](mailto:support@gitguardian.com)** if you are missing a company-owned organization in your perimeter. ## Monitoring private members You can enrich the list of [monitored developers](./developers.md) with the private members of your GitHub organization by providing GitGuardian a GitHub access token. Both token types are supported: - **Fine-grained token** with the `Members: Read` organization permission. - **Classic token** with the `read:org` scope. ### Step 1: Generate a personal access token Generate a personal access token from a GitHub account with access to the organization. **For a fine-grained token**, GitGuardian only needs to read the organization's member list. A fine-grained token is scoped to a single organization, so create one token per organization you want to monitor, and configure it as follows: - **Resource owner**: select the organization you want to monitor. - **Repository access**: select "Public repositories". - **Permissions**: under "Organization permissions", set "Members" to "Read-only". ![Generate a fine-grained GitHub token](/img/public-monitoring/perimeter/generate-github-token-fine-grained.png) **For a classic token**, grant the `read:org` scope and select "No expiration" so that GitGuardian can continuously monitor the future addition/removal of members. A single classic token can cover every organization the account belongs to. ![Generate a classic GitHub token](/img/public-monitoring/perimeter/generate-github-token.png) ### Step 2: Submit the token to GitGuardian Go to your GitGuardian's settings in [Settings > Public monitoring > Perimeter](https://dashboard.gitguardian.com/settings/public-monitoring/perimeter), click "Monitor private members" and submit the GitHub token generated in the previous step. ![Monitor private members](/img/public-monitoring/perimeter/monitor-private-members-button.png) ![Monitor private members - submit token](/img/public-monitoring/perimeter/monitor-private-members-token.png) ### Step 3: Check the status per organization After you submit the token, GitGuardian checks each organization in your perimeter and displays one of the following statuses: - **Private members monitored**: GitGuardian can read the organization's private members and has added them to your monitored developers. - **Private member access unconfirmed**: your organization may have no private members, or your token may lack the required access. Check your token's organization permissions on GitHub - for a fine-grained token, make sure the `Members: Read` organization permission is granted. - **Private members not monitored**: no token is linked to the organization, or the linked tokens are invalid or have no access to it. This is expected for organizations that a fine-grained token is not scoped to - submit a dedicated token for each organization you want to monitor. ## Managing your organization perimeter To view and manage GitHub organizations in your perimeter: 1. Navigate to [Perimeter > Public monitoring > GitHub sources](https://dashboard.gitguardian.com/perimeter/public-monitoring/sources) 2. Review the list of monitored organizations and repositories 3. Contact our **[support team](mailto:support@gitguardian.com)** to add missing company-owned organizations --- ## Company public perimeter The company perimeter defines the scope we are monitoring for your company. It encapsulates the following categories: - [**Developers**](./developers.md) attached to the company; - [**GitHub organizations**](./github-organizations.md) that belong to the company - [**Secret graspers**](./secret-graspers.md), company-specific terms around which we will be looking for secrets. ## Perimeter definition The developers and GitHub organizations above are not listed one by one. GitGuardian derives them from a small set of inputs, called your perimeter definition: - your **company names**, matched against the company and bio fields of GitHub profiles; - your **email domains**, matched against the email addresses developers commit with; - the **GitHub organizations** owned by your company. Your perimeter definition is visible in [Settings > Public monitoring > Perimeter](https://dashboard.gitguardian.com/settings/public-monitoring/perimeter). It is read-only: contact our **[support team](mailto:support@gitguardian.com)** to add or remove a company name, a domain or an organization. Secret graspers work differently. They do not resolve into a list of developers or sources, so they are both part of the definition and monitored in their own right. --- ## Secret graspers Secret graspers are company-specific terms that allow GitGuardian to identify secrets relevant to your organization. When a secret grasper appears in the context of detected secrets, GitGuardian will attach the secret to your company and create a public secret incident. ![Secret graspers](/img/public-monitoring/perimeter/secret-graspers-list.png) *In the above example, GitGuardian will create a public secret incident whenever it detects a secret exposed alongside "jira.dev.acme.io" on public GitHub.* ### Adding a new secret grasper Secret grasper requests can be submitted from the [dedicated settings page](https://dashboard.gitguardian.com/settings/public-monitoring/secret-graspers) and must be validated by GitGuardian to ensure complete relevance. To request a new secret grasper: 1. Navigate to [Settings > Public Monitoring > Secret Graspers](https://dashboard.gitguardian.com/settings/public-monitoring/secret-graspers) 2. Click "Request new secret grasper" 3. Provide a name, the term or pattern you want to monitor, and select the type: - **Raw**: Exact text matching. GitGuardian will look for the exact string you specify (e.g., `mycompany.com` will match exactly `mycompany.com`) - **Regex**: Pattern matching using regular expressions. Allows for more flexible matching (e.g., `mycompany\.(com|org)` will match both `mycompany.com` and `mycompany.org`) 4. If necessary, define tags for this secret grasper (incidents created from this secret grasper will inherit the tag) 5. Submit the request for GitGuardian review ![Request secret grasper](/img/public-monitoring/perimeter/create-secret-grasper-request.png) ### Secret grasper statuses - **Submitted**: the secret grasper request has yet to be reviewed by GitGuardian. - **Active**: the secret grasper has been accepted and is actively monitored - **Paused**: the secret grasper has been accepted but you have chosen to Pause the monitoring. Existing incidents linked to this secret grasper still exist. - **Rejected**: the secret grasper request has been rejected by GitGuardian. :::info GitGuardian will reject a secret grasper request if: - it is not related to your company; - it is too "generic" and will result in too many non-related findings. ::: It is possible to delete a secret grasper - if it's not rejected. In this case, the related incidents/occurrences will be deleted permanently. If you prefer to stop the monitoring of the secret grasper while keeping the existing incidents, you will want to "pause" it. --- ## Agents analysis :::warning[Beta] The agents analysis is in beta and may still evolve. ::: ## Overview The hardest question about a public secret leak is rarely whether it is a secret. It is whether it is *yours*. A leak found on a public source can come from a developer's personal project, from a contractor, or from someone entirely unrelated who happens to work with the same technologies. GitGuardian runs AI agents over your public secret incidents to answer that question on your behalf. A **triage agent** makes a first-pass assessment of each incident, and the most promising ones are promoted to a **deep analysis agent** for a more thorough investigation. Their conclusions show up in three places: - **Company-related**, the agents' verdict on whether a leak is yours, - the **Risk score**, now set by the agents, - the **Analysis** tab on the incident page, which holds the reasoning behind both. The analysis is performed by large language models from GitGuardian's third-party LLM providers, and it is not affected by the workspace AI settings. See the [AI Management Policy](/platform/ai/ai-management-policy) for how your data is handled and which providers are used. :::info Progressive rollout The agents analysis is being rolled out progressively and is not enabled on every workspace yet. If the **Company-related** column and filter do not appear on your public incidents list, your workspace has not been switched yet: contact support@gitguardian.com to request it. ::: ## Company-related Company-related is the agents' answer to "is this leak ours?". It is available as a column in the incidents table, as a filter, and as ready-made saved views. | Value | What it means | |---|---| | **Related** | The agents concluded the leak is related to your company. These are the incidents to prioritize. | | **Uncertain** | The agents could not determine whether the leak is related to your company. Worth a human look. | | **Unrelated** | The agents concluded the leak is not related to your company. | | **Empty** | The incident has not been analyzed yet. | When filtering, each value can be narrowed down by which agent reached the conclusion, for example *Triage ruled out* or *Deep analysis confirmed*. Only the deep analysis agent can confirm a leak as **Related**. **Uncertain** therefore covers two situations: - an incident the deep analysis agent investigated without reaching a conclusion, - and an incident that triage neither ruled out as unrelated nor selected for deep analysis. In both cases, no agent reached a conclusion, so these are the incidents where your own judgment adds the most. Three default saved views pre-filter the list on the verdict, so you do not have to build the filter yourself: **Company-related**, **Unclear if company-related** and **Not company-related**. They sit alongside the existing **All** and **Open** views, and all five show the Company-related and Risk score columns by default. ![Company-related and Risk score in the public incidents list](/img/public-monitoring/remediate/agents-analysis/incident-list.png) :::info Coverage and timing The agents analysis is asynchronous, so it lags behind detection rather than arriving with the incident. Coverage of past incidents also varies by workspace, and some incidents cannot be analyzed yet at all. We are working toward full coverage with analysis as close to detection as possible. Filter on **Company-related** = **Empty** to find incidents with no analysis. ::: :::tip Start from the **Company-related** saved view to work the leaks that are yours, then order them by risk score and severity. Use **Not company-related** to clear out the rest. ::: ## Risk score On workspaces with the agents analysis, the **Risk score** of a public incident is set by the agents. It is still a 0-100 value where **100 indicates the highest risk**, and it still drives the score column, sorting and filtering. Three behaviors are worth knowing: - An incident the agents rule **Unrelated** always scores **0**, whatever the technical risk of the secret. The incident page states why: *Set to 0 because this leak is unrelated to your company.* - An incident that has **not been analyzed yet** has an **empty** risk score, never 0. A score of 0 always means the incident was analyzed, so an empty score should not be read as a harmless one. - Once an incident has been analyzed, its score **does not change on its own**. Unlike the ML risk score it replaces, it is not recalculated as the incident ages. The agents' score supersedes the [ML risk score](./prioritize-incidents.md#risk-score) previously used on public incidents. It is a substantially more precise assessment, and it weighs how relevant the leak is to your company rather than only the technical risk of the secret. ## Analysis tab The **Analysis** tab on the incident page holds the agents' output, in two parts. **Summary** gives you the conclusion at a glance: the verdict on your company, the company the agents identified, a short rationale, the risk score together with the reasoning behind it, and which agent concluded, when. **Investigation details** traces how the agents got there: detection, then the triage assessment, then the deep analysis when it ran. Turn to it when you want to see what the agents actually found on an incident, or to back up a conclusion before acting on it. When an incident was not promoted to deep analysis, that step is marked as skipped. ![Analysis tab of a public incident](/img/public-monitoring/remediate/agents-analysis/analysis-tab.png) ## Next steps - [Prioritize incidents](./prioritize-incidents.md) - severity rules, filtering and saved views - [Remediate incidents](./remediate-incidents.md) - act on the leaks that are related to you, and ignore the ones that are not --- ## Prioritize incidents(Remediate) ## Overview With potentially hundreds or thousands of public secret incidents to review, effective prioritization is crucial for focusing your remediation efforts on the secrets that pose the greatest risk to your organization. This guide explains the capacities available to help you identify which incidents require immediate attention and create an efficient remediation workflow. ## Risk score Each public incident carries a **risk score** from 0 to 100, where **100 indicates the highest risk**. It drives the score column, sorting and filtering in the incidents table, so sorting on it gives you an ordered queue to work through. The score is set by the agents that analyze your public incidents, alongside a **Company-related** verdict. An incident the agents rule **Unrelated** always scores 0, and an incident that has not been analyzed yet has an empty score rather than 0. See [Agents analysis](./agents-analysis.md) for what the score measures and how to work with it. :::info Progressive rollout The agents analysis is being rolled out progressively and is not enabled on every workspace yet. If the **Company-related** column and filter do not appear on your public incidents list, your workspace has not been switched yet: contact support@gitguardian.com to request it. :::
Previous behavior: the ML risk score On workspaces that have not been switched to the agents analysis, the risk score is produced by GitGuardian's machine learning model instead. The risk score is an ML-powered feature that automatically assesses the risk level of each incident on a scale of 0-100, where **100 indicates the highest risk** requiring immediate attention and **0 indicates the lowest risk**. It provides an additional layer of prioritization by analyzing multiple risk signals to help you focus on the incidents that pose the greatest threat. The risk score complements severity scoring by providing a more granular, continuously updated risk assessment. #### How the ML risk score works The risk score is calculated using machine learning models that consider various factors including: - Secret type - Validity (past or present) - Detection context (test files, sensitive files, production environment, etc.) - Secret exposure patterns - Additional contextual signals The score is dynamic and recalculates regularly to reflect changes in the incident's risk profile. #### Using risk score in your workflow :::tip We value your feedback The risk score uses machine learning models that are continuously improved based on user feedback. If you notice incidents with unexpected scores or explanations, we encourage you to share feedback directly through the dashboard — your input helps us refine the scoring model. ::: ##### In the incidents table The risk score can be used to prioritize incidents in multiple ways: **Filtering and sorting**: - **Filter by risk score range**: Use the "Risk score" filter to focus on specific risk levels (e.g., Risk score ≥ 80 for highest priority) - **Sort by risk score**: Select "Sort by Risk score" to order incidents by priority - **Use the "Critical" saved view**: This pre-configured view displays all open incidents with a risk score above 80/100, giving you quick access to the highest-priority incidents **Adding the Risk score column**: By default, the risk score column is not displayed in the incidents table. To view the actual score values: 1. Click the **Columns** button in the top-right of the incidents table 2. Find "Risk score" in the list of available columns 3. Click the eye icon to make it visible 4. The column will now appear in your table, showing the 0-100 score for each incident ![Risk score column configuration](/img/internal-monitoring/remediate/incidents/risk-score-column.png) ##### In the incident detail page When investigating an incident, you'll find the risk score at the top of the incident detail page showing: - **The current risk score** (0-100) with a visual indicator - **A detailed explanation** of what drives the score, based on the incident's context and characteristics, so you know what to prioritize. - **Feedback buttons** to help us improve the feature (thumbs up/down) ![Risk score in incident detail page](/img/public-monitoring/remediate/prioritize-incidents/risk-score-explanation-public-incident.png) **Note for Public incidents:** the ML risk score reflects the technical risk of the secret itself, not whether it's relevant to your company. To assess the real risk to your organization, combine it with company-relation indicators (such as author email domain or repository ownership). **Score evolution:** The risk score is dynamic and recalculates regularly as the incident context evolves. Changes in detection context, exposure patterns, or other risk signals may cause the score to adjust over time. Additionally, our ML model is continuously improved, which may lead to score refinements. **Providing feedback:** Your feedback helps us continuously improve the ML model. In the incident detail page, you can: 1. Review the risk score and its explanation 2. Use the thumbs up button if the score accurately reflects the risk, or the thumbs down button if the score doesn't match your assessment 3. Expand/collapse the explanation using the arrow button Feedback is reviewed by our team to regularly refine the scoring algorithm. #### ML risk score vs. severity Both tools help with prioritization but serve different purposes: | Feature | Risk Score | Severity | |---------|-----------|----------| | Calculation | ML-powered, automatic | Rule-based, can be manual | | Granularity | 0-100 scale | 6 levels (Critical to Unknown) | | Updates | Dynamic, recalculates automatically | Static unless manually changed or rules recomputed | | Best for | Granular risk assessment | Policy-based categorization |
## Severity and severity rules Severity consolidates multiple risk factors into a single, actionable priority level. Unlike the risk score, it can be customized to match your own priorities. The possible severity levels are: Critical, High, Medium, Low, Info, Unknown. ### Severity rules Severity rules automatically evaluate incidents based on various factors (secret type, organizational relevance, validity, company indicators) and assign priority levels accordingly. Your workspace comes with GitGuardian's default severity rules, which you can customize in [Settings > Severity rules](https://dashboard.gitguardian.com/settings/secrets/severity-rules) to match your organization's specific risk priorities. ![Severity rules](/img/public-monitoring/remediate/prioritize-incidents/severity-rules-public.png) When creating or editing a severity rule, you can specify whether it applies to public incidents, internal incidents (from Internal Monitoring), or both. ![Severity rules](/img/public-monitoring/remediate/prioritize-incidents/edit-severity-rule.png) :::info Some rule criteria only apply to specific incident types. For example, company-related tags are unique to Public Monitoring, so rules using these criteria will automatically disable the "internal incidents" option. ::: Incidents with "Unknown" severity indicate they haven't matched any configured severity rules—these may require manual review or additional rule configuration. ### Manual severity override You can manually edit any incident's severity to override the automatic assignment when you have additional context or disagree with the automated assessment. ## Risk score vs. severity Both tools help you prioritize, and they answer different questions. | | Risk score | Severity | |---|---|---| | Set by | GitGuardian's agents (or the ML model on workspaces not yet switched) | Your severity rules, or manually | | Customizable | No | Yes, through severity rules | | Override on a single incident | No | Yes | | Granularity | 0-100 | 6 levels, Critical to Unknown | | Best for | Ordering the queue by actual risk | Encoding your own policy | Use the risk score to decide what to look at first. Use severity when you need to encode something specific to your organization: a secret type you always treat as Critical, a rule your team has agreed on, or an assessment you have made yourself on a single incident. ## Incidents table The Public secret incidents table is where you'll apply these prioritization strategies, along with additional filtering and sorting capabilities. The table comes with several tools to help you have a clearer view on your incident list. ### Filtering and sorting Beyond the risk score and severity, the table supports filters for more targeted prioritization: - **Company relevance**: Company-related verdict, attachment reasons - **Risk indicators**: Secret validity, secret type - **Context**: GitGuardian tags, and your own custom tags Both the risk score and Company-related can be sorted as well as filtered. ### Saved views Create and save filter combinations for quick access to specific incident sets. GitGuardian provides default views to help you get started, but you can build custom [saved views](../../platform/collaboration-and-sharing/saved-views) based on your most frequently used filtering strategies. On workspaces with the [agents analysis](./agents-analysis.md), the default views for public incidents include three based on the company-related verdict. ### Custom tags Create and assign your own [custom tags](../../platform/collaboration-and-sharing/custom-tags) to mark incidents for your specific workflows. These custom tags can then be used in filters and saved views to support your organization's unique prioritization needs. ## Next Steps: From Prioritization to Remediation Once you've identified and prioritized your most critical public incidents, you're ready to begin systematic remediation. **What You Should Have After Prioritization:** - **A focused list** of high-priority incidents that clearly belong to your organization - **Risk assessment** - Understanding which secrets pose the greatest threat - **Workflow organization** - Critical incidents first, with less urgent ones planned for later - **Clear criteria** - Established rules for what constitutes immediate vs. standard priority Move to the [Remediation phase](./remediate-incidents.md) to: - Distinguish between incidents requiring immediate action vs. those that can be ignored - Engage with developers and stakeholders for confirmed threats - Follow structured remediation procedures for public exposures - Implement proper cleanup and monitoring procedures --- ## Remediate incidents(Remediate) ## Overview Effective remediation of public secret incidents requires an approach that balances urgency with informed decision-making. The key is distinguishing between incidents that require immediate security action versus those that can be safely ignored as irrelevant to your organization. ## Understanding incident outcomes Public incident remediation can result in two outcomes: ### Resolve incidents Mark incidents as **Resolved** when they represent actual security risks that you've addressed through proper remediation steps (rotating secrets, removing exposure, etc.). ### Ignore incidents Mark incidents as **Ignored** when they're not relevant to your organization—such as unrelated personal credentials or false positives. Ignoring helps clean your incident backlog so you can focus on genuine threats without feeling overwhelmed by irrelevant alerts. ## Before you remediate: investigate the incident Take time to thoroughly **investigate your incident** and assess its potential impact. It can be difficult to estimate possible damage just by examining the surrounding code. Remember that: - Sensitive data often appears in developers' personal projects - A single credential with elevated privileges can compromise an entire organization - Various applications can share the same secret - Some secrets can lead to discovering additional secrets (e.g., Slack tokens accessing shared files, GitHub tokens accessing private repositories) Use the [incident properties](./understand-incident-properties.md) to assess whether the incident truly impacts your organization. ## Involve the developer Including **the developer responsible for the incident** in the remediation process is often essential as they possess knowledge about: - What the secret provides access to - Services and applications that depend on it - Other team members who might be affected - The context surrounding the exposure GitGuardian offers two ways to collaborate with developers: ### Share public link of the incident Generate a public link that can be sent to the involved developer for feedback on the incident. This approach works regardless of whether the developer is currently part of your organization or workspace. **Use with caution**: These links are publicly accessible without requiring authentication. ### Grant access within the platform If the involved developer is both a current employee of your organization **and** a member of your GitGuardian workspace, you can grant them direct access to the incident. They'll be able to view the incident details in the Public Monitoring section and provide feedback directly through the dashboard. This is the **safer approach** since it doesn't require generating publicly accessible links, but it's only available when the developer is already a workspace member. :::info Developer workspace membership is common when organizations use Internal Monitoring, as developers are typically added to collaborate on internal security incidents. ::: ## Automate remediation with playbooks GitGuardian playbooks can automate remediation workflows for public incidents, helping you handle large volumes of incidents efficiently. Learn more about [configuring playbooks](../../platform/automate-with-playbooks/playbooks-overview.md) for your workspace. Most playbooks that work for internal incidents can also be enabled for public incidents. See the complete list of [available playbooks](../../platform/automate-with-playbooks/available-playbooks.md) and their configuration options. ## Resolving confirmed impactful incidents When an incident is confirmed as relevant and poses a security risk, here are some guidelines to take action: ### 1. Ensure that the compromised secret is revoked Once a secret appears publicly on GitHub, you must consider it compromised and ensure that it is immediately revoked. Depending on the case, this might require the involved developer's assistance. If the secret is under your direct control and used in your systems and applications, here are more detailed steps you can follow: - Vault your secret if it's not yet safely stored in a Secret Manager - Fix your application's code to properly reference the secret, if it has also been leaked in your internal codebase. - Generate new credentials to replace the exposed ones - Update all systems and applications using the old credentials - Revoke or deactivate the compromised credentials ### 2. Optionally: remove evidence Besides revoking the secret, you may want to eliminate all traces of the secret and surrounding code. This might take the involved developer's assistance to: - **Delete the repository** entirely or **make it private** - **Rewrite git history** if technically feasible :::caution Removing evidence is **optional** if the secret was successfully revoked, since it can no longer be used. However, it becomes a **necessary mitigation action** if the secret could not be revoked for any reason. ::: ### 3. Review access logs Investigate potential unauthorized access: - Check logs for suspicious activity using the compromised credentials - Look for evidence of data access, system intrusion, or lateral movement - Consider that some secrets provide access to other secrets or systems - Take additional mitigation actions if you discover further exposure ### Close the incident as "Resolved" After the remediation steps are complete, mark the incident as "Resolved" button, and document your reason by selecting the appropriate option(s): - Repository made private or deleted - DMCA takedown requested - Secret revoked ![Resolution reasons](/img/public-monitoring/remediate/remediate-incidents/resolution-reasons.png) ## Ignoring public secret incidents If your investigation determines that a particular secret leak has no link with your company, or does not present any risk, you can close the incident as "Ignored". Document the reason by selecting the appropriate option(s): - Test credential - Low risk secret - False positive (not a secret) - Developer not connected to the company - Credential not related to the company ![Ignore reasons](/img/public-monitoring/remediate/remediate-incidents/ignore-reasons.png) --- ## Public Secret Remediation Overview ## Understanding Public Secret Exposures When secrets are exposed on public platforms like GitHub, the risk landscape changes dramatically. Unlike internal incidents, public exposures mean your credentials are potentially visible to anyone on the internet, requiring a more urgent but still strategic response. ## The Public Remediation Challenge Public secret incidents present unique challenges: - **Immediate visibility**: Secrets are accessible to potential attackers right away - **Persistence**: Even after removal, secrets may exist in forks, mirrors, or cached versions - **Unknown usage**: You can't know who has accessed the secret or how it might be used - **Limited control**: You may not control all locations where the secret appears ## GitGuardian's Approach to Public Remediation Our philosophy balances urgency with effectiveness: ### 1. **Rapid Assessment** Quickly determine if the exposed secret actually belongs to your organization and poses a real threat. ### 2. **Informed Response** Even in urgent situations, take time to understand what the secret accesses before acting. ### 3. **Systematic Action** Follow a structured approach to ensure nothing is missed while working efficiently. ## Public Incident Outcomes Public remediation typically results in one of two outcomes: ### Resolve Incidents Mark incidents as **Resolved** when they represent actual security risks that you've addressed through proper remediation steps: - Rotating compromised credentials - Removing public exposure where possible - Implementing monitoring for unauthorized usage - Updating affected systems ### Ignore Incidents Mark incidents as **Ignored** when they're not relevant to your organization: - Unrelated personal credentials - Test or dummy secrets with no real access - False positives from the detection engine - Secrets already known to be revoked Ignoring irrelevant incidents helps you focus on genuine threats without feeling overwhelmed by false positives. ## Investigation Before Action Even with public exposures, **investigate before you remediate**: ### Key Questions to Answer: - Is this secret actually related to your organization? - What resources does this secret protect? - How critical are the protected resources? - Are there dependent systems that would break with immediate revocation? ### Use Available Context: - **Repository ownership**: Does the repository belong to your organization or employees? - **Commit history**: When was the secret committed? By whom? - **Code context**: What application or service uses this secret? - **Secret type**: What level of access does this credential provide? ## The Public Remediation Workflow ### For High-Risk Secrets (Immediate Action Required) 1. **Rapid Assessment** (2-5 minutes) - Verify the secret belongs to your organization - Identify what resources it protects - Check if it has elevated privileges 2. **Immediate Revocation** (5-10 minutes) - Revoke the secret through the appropriate service - Generate new credentials immediately - Update critical systems with new credentials 3. **System Updates** (15-30 minutes) - Update all applications using the old secret - Test critical functionality - Monitor for any service disruptions 4. **Repository Cleanup** (Optional) - Make repository private if you own it - Contact repository owner if you don't - Consider git history cleanup (with caution) 5. **Monitoring & Verification** (Ongoing) - Check logs for unauthorized usage - Verify all systems are functioning - Document the incident ### For Lower-Risk Secrets (Controlled Approach) For secrets that don't pose immediate critical risk, you can follow a more controlled approach similar to internal incidents: 1. **Assess Impact** - Understand the full scope 2. **Secure Storage** - Move to proper secret management 3. **Update Code** - Point applications to secure storage 4. **Test & Deploy** - Ensure everything works 5. **Rotate & Revoke** - Replace and disable the old secret ## Platform Support for Public Remediation ### Automated Assessment GitGuardian helps you quickly assess public incidents: - **Secret type detection**: Understand what kind of credential was exposed - **Validity checking**: Determine if the secret is still active - **Context analysis**: Gather information about the repository and commit ### Guided Remediation For supported secret types: - **Revocation instructions**: Step-by-step guides for disabling credentials - **Service provider integration**: Direct links to relevant management consoles - **Best practice recommendations**: Tailored advice based on secret type ### Incident Management - **Priority scoring**: Focus on the most critical incidents first - **Bulk actions**: Handle multiple similar incidents efficiently - **Progress tracking**: Keep track of remediation status across all incidents ## Collaboration in Public Remediation ### When to Involve Others **Immediate escalation for:** - Secrets with administrative access to critical systems - Database credentials for production environments - API keys with financial or payment processing access **Standard process for:** - Application-specific secrets with limited scope - Development or staging environment credentials - Secrets with well-defined, non-critical access ### External Collaboration Sometimes you need to work with external parties: - **Repository owners**: To remove secrets or make repositories private - **Service providers**: For emergency revocation assistance - **Security teams**: For organization-wide incident response ## Prevention After Remediation Once you've handled the immediate threat: 1. **Implement scanning**: Use [GitGuardian CLI](../../ggshield-docs/getting-started.md) to prevent future exposures 2. **Secret management**: Adopt proper [secrets management practices](https://blog.gitguardian.com/secrets-api-management/) 3. **Developer education**: Train teams on secure development practices 4. **Process improvements**: Update development workflows to include security checks ## Next Steps Follow the systematic approach for public incident management: 1. **[Understand Incident Properties](./understand-incident-properties.md)** - Learn to assess whether incidents belong to your organization 2. **[Prioritize Incidents](./prioritize-incidents.md)** - Focus on the most critical threats first 3. **[Remediate Incidents](./remediate-incidents.md)** - Take action on confirmed threats For emergency situations or comprehensive internal secret management, see our [Internal Monitoring Remediation Guide](../../internal-monitoring/remediate/remediation-overview.md). > **Key Takeaway**: Even with public exposures, taking a few minutes to assess and plan your response will lead to more effective remediation than immediate panic-driven actions. --- ## Investigate public incidents Before you prioritize or remediate a public secret incident, you need to know what it represents and whether it is relevant to your organization, which is the hardest part of working with public sources. This page describes the context GitGuardian provides on each incident to help you answer that. The agents' own conclusions, the **Company-related** verdict and the **risk score**, are covered separately in [Agents analysis](./agents-analysis.md). ## Secret detail Every public incident provides detailed information about the secret itself: ### Detector information The detector identifies the type of secret found. This helps you understand what service or system might be compromised. ### Secret validity GitGuardian performs [validity checks](/secrets-detection/customize-detection/validity-checks) when possible to determine if the detected secret is still active and usable. Valid secrets pose immediate security risks and, when related to your company, should be prioritized for quick remediation. ### Secret analyzer results For some detectors, when the secret is valid, our [secret analyzer](/secrets-detection/secrets-detection-engine/secrets_analyzer) provides additional context about the secret's permissions and scope. This analysis helps you understand the potential impact if the secret were to be exploited. ## Occurrences detail The table of occurrences provides you with the detailed information you need: - **Author identity**: The Git author name and email associated with the commit - **Commit timestamp**: When the secret occurrence was committed - **Repository**: The GitHub repository where the secret was found - **Commit hash**: The specific commit containing the secret - **File path**: The exact file and location within the repository - **Patch preview**: A code snippet showing the secret in context (may be hidden for large patches) - **GitHub link**: Direct link to view the occurrence on GitHub (when still publicly visible) - **Presence indicator**: Shows whether the occurrence is still visible on public GitHub. The value "removed from GitHub" typically indicates that the repository has been deleted or made private after the leak, or that the commit itself has been deleted. :::caution The fact that the occurrence has been erased from GitHub does not mean that the incident is resolved! Indeed a malicious actor could have cloned the repository and seen the secret before it was erased from GitHub. ::: ## Attachment reasons Attachment reasons explain why GitGuardian associated a public secret incident with your organization. Understanding these reasons helps validate the relevance of each incident: - **By developer from perimeter**: One of your monitored developer is involved in the secret incident. - **On organization from perimeter**: The secret incident happened on a repository of one of your monitored GitHub organizations. - **From secret grasper**: The secret incident was attached to your company thanks to a [secret grasper](../perimeter/secret-graspers.md) in the commit. :::info Attachment reasons provide insight into the probability that a leak is related to your organization. Incidents attached "By developer from perimeter" may contain company secrets, but could equally be unrelated personal credentials from your developers. In contrast, incidents leaked "On organization from perimeter" are company-related since they originate from your organization's repositories. ::: ## Tags and contextual information GitGuardian automatically applies tags to each incident to surface useful details about the leak and where it was found. They are clues rather than conclusions, and they can be used in filters and saved views. - **Company domain in commit**: One of your monitored domains appears in the file content of the occurrence. - **Company name in commit**: Your company name appears in the patch where the secret is leaked. - **Secret grasper in commit**: One of your defined secret graspers (which can be seen as company-specific identifiers) appears in the occurrence patch. - **Internally leaked**: This tag (only available if you also have Internal Monitoring) indicates that the same secret has been found in an internal incident within your monitored sources. The [exploration map](#exploration-map) will show you the related internal incident. In Internal Monitoring, this relationship is shown as the **Public incident linked** exposure type on internally leaked secrets. See [Public exposure information](/internal-monitoring/remediate/investigate-incidents#public-exposure-information) for more details. - **Sensitive file**: One of the occurrences of the incident happened on a potential sensitive file - **Production**: The commit associated with one of the occurrences seems related to a production environment. - **Test file**: One of the occurrences of the incident happened on a potential test file. A file is automatically classified as a test file if its path contains any of the following patterns (with only numbers or special characters around them): test/tests, example/examples, mock/mocks, fixture/fixtures, fake, dummy, false, or testdata. For example, .test.env or 00testdata.json will match, but dummydata.json will not. - **False positive**: GitGuardian's ML engine has identified this as likely not being an actual secret. These incidents can typically be safely ignored. (Learn more [here](../../secrets-detection/secrets-detection-engine/machine_learning.md#false-positive-remover)) - **From historical scan**: The incident was discovered during a historical scan rather than through real-time monitoring. :::note Previous behavior On workspaces not yet switched to the agents analysis, a **Context related to company** tag also appears: GitGuardian's ML engine flags leaks whose surrounding context looks related to your company, based on company-specific terms or enterprise-grade indicators. The agents analysis supersedes it. ::: ## Exploration map :::info This feature provides the most value when you also use [Internal Monitoring](../../internal-monitoring/home), [NHI Governance](../../nhi-governance/home), or have integrated with your secret managers using [GitGuardian Scout](../../ggscout-docs/integrations/secret-managers) for comprehensive context. ::: The exploration map provides a visual representation of where GitGuardian has detected this specific secret across your integrated sources and what access it potentially grants. ![Exploration map](/img/public-monitoring/remediate/understand-incident-properties/exploration-map.png) The map can reveal: - **Internal incidents** (if you use Internal Monitoring): Whether the secret also appears in your internal codebase, JIRA tickets, Slack messages, or other internal sources - **Secret manager storage** (if you've integrated secret managers): Whether the secret is stored in your vaults or secret managers - **Infrastructure usage** (if you use NHI Governance with infrastructure integrations): Whether the secret is used in infrastructure sources like GitLab CI or Kubernetes clusters :::caution A strong company-related signal **For public secret incidents, an exploration map showing multiple nodes is strong evidence that the secret truly belongs to your company and requires immediate remediation.** ::: ## ML-powered similar incident grouping GitGuardian automatically groups incidents that share similar characteristics, so you can spot recurring patterns and handle related incidents together. On a public incident you get a **Similar incidents** section in the sidebar, a sortable **Similar incidents** column in the incidents table, and a `similar_to` search operator. See [similar incident grouping](../../secrets-detection/secrets-detection-engine/machine_learning.md#similar-incident-grouping-ml-powered) for how the grouping works. --- ## Public Monitoring for self-hosted installations Public Monitoring is available on self-hosted GitGuardian installations starting with the **2026.7** release. This page explains how the feature works on a self-hosted instance, how to enable it, and the network requirements it introduces. :::info Public Monitoring is a business feature that requires a specific license. [Contact us](https://www.gitguardian.com/contact-us) for availability and pricing information. ::: :::info For a general introduction to the feature, see [Public Monitoring core concepts](./core-concepts.md). ::: ## How Public Monitoring works on self-hosted Unlike most GitGuardian capabilities, Public Monitoring does not scan public sources from your own instance. Public sources (public GitHub, DockerHub, and others) are continuously scanned by GitGuardian's hosted Public Monitoring service. Your self-hosted instance connects to that service to retrieve the public secret incidents that match your company's public perimeter. Two consequences follow from this model: - **Your public perimeter is defined and stored on GitGuardian's side**, within the hosted Public Monitoring service, not on your self-hosted instance. The instance retrieves the incidents that match it. - **The connection is always outbound and initiated by your instance.** GitGuardian never initiates a connection into your self-hosted instance. :::caution Requires outbound network access Public Monitoring relies on outbound connections to GitGuardian's Public Monitoring service. Your instance must be able to reach the domains listed under [Network requirements](#network-requirements). A fully isolated installation that cannot reach them cannot use Public Monitoring. ::: ## Enabling Public Monitoring on self-hosted Enabling Public Monitoring on a self-hosted instance is a two-part process: GitGuardian enables it on your license, then an administrator completes the setup from the Admin area. ### 1. Request activation and synchronize your license Public Monitoring is controlled by a dedicated license field that is **disabled by default**. To enable it, contact your GitGuardian representative or support@gitguardian.com. Once GitGuardian has enabled the field, ensure the application's [license is synchronized accordingly](/self-hosting/license-management). After synchronization, a **Public monitoring** page becomes available in the Admin area, under **Settings**. ### 2. Configure the connection GitGuardian provides you with a pair of credentials (a **Client ID** and a **Client secret**) that your instance uses to authenticate against the hosted Public Monitoring service. 1. Open the Admin area of your GitGuardian dashboard (administrative rights required). 2. Go to **Settings > Public monitoring**. 3. Click **Edit**, enter the **Client ID** and **Client secret** provided by GitGuardian, and click **Confirm**. Once the credentials are saved, a confirmation message appears and your instance begins retrieving public secret incidents that match your perimeter. ## Health checks Your instance continuously verifies that the integration is correctly configured and reachable. These checks appear on the **Health Checks** page in the Admin area: - **Credentials**: confirms the Public Monitoring credentials are set. - **Connectivity**: confirms the credentials are valid and the hosted Public Monitoring service is reachable. Use these checks to confirm the integration is healthy after setup, and to diagnose it later if incidents stop being retrieved. ## Showing and hiding the module Once Public Monitoring is set up, you can hide the module from your workspace using the **Deactivate Public Monitoring** option in the product. While the module is hidden, **incident synchronization continues in the background** so no data is lost, but the module is removed from your workspace and Public Monitoring notifications are paused. You can show the module again at any time. ## Network requirements Public Monitoring requires your instance to make **outbound** HTTPS (port 443) requests to the following domains. These must be allowlisted in your firewall and, if applicable, your [HTTP proxy](/self-hosting/management/infrastructure-management/proxy-server). See [Network requirements](/self-hosting/network-requirements) for the general self-hosted network model. | Protocol | Port | Source | Destination | Description | | -------- | ---- | ------------- | ---------------------------------------- | -------------------------------------- | | TCP | 443 | All K8S nodes | `enterprise.gitguardian.com` | GitGuardian Public Monitoring API | | TCP | 443 | All K8S nodes | `gitguardian.auth0.com` | Authentication | | TCP | 443 | All K8S nodes | `gg-gpm-incidents-prod.s3.amazonaws.com` | Retrieval of public secret incidents | --- ## DockerHub :::info Limited availability DockerHub monitoring is currently available to selected workspaces. Contact your Customer Success Management team to request access. ::: GitGuardian Public Monitoring scans public DockerHub container images to detect secrets exposed inside them. Secrets frequently end up baked into image layers - in build artifacts, configuration files, or environment data - where they remain accessible to anyone who pulls the image. ## What we scan GitGuardian analyzes the **layers** of public DockerHub images - the filesystem layers that make up an image - and detects secrets in their content. ## Scan model **Continuous ingestion, one-off attachment.** GitGuardian continuously ingests public DockerHub data into its own database. When DockerHub monitoring is enabled for your workspace, GitGuardian runs a one-off pass that matches the stored occurrences against your [perimeter](../perimeter/overview.md). This attachment is a point-in-time operation: it covers the data ingested up to the day it runs, and it is not re-run automatically yet. Occurrences ingested afterwards are not attached to your perimeter until ongoing scanning is available - see [Limitations](#limitations). ## Attachment reasons A secret found on DockerHub is attached to your company through your [perimeter](../perimeter/overview.md) when it matches one of: - **Secret grasper** - a [secret grasper](../perimeter/secret-graspers.md) from your perimeter is found in the image content. This is the most common reason. - **Domain in secret value** - a domain from your perimeter appears inside the secret value itself. - **Domain in owner profile** - the DockerHub account that published the image has a domain from your perimeter in its public profile (for example, in the account's public email). The match is made on the published account's metadata, so the publisher does not need to be one of your monitored developers. In the dashboard, these incidents appear under the *By dev from perimeter* attachment reason. ## Incident context DockerHub incidents differ from GitHub incidents in the context they provide. Instead of a commit author and commit, you see: - the **image owner account** (user or organization), - the **image and repository**, - the **layer** the secret was found in. :::info Occurrence date For findings dated **January 2025 onward**, the occurrence date is **precise** - it reflects when the secret was actually exposed on DockerHub. For older findings, treat the date with caution: it may reflect GitGuardian's historical backfill rather than the original exposure. ::: ## Limitations - **Continuous monitoring - coming soon.** For now, attachment runs as a point-in-time historical scan over the DockerHub data ingested up to that point (not re-run automatically yet). Ongoing, incremental scanning of new content is on the way. - **No presence checks.** GitGuardian does not yet verify whether a secret is still publicly exposed on DockerHub, so these findings carry an **Unknown** presence status rather than a checked one. - **Large file contents are skipped.** File contents larger than ~10 MB within an image are excluded, so a fraction of image content is not scanned. --- ## GitHub GitHub is monitored across several content surfaces. Public commits are the primary surface and are monitored continuously; public gists are also monitored, through a historical scan. ## Commits **What we scan:** public commits on GitHub. **Scan model:** - *Real-time*: public commits are scanned continuously as they are published. Most incidents are created and alerted within about 10 minutes of the commit. Some commits are detected later. Each incident carries two dates: the occurred date, when the commit was pushed to GitHub, and the detected date, when GitGuardian detected the secret and created the incident. - *Historical*: a historical scan runs when your Public Monitoring dashboard is initialized, to catch secrets exposed before monitoring began. **Attachment reasons:** a commit is attached to your company through your [perimeter](../perimeter/overview.md) when it matches one of: - a [monitored developer](../perimeter/developers.md) - the commit author belongs to your perimeter, - a [monitored GitHub organization](../perimeter/github-organizations.md), - a [secret grasper](../perimeter/secret-graspers.md) found in the commit content. :::info Secret graspers limitation [Secret graspers](../perimeter/secret-graspers.md) only apply to real-time monitoring, not to historical scans. They are monitored from the moment they are created, with no retroactive scanning of past activity. ::: **Coverage limits:** two limits apply to what GitGuardian retrieves from a commit. - *File size*: a file larger than 1 MB is not retrieved and is not scanned. - *Files per commit*: up to 200 files per commit are retrieved. Files beyond that are not retrieved. ## Gists **What we scan:** public gists on GitHub. **Scan model:** historical only. GitGuardian has run a historical scan of public gists. Gists are not yet monitored as new ones are published. **Attachment reasons:** gists are currently attached to your company through [monitored developers](../perimeter/developers.md) only - the gist author belongs to your perimeter of monitored GitHub developers. Organization attachment does not apply to gists, since gists belong to individual accounts rather than organizations. Secret-grasper attachment is not supported on gists yet. --- ## Monitored public sources GitGuardian Public Monitoring continuously scans public GitHub for exposed secrets related to your organization. It is now expanding beyond GitHub to cover additional public sources, starting with DockerHub. Each source is described by the same four characteristics: - **What we scan** - the type of public content we analyze on that source (for example, commits or container image layers). - **Scan model** - how the source is covered over time: - *Real-time*: new content is scanned as it is published. - *Historical*: existing public content is scanned, as opposed to new content as it appears. - **Attachment reasons** - the rules that attach a detected secret to your company. Each source supports a subset of these rules, depending on the data it exposes. See [Company public perimeter](../perimeter/overview.md) for how attachment works. - **Availability** - whether the source is generally available or in limited availability. ## Supported sources | Source | What we scan | Scan model | Attachment reasons | Availability | |--------|--------------|------------|--------------------|--------------| | **GitHub** - Commits | Public commits | Real-time + historical | Developer · Organization · Secret grasper | Generally available | | **GitHub** - Gists | Public gists | Historical only | Developer | Generally available | | **DockerHub** - Image layers | Public image layers | Historical only | Secret grasper · Domain in secret value · Domain in owner profile | Limited availability | For the specifics of each source, see: - [GitHub](./github.md) - commits and gists - [DockerHub](./dockerhub.md) - public container image layers :::info Limited availability Sources marked as *Limited availability* are currently enabled for selected workspaces. Contact your account team to request access. ::: --- ## Secure secrets management ## Managing secrets in the SDLC ### There's no silver bullet Secrets are so widely used in DevOps environments that there simply can’t be a one-size-fits-all for managing them. We have development secrets used by developers, build secrets, application secrets, infrastructure secrets, etc. Even for the most mature DevSecOps organizations or teams, secrets management is very difficult to master, because it is a matter of striking a right balance between security and accessibility. This second point is very important for one simple reason: in modern development teams, secrets are required by everyone. Making it hard to use secrets will inevitably lead to the bypassing of the protective layers in place, and lead to practices such as hardcoding them. In practice, it is easy to see that there is a gap between theory and practice when it comes to handling and sharing credentials in a team, a department, or an organization. For example, the organization may pay for a cloud-based secrets manager, a vault, or maybe even for a dedicated team to administrate these tools, which makes it falsely think it has solved this problem. But under further scrutiny, it would realize that the long-lived credentials are also stored on the devs’ local machines for convenience. ### Find your way to secure secrets management There are various ways with which secrets can be managed in the software development lifecycle. You should explore the following options with infrastructure and engineering teams before deciding which one is the right approach for your organization: - ~~Hardcoded in source code and templates~~ (please, don't.) - Grouping secrets in common, unencrypted configuration files, such as `.env` (outside of the git repository) - Encrypting secrets in a GitOps or sealed secrets approach, with decryption key stored in a vault - Storing secrets in a vault and distributing them through a secrets management service - Generating dynamic secrets, through a complex secrets management infrastructure ## The problem of hardcoded secrets ### Are hardcoded secrets a vulnerability? [OWASP](https://owasp.org), the Open Web Application Security Project foundation that works to improve the security of software, lists hardcoded secrets as one of its famous list of the [Top 10 Web Application Security Risks](https://owasp.org/Top10). The vulnerability ranked #2 in the latest edition published in 2021, under the [Cryptographic Failures (A02:2021)](https://owasp.org/Top10/A02_2021-Cryptographic_Failures/) entry. MITRE, famous for its [ATT&CK](https://attack.mitre.org) knowledge base of adversary tactics and techniques, also lists the use of hardcoded credentials in its [CWE Top 25 Most Dangerous Software Weaknesses](https://cwe.mitre.org/top25/archive/2022/2022_cwe_top25.html). The vulnerability ranked #15 in the 2022 edition, under [CWE-798 – Use of Hard-coded Credentials](https://cwe.mitre.org/data/definitions/798.html). ### What makes hardcoded secrets different? Hardcoded secrets is a unique vulnerability in source code when compared to other vulnerabilities found through static or dynamic analysis. Regardless of whether the code is compiled and in runtime or not, hardcoded secrets represent a risk in themselves. Attackers who gain initial access to a repository can traverse all its branches and commit history to look for valid secrets. It does not matter if a secret is found on the deployed main branch or a short-lived bugfix branch, as long as it is valid and gives access to a resource (e.g. a server, a database, a third-party API). ### Secrets sprawl is a pervasive problem Developers write code with the best of intentions, but they still end up compromising credentials and sensitive data. With 6 million secrets exposed on public GitHub in 2021 and a lot more in the private repositories, our research in the [State of Secrets Sprawl 2022 report](https://www.gitguardian.com/state-of-secrets-sprawl-report-2022) shows that this problem is much more common than developers and security engineers think. ## The solution: automated detection and remediation Detecting secrets in source code is like finding needles in a haystack: there are a lot more sticks than there are needles, and you don’t know how many needles might be in the haystack. In the case of secrets, you don’t even know what all the needles look like! A high-performing automated scanner will be able to achieve: - A low number of false alerts raised. We call this **high precision**. Precision answers the question: "What is the percentage of the secrets that you detect that are actual secrets?". This question is legitimate, especially in a context where security teams have to deal with alert-fatigue. - A low number of secrets missed. This is what we call **high recall**. Considering that a single undetected credential can have a big impact for an organization, some organizations prefer to triage more false alerts but make sure they don’t miss a secret. Balancing the equation to ensure that the algorithm captures as many secrets as possible without flagging too many false results is an intricate and extremely difficult challenge GitGuardian takes care of for its users. GitGuardian builds and maintains a secrets detection engine with 600+ specific types of secrets covered in addition to support for generic and custom patterns. --- ## What is a secret? In everyday language, a secret can be any sensitive data that we want to keep private. When discussing secrets in the context of software development, secrets generally refer to digital authentication credentials that grant access to systems or data. These are most commonly API keys, usernames and passwords, or security certificates. Secrets exist in the context of applications that are no longer standalone monoliths. Applications nowadays rely on thousands of independent building blocks: cloud infrastructure, databases, third-party APIs and services such as Stripe, Slack, HubSpot… Secrets tie together the different building blocks of a single application by authenticating each component against one another. ## What do secrets look like? Secrets are typically high entropy strings which means that they are strings or text that are very random in value. Some API keys can be pre or post fix which means they share the same characters at the start or at the end of the string but most secrets aren’t and are just a highly randomized value that contains different types of character. ### Examples Below is an example of a **specific secret**, a GitHub personal access token: ```yaml - text: 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 apikey: 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 ``` As you can notice the secret is prefixed with the `ghp` string. Below is another example of a secret, this time a **generic** one in the form of a Base64 basic auth string: ```yaml - text: | "Authorization": "Basic aW50ZXJuc2hpcDpjZGk=" username: aW50ZXJuc2hpcD # decodes to `internship` password: pjZGk # decodes to `cdi` ``` --- ## Where should you scan for secrets in the SDLC? We recommend you add automated secrets scanning wherever you can, at every stage of the SDLC. Throwing as many nets as possible builds a layered defense and removes the dangers of having one single point of failure. We believe this should be the pursued strategy by every organization looking to reduce the risk of exposure of its secrets. Counter-intuitively, this layered approach adds little friction and can help you achieve wide-scale adoption from your developers. We recommend starting with continuous monitoring for your VCS instances (server-side). Results at this level are more informative and non-blocking. As you get used to handling these results, you can incrementally increase the level of restriction, up to the point where it feels more accurate and in line with your organization. With GitGuardian, you will be able to gradually move secrets scanning upstream until you reach developer environments (client-side). 1. Start with continuous scanning for your remote repositories using the available native VCS integrations. It is an easy setup and guarantees your security team(s) total visibility over an evolving perimeter since repositories get created and deleted every day. 2. Add automated scanning jobs in CI environments to test supporting branches such as feature, release, and hotfix; before merging into the main one. 3. Configure developer workstations to scan local changes thanks to the pre-commit git hook and ggshield CLI. It prevents secrets from leaving developer workstations in the first place. 4. If you run your own self-hosted VCS instances, you can leverage a globally configured pre-receive git hook to block secrets from entering centralized repositories. --- ## Detector settings You can find the exhaustive list of GitGuardian secrets detectors in the [settings](https://dashboard.gitguardian.com/settings/secrets/detectors) of your workspace. ![Table of secrets detectors](/img/secrets-detection/customize-detection/secrets-detection-table-of-detectors.png) ### Activate or deactivate detectors In [your workspace settings, on the detectors page](https://dashboard.gitguardian.com/settings/secrets/detectors), you can activate or deactivate secrets detectors on an individual basis to refine your focus on incidents. When you deactivate a detector: - you will not receive a notification for incidents that this detector raises, - incidents for deactivated detectors will not be displayed in your dashboard. However, the detector will still detect and store such incidents shall you reactivate the detector later. ### Custom detectors It is not possible to customize the detectors provided with the GitGuardian library. However, you can create your own custom detectors using regular expressions. Please note that this feature is only available for workspaces under our Business plan (or in Business trial). :::info This feature is designed to help you detect secrets specific to your organization (e.g internal API tokens), **all requests for detecting patterns like Personal Identifiable Information (PII) or Protected Health Information (PHI) will be rejected**. ::: #### Submit your custom detector request 1. Navigate to Settings > Secrets > [Detectors](https://dashboard.gitguardian.com/settings/secrets/detectors?sort_f=true) 2. In the navigation bar, click `Table of Detectors` (or scroll down until you get there) 3. Click `Add a custom detector`, a modal will open ![Add a custom detector](/img/secrets-detection/customize-detection/secrets_detection_custom_detector_1.png) 4. Enter the details for your new custom detector: - You must at least provide the name for your detector, and a set of examples for the format of your internal secret pattern. - If you have the regular expression for the desired pattern, please provide it. - You can provide additional information on the pattern, surrounding content or additional match requirements for the secret format you're after. ![Add a custom detector - form](/img/secrets-detection/customize-detection/secrets_detection_custom_detector_2.png) ![Add a custom detector - ticket](/img/secrets-detection/customize-detection/secrets_detection_custom_detector_3.png) > Only Managers can create custom detector requests. > > Please note that every workspace is only allowed to have 5 custom detector requests at a time. To place a new request, you will have to wait until one of your requests is accepted or rejected, or you can simply delete one of your `submitted` requests. #### Leverage your custom detector After submitting your request, our engineering team will promptly acknowledge it and reach out to you for validation of the regular expression. Given the complexity of regular expressions and the potential for high-volume alerts, it is crucial that we thoroughly review the results produced by your custom pattern. This ensures the delivery of precise and highly accurate alerts before deploying it to your workspace. > Requests in the `submitted` state can be modified or deleted. However, requests in the `acknowledged` or `under implementation` state cannot be deleted. Once the implementation of your custom detector is complete, the GitGuardian team will notify you, and your new detector will be ready for detection. ![Add a custom detector - table filtered](/img/secrets-detection/customize-detection/secrets_detection_custom_detector_4.png) #### If you are using a GitGuardian self-hosted instance :::caution Custom detectors are available for self-hosted instances starting version 2023.9.0. ::: If you are using a GitGuardian self-hosted instance, the procedure mentioned above undergoes slight modifications due to the inherent constraints of self-hosting: 1. Your request should be sent to the email address indicated in the final modal of the request procedure. ![Add a custom detector - Manual sending for self-hosted](/img/secrets-detection/customize-detection/secrets-detection-custom-detector-self-hosted-manual-sending.png) 2. upon finalization of your custom detector implementation by our R&D team, you will receive a YAML file that needs to be uploaded to complete the creation of your custom detector. ![Add a custom detector - YAML uploard](/img/secrets-detection/customize-detection/secrets-detection-custom-detector-self-hosted-yaml-upload.png) > If you delete the request before the upload of the YAML file, a brand new request must be submitted. > Ensure that you first import the YAML file to your staging instance for validation. Once satisfied, import it to your production environment. --- ## Exclusion rules ## Filepath exclusions By scanning your entire git history, or simply due to your software development activity, you could have many incidents on your GitGuardian dashboard. **Decreasing the number of incidents and focusing only on those that matter** most is therefore key. This feature only applies to secrets incidents. ### Description In [your workspace settings, under the Secrets detection section](https://dashboard.gitguardian.com/settings/secrets/filepath-exclusions), you can **configure the filepaths you want to exclude from secrets detection**. You can link specific repositories to these excluded filepaths, ensuring that the exclusion only applies to those repositories. When a secret is leaked on an excluded filepath: - you will not receive any notification, - no incident will be created in your dashboard. Note that **newly created filepath exclusions will also apply to existing secret incidents** and these would therefore be removed from your secret incidents table. ![Filepath exclusion](/img/secrets-detection/customize-detection/filepath_exclusion.png) You have the ability to test a filepath against your exclusion list to verify your configuration. ### Filepath format The filepath format is a **subset of the glob-style pattern**. It uses the **“/” character to separate each element of the path (POSIX norm)**, and allows the **special “\*” character as a wildcard**. Additionally, the “\*\*” sequence can be used to recursively match any number of directories. | PATTERN | CORRESPONDING REGEX | MATCHES | NON-MATCHES | | :----------------------- | :------------------------ | :-------------------------------------------------------------- | :-------------------------------------- | | test.py | `test\.py$` | src/tests/test.py | src/test/file.pysrc/test.py/README | | tests/\*.py | `tests/([^/]+)\.py$` | src/tests/test.pysrc/tests/file.py | src/test.pysrc/test.txt | | /tests/\*.py | `^tests/([^/]+)\.py$` | tests/test.py | src/tests/test.py | | /\*/test.py | `^([^/]+)/test\.py$` | src/test.py | test.pysrc/tests/test.py | | src/\*\*/test.py | `src/([^/]+/)*test\.py$` | src/test.pysrc/dir1/dir2/dir3/test.pydir1/src/test.py | dir1/dir2/dir3/test.py | | /src/\*\*/test.py | `^src/([^/]+/)*test\.py$` | src/test.pysrc/dir1/dir2/dir3/test.py | dir1/src/test.py | | \*\*/templates/ | `templates/` | templates/file.htmlsrc/templates/file.html | src/file.html | > If you misuse the glob-style pattern, GitGuardian will automatically correct your input. For instance: - ``src/**/**/**/tests/`` will be corrected to ``src/**/test`` - ``**/src/**`` will be corrected to ``src/`` ## Filepath suggestions To focus on the most relevant secrets, here are some **suggested filepath exclusions**: ### Documentation and static content Documentation files rarely contain secrets: - `**/docs/**` - Documentation directories - `**/README*` - README files - `**/*.md` - Markdown files - `**/*.rst` - reStructuredText files - `**/CHANGELOG*` - Changelog files - `**/LICENSE*` - License files ### Test and mock data Test files may contain fake secrets that shouldn't trigger alerts: - `**/test/**` - Test directories - `**/tests/**` - Test directories alternative - `**/*test*` - Files with 'test' in the name - `**/mock/**` - Mock data directories - `**/*.test.*` - Test files - `**/*.spec.*` - Specification/test files ### Package manager files Dependency files typically don't contain secrets: - `**/package-lock.json` - npm lock file - `**/yarn.lock` - Yarn lock file - `**/Pipfile.lock` - Python Pipfile lock - `**/poetry.lock` - Python Poetry lock file - `**/Gemfile.lock` - Ruby Gemfile lock - `**/go.sum` - Go modules checksum file :::warning Review your exclusions Always review your exclusions periodically to ensure they still align with your project structure and security requirements. ::: ## Secret pattern exclusion ### Description In [your workspace settings, under the Secrets detection section](https://dashboard.gitguardian.com/settings/secrets/secret-pattern-exclusions), you can **configure the secret pattern you want to exclude from secrets detection**. You can link specific repositories to these excluded secret pattern, ensuring that the exclusion only applies to those repositories. The secret pattern you define must use the regular expression pattern. When a secret pattern is triggered: - you will not receive any notification, - no incident will be created in your dashboard. Note that **newly created secret pattern exclusions will also apply to existing secret incidents** and these would therefore be removed from your incidents table. ![Secret Pattern Exclusion](/img/secrets-detection/customize-detection/secret_pattern_exclusion.png) You have the ability to test a secret pattern coverage. --- ## Validity checks ### How validity checks work To provide you with high-precision alerts, GitGuardian tries to **verify the validity of secrets through non-intrusive API calls made to the host, if and when possible**. ![Secret validity preview and filter](/img/internal-monitoring/remediate/incidents/secret_validity_filter.png) The validity check can return 5 possible values: - **valid:** the secret can still be exploited and needs to be revoked and rotated . - **invalid:** the secret has been revoked. - **failed to check**: GitGuardian was not able determine the validity of the secret. It happens when it is not possible to distinguish the error caused by an invalid secret and an IP allowlist or another mechanism preventing the validity check. It can also mean the service provider is temporarily unavailable. - **cannot check:** the service provider or the secret type do not allow for checks by GitGuardian. This status is also displayed when secret validity checks are disabled by a workspace Manager. - **unknown:** GitGuardian has recently introduced a validity checker, this secret’s validity has not been verified yet. GitGuardian automatically runs the secret validity checks in the background. The frequency of these checks depends on your plan and the status and age of secret incidents: | Plan | Incident status | Incident age | Frequency | | -------- | --------------- | -------------------- | ----------- | | Business | Open | Less than a year old | Daily | | Free | Open | Less than a year old | Weekly | | Business | Open | More than a year old | Weekly | | Free | Open | More than a year old | Monthly | | Business | Ignored | Less than a year old | Monthly | | Free | Ignored | Less than a year old | Half-yearly | | Business | Ignored | More than a year old | Half-yearly | | Free | Ignored | More than a year old | Never | | Business | Resolved | Less than a year old | Monthly | | Free | Resolved | Less than a year old | Half-yearly | | Business | Resolved | More than a year old | Half-yearly | | Free | Resolved | More than a year old | Never | > If you use GitGuardian self-hosted, you can change these frequencies in your [admin area](../../self-hosting/management/application-management/admin-area.md). ### Enabling and disabling validity checks It is possible to disable the validity checks for the entire GitGuardian workspace. New secrets that could be marked as `valid` or `invalid` will have their validity set to `unknown` since their associated validity checker is toggled off. Re-enabling the validity checker will trigger the verification process on all existing incidents, if and when possible. ![Secrets detection settings](/img/secrets-detection/customize-detection/secrets_detection_global_validity_checks.png) Please note that these settings also apply to the API and ggshield. Detectors requiring validity checks to be enabled to be active will be deactivated and the rest of the detectors will return the value `unknown` for secrets validity checks. :::caution However, please be advised that **some detectors require validity checks to be enabled to be active**. If you choose to keep validity checks globally disabled, these detectors will be deactivated and will no longer raise any incidents. To verify if a detector requires validity checks to be enabled to raise incidents, go to the detector's dedicated page in the [Secrets Detection documentation](../../secrets-detection/secrets-detection-engine/detectors/supported_credentials) and look for the flag `Only valid secrets raise an alert: True` (eg: [Agora API keys](../../secrets-detection/secrets-detection-engine/detectors/specifics/agora_api_keys.md)). ![Secret detector only valid true](/img/secrets-detection/customize-detection/secrets_detection_global_validity_detector_valid_only_true.png) ::: ### Customize validity checks GitGuardian allows customization of validity checks for certain detectors by specifying a custom host. Consider the [`GitLab token`](../../secrets-detection/secrets-detection-engine/detectors/specifics/gitlab_token.md) detector. By default, it checks secrets against `gitlab.com` (GitLab SaaS). However, if you have a self-hosted GitLab instance, you can provide the URL of your instance. GitGuardian will then verify any detected `GitLab token` secrets against your self-hosted environment. A validity checker endpoint includes: - a host - a path You **only need to provide the host**. GitGuardian uses the same path as the default host for the custom check. So let's say that the validity checker of the GitLab token is `https://gitlab.com/the-route-to-check-the-validity`. You simply need to provide the host (eg: `https://my_gitlab.self_hosted_instance.corp`) and GitGuardian builds the validity checker `https://my_gitlab.self_hosted_instance.corp/the-route-to-check-the-validity`. ![Secret detector custom host](/img/internal-monitoring/remediate/custom-host-for-validity-check/secret_detector_custom_host.png) When you submit a custom host for validity checks, all previously detected secrets for that detector will be re-checked against the new host. This ensures that you have the most accurate validity information. ![Secret valid on custom host](/img/internal-monitoring/remediate/custom-host-for-validity-check/secret_valid_on_custom_host.png) :::info Only detectors that support validity checks and have the attribute `On-premise instance exist: True` can be customized with a custom host URL for validity checks. ![Secret detector eligible for custom host](/img/internal-monitoring/remediate/custom-host-for-validity-check/secrets_detector_eligible_for_custom_host.png) If you are under Business plan, you can see the list on the eligible detectors in the [table of detectors](https://dashboard.gitguardian.com/settings/secrets/detectors). ![Table of detectors eligible for custom host](/img/internal-monitoring/remediate/custom-host-for-validity-check/table_of_detectors_eligible_to_custom_host.png) ::: > Custom hosts for validity checks are only available for workspaces under our Business plan. ### Set your own validity status by API Some credentials are out of reach of GitGuardian's checks. Secrets belonging to your internal services, your in-house platforms and your proprietary APIs, or matched by your own custom detectors, have no validity checker at all: they are reported as **cannot check**. Secrets whose host GitGuardian has no network path to are reported as **failed to check**. Neither status answers the question your team is asking. If you can determine their validity yourself, with your own tooling, your credential inventory or your secrets manager, you can report that result to GitGuardian through the public API: - [Get the validity of a secret](https://api.gitguardian.com/docs#tag/Secrets/operation/get-secret-validity) — read the current validity, and the status you set if there is one. - [Override the validity of a secret](https://api.gitguardian.com/docs#tag/Secrets/operation/set-secret-validity-override) — declare it `valid`, `invalid` or `failed_to_check` based on your own check. - [Remove the validity override](https://api.gitguardian.com/docs#tag/Secrets/operation/remove-secret-validity-override) — hand validity back to GitGuardian. See the [public API reference](https://api.gitguardian.com/docs) for request and response details. You need a [personal access token](../../api-docs/personal-access-tokens.md) with the `secrets:write` scope to set or remove a status, or `secrets:read` to read one — the secrets scopes cannot be granted to a [service account](../../api-docs/service-accounts.md) — and access to the incident the secret belongs to. The status you set becomes the validity of the secret everywhere GitGuardian uses validity: the incident list and validity filters, severity and risk scoring, playbooks, notifications and exports. While it is set, GitGuardian pauses its own periodic checks on that secret. Removing it restores the last status GitGuardian had determined itself and triggers a fresh check. On the incident, the field is labelled **Custom validity** with the date it was set, so your team can tell your result apart from GitGuardian's. Setting and removing are recorded in the incident activity log and in your [audit log](../../platform/enterprise-administration/audit-log.md). ![Custom validity on the secret details of an incident](/img/internal-monitoring/remediate/incidents/secret_custom_validity.png) :::caution **A custom validity status applies to the secret, not to the incident you set it from.** Validity is a property of the credential itself. If the same secret was detected in several repositories, every incident tied to it takes the status you set, in Internal Monitoring and in Public Monitoring alike, and across team perimeters. There is no per-team override: setting one is a workspace-wide decision, even when it is made from a single team's incident. Before overriding a shared secret, make sure the conclusion holds for every environment it is used in — a credential can be revoked on one host and still be live on another. ::: :::info The secret must be attached to at least one Internal Monitoring incident you can access. A secret that only exists in Public Monitoring cannot be the target of a custom validity status. When the same secret exists in both, the status applies to the secret itself, so the Public Monitoring incident displays the custom validity too. Custom statuses are set one secret per call. GitGuardian does not run your check for you, it records the result you determined. ::: --- ## Encrypted Secrets ## What are encrypted secrets? Encrypted secrets are secrets which are not stored in clear-text: they are encrypted using a key stored in a secured area. Those are safe to share publicly. As such, GitGuardian strives not to report encrypted secrets as leaks. ## Heuristics we use Since we don't want to report encrypted secrets as leaks, we have to identify which secrets are encrypted: at first glance, an encrypted secret might seem very similar to an unencrypted one. Here are different heuristics we use to identify encrypted secrets. Note that a secret is often composed of several [matches](./glossary#match). GitGuardian considers the secret encrypted if at least one of the matches is encrypted. ### Found by a generic detector First, the secret must have been found by a generic detector. Patterns used by API-specific detectors are unlikely to mistakenly match an encrypted secret, because these patterns have constraints like starting with a given prefix, being of a precise length, or consisting of a specific set of characters. ### Stored in a file generated by encrypting tools Tools like [SOPS](https://github.com/mozilla/sops) can encrypt and decrypt secrets in JSON or YAML files. We skip files whose extensions match those used by such tools. ### Match BCrypt or Crypt format If one of the secret matches follows the format of a [BCrypt hash string](https://en.wikipedia.org/wiki/Bcrypt#Description) or a [Crypt hash string](https://en.wikipedia.org/wiki/Crypt_(C)) it is considered encrypted. ### Context hints If the text before one of the matches contains one of the following common encryption indicators (this list is non-exhaustive): - "ENC[" or "ENC(" - "SealedSecret" - "encrypteddata" - "encryptedpassword" - "encryptedsecrets" - "encvalues" - "secure" - "type: Opaque" Then the match is considered encrypted. ### Base64 encrypted data If the match is a long Base64-encoded string and the first decoded bytes match: (1, 0), (2, 0), (1,1) or (10, 36, 0) then the match is considered to be Base64 encrypted data. --- ## Frequently Asked Questions(Secrets-detection-engine) At any point when reading this FAQ section you can use our [glossary](./glossary.md) to find some useful definitions. ### How does GitGuardian's detection engine work, roughly speaking? {#engine-workflow} For an extensive response, you can consult [this page](./quick_start.md). GitGuardian's detection engine revolves around the concept of detectors. A detector is a set of instructions that our detection engine will execute on a given input document to catch secrets in it. The flow of instructions is always the same: - Pre-Validation: discard documents as early as possible if they are of no interest for secrets detection. - Matching: look for a given pattern. - Post-Validation: apply some validation steps to select only relevant secrets. All these steps are performed using a combination of regular expressions and heuristics based on contextual information. ### What is the difference between generic and specific detectors? {#generic-vs-specific} Simply put, a **specific detector** is designed to find a well identified type of secret whereas a **generic detector** yields secrets that are not associated with a given provider. For a bit more details, you can refer to this [documentation on detectors](./detectors/introduction.md). ### Does GitGuardian check the validity of credentials? {#validity-check} When possible, **GitGuardian will check the validity of the detected credentials**. To do so, GitGuardian performs the **least intrusive call as possible** to the service. We favor HEAD requests, or GET requests when we cannot. We also select endpoints that do not return any personal information. Once this is done, the secret will be labelled as either: - valid: the service call was successful and confirms the secret is **valid**. - invalid: the service call was successful and confirms the secret is **invalid**. - failed to check: the service call was not successful, so we can't tell whether the secret is valid or not. There are a few situations which can lead to "failed to check". For example, this happens when the service is internal and thus not reachable from our servers. Another common example is if the service was down at the time we tried to call it. We can't tell whether the secret is valid or invalid so we remain cautious and report the incident. ### Why do some detectors only report incidents for valid secrets? {#required-check} The format of some secrets makes it impossible to create a detector with a good enough precision. This is the case for example if the secret has no prefix, no suffix and no fixed length. Reporting all matching potential secrets would produce too many false positives. To avoid that, we only report the secret if it has been confirmed valid by a check. Detectors for these secrets are marked as "Only valid secrets raise an alert". ### What do you call a false positive exactly in the context of secrets detection? {#false-positive} In the context of secrets detection, a false positive occurs when our detection engine raises an alert for a secret that is not one and has never been one. For more details on false positives, recall and precision, we highly recommend reading this [blog post](https://blog.gitguardian.com/secrets-detection-accuracy-precision-recall-explained/). ### How to properly test GitGuardian detection capabilities? {#properly-test} To properly test our engine, we recommend reading this documentation carefully, and especially looking at detector's examples that will provide you with some good test cases. You can also use this [example repository](https://github.com/GitGuardian/sample_secrets) to get familiar with our detection engine's behavior. If a secret is not detected by one of our detectors, you can refer to [this question](#did-not-detect) to get some explanations. ### Why didn't GitGuardian detect my secret? {#did-not-detect} First of all, we recommend building your test cases by following our detector's [documentation](./detectors/supported_credentials.md). For each detector, we provide a set of examples that are detected by our engine. Here are also some possible reasons why we did not raise an alert for your secret: - The associated detector is checked, and your secret is not valid anymore. In that case, the secret is labelled as invalid and no alert is raised. - You somehow obfuscated your secret to test our detection capabilities, and that's a good practice. But you may have broken the pattern of the key in the process: make sure you kept an identical length and charset. - Your secret could not pass our pre-validation steps: for certain detectors we ban markdown files, or we require a given context for the detection to occur. You can refer to the concerned detector's documentation [here](./detectors/supported_credentials.md). - Your secret is not part of the required [assignment](./glossary.md#assignment-and-assigned-variable). Look at the detector's examples to see what patterns are detected. ### We've seen real credentials in .md files in the past already, why do some of your detectors drop .md files? {#md-ban} At GitGuardian one of our biggest challenges is to achieve a detection with the highest precision and the best recall possible, in other words squaring the circle. To do so, we battle test our algorithms on GitHub's live data feed. We also permanently monitor our detector's performance by looking at explicit feedback from developers or from our checkers, as well as implicit feedback: e.g. secrets removal. Thanks to this feedback, we decided to drop markdown files in certain detectors in an effort to reduce alert fatigue and increase our precision. To know which detectors are concerned, you can refer to detectors' pre-validation steps' documentation. ### Are cryptographic keys sensitive objects? {#are-cryptographic-keys-sensitive-objects} **Cryptographic Keys** Cryptographic algorithms are tools used to secure communications over public channels such as the Internet. Based on mathematical hard problems, they are the building blocks of protocols such as TLS (for secure internet browsing via https) or SSH (for secure remote access to servers). The different security features provided by cryptography are authentication, authorization, and encryption. To this end, cryptographic algorithms are bound to cryptographic keys that are used to unlock or lock these functions. We distinguish two types of keys, symmetric or asymmetric keys: - A symmetric key is shared between the communicating entities. - Asymmetric keys are composed of a public and a private key. The public key is distributed to everyone to initiate a communication or a protocol and the private key is used to verify and carry on the communication or the protocol. Having access to someone's symmetric key or asymmetric private key can have devastating consequences. A malicious adversary could then impersonate an entity, tamper its communications, or simply have access to all its secure data. **How we detect private keys** After the introduction of the series of IETF RFC [1421](https://tools.ietf.org/html/rfc1421), [1422](https://tools.ietf.org/html/rfc1422), [1423](https://tools.ietf.org/html/rfc1423), and [1424](https://tools.ietf.org/html/rfc1424) most implementation libraries involving cryptography (such as OpenSSL) use a shared format to store the cryptographic keys called PEM (stands for Privacy-Enhanced Mail). This format has a very structured form, always starting with the same pattern. This is very convenient for detection as it implies a high recall on the different implemented detectors. We based our family of cryptographic key detectors on the particularity of the PEM format to get very efficient and precise detectors. Here is the list of the detectors currently implemented in our suite: - [Generic private key](./detectors/specifics/private_key_generic.md). - [DSA private key](./detectors/specifics/private_key_dsa.md). - [Elliptic curve private key](./detectors/specifics/private_key_elliptic.md). - [RSA private key](./detectors/specifics/private_key_rsa.md). - [OpenSSH private key](./detectors/specifics/private_key_openssh.md). - [PGP private key](./detectors/specifics/private_key_pgp.md). - [Encrypted private key](./detectors/specifics/private_key_encrypted.md). - [Putty private key](./detectors/specifics/putty_private_key.md). We targeted the main cryptographic algorithms or protocols, which are the most commonly used ones and referenced one by standard entities. For each of those algorithms, we implemented a detector for both the PEM format form and the Base64 encoded version. **What about public key certificates?** One frequently asked question by the public and our customers is about the sensitivity of a certificate. Public-key certificates are used in TLS protocols in order to establish authenticated and secure communication channels when browsing the web, displayed as https and a green lock on the website. They are in essence just public keys augmented with a signature that everyone can access to (simply click on the lock). As such, they have no sensitivity and the augmented signatures just provide trust to users that this certificate was issued by a trusted party. The trusted party is usually referenced by either the browser or the OS (Linux, Windows, macOS, etc) during installation. --- ## Glossary(Secrets-detection-engine) This document defines common words used to describe our secrets detection engine. ### Detector A set of rules that will be applied to a document to find one type of secret (e.g.: AWS keys, database URI, Google Key...). ### Generic detector We consider that a detector is generic if we are not able to infer the secret's provider directly. For example the detector looking for a pattern such as `secret={high_entropy_string}` is a generic detector. ### Specific detector A specific detector is a detector designed to find a well identified type of secret such as AWS keys, MySQL URI, Slack token... Specific detectors are often opposed to generic detectors. ### Assignment and assigned variable We refer to an assignment as any statement of the form `{assigned_variable} {assignment_token} {value}`. For example in this statement: `my_variable = "HelloWorld"`, the assigned variable is: `my_variable`. ### Document Any text with a filename. Filename is optional. ### Entropy Measure of randomness of a string. An API key should have a high entropy since it is a randomly generated sequence of characters. When mentioning entropy in this documentation, we mean [Shannon entropy](). ### Filepath / Filename / Extension We adopted the following conventions for naming paths. For example `config/secrets.yaml`: - `yaml` is the extension. - `secrets.yaml` is the filename. - `config/secrets.yaml` is the filepath. ### Insight Additional information on a document or a secret. ### Match A string that is part of a secret. A secret can be composed of one or several matches. ### Matcher A detection rule that is applied to a document and outputs matches. ### PostValidator A validation rule applied to a secret candidate (e.g.: validate that all the matches have sufficient entropy). ### Precision The fraction of secrets detected that are indeed true secrets. We can keep track of this metric with the feedback of our customers. ### PreValidator A validation rule applied to a document (e.g.: look for "datadog" in the document). ### Priority A rule that prioritizes one secret over another one if they are overlapping. A secret detected by a specific detector always has a higher priority than one detected by a generic detector. ### Recall The fraction of secrets we were able to detect and classify as such among all secrets that exist. This metric is almost impossible to measure without human labelling. ### Scanner A collection of detectors. In terms of code, this is the entry point to scan a document, and the only way of scanning one. ### Secret A combination of strings found by a detector in a document. This combination should grant access to a private service. ### Secrets overlapping Two secrets overlap if any of one's matches are partially or completely included in any of the other's secrets matches. ### Validity Check A non intrusive call to the concerned service that allows to determine whether a key is valid or invalid. Some validity checks can be used to improve our precision and be sure that we only raise alerts for valid secrets. --- ## Secret Enricher Categories Reference The "Secret Enricher" feature uses machine learning to analyze the context around generic secrets and automatically classify them into **categories** and identify specific **providers**. This classification helps you prioritize remediation efforts by understanding the potential impact and criticality of each incident. When Secret Enricher successfully enriches a generic incident, the enriched secret name (like "Redis Identifiers" or "Stripe API Key") automatically replaces the generic detector name throughout the platform, giving you immediate, actionable context. :::info This feature is specifically designed for **generic incidents** that couldn't be matched to a specific detector. The GSE analyzes the surrounding context to provide enriched names, categories, and provider insights that help with prioritization and remediation. Later on we will also enrich specific incidents to unveil more context. ::: ## How Secret Enricher Categories and Enriched Names Help with Remediation The Secret Enricher transforms incident management through enriched names and categories: - **Instant Identification**: Enriched names like "PostgreSQL Connection String" or "Stripe API Key" immediately tell you what leaked - **Prioritize critical infrastructure**: Categories help you focus on Cloud providers, Databases, Payment systems first ## Categories Reference ### 🤖 AI **What it includes:** API keys and tokens for artificial intelligence and machine learning services. **Examples:** OpenAI, Anthropic, Hugging Face, Cohere, DeepSeek, Mistral AI, Azure OpenAI **Why it matters:** AI services can be expensive to abuse and may contain sensitive data or model access. Leaked AI tokens could lead to: - Unauthorized API usage and billing - Access to proprietary models or training data - Potential data exfiltration through AI services ### 🌐 CDN **What it includes:** Content Delivery Network services and edge computing platforms. **Examples:** Cloudflare, Fastly, Amazon CloudFront, Akamai, Bunny.net **Why it matters:** CDN credentials can impact website performance, security configurations, and content delivery. Compromise could lead to: - Website defacement or content manipulation - DDoS protection bypass - SSL/TLS certificate compromise ### 🔄 CI/CD **What it includes:** Continuous Integration and Continuous Deployment pipeline credentials. **Examples:** CircleCI, BuildKite, LaunchDarkly, Jenkins, GitLab CI **Why it matters:** CI/CD credentials provide access to deployment pipelines and can impact entire development workflows. Compromise could lead to: - Unauthorized code deployments - Supply chain attacks - Access to production environments - Source code exposure ### ☁️ Cloud Provider **What it includes:** Major cloud infrastructure provider credentials. **Examples:** Amazon AWS, Microsoft Azure, Google Cloud, DigitalOcean, Terraform, OVH **Why it matters:** Cloud provider credentials often have broad access to infrastructure resources. Compromise could lead to: - Data breaches - Resource manipulation or deletion - Cryptocurrency mining - Service disruption - High billing costs ### 🔍 Code Analysis **What it includes:** Code quality, security scanning, and analysis platform credentials. **Examples:** SonarQube, Code Climate, Codacy, Snyk, Sourcegraph **Why it matters:** These tools often have access to source code and security findings. Compromise could lead to: - Source code exposure - Security vulnerability information disclosure - Manipulation of security reports ### 🤝 Collaboration Tool **What it includes:** Team collaboration, project management, and productivity platform credentials. **Examples:** Asana, Trello, Notion, Contentful, Netlify, Atlassian **Why it matters:** Collaboration tools contain business information and team communications. Compromise could lead to: - Sensitive business information exposure - Project manipulation - Unauthorized access to team communications ### 📊 CRM **What it includes:** Customer Relationship Management system credentials. **Examples:** Salesforce, HubSpot, Freshdesk, Zendesk **Why it matters:** CRM systems contain sensitive customer data and business information. Compromise could lead to: - Customer data breaches - Privacy regulation violations (GDPR, CCPA) - Competitive intelligence exposure - Customer relationship damage ### 🪙 Cryptos **What it includes:** Cryptocurrency exchange and blockchain service credentials. **Examples:** Coinbase, Bitfinex, Kraken, various blockchain APIs **Why it matters:** Cryptocurrency credentials can provide direct access to financial assets. Compromise could lead to: - Direct financial theft - Unauthorized trading - Wallet compromise ### 🗄️ Data Storage **What it includes:** Database systems, cloud storage, and data management service credentials. **Examples:** PostgreSQL, MySQL, MongoDB, Redis, Amazon S3, Supabase, PlanetScale **Why it matters:** Data storage credentials provide access to potentially sensitive business and customer data. Compromise could lead to: - Data breaches - Data manipulation or deletion - Privacy regulation violations - Business disruption ### 🛒 E-commerce **What it includes:** Online commerce platform and marketplace credentials. **Examples:** Shopify, Webflow, Etsy, various e-commerce APIs **Why it matters:** E-commerce credentials can affect online sales and customer experience. Compromise could lead to: - Customer data exposure - Order manipulation - Payment system compromise - Revenue impact ### 🔐 Identity Provider **What it includes:** Authentication, authorization, and identity management service credentials. **Examples:** Auth0, Okta, Microsoft Azure Active Directory, Ping Identity, Keycloak **Why it matters:** Identity providers control access to multiple systems and user authentication. Compromise could lead to: - Unauthorized access to connected systems - User impersonation - Single sign-on (SSO) bypass - Privilege escalation ### 🏢 Internal **What it includes:** Internal or proprietary system credentials. **Examples:** Custom internal APIs, proprietary services, internal tools **Why it matters:** Internal credentials provide access to organization-specific systems. Impact varies based on the specific system, but could lead to: - Internal system compromise - Proprietary information exposure - Business process disruption ### 💬 Messaging System **What it includes:** Communication platforms, email services, and messaging APIs. **Examples:** Slack, Twilio, SendGrid, Mailgun, Zoom, Discord, Microsoft Teams **Why it matters:** Messaging systems handle communications and notifications. Compromise could lead to: - Communication interception - Spam or phishing campaigns - Business communication disruption - Social engineering attacks ### 📈 Monitoring **What it includes:** Application performance monitoring, logging, and observability platform credentials. **Examples:** Datadog, New Relic, Splunk, Grafana, GitGuardian, Lacework **Why it matters:** Monitoring tools have access to system metrics, logs, and security information. Compromise could lead to: - Sensitive system information exposure - Security monitoring bypass - Performance data manipulation - Infrastructure intelligence gathering ### 📦 Package Registry **What it includes:** Software package repository and artifact storage credentials. **Examples:** NPM, PyPI, RubyGems, NuGet, JFrog Artifactory, Docker registries **Why it matters:** Package registry credentials can affect software supply chain security. Compromise could lead to: - Malicious package publishing - Supply chain attacks - Dependency compromise - Software integrity issues ### 💳 Payment System **What it includes:** Payment processing, financial services, and fintech platform credentials. **Examples:** Stripe, PayPal, Square, Plaid, Razorpay, GoCardless, Amazon MWS **Why it matters:** Payment credentials provide access to financial transactions and customer payment data. Compromise could lead to: - Financial fraud - Payment data breaches - PCI DSS compliance violations - Direct financial loss ### 🔑 Private Key **What it includes:** Private keys, certificates, and cryptographic material. **Examples:** SSL/TLS certificates, SSH keys, cryptographic signing keys **Why it matters:** Private keys are fundamental to security infrastructure. Compromise could lead to: - Encryption bypass - Digital signature forgery - SSL/TLS certificate compromise - Authentication bypass ### 🔗 Remote Access **What it includes:** Remote access tools, VPN services, and secure connection credentials. **Examples:** SSH, Tailscale, various VPN services, remote desktop tools **Why it matters:** Remote access credentials provide direct system access. Compromise could lead to: - Unauthorized system access - Network lateral movement - Remote system control - Bypassing network security controls ### 🔒 Secret Management **What it includes:** Secret management platforms and credential storage services. **Examples:** HashiCorp Vault, Doppler, 1Password, Delinea, AWS Secrets Manager **Why it matters:** Secret management credentials provide access to other stored secrets and credentials. Compromise could lead to: - Mass credential exposure - Centralized secret compromise - Cascading security failures ### 📱 Social Network **What it includes:** Social media platform and social networking service credentials. **Examples:** LinkedIn, Twitter, Meta/Facebook, various social media APIs **Why it matters:** Social network credentials can impact brand reputation and communications. Compromise could lead to: - Brand reputation damage - Unauthorized social media posting - Social engineering attacks - Customer communication disruption ### 📝 Version Control Platform **What it includes:** Source code management and version control system credentials. **Examples:** GitHub, GitLab, Bitbucket, various Git hosting services **Why it matters:** Version control credentials provide access to source code and development history. Compromise could lead to: - Source code theft - Malicious code injection - Development process disruption - Intellectual property theft ### ❓ Other **What it includes:** Services that don't fit into other categories or are not yet classified. **Examples:** Various APIs, specialized services, or unknown providers ## Using Enriched Names and Categories in Your Workflow ### 1. Set Up Custom Views Create [saved views](../../platform/collaboration-and-sharing/saved-views) that focus on high-priority categories: - **Critical Infrastructure:** Filter for "Secret Management", "Cloud provider", "Data storage", "Identity provider" - **Financial Systems:** Filter for "Payment system", "Cryptos", "E-commerce" - **Development Security:** Filter for "Version control platform", "CI/CD", "Package registry" ### 2. Apply Automated Severity Rules Use Secret categories in your [automated severity scoring rules](../../internal-monitoring/remediate/prioritize-incidents#automated-severity-scoring): - **Critical severity:** Incidents categorized as "Payment system", "Cloud provider", "Identity provider" - **Critical or High severity:** Incidents categorized as "Data storage", "CI/CD", "Version control platform" - **Medium severity:** Other categorized incidents ## Best Practices 1. **Don't ignore "Other" category** - Investigate these incidents to understand their actual impact 2. **Combine with other incident attributes** - Use Secret categories alongside validity checks, tags, and occurrences 3. **Regularly review and refine** - Update your priority matrix as you learn more about your environment 4. **Document decisions** - Keep track of how you handle different categories to improve future response ## Limitations - **Not all generic incidents can be enriched**: Incidents with insufficient context may not receive enriched names and will retain their generic detector names - **Provider availability**: Provider-level enrichment (e.g., "Redis") is available for more incidents than specific enriched names - **Context-based analysis**: Enrichments are based on contextual ML analysis and may not be 100% accurate in all cases - **Continuous improvement**: New categories, providers, and enriched names are continuously being added to improve coverage - **Enriched vs. Specific**: Enriched incidents remain classified as "generic" from a detection standpoint but display specific names for usability :::tip Our goal is for every workspace to have zero truly "generic" secrets—all incidents should have maximum definition possible through either specific detectors or ML-powered enrichment. ::: *This reference guide helps you understand and effectively use enriched names and GSE categories for incident prioritization. For more information on using the Secret Enricher, see the [Machine Learning](./machine_learning) documentation.* --- ## Remediate a leak on public GitHub If you end up on this page, it is likely that you got an alert from our _pro bono_ alerting service. Don't worry, leaks sometimes just happen... even to the best of us... **This section provides a step by step guide on how to remediate a leak that occurred on public GitHub.** > For comprehensive remediation guidance covering both public and internal incidents, see our [Public Monitoring Remediation Overview](../../public-monitoring/remediate/remediation-overview.md). ## ⚠️ What you should NOT do: - **Committing on top of the current source code version is not a solution**. Bear in mind that git keeps track of the history, the secret will still be visible in previous commits. - **Only taking down the involved repository is not a correct solution**. The leaked credentials will still be exposed in forks of the repository, and attackers could still access it in mirrored versions of GitHub. ## ✅ Step by step guide to remediate the leak - **Step 1:** Assess the impact and revoke the exposed secret. - **Step 2:** Clean the git history (optional, see warnings below). - **Step 3:** Inspect logs and verify security. ### 🔒 Step 1: Assess impact and revoke the secret (~ 5-10 min) **First, quickly assess the situation:** - Confirm this secret actually belongs to your organization - Understand what resources this secret can access - Determine the privilege level and potential impact **Then, revoke the secret** - this **is the only way to ensure no attacker will access the involved service.** **How to revoke:** - Having been alerted by GitGuardian, you can navigate to the corresponding GitGuardian [detector's documentation](./detectors/supported_credentials.md), all information about revocation are available in the `Revoke the secret` section of the selected detector. - If you found out about the leak without GitGuardian and it is not a secret type handled by one of our detectors, have a look at the relevant provider's documentation. You can usually revoke your credentials in the same section you issued them. - **If you leaked corporate credentials or credentials you cannot revoke by yourself, we highly recommend you get in touch with your security team immediately.** It's OK to make mistakes, hiding them is often a bigger problem. Whether you managed to revoke the credentials or not, move to step 2 to mitigate the leak and remove evidence of it. ### 🧹 Step 2: Repository cleanup (~ 10 min) - OPTIONAL **⚠️ Important: Once you have revoked the secret, you should typically stop here.** The secret is now useless to attackers, and your security incident is resolved. **Emergency visibility reduction (if revocation failed):** If for any reason you could not revoke the leaked credentials, the quickest action to remove the credentials from most attackers' sight is to make the repository private. Although your credentials are probably mirrored in some other place on the internet, that's already a good way to buy you some time. **How to make repository private:** Go under the `settings` section of your GitHub project and choose the `change visibility` button at the bottom. ![Make a repository private](/img/secrets-detection/make_repo_private.png) **Git history rewriting (proceed with extreme caution):** :::caution **Rewriting git history is generally not recommended** as it can disrupt team workflows and often leaves references to the leaked commits. This is not a trivial action to conduct and may break contributing developers' workflow and can accidentally delete legitimate data. For matters of brand image, you may want to clean the git history to remove any evidence of the leak, but bear in mind that this action is not sufficient as the secret can still be visible to attackers, either in forks of the involved repository, or on mirrored versions of GitHub. ::: **If you still decide to rewrite history:** - You can use tools like [git-filter-repo](https://github.com/newren/git-filter-repo) to rewrite the history of a project. You can refer to this [GitGuardian's blogpost](https://blog.gitguardian.com/rewriting-git-history-cheatsheet/#how-complicated-is-the-situation) for detailed instructions. - Once you fixed your git history and pushed it to the remote server. Be aware that this may result in an orphan leaky commit remaining on GitHub. You can get in touch with [GitHub support](https://support.github.com/request) to permanently delete this data. ### 🔎 Step 3: Monitor and verify security (~ 5-10 min) Inspecting your logs will give you a quick idea of whether the compromised credentials were used by an attacker or not, and what exactly happened there. **How to check for unauthorized access:** - If the involved provider is handled by GitGuardian's detection engine, you can look in the `Check for suspicious activity` section of the concerned detector's documentation. - Otherwise, the API provider usually gives insights on when the credentials were last used in the settings page. If the compromised credentials are database credentials or private keys, you may want to look in relevant server logs. **What to look for:** - Unusual access patterns or timing - Access from unfamiliar IP addresses or locations - Unexpected API calls or data access - Any activity after the suspected exposure time **If you find evidence of unauthorized access:** - Document all suspicious activity - Consider this a confirmed security breach - Follow your organization's incident response procedures - Consider engaging cybersecurity professionals if needed ## 🏁 Finally Congratulations, now you should be covered. As you know mistakes can happen and GitGuardian is here for you. You just have to sign-up for free and benefit from GitGuardian's real-time alerting to be protected in the future. You can also scan your history to verify that you don't have other secrets buried in your code. If you are more of a CLI person, you can have a look at [GitGuardian CLI](https://github.com/GitGuardian/ggshield). This CLI application can run in your local environment, or in a CI environment to detect 600+ types of secrets. --- ## Machine learning Detecting secrets with high quality results is a challenging and intricate task. To enhance our detection engine, we've implemented various machine learning models to analyze code like a professional developer, identify false positives, and enrich generic secrets with contextual information. ## False Positive Remover :::info Business Feature Only workspaces with a Business plan can access this functionality. ::: When it comes to avoiding false positives, we've pushed imperative programming and regular expressions to their limits. It is simply not possible to write conditions or regular expression patterns for every potential scenario. To overcome this technological constraint we implemented machine learning to train machines to quickly and efficiently navigate this complex domain and identify the elements we are looking for. The False Positive Remover accurately identifies and tags incidents as 'false positives' through its thorough analysis. The False Positive Remover runs on findings from all your sources, not just your code repositories. This includes non-code sources such as Confluence, Jira, Slack, and Microsoft Teams. Every new finding from these sources goes through the model automatically, so generic secrets can be detected on non-code sources without flooding your dashboard with false positives. - For VCSs, the False Positive Remover is an **internally** developed and trained model, independent of third-party services, that accurately identifies and tags incidents as 'false positives' through its thorough analysis. - For non-code sources, the False positive filtering relies on an LLM-based model and requires AI features to be enabled in your workspace. See [AI settings](../../platform/ai/ai-settings.md). ### How to use it? ![False positive Remover](/img/secrets-detection/machine-learning/fp-remover.png) You can improve your workflow by using the `Filters > GitGuardian tags > False positive` filter located in the incidents list page. This filter allows you to easily identify and manage false positive incidents, helping you streamline your incident resolution process. [Read more on our blog post](https://blog.gitguardian.com/fp-remover-cuts-false-positives-by-half/) ### FAQ #### What does this model consider as "False positive"? Something that cannot be a secret in any context. In the example below (`"signup_form_confirm_password": " Confirmar contrasinal"`) looks like a true positive for a regex but is not for our model which analyzes a context (lines before/after) ```json { "signup_form_username": "Identificador", "signup_form_password": "Contrasinal", "signup_form_confirm_password": " Confirmar contrasinal", <- a regex may consider this a true positive, not our model. "signup_form_button_submit": "Crear conta", } ``` #### If these are false positives, why don't you just remove them? We tag them as false positives rather than deleting them so you keep full visibility and stay in control. You can filter them out of your view, and you can always review what was tagged. #### Are you catching all the false positives I have? The model runs at high precision (around 95%) to avoid tagging real secrets as false positives. On generic secrets from non-code sources, it filters out 25 to 40% of findings on average. We keep improving recall over time while protecting precision. ## Secret Enricher Secret Enricher is a specialized machine learning model designed to analyze the context around generic secrets and automatically classify them into **categories** and **providers**. This enhanced classification helps you prioritize remediation efforts by understanding the potential impact and criticality of each incident. :::info This feature is specifically designed for **generic incidents** that couldn't be matched to a specific detector. The Secret Enricher analyzes the surrounding context to provide category and provider insights that help with prioritization and remediation. ::: ### Enrichment-Driven Incident Display When Secret Enricher successfully enriches a generic incident, **the enriched secret name automatically replaces the generic detector name**. This means instead of seeing vague names like "Generic Database Assignment" or "Generic High Entropy Secret," you'll see precise, actionable names: - **Redis Identifiers** instead of "Generic Database Assignment" - **Stripe API Key** instead of "Generic High Entropy Secret" - **PostgreSQL Connection String** instead of "Generic Database Assignment" - **AWS Access Key** instead of "Generic High Entropy Secret" ![Secret Enricher thumbnail](/img/secrets-detection/machine-learning/secretenricherv2.png) This enrichment-driven UX provides immediate context at a glance, eliminating the need to open each incident to understand what type of secret was exposed. The enriched names appear in: - Incident lists - Search results - API responses - CSV and JSON exports :::info In some instances, the detector name (e.g., "Generic High Entropy Secret") may be visible instead of the enriched name. We are working on this harmonization throughout the first months of 2026. ::: ### How Secret Enricher categories help with remediation Understanding Secret Enricher categories helps you: - **Prioritize critical infrastructure secrets** (Cloud providers, Databases, etc.) - **Focus on high-impact services** (Payment systems, Identity providers, etc.) - **Identify secrets that could affect business operations** (Messaging systems, E-commerce platforms, etc.) - **Streamline remediation workflows** by grouping similar types of secrets - **Apply appropriate security policies** based on the service type ### How to use it? #### Enriched names in incident lists Enriched secret names are automatically displayed as the primary incident name in your incident lists. No configuration needed—when our ML model successfully identifies a secret type, you'll see it immediately. This enrichment-driven approach makes incident triage faster and more intuitive. You can instantly identify: - Database credentials (Redis, PostgreSQL, MongoDB) - Cloud provider secrets (AWS, Azure, GCP) - Payment system tokens (Stripe, PayPal, Square) - API keys for specific services (Twilio, SendGrid, Slack) #### Customize your views {#customize-your-views} From the incidents list, you can customize how your incidents are displayed by clicking on the "Columns" button in the top-right corner of the table. This allows you to add the "Secret category" and "Secret provider" columns, which display additional enrichment properties inferred by the model alongside the enriched secret name. With this customization, you can quickly spot important categories (such as "Data Storage") or specific providers that might require immediate attention among your incidents. #### Filter your data {#filter-your-data} Three filters (Provider, Category, Family) help you identify the most significant or critical generic incidents, such as those classified under "Data Storage" or linked to the provider "Postgresql." You can apply these filters in several ways: **Example 1 > Filter enriched incidents directly**: Use "Detector Type is Generic" + "Secret Provider is not Empty" to find enriched generic secrets with at least a provider inferred **Example 2 > Group Generic Incidents by Secret Category**: Use "Detector Type is Generic" + "Secret Category is Data Storage" to find enriched generic secrets related to Data management/storage ![GSE-filters](/img/secrets-detection/machine-learning/gse-howto.png) With these filters you can explore your enriched incidents and quickly identify the ones that matter most for your operations. ### Categories and providers reference For detailed definitions of all GSE categories and providers, including what they mean and how to prioritize them, see our comprehensive [GSE Categories and Providers Reference](./gse-categories-providers-reference). ### FAQ #### What happens if a secret can't be enriched? If the ML model cannot identify a provider or category with confidence, the incident will retain its original generic detector name (like "Generic Database Assignment"). You can still use our filtering capabilities to find and investigate these unenriched incidents. #### Why aren't these transformed into specific incidents? Enriched incidents remain classified as "generic" from a detection perspective because the enrichment is based on contextual analysis, not pattern-based detection rules. However, the enriched name provides the actionable specificity you need for prioritization and remediation. As we continue to refine this feature, our definitions will become more precise, and we may convert highly confident enrichments into specific detectors. #### What is the model trained to discover? The model can identify a comprehensive set of categories and providers:
The model can identify the following categories: AI CDN CI/CD Cloud provider Code analysis Collaboration tool CRM Cryptos Data storage E-commerce Identity provider Internal Messaging system Monitoring Other Package registry Payment system Private key Remote access Secret management Social network Version control platform
The model can identify hundreds of providers including: Amazon AWS and related services Microsoft Azure and related services Google Cloud Platform Popular databases (PostgreSQL, MySQL, MongoDB, Redis) CI/CD platforms (GitHub, GitLab, Jenkins, CircleCI) Payment systems (Stripe, PayPal, Square) AI services (OpenAI, Anthropic, Hugging Face) Messaging platforms (Slack, Discord, Twilio) And many more...
For the complete list of supported categories and providers, see the [GSE Categories and Providers Reference](./gse-categories-providers-reference). ## Risk score (ML-powered incident prioritization) The risk score is a machine learning-powered feature that automatically assesses the risk level of each incident on a scale of 0-100, where **100 indicates the highest risk** and **0 the lowest**. It analyzes multiple risk signals including secret type, validity, exposure context, and behavioral patterns to help you focus on the incidents that pose the greatest threat. :::tip We value your feedback The risk score uses machine learning models that are continuously improved based on user feedback. If you notice incidents with unexpected scores or explanations, we encourage you to share feedback directly through the dashboard — your input helps us refine the scoring model. ::: ### Key capabilities - **Automatic risk assessment** for all secret incidents (both Internal and Public Monitoring) - **Dynamic scoring** that updates as incident context evolves - **Natural language explanations** generated for each incident - **Granular prioritization** with a 0-100 scale for fine-tuned remediation workflows - **Feedback loop** for future model improvement ### Where to use it The risk score is available as part of the incident prioritization and investigation features: - [Risk score for Internal Monitoring](../../internal-monitoring/remediate/prioritize-incidents.md#risk-score-ml-powered-prioritization) - [Risk score for Public Monitoring](../../public-monitoring/remediate/prioritize-incidents.md#risk-score) - superseded by the agents analysis on workspaces that have been switched This feature is part of GitGuardian's broader ML initiative to enhance both detection precision and remediation efficiency. ## Similar incident grouping (ML-powered) Similar incident grouping is a machine learning-powered feature that automatically identifies and groups related incidents based on contextual similarities. Instead of reviewing incidents one by one, you can process entire groups of similar incidents together, dramatically accelerating your remediation workflow. ### Key capabilities - **Automatic grouping** of incidents sharing similar characteristics (similar code context in the patch) - **Bulk remediation actions** to resolve multiple related incidents at once - **Dynamic group updates** as new incidents are detected or existing ones are resolved ### How it helps Similar incident grouping helps you: - **Reduce remediation time** by handling groups of related incidents together instead of individually - **Identify systemic issues** when the same type of secret appears across multiple locations - **Apply consistent remediation** across similar incidents to maintain security policy coherence - **Focus on unique incidents** by quickly processing groups of similar ones first ### Where to use it Similar incident grouping is available in the incident remediation workflows: - [Similar incidents for Internal Monitoring](../../internal-monitoring/remediate/investigate-incidents#ml-powered-similar-incident-grouping) - [Similar incidents for Public Monitoring](../../public-monitoring/remediate/understand-incident-properties#ml-powered-similar-incident-grouping) This feature is part of GitGuardian's broader ML initiative to enhance both detection precision and remediation efficiency. --- ## Secrets Detection Engine ## Philosophy Secrets detection is probabilistic: some secrets are easier to find than others. There is a trade-off between low number of false alerts and low number of missed credentials (precision/recall trade-off) Our secrets detection engine has been **running in production since 2017**, analyzing billions of commits coming from GitHub. Since day one we began to train and benchmark our algorithms against the open source code. It allowed GitGuardian to build a language agnostic secrets detection engine, integrating new secrets or new way of declaring secrets really fast while keeping a really low number of false positives. We are also collecting feedback from the alerts we are sending including the pro bono alerts: - Explicit feedback when a developer or security team marks an alert as a false alert. - Implicit feedback when a developer takes down a public repository or deletes a public commit a few minutes after we sent an alert. We are currently implementing two types of detectors: - Specific detectors: we implement an algorithm dedicated to looking for one specific type of secret like AWS keys, Postgres URI or SMTP credentials. This type of detector aims at having high recall and precision for the targeted type of secret. The downside of this approach is that we have to implement a lot of specific detectors to have a good coverage of all existing secrets. - Generic detectors: The purpose of these detectors is to catch what our specific detectors are missing with a generic approach. We will implement generic detectors capturing patterns such as `secret=\{high_entropy_string\}` or `password=xxx, email=yyy@corp.com`. We can thereby achieve a low number of secrets missed even if the precision of these detectors is slightly lower than the specific ones. You can of course choose what detectors you want to allow or deny in our different web applications. ## How it works Our secrets detection engine takes as input a `Document` having as parameter a string (a Git Patch, a GitHub gist, a Slack message) and an _optional_ parameter which is the filename (`secrets.py`, `index.html`, ...) Note that this detection engine can use the filename when available in a pre-validation step: for example we won't scan an image or a video file since nobody puts secrets in it. We currently have the following ban-lists in place: 1. We do not scan binary files such as `jpg`, `tar.*`, ... 2. We exclude some filepaths using the following regexes: ``` node_modules(/|\\) vendors?(/|\\) top-1000\.txt$ \.sops$ \.sops\.yaml$ ``` 3. In most cases, we do not scan documents with the following extensions because they bring a lot of false positives and almost no real secrets: `["html", "css", "md", "lock", "storyboard", "xib"]` ## Tao of our secrets detection engine - 🎯 **High precision**: We want to keep a low number of false positives to avoid alert fatigue. - 🔐 **High recall**: We want to keep a low number of missed secrets to keep our customers safe. - ⚡ **Speed**: While speed is less important than recall and precision our secrets detection engine is designed to be fast and scan a common Git repository history in less than a minute. - 👥 **Community and customer driven**: Our engine is constantly trained and improved by feedback from hundreds of thousands of developers using our applications and by feedback from our customers. ## Main features ### Broad coverage with 600+ specific detectors We have developed the vastest library of specific detectors being able to detect 600+ different types of secrets (10 times more than the current competition). You can find the exhaustive list [here](./detectors/introduction.md). ### Detecting secrets with multiple matches and multi-line secrets {#detecting-secrets-with-multiple-matches-and-multi-line-secrets} GitGuardian supports the detection of multi-matches secrets such as oauth `client_id` and `client_secret`, database credentials, SMTP credentials... GitGuardian supports the detection of multi-line secrets such as private keys. For example we are able to detect AWS keys from the following snippet and the output will be two matches: one for the client id and one for the client secret. ```yaml input: 'id=AKIAFJKR45SAWSZ5XDF3, client_secret: hjshnk5ex5u34565d4654HJKGjhz545d89sjkjka' output: client_id: AKIAFJKR45SAWSZ5XDF3 client_secret: hjshnk5ex5u34565d4654HJKGjhz545d89sjkjka ``` Example for database credentials: ```yaml input: | dbusername = admin dbpassword = 8095uohoiw4ur90 dbhost = db-postgres-nyc1-1111-do-user-111111-0.db.ondigitalocean.com dbport = 25060 dbdatabase = defaultdb dbsslmode = require output: username: admin password: 8095uohoiw4ur90 host: db-postgres-nyc1-1111-do-user-111111-0.db.ondigitalocean.com port: 25060 ``` ### Automatic de-duplication - If two detectors match the same characters and have the same matches we drop the output of the detectors bringing less information. For example the following content `slack_token="xoxp-198947049743-7861195093-830655328819-9d40a979cac97bccf1190afb660b37e1"` triggers two detectors: our `slack_user_token` detector and our detector catching generic secrets (token=\{high_entropy_string\}). We only keep the results of the `slack_user_token` detector in order to reduce alert fatigue and attach the maximum information to help with the remediation process. ### Detecting prefixed Base64 encoded secrets Recent frameworks like Kubernetes use Base64-encoded secrets and it is becoming pretty common to see Base64-encoded secrets. We are able to detect prefixed secrets encoded in Base64 like private keys. ### Add insights to secrets to ease the work of security engineers and analysts We attach insights to secrets so the application security analysts can have more context information for the remediation. Currently we support the following insights: - `test_file`: We found the secret in a test context (test folder, test filename). - `sensitive_file`: We found the secret in a document with a filename considered as sensitive (`.env`, `credentials.json`, ...). - `whitelisted`: The secret has been white-listed by the developer that wrote the code. - `decoded value for encoded secret`: We can attach the decoded secret value to encoded secret. ## Limitations 1. We are not able to scan binary files (for now). Some binary filenames can contain secrets, such as `.pyc` files in Python for example. 2. By default, the number of secrets detected per detector and per file is capped at 8. For high-recall detectors that typically return a single match per document, this limit is increased to 50. These thresholds help prevent alert fatigue from noisy documents, while still handling files that legitimately contain many secrets (such as a file with dozens of Slack webhooks). We always recommend reviewing the full document when a secret is detected, as it may contain additional sensitive information that wasn't surfaced. ## Architecture Our secret detection engine is based on the following logic: ```mermaid graph LR Doc[Document] --> Ban{Banlisted?} Ban -->|Yes| Drop1[Drop] Ban -->|No| Kw{Has keywords?} Kw -->|No| Drop2[Drop] Kw -->|Yes| Scan[Scanner] Scan --> Cand[Candidate] Cand --> Post[Post-validation] Post -->|Pass| Secret[Secret] ``` We use `PreValidators` to remove some filenames bringing false positives or to select a document based on the presence of a keyword. For example every `SendGrid API key` must start with the prefix `SG.`, we can discard all documents that don't contain this prefix. You can find more information about pre-validators [here](./validation.md#pre-validation). Our `Scanner` is a collection of detectors that scans a `Document` and yields `Secret` candidates. We then use `PostValidators` to validate if our secret candidates are real secrets. We configure `PostValidators` for each `Detector` so we can achieve the best trade-off between recall and precision. Post-validation rules filter out false positives by: - Filtering example keys - Filtering secrets with low entropy - Filtering secrets with substrings from English dictionary - Machine learning models to exclude false secrets based on context You can find more information about all the `PostValidators` we currently use and support [here](./validation.md#post-validation). --- ## Secrets Analyzers Two Slack API keys may seem to offer the same accesses, but their associated permissions can differ significantly. If a secret with the permission `read:profile` is exposed, it will cause less harm than a secret with `read:everything`. It's important to share this information with users so they can prioritize their remediation efforts. The Secrets Analyzer feature offers additional context on detected secrets, including their roles and permissions, as well as relevant contextual information such as ownership and perimeter when found. This helps security teams evaluate the potential impact of a secret incident and effectively prioritize their remediation efforts. Understanding the context of a secret is a game changer for assessing the impact of a secret incident, as it directly correlates to the possible damages in the event of a breach. ## Activate the feature The feature is activated by default. To disable it, navigate to `Settings > Secrets > General`. Once activated, the analyzer will immediately work on upcoming incidents but also existing incidents. ## Helping Prioritize with a Built-in Saved View: `Critical Scopes` To help you quickly identify incidents involving secrets with permissions that require your immediate attention, we provide the built-in saved view `Critical Scopes`. This view filters for the most critical permissions associated with the analyzers we currently implement. In the future, we will update this saved view to include additional permissions as we add more analyzers. ![Secrets Analyzer Saved View](/img/secrets-detection/secrets-analyzers/secrets_analyzer_saved_view.png) #### What permissions does this saved view encompass ? ##### GitHub PAT Fine Grained ``` # Repo permissions Administration:Read, ReadWrite Contents:Read, ReadWrite Environments:Read, ReadWrite Secret scanning alerts:Read,ReadWrite Secrets:Read, ReadWrite # Accounts permissions Codespaces user secrets:Read, ReadWrite GPG keys: Read, ReadWrite Git SSH keys: Read, ReadWrite ``` ##### GitHub PAT Classic ``` admin:org repo write:packages write:org delete:packages read:org admin:public_key admin:org_hook delete_repo admin:enterprise admin:gpg_key admin:ssh_signing_key ``` ##### Gitlab PAT ``` api read_repository read_api admin_mode sudo ``` ##### Stripe ``` credit_note_read credit_note_write coupon_read promotion_code_read terminal_reader_read terminal_reader_write secret_write token_read token_write transfer_read transfer_write charge_read charge_write apple_pay_domain_read apple_pay_domain_write terminal_connection_token_write ``` ## New Filters for Navigating Incidents with Discovered Permissions The **Secret Scopes** filter enables you to filter incidents based on the permissions associated with your secret. This lets you quickly identify incidents involving secrets with the most impactful permissions. Additionally, the **Secret Analyzer** lets you filter incidents by their analyzer statuses, such as "Successful" and "Failed." ![Secrets Analyzer Filters](/img/secrets-detection/secrets-analyzers/secrets_analyzer_filters.png) ## When is the analysis triggered ? This chapter outlines the automated system for secret analysis. The system performs regular checks on secrets to ensure analysis results are up-to-date. ### Backpopulate Task A backpopulate task runs every 15 minutes to identify any secrets missing analysis and initiates the analysis process for them. This ensures continuous monitoring of all secrets in the system. ### Immediate Task Scheduling Tasks are scheduled for immediate execution in the following scenarios: - **Incident Creation**: When a new incident is created, analysis is scheduled immediately and typically completes within a few minutes. - **Manual Trigger**: When a user manually triggers an analysis, the task is scheduled immediately and typically completes within a few minutes. ### Periodic Re-checking For secrets that have already been analyzed, the system implements a periodic re-checking mechanism. #### Validity Check and Analysis Secrets with validity status of **VALID**, **NOT_CHECKED**, or **FAILED_TO_CHECK** are re-checked periodically until they are found invalid. During these checks, both validity verification and analysis are performed. #### Check Frequency The frequency of checks varies based on several factors: 1. **Incident Status**: Whether the incident is open, resolved, or ignored 2. **Incident Age**: Whether the incident is recent (less than 1 year old) or old This approach prevents excessive API calls that could trigger rate limits on the checked services, which would compromise the accuracy of the checks. #### Default Check Periods (in days) | Status & Age | Business Account | |-------------|-----------------| | Open & Recent | 1 | | Open & Old | 7 | | Resolved & Recent | 30 | | Resolved & Old | 178 | | Ignored & Recent | 178 | | Ignored & Old | Never | *Note: "Never" indicates that no automatic re-checking is scheduled for these categories.* ## Available Analyzers - [Airtable API Key](./detectors/specifics/airtable_apikey.md#secret-analyzer) - [Algolia Keys](./detectors/specifics/algolia_keys.md#secret-analyzer) - [Artifactory Access Token](./detectors/specifics/artifactory_access_token.md#secret-analyzer) - [Artifactory Reference Token With Host](./detectors/specifics/artifactory_reference_token_with_host.md#secret-analyzer) - [Artifactory Token](./detectors/specifics/artifactory_token.md#secret-analyzer) - [Auth0 Keys](./detectors/specifics/auth0_keys.md#secret-analyzer) - [Bitbucket Access Token](./detectors/specifics/bitbucket_access_token.md#secret-analyzer) - [BitBucket App Password](./detectors/specifics/bitbucket_app_password.md#secret-analyzer) - [Buildkite API Token](./detectors/specifics/buildkite_api_token.md#secret-analyzer) - [CircleCI Personal Token](./detectors/specifics/circleci_personal_token.md#secret-analyzer) - [DigitalOcean Spaces Keys](./detectors/specifics/digitalocean_spaces_token.md#secret-analyzer) - [Fastly Personal Token](./detectors/specifics/fastly_personal_token.md#secret-analyzer) - [GitHub Personal Access Token](./detectors/specifics/github_access_token.md#secret-analyzer) - [GitLab Token](./detectors/specifics/gitlab_token.md#secret-analyzer) - [HubSpot Private Application Token](./detectors/specifics/hubspot_private_app_token.md#secret-analyzer) - [Hugging Face user access token](./detectors/specifics/hugging_face_user_access_token.md#secret-analyzer) - [IBM Cloud Key](./detectors/specifics/ibm_cloud_key.md#secret-analyzer) - [Jira Token](./detectors/specifics/jira_token.md#secret-analyzer) - [MongoDB Credentials](./detectors/specifics/mongodb_credentials.md#secret-analyzer) - [MySQL Credentials](./detectors/specifics/mysql_credentials.md#secret-analyzer) - [OpenAI Admin API Key](./detectors/specifics/openai_admin_apikey.md#secret-analyzer) - [OpenAI API Key](./detectors/specifics/openai_apikey.md#secret-analyzer) - [OpenAI Project API Key](./detectors/specifics/openai_project_apikey.md#secret-analyzer) - [OpenAI Project API Key v2](./detectors/specifics/openai_project_apikey_v2.md#secret-analyzer) - [OpenAI Service Account](./detectors/specifics/openai_service_account.md#secret-analyzer) - [PayPal OAuth2 Keys](./detectors/specifics/paypal_oauth2_keys.md#secret-analyzer) - [Plaid Keys](./detectors/specifics/plaid_keys.md#secret-analyzer) - [PostgreSQL Credentials](./detectors/specifics/postgresql_credentials.md#secret-analyzer) - [SendGrid Key](./detectors/specifics/sendgrid_key.md#secret-analyzer) - [SendinBlue Key](./detectors/specifics/sendinblue_key.md#secret-analyzer) - [Shopify Generic App Token With Subdomain](./detectors/specifics/shopify_generic_app_token_subdomain.md#secret-analyzer) - [Slack App Token](./detectors/specifics/slack_app_token.md#secret-analyzer) - [Slack User Token](./detectors/specifics/slack_user_token.md#secret-analyzer) - [Slack Bot Token](./detectors/specifics/slackbot_token.md#secret-analyzer) - [Square Token](./detectors/specifics/square_token.md#secret-analyzer) - [Stripe Keys](./detectors/specifics/stripe_keys.md#secret-analyzer) - [Terraform Cloud Token](./detectors/specifics/terraform_cloud_token.md#secret-analyzer) - [Xray Access Token](./detectors/specifics/xray_access_token.md#secret-analyzer) - [Zendesk Token](./detectors/specifics/zendesk_token.md#secret-analyzer) ## Infrastructure If your account is on our SaaS environment (EU or US), please be aware that all requests made by the Secret Analyzer will originate [from these listed IP addresses.](/internal-monitoring/integrate-sources/monitored-perimeter#troubleshooting-connectivity-problems) --- ## Pre-Validators and Post-Validators A `Detector` consists of three core components: - **Pre-Validators**: These rules are applied before the detection process begins. They determine whether the detection should proceed. - **Matchers**: Matchers are string extractors that identify and return matched strings, also known as "matches". Typically, matchers use regular expressions, but they can be more complex, such as detecting connection strings. - **Post-Validators**: These rules are applied after the matchers. They validate the identified matches. Note that post-validators can be applied to a single match or to all matches found by the matcher. ## Pre-Validation Pre-validators are an essential component of the secrets detection process. They serve as an initial filter, determining whether further analysis and detection should occur. Pre-validators apply specific rules and conditions before the actual detection process takes place. Their purpose is to ensure that documents meet certain criteria before scanning them. These criteria include checking for specific patterns in the content, filename, path or extensions, or banning minified JavaScript files. Pre-validators optimize the scanning process by focusing on relevant documents. The following pre-validators are used by our secrets detection engine: - `BanMinifiedPreValidator`: Bans minified JavaScript files based on a specified threshold. - `ContentWhitelistPreValidator`: Returns true if the filename or content contains specific patterns. - `FilenameWhitelistPreValidator`: Returns true if the filename matches an allow-listed name or extension. - `FilenameBanlistPreValidator`: Returns false if the filename matches a ban-listed name, path, or extension. ## Post-Validation Post-validators are critical in the secrets detection pipeline as they validate and filter the matches identified by the matchers. After the initial matches are identified, post-validators apply additional rules and checks to determine the legitimacy of the detected secrets. These validators ensure that the matches meet specific criteria, such as banning common false positives. They can also assess the entropy of the matches, verify the presence of a minimum number of digits, and apply various heuristics to filter out irrelevant matches. Post-validators provide an additional layer of validation and fine-tuning, improving the accuracy and reliability of the detected secrets by reducing the false positives rate and enhancing the overall effectiveness of the secrets detection engine. The following post-validators are used by our secrets detection engine: - `AssignmentBanlistPostValidator`: Discards matches based on the pattern of their assignment variables. - `CommonHostBanlistPostValidator`: Bans commonly used false positive hosts. - `CommonPasswordBanlistPostValidator`: Bans commonly used false positive passwords. - `CommonUsernameBanlistPostValidator`: Bans commonly used false positive usernames. - `CommonHighEntropyBanlistPostValidator`: Bans commonly used placeholder or generic high entropy values. - `CommonValueBanlistPostValidator`: Bans commonly used false positive generic values. - `DictFilterPostValidator`: Filters out matches that contain common dictionary words. - `EntropyPostValidator`: Ensures that the entropy of the match is above a specified threshold. - `HeuristicPostValidator`: Applies various heuristics to filter out certain types of matches. - `MatchesPostValidator`: Applies post-validators to a subset of matches. - `MinimumDigitsPostValidator`: Verifies that matches contain a minimum number of digits. - `ValueBanlistPostValidator`: Bans matches that match specific value patterns. - `ValueSimilarityPostValidator`: Bans match groups with a similarity above a specified threshold. - `ContextWindowBanlistPostValidator`: Bans value patterns in a window around the matched string. ## Example Let's consider the example of the [Slack App Token](detectors/specifics/slack_app_token.md) detector. It utilizes a `ContentWhitelistPreValidator` pre-validator which specifically looks for the prefix `xapp-` in the documents, which is a rare occurrence, appearing in only around one document per million on GitHub. As a result, the pre-validator quickly eliminates 99.9999% of the documents, significantly narrowing down the search. Here are some examples of documents that would be accepted by the pre-validator: ```bash curl -X POST https://slack.com/api/chat.postMessage \ -d '{"channel":"C12345678","text":"Hello, Slack!"}' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer xapp-1-XQ1QRVG5098-91645510917198-7bda3ae63ec19bcbc94c9907a52835cd47f8835e0a7553ffa3a494a4bd82e572" ``` ```text bin/xfce4-set-wallpaper include/xapp/libxapp/xapp-gtk-window.h ``` ```python SLACK_APP_TOKEN="xapp-1-ABCDEFGHIJK-12345678901234-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ``` Among those documents, the matcher identifies two matches: - `xapp-1-XQ1QRVG5098-91645510917198-7bda3ae63ec19bcbc94c9907a52835cd47f8835e0a7553ffa3a494a4bd82e572` - `xapp-1-ABCDEFGHIJK-12345678901234-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` However, the Slack App Token detector also employs an `EntropyPostValidator`, which filters out the second match due to its low entropy. In conclusion, based on the example documents, the detector successfully identifies the only valid secret: `xapp-1-XQ1QRVG5098-91645510917198-7bda3ae63ec19bcbc94c9907a52835cd47f8835e0a7553ffa3a494a4bd82e572`. --- ## GitGuardian Architecture The GitGuardian application is built on a flexible cloud-native architecture. It leverages Helm charts for streamlined deployment, offering two primary methods: the KOTS admin interface (KOTS-based deployment) or the Helm CLI (Helm-based deployment). ## Scalable and Modular Architecture GitGuardian employs a modular architecture, where each core component is deployed as an independent service. This design enhances scalability and allows for greater flexibility: - **Replica Scaling:** Adjust the number of replicas for each service to meet demand. - **Resource Configurations:** Fine-tune resource requests and limits. These settings can be configured via Helm during installation or within the KOTS UI with some restrictions. - **Dedicated Workers:** Create dedicated worker pods to handle high-demand queues (available in Helm-based deployments). - **Autoscaling:** Leverage Horizontal Pod Autoscaling to automatically adjust worker pod counts based on load. #### Architecture Overview The GitGuardian architecture uses a single entry point for all API calls—either an Ingress or a Service of type LoadBalancer—which routes traffic through an Nginx service acting as both a frontend and a reverse proxy. Nginx is responsible for distributing incoming requests among the internal APIs, public APIs, and hook APIs. In this setup, Nginx handles all the routing logic, and there is only one Ingress or LoadBalancer resource exposing the application to the outside world. ![GitGuardian Architecture](/img/self-hosting/gitguardian-arch-ingress-agnostic.drawio.png) For more details on deployment configurations, pod types, and usage, check the [GitGuardian Application Topology](./troubleshoot/topology) page. For scaling guidelines, visit [Scaling GitGuardian](./management/infrastructure-management/scaling). ## ClickHouse for high-scale analytics Some features require [ClickHouse](./management/infrastructure-management/clickhouse/overview), an optional in-cluster stateful component shipped as part of the GitGuardian Helm chart, used for analytics workloads that require fast queries over large volumes of data. Unlike PostgreSQL and Redis, it is not designed to be replaced by a fully externally managed service: it always runs in-cluster, backed by object storage that you provide. ## Helm command line support The `helm install` feature enables streamlined deployment and management via the widely adopted Helm package manager. This integration simplifies installation, upgrades, and configuration as code. Looking ahead, future releases will extend support for GitOps tools like ArgoCD and introduce more advanced configuration options, including: - External Secrets Operator - Istio Service Mesh & Gateway - Certificate Manager **Learn More:** [Install on an Existing Cluster using Helm](./installation/installation-existing-cluster-helm). ## Enhanced security with Chainguard integration The GitGuardian architecture incorporates [Chainguard](https://www.chainguard.dev), a next-generation security tool that helps mitigate Common Vulnerabilities and Exposures (CVEs) in self-hosted container images. With Chainguard, GitGuardian strengthens its security posture by: - Reducing vulnerability risks in container images. - Implementing FIPS-approved cryptographic modules for secure encryption of sensitive data both at rest and in transit. This integration reinforces GitGuardian’s commitment to meeting the highest security and compliance standards. **Read More:** [Common Vulnerabilities and Exposures](./security/recommendations#common-vulnerabilities-and-exposures). --- ## Install on an Existing Cluster using Helm (airgap) ## Introduction This guide covers installing GitGuardian in air-gapped environments using Helm on an existing Kubernetes cluster. In air-gapped environments, there is no direct internet connectivity, so this installation method requires downloading GitGuardian Helm charts and images from the internet on a separate machine, then transferring them to your isolated environment. ## Prerequisites ### Required Infrastructure 1. **Kubernetes Cluster**: A running Kubernetes cluster in your isolated environment. See [system requirements](../system-requirements#kubernetes-for-existing-clusters) for details. For OpenShift clusters, refer to the [OpenShift installation guidelines](./openshift). 2. **PostgreSQL Database**: An external PostgreSQL instance with required extensions installed. See [database configuration](./databases/database-config) for setup details. 3. **Redis Instance**: A dedicated Redis instance. See [system requirements](../system-requirements#redis) for configuration details. 4. **Private Image Registry**: A private container registry accessible from your Kubernetes cluster to host GitGuardian images. ### Additional Requirements 5. **Helm**: Helm version 3.13+ installed. See [system requirements](../system-requirements#helm) for version compatibility. Currently, deployment of the app using Helm charts supports only **Helm CLI**, **[ArgoCD](https://argo-cd.readthedocs.io/en/stable/getting_started/)**, and **[FluxCD](https://fluxcd.io/flux/installation/)**. 6. **Domain Name**: A Fully Qualified Domain Name (FQDN) for accessing the application. See [system requirements](../system-requirements#domain-name-requirements). 7. **Image Transfer Tools**: Tools like [Docker](https://docs.docker.com/) or [Skopeo](https://github.com/containers/skopeo) to transfer images to your private registry. 8. **Network Access**: Ensure your isolated environment meets the [network requirements](../network-requirements#isolated-network). :::caution Requirements Before starting the installation, ensure to review the **[system](../system-requirements)** and **[network](../network-requirements#isolated-network)** requirements. ::: ## Installation ### Accessing and Downloading the GitGuardian Helm Chart ⚠️ Ensure you're using the latest version of [helm](https://helm.sh/docs/helm/helm_install/). The GitGuardian Helm chart is available in the Replicated private registry. The license is included directly in the Helm chart, so no separate license file download is required. 1. **Login to Helm chart registry**: Contact the GitGuardian team at support@gitguardian.com to obtain the password. Log in with this command (replace email with the one provided by GitGuardian): ```bash helm registry login registry.replicated.com --username your.name@yourcompany.com ``` 2. **Download Helm chart locally**: After logging in, download and extract the GitGuardian Helm chart into a local directory (e.g., `/home/user`) using: ```bash cd /home/user helm fetch oci://registry.replicated.com/gitguardian/gitguardian ``` ### Download GitGuardian Images :::tip GitGuardian images are accessible through the Replicated proxy registry. To learn how to connect it to a Harbor or JFrog Container Registry instance for pull-through image caching, visit [Using a Registry Proxy for Helm Air Gap Installations](https://docs.replicated.com/vendor/using-third-party-registry-proxy). ::: You may get current versions in [values reference documentation](/self-hosting/management/infrastructure-management/helm-values). Below is a list of images to download and upload to your private image registry: | Image Type | Repository and Image Name | 2026.8.1 | | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | GitGuardian Frontend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-static-chainguard | 2026.8.1 | | GitGuardian Backend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard | 2026.8.1 | | Helm Tooling — preflights, support bundle, and upgrade path check (until 2026.4.0) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-helm-tooling | 2026.8.1 | | Replicated SDK — [licensing](/self-hosting/license-management) | proxy.replicated.com/proxy/gitguardian/docker.io/replicated/replicated-sdk | 1.19.10 | | [Machine Learning](/self-hosting/management/application-management/machine-learning) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/ml-secret-engine-app-chainguard | 2.0.0 | | [File Scanner](/self-hosting/management/application-management/non-vcs-sources) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/apache-tika | 3.3 | | [Analytics](/platform/analytics/overview) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/basalt-onprem-analytics | 0.8.1 | | [ggscout](/ggscout-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/ggscout/chainguard | 0.31.1 | | [MCP Server](/ggmcp-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/mcp-server | 0.7.0 | | [ClickHouse](/self-hosting/management/infrastructure-management/clickhouse/overview) | proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com/cgr.dev/gitguardian.com/clickhouse-iamguarded | 26.2 | | [ClickHouse backup sidecar](/self-hosting/management/infrastructure-management/clickhouse/backup-restore) | proxy.replicated.com/proxy/gitguardian/docker.io/altinity/clickhouse-backup | 2.8.0 | | [Log collector](/self-hosting/troubleshoot/logs) — fluent-bit | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/fluent-bit | 4.2.4 | | [Log collector](/self-hosting/troubleshoot/logs) — loki | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/loki | 3.7.7 | | [Log collector](/self-hosting/troubleshoot/logs) — minio | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/minio | 0.20260717 | | Bash — [Custom CA](/self-hosting/security/custom-ca) and upgrade path check (starting 2026.5.0) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/bash | 5.3 | The MCP Server and both ClickHouse images are only needed if you enable those components (`mcpServer.enabled` and `clickhouse.enabled`, both `false` by default). :::caution ClickHouse backup sidecar The backup sidecar is the one image the chart does not resolve through `global.imageRegistry`, because it is declared as a plain container in `clickhouse-server.sidecars`. Mirroring it into your private registry is not enough: you also have to point the sidecar at your copy by overriding `clickhouse-server.sidecars` in your values file. ::: | Image Type | Repository and Image Name | 2026.8.1 | | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | GitGuardian Frontend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-static-chainguard | 2026.8.1 | | GitGuardian Backend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard | 2026.8.1 | | Helm Tooling — preflights, support bundle, and upgrade path check (until 2026.4.0) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-helm-tooling | 2026.8.1 | | Replicated SDK — [licensing](/self-hosting/license-management) | proxy.replicated.com/proxy/gitguardian/docker.io/replicated/replicated-sdk | 1.19.10 | | [Machine Learning](/self-hosting/management/application-management/machine-learning) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/ml-secret-engine-app-chainguard | 2.0.0 | | [File Scanner](/self-hosting/management/application-management/non-vcs-sources) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/apache-tika | 3.3 | | [Analytics](/platform/analytics/overview) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/basalt-onprem-analytics | 0.8.1 | | [ggscout](/ggscout-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/ggscout/chainguard | 0.31.1 | | [MCP Server](/ggmcp-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/mcp-server | 0.7.0 | | [ClickHouse](/self-hosting/management/infrastructure-management/clickhouse/overview) | proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com/cgr.dev/gitguardian.com/clickhouse-iamguarded | 26.2 | | [ClickHouse backup sidecar](/self-hosting/management/infrastructure-management/clickhouse/backup-restore) | proxy.replicated.com/proxy/gitguardian/docker.io/altinity/clickhouse-backup | 2.8.0 | | [Log collector](/self-hosting/troubleshoot/logs) — fluent-bit | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/fluent-bit | 4.2.4 | | [Log collector](/self-hosting/troubleshoot/logs) — loki | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/loki | 3.7.7 | | [Log collector](/self-hosting/troubleshoot/logs) — minio | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/minio | 0.20260717 | | Bash — [Custom CA](/self-hosting/security/custom-ca) and upgrade path check (starting 2026.5.0) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/bash | 5.3 | The MCP Server and both ClickHouse images are only needed if you enable those components (`mcpServer.enabled` and `clickhouse.enabled`, both `false` by default). :::caution ClickHouse backup sidecar The backup sidecar is the one image the chart does not resolve through `global.imageRegistry`, because it is declared as a plain container in `clickhouse-server.sidecars`. Mirroring it into your private registry is not enough: you also have to point the sidecar at your copy by overriding `clickhouse-server.sidecars` in your values file. ::: Contact the GitGuardian team at support@gitguardian.com to obtain your license ID. Use this ID to authenticate with the GitGuardian image repository by executing the command below. Replace `` with your actual License ID. ```shell LICENSE_ID=""; echo "{\"auths\": {\"proxy.replicated.com\": {\"auth\": \"$(echo -n "${LICENSE_ID}:${LICENSE_ID}" | base64)\"}, \"registry.replicated.com\": {\"auth\": \"$(echo -n "${LICENSE_ID}:${LICENSE_ID}" | base64)\"}}}" > ~/.docker/config.json ``` Example on how to download the images with docker pull with the latest release: ::::info Image architecture All GitGuardian images are published as multi-architecture (multi-arch) manifests. The correct image variant is automatically selected based on the Docker engine host architecture. :::: ```bash docker pull proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-static-chainguard:2026.8.1 docker pull proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard:2026.8.1 docker pull proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-helm-tooling:2026.8.1 docker pull proxy.replicated.com/proxy/gitguardian/docker.io/replicated/replicated-sdk:1.19.10 docker pull proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/ml-secret-engine-app-chainguard:2.0.0 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/apache-tika:3.3 docker pull proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/basalt-onprem-analytics:0.8.1 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/ggscout/chainguard:0.31.1 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/ggscout/chainguard-bash:0.31.1 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/mcp-server:0.7.0 docker pull proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com/cgr.dev/gitguardian.com/clickhouse-iamguarded:26.2 docker pull proxy.replicated.com/proxy/gitguardian/docker.io/altinity/clickhouse-backup:2.8.0 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/fluent-bit:4.2.4 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/loki:3.7.7 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/minio:0.20260717 docker pull proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/bash:5.3 ``` You can verify that the images have been correctly downloaded and upload them to your private image registry. ```bash docker images | grep replicated ``` :::info For this process, you can utilize a tool like [Skopeo](https://github.com/containers/skopeo) to handle image transfers. Additionally, if you need to set up a proxy to access the replicated registry, refer to the [Docker documentation](https://docs.docker.com/network/proxy/#configure-the-docker-client). ::: ### Upload GitGuardian Images Ensure the following directory structure is respected in your **private registry**: | Image Type | Path and image name | | --------------------------- | --------------------------------------------------- | | GitGuardian Frontend | `/gitguardian/prm-static-chainguard` | | GitGuardian Frontend (FIPS) | `/gitguardian/prm-static-chainguard-fips` | | GitGuardian Backend | `/gitguardian/prm-app-chainguard` | | GitGuardian Backend (FIPS) | `/gitguardian/prm-app-chainguard-fips` | | Helm Tooling | `/gitguardian/prm-helm-tooling` | | Replicated SDK | `/replicated/replicated-sdk` | | Machine Learning | `/gitguardian/ml-secret-engine-app-chainguard` | | Machine Learning (FIPS) | `/gitguardian/ml-secret-engine-app-chainguard-fips` | | File Scanner | `/gitguardian/wolfi/apache-tika` | | Analytics | `/gitguardian/basalt-onprem-analytics` | | ggscout | `/gitguardian/ggscout/chainguard` | | ggscout (bash) | `/gitguardian/ggscout/chainguard-bash` | | MCP Server | `/gitguardian/mcp-server` | | ClickHouse | `/cgr.dev/gitguardian.com/clickhouse-iamguarded` | | Log collector — fluent-bit | `/gitguardian/wolfi/fluent-bit` | | Log collector — loki | `/gitguardian/wolfi/loki` | | Log collector — minio | `/gitguardian/wolfi/minio` | | Bash | `/gitguardian/wolfi/bash` | The ClickHouse backup sidecar is not part of this structure: it is the one image the chart does not resolve through `global.imageRegistry`, so its location in your registry is whatever you set in `clickhouse-server.sidecars`. #### FIPS Compliance for Airgap Installations :::info FIPS (Federal Information Processing Standards) compliance is available for airgap Helm installations with additional steps. ::: If you require FIPS-compliant cryptographic modules for your air gap installation, download the FIPS images (with `-fips` suffix): - `proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-static-chainguard-fips` - `proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard-fips` - `proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/ml-secret-engine-app-chainguard-fips` ### Kubernetes Application RBAC {#kubernetes-application-rbac} The following RBAC roles are required for the proper functioning of the application, enabling the Replicated SDK to validate customer license entitlements, ensuring non-skippable versions are not bypassed during upgrades, and allowing [in-cluster support bundle generation](../troubleshoot/support#generate-from-the-admin-area-in-cluster) (restricted by a `ValidatingAdmissionPolicy`). If you are not a `cluster-admin` in your Kubernetes cluster, you will need to apply the configuration below in your targeted namespace ``:
RBAC Roles Helm install ```yaml # GitGuardian Role --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: gim-role rules: - apiGroups: - '' resources: - configmaps - secrets verbs: - get - list - watch # Spawns the support-bundle collector pod. Locked down by a # ValidatingAdmissionPolicy (Kubernetes 1.30+) — see Troubleshoot > Support. - apiGroups: - '' resources: - pods verbs: - create - apiGroups: - '' resources: - pods - pods/log verbs: - get - delete resourceNames: - gitguardian-support-bundle # GitGuardian RoleBinding --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gim-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: gim-role subjects: - kind: ServiceAccount name: gim-migration - kind: ServiceAccount name: gim # Upgrade-path-check Role --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: upgrade-path-check rules: - apiGroups: - '' resources: - configmaps verbs: - get - list # Upgrade-path-check RoleBindng --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: upgrade-path-check roleRef: kind: Role name: upgrade-path-check apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: upgrade-path-check # Replicated SDK Role --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: replicated-role rules: - apiGroups: - '' resources: - configmaps - persistentvolumeclaims - pods - secrets - services verbs: - get - list - watch - apiGroups: - apps resources: - daemonsets - deployments - replicasets - statefulsets verbs: - get - list - watch - apiGroups: - networking.k8s.io - extensions resources: - ingresses verbs: - get - list - watch - apiGroups: - '' resources: - secrets verbs: - create - apiGroups: - '' resources: - secrets verbs: - update resourceNames: - replicated - replicated-instance-report - replicated-custom-app-metrics-report - replicated-meta-data # Replicated SDK RoleBinding --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: replicated-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: replicated-role subjects: - kind: ServiceAccount name: replicated # Support Bundle # Below role is mandatory --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: support-bundle namespace: rules: - apiGroups: ['*'] resources: ['*'] verbs: ['get', 'list', 'watch'] - apiGroups: [''] resources: ['pods/exec'] verbs: ['create'] # This role is optional and is used to retrieve cluster-scoped information, which can be useful for troubleshooting --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: support-bundle rules: - apiGroups: [''] resources: ['namespaces', 'nodes'] verbs: ['get', 'list', 'watch'] - apiGroups: ['apiextensions.k8s.io'] resources: ['customresourcedefinitions'] verbs: ['get', 'list', 'watch'] - apiGroups: ['storage.k8s.io'] resources: ['storageclasses'] verbs: ['get', 'list', 'watch'] ```
### Create encryption secret Create a Kubernetes secret in the target namespace with `DJANGO_SECRET_KEY`. GitGuardian uses it to encrypt sensitive application data in the database. See [Mandatory secret](./helm-secrets#mandatory-secret) for commands and values. :::caution Backup the key It is critical to back up your key in a secure vault. Key loss results in irreversible data loss from your GitGuardian instance. ::: ### Customize the local values file This installation offers multiple customization options. Use a local values file (named `local-values.yaml`) for customizations when installing any Helm application. Ensure your values file configures these essential elements: At the minimum, your values must configure the following elements: - `hostname` - `postgres` - `redis` - `onPrem.adminUser` Below is an example values file covering these elements, **adapted for airgap installation**: ```yaml hostname: gitguardian.internal.yourcompany.com # Hostname where the instance will be accessed # Airgap-specific configuration global: imageRegistry: docker.internal/example/path # Location of the GitGuardian images in your private registry image: registry: docker.internal/example/path # Location of the GitGuardian images (same as imageRegistry) imagePullSecrets: - name: pull-secret # Existing docker secret used to pull images from your private registry proxy: noProxyHostNames: - 127.0.0.1 - 10.0.0.0/8 existingSecret: 'gim-proxy' existingSecretKeys: httpProxyUrl: 'http_proxy' # Secret should contain: http://username:password@proxy.company.com:8080 httpsProxyUrl: 'https_proxy' # Secret should contain: https://username:password@proxy.company.com:8080 replicated: isAirgap: false # Set to true only for environments without Internet access and no HTTP proxy configured privateCASecret: # optional if you are using a custom CA name: custom-ca-secret-name key: 'custom-ca.pem' extraEnv: - name: NO_PROXY valueFrom: configMapKeyRef: name: gim-config key: 'NO_PROXY' - name: HTTP_PROXY valueFrom: secretKeyRef: name: 'gim-proxy' key: 'http_proxy' # Example: http://username:password@proxy.company.com:8080 - name: HTTPS_PROXY valueFrom: secretKeyRef: name: 'gim-proxy' key: 'https_proxy' # Example: https://username:password@proxy.company.com:8080 postgresql: host: gitguardian-postgres # PostgreSQL host username: postgres # PostgreSQL username database: gitguardian # PostgreSQL database name existingSecret: gitguardian-postgresql-secret # Kubernetes secret where to check the PostgreSQL password existingSecretKeys: password: postgres-password # Name of the key containing password in the secret redis: main: host: gitguardian-redis # Redis host tls: enabled: false # Set TLS encryption for Redis existingSecret: gitguardian-redis-secret # Kubernetes secret where to check the Redis password existingSecretKeys: url: redis-url # Name of the key containing redis url in the secret onPrem: adminUser: email: your.name@yourcompany.com # email of the instance admin user firstname: YourName # name of the instance admin user ``` **Important Airgap Configuration Notes:** Replace `docker.internal/example/path` with your private registry and the appropriate path where the images are stored in your registry. Ensure you maintain the specified directory structure outlined in the "Upload GitGuardian Images" section. For detailed guidance on: - configurable parameters, refer to the [Helm Chart Values Reference](../management/infrastructure-management/helm-values) page. - `existingSecret` parameter and its setup process, visit the [Helm Sensitive Information Management](./helm-secrets) page. - database configuration, see [Configure Your Database](./databases/database-config). - scaling options, consult the [Scaling Documentation](../management/infrastructure-management/scaling). - HTTP proxy, see [Configure a proxy server](../management/infrastructure-management/proxy-server). ### Enable FIPS Compliance (Optional) If you require FIPS-compliant cryptographic modules, you can enable them by adding the following to your `local-values.yaml` file: ```yaml global: fips: enabled: true ``` When FIPS is enabled in airgap environments, ensure you have downloaded and uploaded the FIPS images as outlined in the [FIPS Compliance for Airgap Installations](#fips-compliance-for-airgap-installations) section above. The installation will automatically use FIPS-compliant versions of the application images that include specialized cryptographic modules meeting Federal Information Processing Standards. For more information about FIPS compliance and security considerations, see the [Security Recommendations](../security/recommendations) page. ### Configure network access to the application The application front end is behind a Service object named `nginx`. You can configure access to the application in different ways: 1. Configure the service as a `LoadBalancer` using `front.service.type` value. See [Load-balancer](../management/infrastructure-management/load-balancer) for more details. 2. Add an Ingress object routing to the `nginx` service. See [Ingress](../management/infrastructure-management/ingress) for more details. 3. If your cluster has `istio` service mesh, activate it with the `istio.enabled` value. This will enable the proper Gateway and VirtualService objects. Please note that the `nginx` service is not configured with SSL support. You must configure it and manage your TLS certificate through your Load-Balancer, Ingress or Service Mesh. ### Run preflight checks 🚦 :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the installation must not continue until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../system-requirements)**. ::: We strongly advise you to run our preflight script to ensure your existing cluster meets GitGuardian's requirements. Retrieve the script from our public repository [here](https://github.com/GitGuardian/ggtools/tree/main/helm-preflights). Specify an existing Kubernetes namespace using the `-n` option. If not specified, the script will run in your default namespace. Replace `` with your desired [helm release name](https://helm.sh/docs/intro/using_helm/#helm-install-installing-a-package). **For airgap installations**, use the local Helm chart file: ```bash ./preflights.sh -r -n gitguardian-.tgz -f local-values.yaml ``` ### Install the application Use the following command to install the application using your `local-values.yaml` file. Replace `` with your desired [helm release name](https://helm.sh/docs/intro/using_helm/#helm-install-installing-a-package). Specify an existing kubernetes namespace with the `-n` option. If not specified, Helm installs GitGuardian in your default namespace. Use the `--create-namespace` option to create the namespace if it doesn't exist. **For airgap installations**, use the local Helm chart file instead of the remote repository: ```bash helm install --timeout 30m -n --create-namespace gitguardian-.tgz -f local-values.yaml ``` **Note**: The installation may take a few minutes due to database migrations. ### Verify the installation Upon successful installation, you should see the following output: ```shell NAME: LAST DEPLOYED: Mon May 15 16:15:56 2023 NAMESPACE: STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Thank you for installing GitGuardian Internal Monitoring. ``` These notes can later be retrieved with `helm get notes ` ### Save the Data Encryption Key :::caution GitGuardian encrypts all sensitive information in the database using an encryption key (aka Django Secret Key). In case of disaster recovery, this key will be needed to restore your data. ::: When you don't specify it either using inline parameter `miscEncryption.djangoSecretKey` or using an existing secret with `miscEncryption.existingSecret`, the data encryption key is automatically generated by the Helm chart. You should save it and keep it in **a secure location**. Use the following command to display the key: ```shell kubectl get secrets gim-secrets --namespace= -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ### Application login Upon successful installation, you will need to get your temporary admin password. Use the following command: ```bash kubectl get secrets gim-secrets --namespace= -o jsonpath='{.data.ADMIN_PASSWORD}'| base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). You can access the application using the hostname you provided, using the login with the email provided in the `onPrem.adminUser.email` and the temporary password. ### Troubleshooting If you encounter issues during the installation process, you can generate a support bundle for the GitGuardian team to diagnose and resolve problems more efficiently. See the [support bundle documentation](../troubleshoot/support#helm-based-installation) for detailed instructions. ## Next Steps After successful installation: - Access your GitGuardian instance using the hostname you configured - Log in with the administrator credentials you set up (change the temporary password on first login) - Configure [email settings](../management/application-management/email-configuration) for notifications - Set up [SSO](../../platform/enterprise-administration/saml-sso-configuration) and [SCIM](../../platform/enterprise-administration/scim-configuration) integration (optional) - [Integrate your first repositories](/platform/getting-started/integrate) to begin secret detection --- ## Install airgap using KOTS existing cluster ## Introduction :::danger Deprecation Notice The KOTS existing cluster installation method is deprecated as of the June 2026 release (version 2026.6.0) and will be completely removed in the 2027.1 release. Deprecated installation methods no longer benefit from the latest platform improvements, such as ClickHouse-based analytics and S3 object storage support. We strongly recommend migrating to the [Helm installation on an existing cluster](./airgap-installation-existing-cluster-helm) as soon as possible. See the [customer notice](/support/customer-notices/kurl-kots-installation-deprecation) for details, or reach out to [support@gitguardian.com](mailto:support@gitguardian.com) for guidance on your migration. ::: **⚠️ Use the [Helm installation on an existing cluster](./airgap-installation-existing-cluster-helm) unless instructed otherwise.** This guide covers installing GitGuardian in air-gapped environments using KOTS (Kubernetes Off-The-Shelf) on an existing Kubernetes cluster. In air-gapped environments, there is no direct internet connectivity, so this installation method requires downloading GitGuardian bundles from the internet on a separate machine, then transferring them to your isolated environment. ## Prerequisites ### Required Infrastructure 1. **Kubernetes Cluster**: A running Kubernetes cluster in your isolated environment. See [system requirements](../system-requirements#kubernetes-for-existing-clusters) for details. For OpenShift clusters, refer to the [OpenShift installation guidelines](./openshift). 2. **PostgreSQL Database**: An external PostgreSQL instance with required extensions installed. See [database configuration](./databases/database-config) for setup details. 3. **Redis Instance**: A dedicated Redis instance. See [system requirements](../system-requirements#redis) for configuration details. 4. **Private Image Registry**: A private container registry accessible from your Kubernetes cluster to host GitGuardian images. ### Additional Requirements 1. **License File** (for KOTS installation): Download your GitGuardian license from the portal. See [license management](../license-management) for instructions. 2. **Network Access**: Ensure your isolated environment meets the [network requirements](../network-requirements#isolated-network). 3. **Domain Name**: A Fully Qualified Domain Name (FQDN) for accessing the application. See [system requirements](../system-requirements#domain-name-requirements). :::caution Requirements Before starting the installation, ensure to review the **[system](../system-requirements)** and **[network](../network-requirements#isolated-network)** requirements, and **[download your license](../license-management)**. ::: ## Installation ### Download and Install the KOTS Admin Console First, install the `kubectl` KOTS plugin on your machine: ```shell curl https://kots.io/install | bash ``` Then, you need to download the latest bundle for the KOTS Admin Console. There are two places to download it. The first and recommended one is the download portal where you can also download your license and the application bundle. The second one is the [release assets on GitHub](https://github.com/replicatedhq/kots/releases). In both cases, make sure to match your locally installed KOTS plugin version. You can check it by running: ```shell kubectl kots version ``` ### Kubernetes Application RBAC {#kubernetes-application-rbac} The KOTS Admin Console will have full control over all resources across all namespaces in the cluster. More information in [Replicated documentation](https://docs.replicated.com/vendor/packaging-rbac#about-cluster-scoped-rbac). If you are not `cluster-admin` in your Kubernetes cluster or do not want to grant the KOTS Admin Console such wide permissions, you will need to apply the below configuration in your targeted namespace ``:
RBAC Roles KOTS install ```yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: kotsadm namespace: labels: kots.io/backup: velero kots.io/kotsadm: 'true' --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: kotsadm-role namespace: labels: kots.io/backup: velero kots.io/kotsadm: 'true' rules: - apiGroups: [''] resources: [ 'configmaps', 'persistentvolumeclaims', 'pods', 'secrets', 'services', 'limitranges', 'serviceaccounts', ] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['apps'] resources: [ 'daemonsets', 'deployments', 'deployments/scale', 'replicasets', 'statefulsets', ] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['batch'] resources: ['jobs', 'cronjobs'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['networking.k8s.io', 'extensions'] resources: ['ingresses', 'networkpolicies'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['policy'] resources: ['poddisruptionbudgets'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: [''] resources: ['namespaces', 'endpoints'] verbs: ['get'] - apiGroups: ['authorization.k8s.io'] resources: ['selfsubjectaccessreviews', 'selfsubjectrulesreviews'] verbs: ['create'] - apiGroups: ['rbac.authorization.k8s.io'] resources: ['roles', 'rolebindings'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: [''] resources: ['pods/log', 'pods/exec'] verbs: ['get', 'list', 'watch', 'create'] - apiGroups: ['batch'] resources: ['jobs/status'] verbs: ['get', 'list', 'watch'] - apiGroups: ['monitoring.coreos.com'] resources: ['servicemonitors'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: [''] resources: ['events'] verbs: ['list'] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kotsadm-rolebinding namespace: labels: kots.io/backup: velero kots.io/kotsadm: 'true' roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kotsadm-role subjects: - kind: ServiceAccount name: kotsadm ```
### Upload Admin Console Images to Private Registry Now you need to upload these images to your registry using a user with write access to your internal registry: ```bash kubectl kots admin-console push-images ./kotsadm.tar.gz \ ${private.registry.host}/gitguardian \ --registry-username ${rw-username} \ --registry-password ${rw-password} ``` The username and password for the registry are not stored anywhere. ### Install the KOTS Admin Console Finally, you can run the install command for the KOTS Admin Console. If you are `cluster-admin`: ```bash kubectl kots install gitguardian \ --kotsadm-namespace gitguardian \ --kotsadm-registry ${private.registry.host} \ --registry-username ${ro-username} \ --registry-password ${ro-password} ``` If you are not `cluster-admin` (and applied the RBAC configuration above): ```bash kubectl kots install --ensure-rbac=false gitguardian \ --kotsadm-namespace gitguardian \ --kotsadm-registry ${private.registry.host} \ --registry-username ${ro-username} \ --registry-password ${ro-password} ``` A Kubernetes secret will be used to store these credentials. You will be prompted to choose a password to access the KOTS Admin Console if one wasn't provided during installation. An automatic port-forward is launched, you can now access the KOTS Admin Console on http://localhost:8800. :::tip **KOTS Admin Console** By default, this is accessed on http://localhost:8800 using this command `kubectl kots admin-console --namespace=`, which is a wrapper around `kubectl port-forward`. You can configure an ingress if you want a public endpoint. ::: ### Download Application Bundle First, you will need to download the license and the application bundle from the download portal. The application bundle filename should end with `.airgap`. ![Download portal airgap embedded](/img/self-hosting/installation/replicated_download_portal_airgap_existing.png) Transfer both the license file and the application bundle to your airgap environment where you can access the KOTS Admin Console. ## Application Configuration Once the KOTS Admin Console is running and you have uploaded the admin console bundle, you can proceed with the application configuration: 1. Enter the password provided at the end of the cluster installation. ![Admin console password](/img/self-hosting/installation/replicated_password_form.png) 2. Upload the license downloaded on the portal ([see instructions on how to download the license file](../license-management#download)). ![License upload](/img/self-hosting/installation/replicated_license_upload.png) 3. Configure the application. You need to fill in all the required fields: - **Application Hostname**: Enter the Fully Qualified Domain Name (FQDN) for the GitGuardian application. - **Admin User Fields**: These fields are used to create the first GitGuardian user. You'll need to change the password upon the first login. - **Databases**: You must select an external PostgreSQL and Redis, see [Configure your database](./databases/database-config). When utilizing Redis Sentinel for high availability, ensure that the Redis master password matches with the Redis sentinel's password and that you're using the correct Sentinel port (default: 26379). ![Admin console application configuration](/img/self-hosting/installation/replicated_configure_app.png) Additional configuration options include: - **Scaling**: Adjust the number of replicas for each application component. For more details, visit the [Scaling](../management/infrastructure-management/scaling) page. - **Prometheus**: Activate an exporter for [Prometheus](../management/application-management/metrics). - **Ingress TLS Certificate**: This is for the GitGuardian Application. You can either use auto-generated self-signed certificates or upload your own. For self-signed or private CA certificates, disable SSL verification for the GitHub webhook. Learn more on the [Configure TLS certificates](../security/tls-certificates) page. - **Load Balancer**: Change the Service type can be changed from ClusterIP to [LoadBalancer](../management/infrastructure-management/load-balancer) if needed. - **Custom Certificate Authority**: Provide a [custom CA](../security/custom-ca) if necessary. - **HTTP(s) Proxy**: Refer to the [proxy](../management/infrastructure-management/proxy-server) section if needed. 4. Check if preflight checks pass. :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the installation **must not continue** until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../system-requirements)**. ::: ![Admin console preflights](/img/self-hosting/installation/replicated_preflights.png) 5. Launch The first installation of the application requires a few minutes to create all database objects. Once the process is completed, you will be able to log in to the dashboard using the administrator user you defined. ### Save the Data Encryption Key :::caution GitGuardian encrypts all sensitive information in the database using an encryption key (aka Django Secret Key). In case of disaster recovery, this key will be needed to restore your data. ::: You should save it and keep it in **a secure location**. Use the following command to display the key: ```shell kubectl get secrets gim-secrets --namespace= -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ### Troubleshooting If you encounter issues during the installation process, you can generate a support bundle for the GitGuardian team to diagnose and resolve problems more efficiently. See the [support bundle documentation](../troubleshoot/support#kots-based-installation) for detailed instructions. ## Next Steps After successful installation: - Access your GitGuardian instance using the hostname you configured - Log in with the administrator credentials you set up (change the temporary password on first login) - Configure [email settings](../management/application-management/email-configuration) for notifications - Set up [SSO](../../platform/enterprise-administration/saml-sso-configuration) and [SCIM](../../platform/enterprise-administration/scim-configuration) integration (optional) - [Integrate your first repositories](/platform/getting-started/integrate) to begin secret detection --- ## Install using Argo CD ## Introduction Using the GitGuardian Helm repository, you can easily install GitGuardian on your existing Kubernetes cluster with [Argo CD](https://argo-cd.readthedocs.io/en/stable/). :::caution Requirements Before starting the installation, ensure to review the **[system](../system-requirements)** and **[network](../network-requirements)** requirements. ::: ## Known issue — Hook Jobs may not be re-triggered on chart upgrade {#hook-jobs-not-retriggered} :::warning Affects every GitGuardian chart upgrade through Argo CD with Server-Side Apply enabled We have observed a potential upstream Argo CD bug affecting GitGuardian Helm hook Jobs (`pre-deploy` for database migrations, `post-deploy`, `upgrade-path-check`, `data-access-deploy`) when the Argo CD `Application` is configured with `ServerSideApply=true`. On a chart upgrade, these Jobs may not be updated or re-triggered: Argo CD reports the sync as successful, but the previous Jobs remain in place on the cluster, so the migrations and post-deploy tasks never run for the new version. This can surface later as cryptic database errors (e.g. `column ... does not exist`). **Workaround**: if you suspect this has occurred after an upgrade, trigger a **manual sync** of the GitGuardian `Application` from the Argo CD UI or CLI: ```shell argocd app sync gitguardian ``` A manual sync re-creates the affected Job resources and properly re-runs the migrations and post-deploy steps for the new chart version. ::: ## Add GitGuardian Helm repository First, you need to add the GitGuardian Helm repository to Argo CD using the following settings: ```yaml name: gitguardian type: helm enableOCI: 'true' url: registry.replicated.com/gitguardian username: password: ``` The GitGuardian team will provide you the username and the password. You can follow the [official documentation](https://argo-cd.readthedocs.io/en/stable/user-guide/private-repositories/) and choose from the following methods: 1. [Declarative setup](https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories) Create the following Argo CD repository secret using `kubectl`: You need to set the username and the password before. ```shell cat < password: EOF ``` 2. [Argo CD CLI](https://argo-cd.readthedocs.io/en/stable/cli_installation/) :::caution Requirements You must first authenticate on your Argo CD server by using the command: `argocd login ` ::: Set your username/password and run this command: ```shell argocd repo add registry.replicated.com \ --name replicated \ --type helm \ --enable-oci \ --username \ --password ``` 3. [Argo CD UI](https://argo-cd.readthedocs.io/en/stable/user-guide/private-repositories/#https-username-and-password-credential) Navigate to `Settings/Repositories` and add the GitGuardian Helm repository: ![UI - add repository](/img/self-hosting/installation/installation_argocd_repository_1.png) :::caution Requirements Ensure to enable OCI ::: ![UI - enable OCI](/img/self-hosting/installation/installation_argocd_repository_2.png) Once added, you should see the GitGuardian Helm repository: ![UI - repository list](/img/self-hosting/installation/installation_argocd_repository_3.png) The connection status must be `successful`. ## Configure GitGuardian Application You can configure GitGuardian application by providing custom Helm values, follow the [Helm instructions](./installation-existing-cluster-helm) to proceed. We highly recommend managing secrets on your own and referencing them via `existingSecret` Helm parameters (See [Helm Secrets Management](./helm-secrets#existing-secret) page). We also suggest visiting the [Argo CD Secret Management page](https://argo-cd.readthedocs.io/en/stable/operator-manual/secret-management/) to efficiently manage your secrets. ## Create encryption secret Create a Kubernetes secret in the target namespace with `DJANGO_SECRET_KEY`. GitGuardian uses it to encrypt sensitive application data in the database. See [Mandatory secret](./helm-secrets#mandatory-secret) for commands and values. :::caution Backup the key It is critical to back up your key in a secure vault. Key loss results in irreversible data loss from your GitGuardian instance. ::: :::tip This secret is managed outside of Argo CD and will persist across syncs and upgrades. ::: ## Install GitGuardian Application After creating the Helm value file `values.yaml` following above instructions, you can create the GitGuardian application using Argo CD CLI by running the following command: ```shell argocd app create gitguardian \ --dest-server \ --dest-namespace \ --repo registry.replicated.com/gitguardian \ --helm-chart gitguardian \ --revision 2025.x.y \ --values-literal-file values.yaml \ --self-heal \ --auto-prune \ --sync-option PruneLast=true ``` If `autoscaling` is enabled, you must configure the Argo application to ignore changes made to the number of replicas for all deployments: ```shell argocd app patch gitguardian \ --patch '{"spec": {"ignoreDifferences": [{"group": "apps", "kind": "Deployment", "jsonPointers": ["/spec/replicas"]}]}}' \ --type merge ``` :::tip Missing status on MinIO bucket-init job If the MinIO bucket-init job appears with a **Missing** status in Argo CD, add the following annotations in your `values.yaml` to let Argo CD properly track the job: ```yaml loki-minio: bucketInitJob: annotations: argocd.argoproj.io/hook: Sync argocd.argoproj.io/hook-delete-policy: BeforeHookCreation ``` ::: ## Upgrade GitGuardian Application :::caution Prior to upgrading, ensure you back up your PostgreSQL database. For detailed instructions, refer to the **[Backup](../management/infrastructure-management/backup.md)** page. ::: To upgrade GitGuardian, you need first to update the Helm chart version using Argo CD CLI by running the following command: ```shell argocd app patch gitguardian \ --patch '{"spec": { "source": { "targetRevision": "2024.x.y" } }}' \ --type merge ``` Sync the GitGuardian app: ```shell argocd app sync gitguardian ``` --- ## Choose your installation method Before installing the application, you'll have to choose between these installation types: - **Existing Cluster using Helm** **(recommended)** - for deployments on existing Kubernetes clusters using Helm charts (includes GCP Marketplace option), - **Embedded Cluster using KOTS** - for all-in-one installations that create their own Kubernetes cluster with a web-based management interface. This guide will explain the differences between these methods and help you decide which is the best for your needs. ## What is Helm? **[Helm](https://helm.sh/)** is a package manager for Kubernetes, often referred to as the "Kubernetes equivalent of apt/yum/homebrew." It allows you to define, install, and upgrade even the most complex Kubernetes applications. Helm uses "charts," which are collections of YAML files that describe a related set of Kubernetes resources. This tool simplifies the management of Kubernetes applications by providing a single command to deploy an application, manage its lifecycle, and track version history. Helm configurations can be versioned in a Git Repository and integrate well with CD tools like ArgoCD or FluxCD. :::info FIPS Compliance **FIPS (Federal Information Processing Standards) compliance is available exclusively for Helm-based installations.** If you require FIPS-compliant cryptographic modules for regulatory compliance, you must choose the Helm installation method. For more details, see the [Security Recommendations](../security/recommendations) page. ::: #### GCP Marketplace GitGuardian is also available on **[GCP Marketplace](https://console.cloud.google.com/marketplace/product/gitguardian-public/gitguardiansaas)**, Google Cloud's platform for discovering, deploying, and managing third-party software solutions. This enables deployment on Google Kubernetes Engine (GKE) clusters with **consolidated billing through your GCP account**. The main benefits of GCP Marketplace deployment are consolidated billing through your GCP invoice, the ability to apply committed use discounts, and simplified procurement through existing GCP agreements. The GCP Marketplace deployment uses **Helm**. The initial deployment is done through the GCP console, but upgrades and ongoing management are performed directly with Helm, this means you get all the benefits of Helm-based installations. For more details, see the [GCP Marketplace deployment guide](https://github.com/GitGuardian/gcpmarketplace). ## What is KOTS? **KOTS** (Kubernetes Off-The-Shelf) is a framework designed to help software vendors manage the lifecycle of Kubernetes applications in a way that’s user-friendly for enterprise customers. It provides a set of tools and a UI that simplifies the deployment, management, and support of Kubernetes applications. ## What is an existing cluster installation You can install the application on an existing Kubernetes cluster that already contains nodes using Helm. Ensure this cluster meets the [system](../system-requirements) and [network](../network-requirements) requirements. The [database preparation section](./databases/database-config) will help you correctly configure them for your environment. :::tip Quick PoC setup on an existing cluster For a Proof of Concept or testing, you can quickly stand up PostgreSQL and Redis inside your cluster using the **[helm-pg-redis-poc presets](https://github.com/GitGuardian/ggtools/tree/main/helm-pg-redis-poc)**, which provide ready-to-use Small/Medium/Large configurations aligned with the [Scaling](../management/infrastructure-management/scaling) guide. For production, prefer your cloud provider's managed services. ::: ![Existing Installation Schema with an external database](/img/self-hosting/installation/installation_existing_external_db.png) If you plan to install GitGuardian on an OpenShift cluster, please refer to the [detailed guidelines for OpenShift cluster installation](./openshift). ## What is an embedded cluster installation The Embedded Installation is an "all-in-one" installation where the Kubernetes cluster is created on your machine, and all components needed for the application are installed. This installation method uses **KOTS** (Kubernetes Off-The-Shelf) to provide a user-friendly web interface for deployment and management. ![Embedded Installation Schema](/img/self-hosting/installation/installation_embedded.png) You can also use external databases to your embedded Kubernetes cluster (and we recommend it). The [database preparation section](./databases/database-config) will help you correctly configure them for your environment. ## How to choose between these options Before installing the application, you'll need to consider the following: - do you possess the necessary resources and expertise to manage your Kubernetes cluster? - do you have security policies in place in your Kubernetes cluster? - do you have the expertise and resources to handle your own databases? - will you require fine-tuning of the application? If you already have a Kubernetes cluster, that is running different applications, with precise management and security policies and a dedicated maintainer in your teams, you should use [the existing cluster installation using Helm](./installation-existing-cluster-helm). The application can be installed in a dedicated namespace for better isolation and organization. Please note you will also need access to Postgres database and Redis cache. Helm installation offers extensive configuration options and integrates well with automation pipelines and Infrastructure as Code practices. If you are deploying on **Google Cloud Platform** and want to consolidate billing through your GCP account, consider using the [GCP Marketplace deployment](https://console.cloud.google.com/marketplace/product/gitguardian-public/gitguardiansaas). This allows you to use your GCP committed spend and simplifies procurement while leveraging GCP's managed services (Cloud SQL, Memorystore, GKE). If you don't have resources dedicated to the maintenance of a Kubernetes cluster and databases, prefer [the embedded installation](./installation-embedded-cluster-v2), which uses KOTS to provide a user-friendly web interface for configuration and management. However, please note that embedded installations are not recommended for production use and are better suited for trial or Proof of Concept (PoC) purposes. ## Feature matrix: Existing cluster (Helm) vs Embedded cluster (KOTS) This feature matrix provides a comprehensive comparison between Helm installations (for existing clusters) and KOTS installations (for embedded clusters), highlighting their capabilities and key differences. | Feature Name | Existing Cluster (Helm) | Embedded Cluster (KOTS) | | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | ----------------------- | | [Infrastructure as Code (IaC)](../management/infrastructure-management/helm-values) deployment **(recommended)** | Yes | No | | [Graphical User Interface (GUI)](../management/infrastructure-management/admin-console) deployment | No | Yes | | [Airgap deployment](../installation/airgap-installation-existing-cluster-helm) | Yes | Yes | | [Support OpenShift](../installation/openshift) | Yes | Yes | | [External PostgreSQL and Redis](./databases/database-config) **(recommended)** | Yes | Yes | | [Embedded PostgreSQL and Redis](./databases/embedded) | No | Yes | | [Workload management (Replicas count)](../management/infrastructure-management/scaling#configure-scaling-settings) | Yes | Yes | | [Resources management (CPU/memory requests/limits)](../management/infrastructure-management/scaling#configure-scaling-settings) | Yes | Yes | | [HTTP Proxy](../management/infrastructure-management/proxy-server) | Yes | Yes | | [Custom CA](../security/custom-ca) | Yes | Yes | | [Load balancer + Ingress](../management/infrastructure-management/load-balancer) | Yes | Yes | | [ARM support](../system-requirements#architecture) | Yes | No | | [Ingress aware Architecture](../architecture#architecture-overview) | Yes | No | | [Horizontal Pod Autoscaling](../management/infrastructure-management/autoscaling) | Yes | No | | [External log aggregation systems](../troubleshoot/logs#helm-based-installation) | Yes | No | | [Generic Ephemeral Inline Volumes](../management/infrastructure-management/scaling#generic-ephemeral-inline-volumes) | Yes | No | | [Premium scan retry worker](../management/infrastructure-management/scaling#premium-scan-retry-worker) | Yes | No | | [Node Affinity Scheduling](../management/infrastructure-management/scaling#node-affinity-scheduling) | Yes | No | | [Istio service mesh](../management/infrastructure-management/helm-values) | Yes | No | | [Set custom labels on pods](../management/infrastructure-management/helm-values) | Yes | No | | [Existing Kubernetes secrets](../installation/helm-secrets#existing-secret) | Yes | No | | [Private Docker Registry](../installation/airgap-installation-existing-cluster-helm#upload-gitguardian-images) | Yes | No | | [Deploy with ArgoCD](../installation/argocd) | Yes | No | | [Deploy with FluxCD](../installation/fluxcd) | Yes | No | | [FIPS](../security/recommendations) | Yes | No | | [IPv6](../management/infrastructure-management/ipv6-networking) | Yes | No | | [GCP Marketplace](https://console.cloud.google.com/marketplace/product/gitguardian-public/gitguardiansaas) | Yes | No | --- ## Configure your database This guide will help you configure your database. Parameters here should not be changed after installation unless you know what you are doing, as it may result in data losses. :::caution If you are using external databases, remember to open ports between the GitGuardian application cluster and your databases. ::: ## PostgreSQL You can use the provided database with the embedded cluster installation or bring your own for both embedded and external cluster installations. We encourage you to use an external database. ### Embedded versus external The embedded PostgreSQL requires no additional configuration. It is great for testing and small-size instances. It does not provide high availability. For backups, refer to the [backup page](../../management/infrastructure-management/backup). The external PostgreSQL requires having an external database set up (e.g. with RDS on AWS). This is the recommended setup for large-scale deployments. Scaling, high availability, and backups should be managed with the provider's tools. :::tip Quick PoC setup on an existing cluster If you want to run PostgreSQL and Redis inside your Kubernetes cluster for a Proof of Concept or testing, you can use the **[helm-pg-redis-poc presets](https://github.com/GitGuardian/ggtools/tree/main/helm-pg-redis-poc)**. They provide ready-to-use Small/Medium/Large Helm configurations aligned with the [Scaling](../../management/infrastructure-management/scaling) guide. For production, prefer your cloud provider's managed services. ::: ### Embedded configuration :::info If you have not yet upgraded to PostgreSQL version 16, please follow the **[migration guide](https://github.com/GitGuardian/ggtools/tree/main/postgresql-16-upgrade)** to migrate your existing embedded cluster to PostgreSQL 16. ::: The embedded PostgreSQL is a PostgreSQL 16 running on a single pod. :::caution If you are using PgBouncer, add the following to the `pgbouncer.ini` file to allow GitGuardian tasks such as repository integration to perform correctly: ```bash [pgbouncer] pool_mode = session ignore_startup_parameters = options,[... other parameters if needed] ``` For additional details, visit: [PgBouncer Configuration](https://www.pgbouncer.org/config.html) ::: ### External configuration For an external PostgreSQL, you have the following configuration options: - **Host:** the IP or hostname for your PostgreSQL. Defaults to "postgres". - **Port:** the port on which PostgreSQL listens. Defaults to "5432". - **Username:** the user used to connect to the database. Required. - **Password:** the password used to connect to the database. Required. - **Database:** the name of the database to connect to. Defaults to "prm". The database must exist. - **Schema:** GitGuardian will use the default schema set for the user (usually 'public'). For scaling recommendations, refer to the hardware requirements [for embedded clusters](../../system-requirements#embedded-kubernetes-cluster-installation) or [existing clusters](../../system-requirements#existing-kubernetes-cluster-installation). ### Helm-based installation Helm installation currently supports only external databases. [When installing via Helm](../installation-existing-cluster-helm), parameters will be passed via a YAML file. The following parameters must be set inline : - `host` - `username` if relevant - `database` - `port` (5432 will be used as default) :::tip For ensuring that your databases are properly configured and accessible, you can use our **[preflight script](../installation-existing-cluster-helm#run-preflight-checks-)**. ::: As for the password, it can either be set inside a [Kubernetes secret](../helm-secrets), or set inline like the other parameters. Using secrets should be preferred over setting sensitive parameters inline in values. If you choose the first method, add a secret to your namespace, if it doesn't exist yet: ```shell kubectl create secret generic gitguardian-postgresql-secret \ --from-literal=POSTGRES_PASSWORD=my_pg_password ``` If you intend to [enable TLS for your PostgreSQL database](./tls#certificates-as-a-secret), the secret containing the password should also contain the TLS information. Refer to the secret as the `postgresql.existingSecret` parameter. the key to the password in this secret should be set as `postgresql.existingSecretKeys.password`: ```yaml postgresql: host: null # PostgreSQL database hostname username: null # PostgreSQL database username database: null # PostgreSQL database name port: 5432 existingSecret: gitguardian-postgresql-secret existingSecretKeys: password: 'POSTGRES_PASSWORD' ``` If you choose the second method, your YAML file should contain this extract: ```yaml postgresql: host: null # PostgreSQL Database host name username: null # PostgreSQL Database username database: null # PostgreSQL database name port: 5432 password: 'my_pg_password' ``` ### Database User Permissions When setting up your PostgreSQL database, it is essential to configure the database user with the appropriate permissions. The user specified in the configuration (`username` parameter) should be the owner of the database: ```sql ALTER DATABASE my_pg_database OWNER TO my_pg_database_user; ``` If this is not possible due to internal regulation, the user will need the following rights: 1. **Connection and object creation to the database:** The user should have the privilege to connect to the database, and to create extensions and schemas in it. ```sql GRANT ALL ON DATABASE my_pg_database TO my_pg_database_user; ``` 2. **Table and other objects Creation:** To create tables, indexes, triggers and views, the user needs the right to create objects in the specified schema. ```sql GRANT ALL ON SCHEMA public TO my_pg_database_user; ``` 3. **Data Modification Rights:** The user must have the necessary rights to insert, update, and delete data in the tables. ```sql GRANT ALL ON ALL TABLES IN SCHEMA public TO my_pg_database_user WITH GRANT OPTION; ``` ## Redis You can use the provided cache with the embedded cluster installation or bring your own for both embedded and external cluster installations. :::warning Redis Compatibility **Redis Cluster** is not supported by GitGuardian. Only **Redis Sentinel** is supported for high availability configurations. ::: ### Type: embedded/external The embedded Redis requires no additional configuration. It is great for testing and small-size instances. It does not provide high availability. For backups, refer to the [backup page](../../management/infrastructure-management/backup). The external Redis requires having an external cache set up (e.g. with Elasticache on AWS). This is the recommended setup for large-scale deployments. Scaling, high availability, and backups should be managed with the provider's tools. ### KOTS-based installation #### External configuration For an external Redis, you have the following configuration options: - **Host:** the IP or hostname for your Redis. Defaults to "redis". - **Port:** the port on which Redis listens. Defaults to "6379". - **Username:** the user used to connect to the cache. Can be left empty. - **Password:** the password used to connect to the cache. Required. - **Use TLS:** checkbox to specify how to communicate with Redis. #### External Redis Sentinel configuration For an external Redis Sentinel, you have the following configuration options: - **Host:** Comma-separated list of Redis Sentinel hosts. - **Port:** the port on which Redis listens. Defaults to "6379". - **Master Service Name:** the master Set name. Required. - **Master Username:** the master user used to connect to the cache. Can be left empty. - **Master Password:** the master password used to connect to the cache. Required. - **Sentinel Username:** the sentinel user used to connect to the cache. Can be left empty. - **Sentinel Password:** the sentinel password used to connect to the cache. Required. :::info TLS is not supported with Redis Sentinel. ::: When utilizing **Redis Sentinel** for high availability, ensure that the Redis master password matches with the Redis sentinel's password. By default, Sentinel operates on TCP port "26379". ### Helm-based installation [When installing via Helm](../installation-existing-cluster-helm), parameters will be passed via a YAML file. #### External redis server configuration You can pass the whole URL directly, or provide `host`, `username`, `password` and `port` individually. The URL will be composed in the following way: ``` redis(s)://$user:$password@$host:$port ``` Additionally, the `password` and `url` should be passed inline or via a [Kubernetes existing secret](../helm-secrets). Using secrets should be preferred over setting sensitive parameters inline in values. If you choose the first option, create a Kubernetes secret in your cluster containing either the URL or the password to your Redis, and refer to it as the `existingSecret` in your values file. ```shell kubectl create secret generic gitguardian-redis-secret \ --from-literal=REDIS_URL=my_redis_url ``` If you intend to [enable TLS for your Redis](./tls#certificates-as-a-secret), the secret containing the password should also contain the TLS information. Depending on your choices, your YAML file should contain one of: Sensitive parameter in secret (preferred) Sensitive parameter inline Url passed directly ```yaml redis: main: existingSecret: 'gitguardian-redis-secret' existingSecretKeys: url: 'REDIS_URL' ``` ```yaml redis: main: url: 'redis://:redis_password@123.456.789.123:6379' ``` Url recomposed from elements ```yaml redis: main: user: 'redis_user' host: '123.456.789.123' port: 6379 existingSecret: 'gitguardian-redis-secret' existingSecretKeys: password: 'REDIS_PASSWORD' ``` ```yaml redis: main: user: 'redis_user' host: '123.456.789.123' port: 6379 password: 'redis_password' ``` #### External Redis Sentinel configuration Under `redis.main`, you need to configure `user`, `password`. Those credentials belongs to the master. Under `redis.main.sentinel`, you need to configure `enabled`, `url`, `user`, `password` and `masterServiceName`. :::info TLS is not supported with Redis Sentinel. ::: Additionally, both `password` fields and `url` should be passed via a Kubernetes secret, though it is possible to pass them inline, or via an [external secret](../helm-secrets). Using secrets should be preferred over setting sensitive parameters inline in values. If you choose the first option, create a Kubernetes secret in your cluster containing either the URL or the password to your Redis, and refer to it as the `existingSecret` in your values file. ```shell kubectl create secret generic gitguardian-redis-secret \ --from-literal=REDIS_URL=my_redis_url ``` If you intend to [enable TLS for your Redis](./tls#certificates-as-a-secret), the secret containing the password should also contain the TLS information. Depending on your choices, your YAML file should contain one of: Sensitive parameter in secret (preferred) Sensitive parameter inline Sentinel ```yaml redis: main: existingSecret: gitguardian-redis-secret existingSecretKeys: password: redis-password sentinel: url: redis-sentinel-url password: redis-password sentinel: enabled: true masterServiceName: gitguardian-redis ``` ```yaml redis: main: password: 'redis_password' sentinel: enabled: true url: 123.456.789.123:26379 password: 'redis_sentinel_password' masterServiceName: gitguardian-redis ``` ### Second Redis instance for commit cache You can configure a second Redis instance that will be dedicated to the commit cache feature. Commit cache allows better performances for both real-time and historical scans by keeping the results of commits already scanned in a cache. You can configure a second Redis instance that will be dedicated to the commit cache feature. We only recommend this option for big instances (more than 100GB of code for the entire perimeter) where the commit cache should be configured with a minimum of 16GB. This second Redis instance has the same configuration options as the main one. On KOTS-based installations, you can access configuration options by checking the `Commit cache Redis` checkbox in the Redis section in the KOTS Admin Console. On Helm-based installations, you can configure this option [under the `redis.commitCache` keys](../../management/infrastructure-management/helm-values) in your values file. ## ClickHouse Some features require [ClickHouse](../../management/infrastructure-management/clickhouse/overview), used for high-scale analytics. Unlike PostgreSQL and Redis, there is no "bring your own external ClickHouse" option: ClickHouse is shipped and deployed as part of the GitGuardian Helm chart. What you configure is its local persistent volumes and its **object storage backend** (S3-compatible, Azure Blob Storage, or GCS): see [ClickHouse storage](../../management/infrastructure-management/clickhouse/storage). --- ## Embedded PostgreSQL and Redis ## Introduction To deploy the GitGuardian app, a PostgreSQL instance and a Redis instance are required. This page is dedicated to helping you set up and managed an embedded one. :::caution The GitGuardian application comes bundled with basic PostgreSQL and Redis. These are suitable for testing and small-scale infrastructures but are not intended for production use. For a more robust setup, we recommend using external, production-grade PostgreSQL and Redis. ::: ## High-Availability Embedded databases are **not** highly available. ## Installation Select "Embedded Postgres/Redis" on the configuration page during the installation, and choose the disk size if needed. But in most cases, the default disk size is enough. ## Upsizing the disk ### On an existing cluster If you installed the GitGuardian app on one of your clusters, you need to follow these steps: - Make sure your default storage class handles volume expansion - Check the `allowVolumeExpansion` flag for your default storage class. To get information about your storage classes, run `kubectl get storageclasses`: ```bash > kubectl get storageclasses.storage.k8s.io NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE default (default) ceph.rook.io/block Delete Immediate false 2d17h ``` - If needed, run `kubectl patch storageclass -p '{"allowVolumeExpansion": true}'`. - Go to the KOTS Admin Console, select the "Config" tab, edit the disk size, save the new configuration, and deploy it. - Upsizing will be done on the next restart of the PostgreSQL or Redis container. You can force it by deleting the pod. This will cause a small interruption in the application. #### Rook version >= 1.4.3 Follow these steps: - Set the `allowVolumeExpansion` flag to true with `kubectl patch storageclass default -p '{"allowVolumeExpansion": true}'` - Go to the KOTS Admin Console, select the "Config" tab, edit the disk size, save the new configuration, and deploy it. - Upsizing will be done on the next restart of the PostgreSQL or Redis container. You can force it by deleting the pod. This will cause a small interruption in the application. #### Rook version 1.0.4 This version of Rook Ceph does not handle volume expansion through Kubernetes. It's also not easily upgradeable. You can follow the procedure below to increase the size of your PostgreSQL or Redis disk. If you wish to upgrade from rook 1.0.4 to rook >= 1.4.3, you will need to do a backup/restore of your instance. To do this, follow [this procedure](../../management/infrastructure-management/backup). **Before continuing, please make sure you have functional backups. Documentation is available [here](../../management/infrastructure-management/backup)** First, make sure the package `e2fsprogs` is installed on your instance. To upsize the disk for PostgreSQL, run these commands. You can change the disk size (50G here), by using the same value in the first two commands. ```bash kubectl -n rook-ceph exec $(kubectl -n rook-ceph get pod -l app=rook-ceph-operator -o name | head -n1) -- rbd -p replicapool resize $(kubectl -n default get pvc -o custom-columns=NAME:.metadata.name,VOLUME:.spec.volumeName | grep postgresql-data | awk '{print $2}') --size 50G kubectl -n rook-ceph exec $(kubectl -n rook-ceph get pod -l app=rook-ceph-operator -o name | head -n1) -- rbd -p replicapool resize $(kubectl -n default get pvc -o custom-columns=NAME:.metadata.name,VOLUME:.spec.volumeName | grep postgresql-backup | awk '{print $2}') --size 50G sudo resize2fs /dev/$(lsblk | grep $(kubectl -n default get pvc -o custom-columns=NAME:.metadata.name,VOLUME:.spec.volumeName | grep postgresql-data | awk '{print $2}') | awk '{print $1}') sudo resize2fs /dev/$(lsblk | grep $(kubectl -n default get pvc -o custom-columns=NAME:.metadata.name,VOLUME:.spec.volumeName | grep postgresql-backup | awk '{print $2}') | awk '{print $1}') ``` To upsize the disk for Redis, run these commands. You can change the disk size (20G here). ```bash Inline kubectl -n rook-ceph exec $(kubectl -n rook-ceph get pod -l app=rook-ceph-operator -o name | head -n1) -- rbd -p replicapool resize $(kubectl -n default get pvc -o custom-columns=NAME:.metadata.name,VOLUME:.spec.volumeName | grep redis-data | awk '{print $2}') --size 20G sudo resize2fs /dev/$(lsblk | grep $(kubectl -n default get pvc -o custom-columns=NAME:.metadata.name,VOLUME:.spec.volumeName | grep redis-data | awk '{print $2}') | awk '{print $1}') ``` Resizing is done live, you do not need to restart the container. --- ## Azure Database: PostgreSQL on Azure ## Introduction To deploy the GitGuardian app, a PostgreSQL instance is required. This page is dedicated to helping you set up PostgreSQL on Azure using Azure Database for PostgreSQL (Flexible Server). ## High-Availability Azure Database for PostgreSQL Flexible Server provides built-in high availability with zone-redundant deployment. This ensures automatic failover and minimal downtime during maintenance or outages. For more details, see [High availability in Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-high-availability). ## Installation ### From the Azure Portal To create a PostgreSQL instance from the Azure Portal, we recommend following the [official documentation](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/quickstart-create-server-portal). We recommend you use the 'Production' configuration for high availability and security. You need to set the following fields: - Ensure `High availability` is set to `Zone redundant` for production workloads. - Set the `Authentication method` to `Password authentication`. - Set the `Admin username` to your liking or keep the default `azureuser`. - Set the `Password` or auto-generate it. You must save this value as it is required to configure the GitGuardian application. ### Using Terraform To create a PostgreSQL instance using Terraform, you need the following resources: - [azurerm_postgresql_flexible_server](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_flexible_server) In addition to the fields required by Terraform, we require the following fields to be set: - `administrator_login=`: username for the admin user. - `administrator_password=`: password for the admin user. - `high_availability.mode="ZoneRedundant"`: enables high availability. - `version`: set to a supported PostgreSQL version (e.g., `16`). ## Plugins installation (like pgvector) To install a plugin on Azure Database for PostgreSQL, your admin user can enable supported extensions directly. For more information, see [PostgreSQL extensions in Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions). This elevated privilege is only needed for plugin installation; the user configured in the GitGuardian application does not require it. --- ## Cloud SQL: PostgreSQL on GCP ## Introduction To deploy the GitGuardian app, a PostgreSQL instance is required. This page is dedicated to helping you set up a PostgreSQL on GCP using Cloud SQL. ## High-Availability GCP handles failover and redirects the traffic by itself. As long as your Cloud SQL is set up to be highly available, upgrades and single-node issues will not cause an outage. ## Installation ### From the Google Cloud Console To create a PostgreSQL from the Google Cloud Console, we recommend following the [official documentation](https://cloud.google.com/sql/docs/postgres/create-instance). To customize the database name, please follow [Create and manage databases](https://cloud.google.com/sql/docs/postgres/create-manage-databases). To customize the user used to access the database, please follow [Create and manage users](https://cloud.google.com/sql/docs/postgres/create-manage-users). You need to ensure that the Availability mode is set to `Multiple zones (Highly available)`. ### Using Terraform To create a PostgreSQL instance using TF, you need the following resources: - [google_sql_database_instance](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance) - (Optional) [google_sql_database](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database) - (Optional) [google_sql_user](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_user) In addition to the fields required by Terraform, we require the following fields to be set on the `google_sql_database_instance`: - `availability_type="REGIONAL"`: the availability type of the Cloud SQL instance, high availability (REGIONAL) or single zone (ZONAL). --- ## RDS: PostgreSQL on AWS ## Introduction To deploy the GitGuardian app, a PostgreSQL instance is required. This page is dedicated to helping you set up a PostgreSQL on AWS using RDS. ## High-availability AWS handles failover by updating a DNS record. This allows zero downtime for planned maintenance, upgrades and reboots. ## Installation ### From the AWS console To create a PostgreSQL from the AWS Console, we recommend following the [official documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateDBInstance.html). We recommend you use the `Production` template as it contains sensible defaults for a production-ready cluster. You need to set the following fields: - Ensure `Multi-AZ deployment` is set to `Create a standby instance`. - Ensure `Database authentication options` are set to `Password authentication`. - Set the `Master Username` to your liking or keep the default `postgres`. - Set the `Master password` or Auto generate it. You must save this value as it is required to configure the GitGuardian application. ### Using Terraform To create a PostgreSQL instance using TF, you need the following resources: - [aws_db_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance) In addition to the fields required by Terraform, we require the following fields to be set: - `engine=postgres`: the name of the database engine to be used for this DB cluster. - `username=`: username for the master DB user. - `password=`: password for the master DB user. ## Plugins installation (like pgvector) To install a plugin on RDS, your user need the `rds_superuser` role. This role is granted on your [RDS default master user](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser.html). This role is only needed for plugin installation, the user configured in GitGuardian application does not require the role. --- ## Azure Cache: Redis on Azure ## Introduction To deploy the GitGuardian app, a Redis instance is required. This page is dedicated to helping you set up Redis on Azure using Azure Cache for Redis. :::warning Redis Compatibility **Azure Managed Redis** is not supported by GitGuardian. Please use **Azure Cache for Redis** instead. ::: ## High-Availability Azure Cache for Redis provides high availability through its Premium and Standard tiers, which offer replication and automatic failover. During failover or maintenance, there may be a brief window where the GitGuardian application may experience read-only access or a short downtime. ## Installation ### From the Azure Portal To create an Azure Cache for Redis instance from the Azure Portal, we recommend reading the [official documentation](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/quickstart-create-redis). You need to set the following fields: - Choose the **Premium** or **Standard** tier for high availability. - Enable **Geo-replication** if cross-region redundancy is required. - Enable **SSL** to ensure encryption in transit. - Enable **Data persistence** if you require data recovery after failures (Premium tier only). - Set the **Access keys** (primary/secondary) as the Redis AUTH password. You must save this value as it is required to configure the GitGuardian application. :::info Our Helm installation supports Redis authentication from Azure Cache for Redis as long as the authentication is managed through a password mechanism and not via Azure Active Directory (AAD). ::: ### Using Terraform To create a Redis instance using Terraform, you need the following resources: - [azurerm_redis_cache](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/redis_cache) In addition to the fields required by Terraform, we require the following fields to be set: - `enable_non_ssl_port = false`: ensures only encrypted connections are allowed. - `minimum_tls_version = "1.2"`: enforces a secure TLS version. - `sku_name = "Premium"` or `"Standard"`: for high availability and replication. - `redis_configuration = { "maxmemory-policy" = "allkeys-lru" }`: recommended memory policy. - `redis_version = "6"` : Redis 6 is currently the latest available Redis version on Azure Cache. - Use the **primary_access_key** as the password for the GitGuardian application. - Enable **replicas_per_master** for additional redundancy (Premium tier). --- ## ElasticCache: Redis on AWS ## Introduction To deploy the GitGuardian app, a Redis instance is required. This page is dedicated to helping you set up a Redis on AWS using ElasticCache. ## High-Availability AWS handles failover by updating a DNS record. This creates a small window where the GitGuardian application will use the ReadOnly replica in case of maintenance. ## Installation ### From the AWS Console To create an ElasticCache from the AWS Console, we recommend reading the [official documentation](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/GettingStarted.CreateCluster.html). You need to set the following fields: - Ensure `Multi-AZ` is enabled. - Enable `Encryption at-rest`. - Enable `Encryption in-transit`. - Set `Access Control Option` to `Redis AUTH Default User`. - Set `Redis AUTH Token` to ``. You must save this value as it is required to configure the GitGuardian application. Do not enable `Cluster Mode`, this option is not supported by the GitGuardian application. :::info Our Helm installation supports Redis RBAC from AWS ElastiCache as long as the RBAC user authentication is managed through a password mechanism and not via IAM. ::: ### Using Terraform To create a Redis instance using TF, you need the following resources: - [elasticache_replication_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_replication_group) In addition to the fields required by Terraform, we require the following fields to be set: - `transit_encryption_enabled=true`: whether to enable encryption in transit. - `auth_token=`: the password used to access a password-protected server. - `at_rest_encryption_enabled=true`: whether to enable encryption at rest. - `automatic_failover_enabled=true`: specifies whether a read-only replica will be automatically promoted to read/write primarily if the existing primary fails. - `multi_az_enabled=true`: specifies whether to enable Multi-AZ Support for the replication group. --- ## MemoryStore: Redis on GCP ## Introduction To deploy the GitGuardian app, a Redis instance is required. This page is dedicated to helping you set up a Redis on GCP using MemoryStore. ## High-Availability GCP handles failover and redirects the traffic by itself. As long as your MemoryStore is set up to be highly available, upgrades and single-node issues will not cause an outage. ## Installation ### From the Google Cloud Console To create a MemoryStore from the Google Cloud Console, we recommend following the [official documentation](https://cloud.google.com/memorystore/docs/redis/creating-managing-instances). You need to set the following fields: - Enable `Redis AUTH` - Enable `in-transit encryption` - Set `Redis Tier` to `Standard` ### Using Terraform To create a Redis instance using TF, you need the following resources: - [google_redis_instance](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/redis_instance) In addition to the fields required by Terraform, we require the following fields to be set: - `auth_enabled=true`: indicates whether OSS Redis AUTH is enabled for the instance. If set to "true" AUTH is enabled on the instance. The default value is "false" meaning AUTH is disabled. - `auth_string=`: AUTH String set on the instance. This field will only be populated if auth_enabled is true. - `tier="STANDARD_HA"`: the service tier of the instance. Must be one of these values: - `transit_encryption_mode="SERVER_AUTHENTICATION"`: the TLS mode of the Redis instance, If not provided, TLS is disabled for the instance. --- ## Configure TLS ## KOTS-based installation ### PostgreSQL To configure TLS for an external PostgreSQL, you have the following configuration options: - PostgreSQL TLS mode: PostgreSQL server supports the following TLS mode: - Allow: first try an SSL connection; if that fails, try a non-SSL connection. - Require: only try an SSL connection. If a root Certificate Authority file is present, verify the certificate in the same way as if Verify Certificate Authority was specified. - Verify Certificate Authority: only try an SSL connection, and verify that the server certificate is issued by a trusted certificate authority (CA). - Verify Certificate Authority and Hostname: only try an SSL connection, and verify that the server certificate is issued by a trusted CA and that the requested server hostname matches that in the certificate. - Custom certificate authority: custom certificate authority to use to authenticate PostgreSQL server identity. - Client authentication required: PostgreSQL server configured to authenticate a client. - PostgreSQL client TLS key. - PostgreSQL client TLS certificate. To disable TLS configuration, you should first set "Postgres TLS mode" to Allow in the Admin Console and deploy the configuration. Then you can disable TLS on the PostgreSQL server. Finally, disable the TLS configuration within the Admin Console. ### Redis To configure TLS for Redis, you have the following configuration options: - Require Redis server authentication: force the application to require the Redis server to authenticate with a valid certificate. By checking this setting, you can provide a custom certificate authority to validate the Redis server certificate. - Client authentication required: if the Redis server is configured to require client authentication, you need to check this box and provide: - a TLS key, - a TLS certificate. For scaling recommendations, refer to the [hardware requirements documentation](/self-hosting/system-requirements). ## Helm-based installation With Helm-based installations, instead of parameters being set in the console, they should be put in a YAML file served at installation. There are 2 methods for handling certificates, but in both cases: - For PostgreSQL, set `postgresql.tls.mode` to the SSL mode of your choice among `disable`, `allow`, `prefer`, `require`, `verify-ca`, and `verify-full` - For Redis, set `redis.tls.requireServerCert` to true if you wish to require a Redis server certificate check. ### Certificates as a secret This is the preferred method. - Create a Kubernetes secret containing your custom certificate authority, TLS certificate and key. ```shell kubectl create secret generic gitguardian-(postgresql|redis)-tls-secret \ --from-file client.crt=/path/to/pg-tls-cert \ --from-file client.key=/path/to/pg-tls-key \ --from-file ca.crt=/path/to/ca-cert ``` :::caution Previously, Postgresql and Redis TLS secrets were referenced directly in `(postgresql|redis).existingSecret` by specifying keys in `(postgresql|redis).existingSecretKeys.tls.(crt|key|caCrt)`, they must be now referenced in `(postgresql|redis).tls.existingSecret` by specifying keys in `(postgresql|redis).tls.existingSecretKeys.(crt|key|caCrt)`. This change allows the use of TLS dedicated secrets. ::: - Reference this secret in the YAML file under `(postgresql|redis).tls.existingSecret` - Specify the keys used in the secret under `(postgresql|redis).tls.existingSecretKeys.(crt|key|caCrt)` The file should look like this extract: ```yaml postgresql: tls: # Possible values: disable, allow, prefer, require, verify-ca, verify-full mode: require existingSecret: gitguardian-postgresql-tls-secret existingSecretKeys: crt: client.crt key: client.key caCrt: ca.crt redis: main: tls: requireServerCert: true existingSecret: gitguardian-redis-tls-secret existingSecretKeys: crt: client.crt key: client.key caCrt: ca.crt ``` ### Certificates inline Add the certificates inline under `(postgresql|redis).tls.(crt|key|caCrt)` The file should look like this extract: ```yaml postgresql: tls: # Possible values: disable, allow, prefer, require, verify-ca, verify-full mode: require crt: | -----BEGIN CERTIFICATE----- My certificate -----END CERTIFICATE----- key: | -----BEGIN RSA PRIVATE KEY----- My key -----END RSA PRIVATE KEY----- caCrt: | -----BEGIN CERTIFICATE----- My CA certificate -----END CERTIFICATE----- redis: main: tls: requireServerCert: true crt: | -----BEGIN CERTIFICATE----- My certificate -----END CERTIFICATE----- key: | -----BEGIN RSA PRIVATE KEY----- My key -----END RSA PRIVATE KEY----- caCrt: | -----BEGIN CERTIFICATE----- My CA certificate -----END CERTIFICATE----- ``` --- ## Install using Flux CD ## Introduction Using the GitGuardian Helm repository, you can easily install GitGuardian on your existing Kubernetes cluster with [Flux CD](https://fluxcd.io/). :::caution Requirements Before starting the installation, ensure to review the **[system](../system-requirements)** and **[network](../network-requirements)** requirements. ::: ## Add the GitGuardian Helm repository First, you need to add the GitGuardian Helm repository to Flux CD using the following command: ```shell flux create source helm gitguardian \ --url=oci://registry.replicated.com/gitguardian/gitguardian \ --username= \ --password= ``` The GitGuardian team will provide you the username and the password. ## Configure the GitGuardian Application You can configure the GitGuardian application by providing custom Helm values, follow the [Helm instructions](./installation-existing-cluster-helm) to proceed. We highly recommend managing secrets on your own and referencing them via `existingSecret` Helm parameters (See [Helm Secrets Management](./helm-secrets#existing-secret) page). ## Create encryption secret Create a Kubernetes secret in the target namespace with `DJANGO_SECRET_KEY`. GitGuardian uses it to encrypt sensitive application data in the database. See [Mandatory secret](./helm-secrets#mandatory-secret) for commands and values. :::caution Backup the key It is critical to back up your key in a secure vault. Key loss results in irreversible data loss from your GitGuardian instance. ::: ## Install the GitGuardian Application You can define a Helm release to install the GitGuardian application using Flux CD by applying the following manifest: ```yaml apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: gitguardian spec: interval: 10m install: timeout: 30m upgrade: timeout: 30m chart: spec: chart: gitguardian version: 2025.x.y sourceRef: kind: HelmRepository name: gitguardian interval: 10m values: ``` --- ## Helm Sensitive Information Management ## Introduction GitGuardian Helm installations are configured through a values file (see [GitGuardian Helm Installation](./installation-existing-cluster-helm) for more information). It requires configuring sensitive information. GitGuardian supports three ways to set this information: - Sensitive parameters in Kubernetes secrets - Parameters inherited from external secrets (deprecated) - All parameters inline Passing sensitive information through secrets should be favored over the inline option. ## Kubernetes secrets In the namespace prepared for the GitGuardian installation, you can set up secrets to safely store the sensitive information needed for the deployment and the configuration. If you choose this method for the deployment, you can optionally specify Docker secrets used to pull images from a private container registry. For the configuration, two secrets are needed for PostgreSQL and Redis information, and another one can optionally be added for encryption parameters. ### Docker secret (optional) You can create a [Docker secret](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) to pull images from a private registry. Once created, you can specify the secret name in your `local-values.yaml` file: ```yaml global: imageRegistry: docker.internal # The host of the private registry imagePullSecrets: - name: pull-secret # The name of the secret previously created ``` With this configuration, pods will use `pull-secret` docker secret to pull images from the `docker.internal` private registry. > Note: Replicated SDK is not impacted by the `global.imageRegistry` attribute and is pulled directly from `docker.io` at the moment. You may pull this image from another registry using `replicated.images.replicated-sdk` and `replicated.imagePullSecrets`. ### Database parameters Check the relevant pages to see how to implement this option for : - [PostgreSQL password](./databases/database-config#postgresql) - [PostgreSQL TLS parameters](./databases/tls#postgresql) - [Redis password](./databases/database-config#redis) - [Redis TLS parameters](./databases/tls#redis) ### Existing secrets {#existing-secret} You can store sensitive configuration values in [Kubernetes secrets](https://kubernetes.io/docs/concepts/configuration/secret/) and reference them in your `local-values.yaml` file with the `existingSecret` parameter. :::tip Working with external secret stores The `existingSecret` parameter decouples GitGuardian from any external secret store. GitGuardian only reads sensitive values (Django secret key for database encryption, database and cache credentials, SAML certificates) from a Kubernetes secret already present in the cluster. We never connect to your secret manager directly. Your own tooling is responsible for getting secrets into that Kubernetes secret. For example: - [External Secrets Operator](https://external-secrets.io/) syncing from AWS Secrets Manager, GCP Secret Manager, or Azure Key Vault. - [Vault Secrets Operator](https://developer.hashicorp.com/vault/docs/platform/k8s/vso) syncing from HashiCorp Vault. GitGuardian has no role in that flow and requires no access to the upstream store. Using a Kubernetes secret for these credentials is standard Kubernetes practice and lets the application access them securely without coupling the deployment to your secret backend. ::: #### Mandatory secret You must pre-create the application encryption secret before deploying. Generate a random key and create the secret: ```shell DJANGO_SECRET_KEY=$(openssl rand -hex 32) && \ echo "⚠️ Please save this key in a secure vault: $DJANGO_SECRET_KEY" && \ kubectl create secret generic gitguardian-encryption \ --namespace \ --from-literal=DJANGO_SECRET_KEY="$DJANGO_SECRET_KEY" ``` ```powershell $DJANGO_SECRET_KEY = -join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Maximum 256) }) Write-Host "⚠️ Please save this key in a secure vault: $DJANGO_SECRET_KEY" -ForegroundColor Yellow kubectl create secret generic gitguardian-encryption ` --namespace ` --from-literal=DJANGO_SECRET_KEY=$DJANGO_SECRET_KEY ``` Then reference it in your `values.yaml`: ```yaml miscEncryption: existingSecret: 'gitguardian-encryption' existingSecretKeys: djangoSecretKey: 'DJANGO_SECRET_KEY' ``` #### Optional secrets You may choose to set parameters relevant to the application using an [existing secret](https://kubernetes.io/docs/concepts/configuration/secret/). You can create one or more secret(s) to store some sensitive information such as: - `ADMIN_PASSWORD`: admin password (only used during the first install) - `DB_ENCRYPTION_KEY`: encryption keys (optional, only needed for [database encryption key rotation](../security/database-security#update-postgresql-data-encryption-key)) - `REDIS_URL`: redis://username:password@host:port - `POSTGRES_PASSWORD` - `SP_X509_CERT`: a valid X509 certificate for SAML SP - `SP_PRIVATE_KEY`: a valid X509 private key for SAML SP ```bash kubectl create secret generic gitguardian-secret \ --from-literal=ADMIN_PASSWORD=my_admin_password \ --from-literal=REDIS_URL=my_redis_url \ --from-literal=POSTGRES_PASSWORD=my_postgres_password \ --from-file=SP_PRIVATE_KEY=/path/to/x509-key \ --from-file=SP_X509_CERT=/path/to/x509-cert \ --namespace ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). To reference this secret for installation, include this extract in your `local-values.yaml` file: ```yaml onPrem: adminUser: email: your.email@example.com firstname: user_name existingSecret: gitguardian-secret existingSecretKeys: password: ADMIN_PASSWORD postgresql: existingSecret: gitguardian-secret existingSecretKeys: password: POSTGRES_PASSWORD redis: main: existingSecret: gitguardian-secret existingSecretKeys: url: REDIS_URL miscEncryption: existingSecret: gitguardian-secret # The name of the secret previously created existingSecretKeys: x509Cert: SP_X509_CERT x509PrivateKey: SP_PRIVATE_KEY ``` In this case, as some pieces of configuration are managed outside of the Helm chart, you should consider using [Reloader](https://github.com/stakater/Reloader/blob/master/README.md) to automatically perform a rolling upgrade on relevant Kubernetes workloads like `Deployments`. For example, if you annotate the `gitguardian-secret` secret with `reloader.stakater.com/match: 'true'`, you can configure the following annotations in `local-values.yaml` to perform a rollout on secret changes: ```yaml front: nginx: annotations: reloader.stakater.com/search: 'true' webapps: hook: annotations: reloader.stakater.com/search: 'true' internal_api: annotations: reloader.stakater.com/search: 'true' internal_api_long: annotations: reloader.stakater.com/search: 'true' public_api: annotations: reloader.stakater.com/search: 'true' celeryWorkers: email: annotations: reloader.stakater.com/search: 'true' long: annotations: reloader.stakater.com/search: 'true' realtime-ods: annotations: reloader.stakater.com/search: 'true' scanners: annotations: reloader.stakater.com/search: 'true' worker: annotations: reloader.stakater.com/search: 'true' ``` After installation, if you didn't set these values yourself, you should retrieve the ones generated automatically and **store them in a secure location**. ```shell kubectl get secrets gim-secrets --namespace -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d kubectl get secrets gim-secrets --namespace -o jsonpath='{.data.SP_X509_CERT}' | base64 -d kubectl get secrets gim-secrets --namespace -o jsonpath='{.data.SP_PRIVATE_KEY}' | base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). :::note ClickHouse credentials If you enable [ClickHouse](../management/infrastructure-management/clickhouse/overview), it uses its own separate `clickhouse-credentials` secret holding `admin-password`, `api-password`, and `api-username`, not the shared `gitguardian-secret` above. See [ClickHouse → Prerequisites](../management/infrastructure-management/clickhouse/overview#prerequisites) for the full setup. ::: ## Inline parameters You may store all information required for the configuration directly in your `local-values.yaml` file. If you choose to do so, the below example file shows the minimal elements that are required for a successful installation. ```yaml hostname: gitguardian.internal.yourcompany.com postgresql: host: 'postgresql' username: postgres database: postgres password: postgres-password redis: main: url: redis-url onPrem: adminUser: email: your.email@example.com firstname: user_name ``` For optional fields that may be needed for your specific installations, such as TLS parameters, see the [values reference documentation](/self-hosting/management/infrastructure-management/helm-values). ```shell kubectl get secrets gim-secrets --namespace -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ## External Secret (deprecated) {#external-secret} :::caution External secrets handling is deprecated and removed in 2026.4.0. You must handle the management of `externalSecret` resources on your own and use `existingSecrets` parameters instead. This will help you to better organize and secure your secrets. ::: You may want to store the sensitive information in your secret management system. If that is the case, you should reference it in the `local-values.yaml` file in this way : ```yaml externalSecrets: enabled: true path: 'path/to/file' secretStoreRef: name: vault # The secretStoreRef name kind: SecretStore ``` The secret described there must contain the following keys : - `DJANGO_SECRET_KEY` - `REDIS_URL`: redis://username:password@host:port - `POSTGRES_PASSWORD` - `SP_X509_CERT`: a valid X509 certificate for SAML SP - `SP_PRIVATE_KEY`: a valid X509 private key for SAML SP ## Expected result After the installation, no matter the method you chose, there should be a secret called `gim-secrets` in your namespace. It is expected to contain 6 parameters : - `ADMIN_PASSWORD` - `DJANGO_SECRET_KEY` - `POSTGRES_PASSWORD` - `REDIS_URL` - `SP_PRIVATE_KEY` - `SP_X509_CERT` You can check this secret has been correctly created with: ```shell kubectl get secrets gim-secrets --namespace -o jsonpath='{.data}' | python -m json.tool ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). --- ## Install on an Embedded cluster ## Introduction **⚠️ Note that embedded installations are not recommended for production use and are better suited for trial or Proof of Concept (PoC) purposes. More information [here](./choose-embedded-existing#how-to-choose-between-these-options).** GitGuardian can be installed with an embedded Kubernetes distribution packaged with it and supports deployment on bare metal, private, or public clouds. ## Prerequisites ### Required Infrastructure 1. **Linux Virtual Machine**: See [system requirements](../system-requirements#embedded-kubernetes-cluster-installation) for detailed hardware and OS specifications, including the **Small / Medium / Large** sizing tiers for PoCs. Size the VM according to the volume you plan to scan during your PoC. Example VM instances per tier: | Tier | AWS | GCP | Azure | | :----- | :--------------------------------- | :----------------------------------- | :-------------------------------------- | | Small | `m7a.4xlarge` (16 vCPU / 64 GiB) | `n2-standard-16` (16 vCPU / 64 GB) | `Standard_D16s_v5` (16 vCPU / 64 GiB) | | Medium | `m7a.8xlarge` (32 vCPU / 128 GiB) | `n2-standard-32` (32 vCPU / 128 GB) | `Standard_D32s_v5` (32 vCPU / 128 GiB) | | Large | `m7a.16xlarge` (64 vCPU / 256 GiB) | `n2-standard-64` (64 vCPU / 256 GB) | `Standard_D64s_v5` (64 vCPU / 256 GiB) | :::caution Large-volume PoCs The single-node embedded cluster cannot scale horizontally. For high-volume PoCs (many repositories, or document sources such as SharePoint and OneDrive), provision a Large VM or use an **[existing cluster installation](./choose-embedded-existing#what-is-an-existing-cluster-installation)**. To quickly stand up PostgreSQL and Redis on an existing cluster for a PoC, you can use the **[helm-pg-redis-poc presets](https://github.com/GitGuardian/ggtools/tree/main/helm-pg-redis-poc)**, which provide Small/Medium/Large configurations aligned with the [Scaling](../management/infrastructure-management/scaling) guide. ::: ### Additional Requirements 2. **License File**: Download your GitGuardian license from the portal. See [license management](../license-management) for instructions. 3. **Network Access**: Ensure your cluster meets the [network requirements](../network-requirements). 4. **Domain Name**: A Fully Qualified Domain Name (FQDN) for accessing the application. See [system requirements](../system-requirements#domain-name-requirements). :::caution Requirements Review the complete **[system](../system-requirements)** and **[network](../network-requirements)** requirements before proceeding. ::: ## Installation ### Embedded cluster Contact the GitGuardian team at support@gitguardian.com to obtain your license ID. The license is embedded directly in the installer bundle, eliminating the need for a separate license file download. To begin the installation, execute the following commands on your host system. The installation process takes approximately 5 minutes to complete. Consider using a terminal multiplexer like `screen` or `tmux` to prevent interruption due to connection loss. Replace `your_license` with the license ID provided by the GitGuardian team. ```bash LICENSE_ID=your_license curl -f "https://replicated.app/embedded/gitguardian/stable" -H "Authorization: $LICENSE_ID" -o gitguardian.tgz tar -xvzf gitguardian.tgz sudo ./gitguardian install --license license.yaml ``` :::info **Airgap** To use in airgap mode, use this instead: ```bash LICENSE_ID=your_license curl -f https://replicated.app/embedded/gitguardian/stable?airgap=true -H "Authorization: $LICENSE_ID" -o gitguardian.tgz tar -xvzf gitguardian.tgz sudo ./gitguardian install --license license.yaml --airgap-bundle gitguardian.airgap ``` **HTTP Proxy** To use an HTTP proxy, use this instead: ```bash LICENSE_ID=your_license curl -f https://replicated.app/embedded/gitguardian/stable -H "Authorization: $LICENSE_ID" -o gitguardian.tgz tar -xvzf gitguardian.tgz sudo ./gitguardian install --license license.yaml \ --http-proxy http://proxy.example.com:8080 \ --https-proxy http://proxy.example.com:8080 ``` For proxies with authentication, include credentials in the URL: ```bash sudo ./gitguardian install --license license.yaml \ --http-proxy http://username:password@proxy.example.com:8080 \ --https-proxy http://username:password@proxy.example.com:8080 ``` For detailed proxy configuration instructions, including troubleshooting authenticated proxies, see the [HTTP Proxy documentation](../management/infrastructure-management/proxy-server#embedded-cluster-specific). ::: You will be prompted to enter the Admin console password. This password is used to manage the GitGuardian application and is different from the GitGuardian dashboard password that you will configure later. If you are prompted to select from multiple network interfaces, choose the one connected to your private network. This will install a single node-managed Kubernetes cluster with everything it needs to run the GitGuardian application. Once the installation is completed, instructions will appear on how to access the Admin Console. ![Installation's end screenshot](/img/self-hosting/installation/replicated_embedded_v2_end.png) :::note The deployment namespace for KOTS (and GitGuardian) cannot be changed at this time. ::: ### Application With the embedded Kubernetes cluster now set up, let's move on to installing the GitGuardian application. 1. Access the **Admin Console** with the link provided and configure TLS. You have the option to upload your TLS certificates or use self-signed ones. ![Admin console TLS setup](/img/self-hosting/installation/replicated_tls_setup.png) 2. Enter the password provided at the end of the cluster installation. ![Admin console password](/img/self-hosting/installation/replicated_password_form.png) 3. You can see cluster status (with one node currently). Then click continue. ![Cluster management](/img/self-hosting/installation/replicated_embedded_v2_cluster_view.png) 4. Configure the application by completing all the required fields: - **Application Hostname**: Enter the Fully Qualified Domain Name (FQDN) for the GitGuardian application. - **Admin User Fields**: These fields are used to create the first GitGuardian user. You'll need to change the password upon the first login. ![Admin Console Application Configuration](/img/self-hosting/installation/replicated_configure_app.png) Additional configuration options include: - **Scaling**: Adjust the number of replicas for each application component. For more details, visit the [Scaling](../management/infrastructure-management/scaling) page. - **Prometheus**: Activate an exporter for [Prometheus](../management/application-management/metrics). - **TLS Certificate**: This is for the GitGuardian Application. You can either use auto-generated self-signed certificates or upload your own. For self-signed or private CA certificates, disable SSL verification for the GitHub webhook. Learn more on the [Configure TLS certificates](../security/tls-certificates) page. - **Custom Certificate Authority**: Provide a [custom CA](../security/custom-ca) if necessary. - **HTTP(s) Proxy**: Refer to the [proxy](../management/infrastructure-management/proxy-server) section if needed. - **Databases/Datastores**: Choose between using embedded PostgreSQL/Redis or an external one. For more information, see [Configure your database](./databases/database-config). - **Load balancer considerations**: To use the embedded cluster behind a load balancer, please read [Configure your instance to work behind a load balancer](../management/infrastructure-management/load-balancer#embedded-clusters). 5. Check if preflight checks pass. :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the installation **must not continue** until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../system-requirements)**. ::: ![Admin console preflights](/img/self-hosting/installation/replicated_preflights.png) 6. Launch The first installation of the GitGuardian application requires a few minutes to create all database objects. Once the process is completed, you will be able to log in to the dashboard using the administrator user you defined. ### Save the Data Encryption Key :::caution GitGuardian encrypts all sensitive information in the database using an encryption key (aka Django Secret Key). In case of disaster recovery, this key will be needed to restore your data. ::: You should save it and keep it in **a secure location**. Use the following command to display the key: ```shell sudo ./gitguardian shell kubectl get secrets gim-secrets -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` ### Troubleshooting If you encounter issues during the installation process, you can generate a support bundle for the GitGuardian team to diagnose and resolve problems more efficiently. See the [support bundle documentation](../troubleshoot/support#kots-based-installation) for detailed instructions. ## Next Steps After successful installation: - Access your GitGuardian instance using the hostname you configured - Log in with the administrator credentials you set up (change the temporary password on first login) - Configure [email settings](../management/application-management/email-configuration) for notifications - Set up [SSO](../../platform/enterprise-administration/saml-sso-configuration) and [SCIM](../../platform/enterprise-administration/scim-configuration) integration (optional) - [Integrate your first repositories](/platform/getting-started/integrate) to begin secret detection --- ## Install on an Embedded cluster (kURL) ## Introduction :::danger Deprecation Notice The kURL embedded cluster installation method is deprecated as of the June 2026 release (version 2026.6.0) and will be completely removed in the 2027.1 release. Deprecated installation methods no longer benefit from the latest platform improvements, such as ClickHouse-based analytics and S3 object storage support. We strongly recommend migrating to the new [Embedded Cluster installation](./installation-embedded-cluster-v2) as soon as possible. See the [customer notice](/support/customer-notices/kurl-kots-installation-deprecation) for details, or reach out to [support@gitguardian.com](mailto:support@gitguardian.com) for guidance on your migration. ::: **⚠️ Use the new [Embedded Installation](./installation-embedded-cluster-v2) unless instructed otherwise.** GitGuardian can be installed with an embedded Kubernetes distribution packaged with it and supports deployment on bare metal, private, or public clouds. This installation uses [KOTS](https://kots.io), a kubectl plugin and KOTS Admin Console to help manage Kubernetes Off-The-Shelf software. :::caution Requirements Before starting the installation, ensure to review the **[system](../system-requirements)** and **[network](../network-requirements)** requirements, and **[download your license](../license-management)**. ::: ## Installation ### Embedded cluster To start the installation, run the following command on your host as root. This command will run for 10-20 minutes, putting in a screen or a `tmux` session can prevent an interruption due to a loss of connection. ```bash sudo -i curl -sSL https://kurl.sh/gitguardian | bash ``` If prompted to select from multiple network interfaces, opt for the one connected to your private network. This will install a single node-managed Kubernetes cluster with everything it needs to run the GitGuardian application. Once the installation is completed, instructions will appear on how to access the KOTS Admin Console. Use provided **IP address** on port **8800**. ![Installation's end screenshot](/img/self-hosting/installation/replicated_installation_end.png) Save this information, especially passwords, they will be useful later. ### Application With the embedded Kubernetes cluster now set up, let's move on to installing the GitGuardian application. 1. Access the **KOTS Admin Console** at `https://:8800` and configure TLS. You have the option to upload your TLS certificates or use self-signed ones. ![Admin console TLS setup](/img/self-hosting/installation/replicated_tls_setup.png) 2. Enter the password provided at the end of the cluster installation. ![Admin console password](/img/self-hosting/installation/replicated_password_form.png) 3. Upload the license downloaded on the portal. Refer to the [download your license](../license-management) page. ![License upload](/img/self-hosting/installation/replicated_license_upload.png) 4. Configure the application by completing all the required fields: - **Application Hostname**: Enter the Fully Qualified Domain Name (FQDN) for the GitGuardian application. - **Admin User Fields**: These fields are used to create the first GitGuardian user. You'll need to change the password upon the first login. ![Admin Console Application Configuration](/img/self-hosting/installation/replicated_configure_app.png) Additional configuration options include: - **Scaling**: Adjust the number of replicas for each application component. For more details, visit the [Scaling](../management/infrastructure-management/scaling) page. - **Prometheus**: Activate an exporter for [Prometheus](../management/application-management/metrics). - **TLS Certificate**: This is for the GitGuardian Application. You can either use auto-generated self-signed certificates or upload your own. For self-signed or private CA certificates, disable SSL verification for the GitHub webhook. Learn more on the [Configure TLS certificates](../security/tls-certificates) page. - **Custom Certificate Authority**: Provide a [custom CA](../security/custom-ca) if necessary. - **HTTP(s) Proxy**: Refer to the [proxy](../management/infrastructure-management/proxy-server) section if needed. - **Databases/Datastores**: Choose between using embedded PostgreSQL/Redis or an external one. For more information, see [Configure your database](./databases/database-config). - **Load balancer considerations**: To use the embedded cluster behind a load balancer, please read [Configure your instance to work behind a load balancer](../management/infrastructure-management/load-balancer#embedded-clusters). 5. Check if preflight checks pass. :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the installation **must not continue** until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../system-requirements)**. ::: ![Admin console preflights](/img/self-hosting/installation/replicated_preflights.png) 6. Launch The first installation of the GitGuardian application requires a few minutes to create all database objects. Once the process is completed, you will be able to log in to the dashboard using the administrator user you defined. ### Save the Data Encryption Key :::caution GitGuardian encrypts all sensitive information in the database using an encryption key (aka Django Secret Key). In case of disaster recovery, this key will be needed to restore your data. ::: You should save it and keep it in **a secure location**. Use the following command to display the key: ```shell kubectl get secrets gim-secrets -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ### Network and storage configuration #### Configuring proxy settings If a proxy is required for outgoing access to the internet, please create a `patch.yaml`: ```yaml apiVersion: 'cluster.kurl.sh/v1beta1' kind: 'Installer' metadata: name: 'patch' spec: kurl: proxyAddress: http://: noProxy: false ``` And run the installer with `-installer-spec-file=patch.yaml` as root: ```bash sudo -i curl -sSL https://kurl.sh/gitguardian | bash -s installer-spec-file=patch.yaml ``` #### Managing disk space The kURL Embedded cluster will create a [MinIO](https://min.io/) Persistent Volume mounted on `/mnt/data`. You can use a specific disk for this volume and, in this case, it must have at least 200GB of free space. The kURL installer will look for the existence of the `/var` directory as well as all the core directories mentioned in its documentation. Otherwise, the root storage **should not be partitioned**. You can read more about the disk space requirements in the [kURL documentation](https://kurl.sh/docs/install-with-kurl/system-requirements#disk-space-requirements). Note that if your disk is **not** a SCSI device, you will need to patch the install script following [these guidelines](https://kurl.sh/docs/install-with-kurl/#modifying-an-install-using-a-yaml-patch-file-at-runtime): 1. Create a YAML file and add the following parameters (this is an example for a `nvme` device): ```yaml kind: Installer metadata: name: patch spec: rook: blockDeviceFilter: nvme1n[0-1] ``` 2. Run the install script with that patch as root: ```bash sudo -i curl -sSL https://kurl.sh/gitguardian | bash -s installer-spec-file=[path of the above YAML patch file] ``` ### Troubleshooting If you encounter issues during the installation process, you can generate a support bundle for the GitGuardian team to diagnose and resolve problems more efficiently. See the [support bundle documentation](../troubleshoot/support#kots-based-installation) for detailed instructions. --- ## Install on an Existing Cluster using Helm ## Introduction GitGuardian can be installed on your existing Kubernetes cluster using [Helm](https://helm.sh/), a package manager for Kubernetes. GitGuardian supports deployment on bare metal, private, or public clouds. ## Prerequisites ### Required Infrastructure 1. **Kubernetes Cluster**: A running Kubernetes cluster. See [system requirements](../system-requirements#kubernetes-for-existing-clusters) for details. For OpenShift clusters, refer to the [OpenShift installation guidelines](./openshift). 2. **PostgreSQL Database**: An external PostgreSQL instance with required extensions installed. See [database configuration](./databases/database-config) for setup details. 3. **Redis Instance**: A dedicated Redis instance. See [system requirements](../system-requirements#redis) for configuration details. ### Additional Requirements 4. **Helm**: Helm version 3.13+ installed. See [system requirements](../system-requirements#helm) for version compatibility. Currently, deployment of the app using Helm charts supports only **Helm CLI**, **[ArgoCD](https://argo-cd.readthedocs.io/en/stable/getting_started/)**, and **[FluxCD](https://fluxcd.io/flux/installation/)**. Helm installations support both AMD64 and ARM64 clusters; see [architecture](../system-requirements#architecture). 5. **Network Access**: Ensure your cluster meets the [network requirements](../network-requirements). 6. **Domain Name**: A Fully Qualified Domain Name (FQDN) for accessing the application. See [system requirements](../system-requirements#domain-name-requirements). :::caution Requirements Review the complete **[system](../system-requirements)** and **[network](../network-requirements)** requirements before proceeding. ::: ## Installation :::note Only the following methods are supported to deploy the app using Helm charts: **Helm CLI** and **ArgoCD**. For GitGuardian installation in an Airgap environment, utilize a private image repository. Detailed instructions are available on the **[Install on Airgap](./airgap-installation-existing-cluster-helm)** page. ::: ### Kubernetes Application RBAC {#kubernetes-application-rbac} The following RBAC roles are required for the proper functioning of the application, enabling the Replicated SDK to validate customer license entitlements, ensuring non-skippable versions are not bypassed during upgrades, and allowing [in-cluster support bundle generation](../troubleshoot/support#generate-from-the-admin-area-in-cluster) (restricted by a `ValidatingAdmissionPolicy`). If you are not a `cluster-admin` in your Kubernetes cluster, you will need to apply the configuration below in your targeted namespace ``:
RBAC Roles Helm install ```yaml # GitGuardian Role --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: gim-role rules: - apiGroups: - '' resources: - configmaps - secrets verbs: - get - list - watch # Spawns the support-bundle collector pod. Locked down by a # ValidatingAdmissionPolicy (Kubernetes 1.30+) — see Troubleshoot > Support. - apiGroups: - '' resources: - pods verbs: - create - apiGroups: - '' resources: - pods - pods/log verbs: - get - delete resourceNames: - gitguardian-support-bundle # GitGuardian RoleBinding --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gim-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: gim-role subjects: - kind: ServiceAccount name: gim-migration - kind: ServiceAccount name: gim # Upgrade-path-check Role --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: upgrade-path-check rules: - apiGroups: - '' resources: - configmaps verbs: - get - list # Upgrade-path-check RoleBindng --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: upgrade-path-check roleRef: kind: Role name: upgrade-path-check apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: upgrade-path-check # Replicated SDK Role --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: replicated-role rules: - apiGroups: - '' resources: - configmaps - persistentvolumeclaims - pods - secrets - services verbs: - get - list - watch - apiGroups: - apps resources: - daemonsets - deployments - replicasets - statefulsets verbs: - get - list - watch - apiGroups: - networking.k8s.io - extensions resources: - ingresses verbs: - get - list - watch - apiGroups: - '' resources: - secrets verbs: - create - apiGroups: - '' resources: - secrets verbs: - update resourceNames: - replicated - replicated-instance-report - replicated-custom-app-metrics-report - replicated-meta-data # Replicated SDK RoleBinding --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: replicated-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: replicated-role subjects: - kind: ServiceAccount name: replicated # Support Bundle # Below role is mandatory --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: support-bundle namespace: rules: - apiGroups: ['*'] resources: ['*'] verbs: ['get', 'list', 'watch'] - apiGroups: [''] resources: ['pods/exec'] verbs: ['create'] # This role is optional and is used to retrieve cluster-scoped information, which can be useful for troubleshooting --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: support-bundle rules: - apiGroups: [''] resources: ['namespaces', 'nodes'] verbs: ['get', 'list', 'watch'] - apiGroups: ['apiextensions.k8s.io'] resources: ['customresourcedefinitions'] verbs: ['get', 'list', 'watch'] - apiGroups: ['storage.k8s.io'] resources: ['storageclasses'] verbs: ['get', 'list', 'watch'] ```
### Accessing the Helm Chart Registry ⚠️ Ensure you're using the latest version of [helm](https://helm.sh/docs/helm/helm_install/). The GitGuardian Helm chart is available in the Replicated private registry. The license is included directly in the Helm chart, so no separate license file download is required. Contact the GitGuardian team at support@gitguardian.com to obtain the password. To log in, use the command below, replacing the email with the one provided by the GitGuardian team: ```bash helm registry login registry.replicated.com --username your.name@yourcompany.com ``` ### Create encryption secret Create a Kubernetes secret in the target namespace with `DJANGO_SECRET_KEY`. GitGuardian uses it to encrypt sensitive application data in the database. See [Mandatory secret](./helm-secrets#mandatory-secret) for commands and values. :::caution Backup the key It is critical to back up your key in a secure vault. Key loss results in irreversible data loss from your GitGuardian instance. ::: ### Customize the local values file This installation offers multiple customization options. Use a local values file (named `local-values.yaml`) for customizations when installing any Helm application. Ensure your values file configures these essential elements: At the minimum, your values must configure the following elements: - `hostname` - `postgres` - `redis` - `onPrem.adminUser` Below is an example values file covering these elements: ```yaml hostname: gitguardian.internal.yourcompany.com # Hostname where the instance will be accessed postgresql: host: gitguardian-postgres # PostgreSQL host username: postgres # PostgreSQL username database: gitguardian # PostgreSQL database name existingSecret: gitguardian-postgresql-secret # Kubernetes secret where to check the PostgreSQL password existingSecretKeys: password: postgres-password # Name of the key containing password in the secret redis: main: host: gitguardian-redis # Redis host tls: enabled: false # Set TLS encryption for Redis existingSecret: gitguardian-redis-secret # Kubernetes secret where to check the Redis password existingSecretKeys: url: redis-url # Name of the key containing redis url in the secret onPrem: adminUser: email: your.name@yourcompany.com # email of the instance admin user firstname: YourName # name of the instance admin user ``` For detailed guidance on: - configurable parameters, refer to the [Helm Chart Values Reference](../management/infrastructure-management/helm-values) page. - `existingSecret` parameter and its setup process, visit the [Helm Sensitive Information Management](./helm-secrets) page. - database configuration, see [Configure Your Database](./databases/database-config). - scaling options, consult the [Scaling Documentation](../management/infrastructure-management/scaling). - HTTP proxy, see [Configure a proxy server](../management/infrastructure-management/proxy-server). ### Enable FIPS Compliance (Optional) If you require FIPS-compliant cryptographic modules, you can enable them by adding the following to your `local-values.yaml` file: ```yaml global: fips: enabled: true ``` When FIPS is enabled, the installation will use FIPS-compliant versions of the application images that include specialized cryptographic modules meeting Federal Information Processing Standards, ensuring top-tier encryption of sensitive data, both at rest and in transit. For more information about FIPS compliance and security considerations, see the [Security Recommendations](../security/recommendations) page. ### Configure network access to the application The application front end is behind a Service object named `nginx`. You can configure access to the application in different ways: 1. Configure the service as a `LoadBalancer` using `front.service.type` value. See [Load-balancer](../management/infrastructure-management/load-balancer) for more details. 2. Add an Ingress object routing to the `nginx` service. See [Ingress](../management/infrastructure-management/ingress) for more details. 3. If your cluster has `istio` service mesh, activate it with the `istio.enabled` value. This will enable the proper Gateway and VirtualService objects. Please note that the `nginx` service is not configured with SSL support. You must configure it and manage your TLS certificate through your Load-Balancer, Ingress or Service Mesh. ### Run preflight checks 🚦 :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the installation must not continue until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../system-requirements)**. ::: We strongly advise you to run our preflight script to ensure your existing cluster meets GitGuardian's requirements. Retrieve the script from our public repository [here](https://github.com/GitGuardian/ggtools/tree/main/helm-preflights). Specify an existing Kubernetes namespace using the `-n` option. If not specified, the script will run in your default namespace. Replace `` with your desired [helm release name](https://helm.sh/docs/intro/using_helm/#helm-install-installing-a-package). ```bash ./preflights.sh -r -n oci://registry.replicated.com/gitguardian/gitguardian -f local-values.yaml ``` ### Install the application Use the following command to install the application using your `local-values.yaml` file. Replace `` with your desired [helm release name](https://helm.sh/docs/intro/using_helm/#helm-install-installing-a-package). Specify an existing kubernetes namespace with the `-n` option. If not specified, Helm installs GitGuardian in your default namespace. Use the `--create-namespace` option to create the namespace if it doesn't exist. ```bash helm install --timeout 30m -n --create-namespace oci://registry.replicated.com/gitguardian/gitguardian -f local-values.yaml ``` **Note**: The installation may take a few minutes due to database migrations. ### Verify the installation Upon successful installation, you should see the following output: ```shell NAME: LAST DEPLOYED: Mon May 15 16:15:56 2023 NAMESPACE: STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Thank you for installing GitGuardian Internal Monitoring. ``` These notes can later be retrieved with `helm get notes ` ### Save the Data Encryption Key :::caution GitGuardian encrypts all sensitive information in the database using an encryption key (aka Django Secret Key). In case of disaster recovery, this key will be needed to restore your data. ::: When you don't specify it either using inline parameter `miscEncryption.djangoSecretKey` or using an existing secret with `miscEncryption.existingSecret`, the data encryption key is automatically generated by the Helm chart. You should save it and keep it in **a secure location**. Use the following command to display the key: ```shell kubectl get secrets gim-secrets --namespace= -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ### Application login Upon successful installation, you will need to get your temporary admin password. Use the following command: ```bash kubectl get secrets gim-secrets --namespace= -o jsonpath='{.data.ADMIN_PASSWORD}'| base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). You can access the application using the hostname you provided, using the login with the email provided in the `onPrem.adminUser.email` and the temporary password. ### Troubleshooting If you encounter issues during the installation process, you can generate a support bundle for the GitGuardian team to diagnose and resolve problems more efficiently. See the [support bundle documentation](../troubleshoot/support#helm-based-installation) for detailed instructions. ## Next Steps After successful installation: - Access your GitGuardian instance using the hostname you configured - Log in with the administrator credentials you set up (change the temporary password on first login) - Configure [email settings](../management/application-management/email-configuration) for notifications - Set up [SSO](../../platform/enterprise-administration/saml-sso-configuration) and [SCIM](../../platform/enterprise-administration/scim-configuration) integration (optional) - [Integrate your first repositories](/platform/getting-started/integrate) to begin secret detection --- ## Install on an Existing Cluster using KOTS ## Introduction :::danger Deprecation Notice The KOTS existing cluster installation method is deprecated as of the June 2026 release (version 2026.6.0) and will be completely removed in the 2027.1 release. Deprecated installation methods no longer benefit from the latest platform improvements, such as ClickHouse-based analytics and S3 object storage support. We strongly recommend migrating to the [Helm installation on an existing cluster](./installation-existing-cluster-helm) as soon as possible. See the [customer notice](/support/customer-notices/kurl-kots-installation-deprecation) for details, or reach out to [support@gitguardian.com](mailto:support@gitguardian.com) for guidance on your migration. ::: **⚠️ Use the [Helm installation on an existing cluster](./installation-existing-cluster-helm) unless instructed otherwise.** GitGuardian can be installed on your existing Kubernetes cluster using [KOTS](https://kots.io), a kubectl plugin and KOTS Admin Console to help manage Kubernetes Off-The-Shelf software. GitGuardian supports deployment on bare metal, private, or public clouds. ## Prerequisites ### Required Infrastructure 1. **Kubernetes Cluster**: A running Kubernetes cluster. See [system requirements](../system-requirements#kubernetes-for-existing-clusters) for details. For OpenShift clusters, refer to the [OpenShift installation guidelines](./openshift). 2. **PostgreSQL Database**: An external PostgreSQL instance with required extensions installed. See [database configuration](./databases/database-config) for setup details. 3. **Redis Instance**: A dedicated Redis instance. See [system requirements](../system-requirements#redis) for configuration details. ### Additional Requirements 4. **License File**: Download your GitGuardian license from the portal. See [license management](../license-management#kots-existing-cluster-installation) for instructions. 5. **Network Access**: Ensure your cluster meets the [network requirements](../network-requirements). 6. **Domain Name**: A Fully Qualified Domain Name (FQDN) for accessing the application. See [system requirements](../system-requirements#domain-name-requirements). :::caution Requirements Review the complete **[system](../system-requirements)** and **[network](../network-requirements)** requirements before proceeding. ::: ## Installation ### KOTS plugin First, you need to install the KOTS plugin for `kubectl`. You can do this with this command: ```bash curl https://kots.io/install | bash ``` ### Kubernetes Application RBAC {#kubernetes-application-rbac} The KOTS Admin Console will have full control over all resources across all namespaces in the cluster. More information in [Replicated documentation](https://docs.replicated.com/vendor/packaging-rbac#about-cluster-scoped-rbac). If you are not `cluster-admin` in your Kubernetes cluster or do not want to grant the KOTS Admin Console such wide permissions, you will need to apply the below configuration in your targeted namespace ``:
RBAC Roles KOTS install ```yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: kotsadm namespace: labels: kots.io/backup: velero kots.io/kotsadm: 'true' --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: kotsadm-role namespace: labels: kots.io/backup: velero kots.io/kotsadm: 'true' rules: - apiGroups: [''] resources: [ 'configmaps', 'persistentvolumeclaims', 'pods', 'secrets', 'services', 'limitranges', 'serviceaccounts', ] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['apps'] resources: [ 'daemonsets', 'deployments', 'deployments/scale', 'replicasets', 'statefulsets', ] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['batch'] resources: ['jobs', 'cronjobs'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['networking.k8s.io', 'extensions'] resources: ['ingresses', 'networkpolicies'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: ['policy'] resources: ['poddisruptionbudgets'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: [''] resources: ['namespaces', 'endpoints'] verbs: ['get'] - apiGroups: ['authorization.k8s.io'] resources: ['selfsubjectaccessreviews', 'selfsubjectrulesreviews'] verbs: ['create'] - apiGroups: ['rbac.authorization.k8s.io'] resources: ['roles', 'rolebindings'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: [''] resources: ['pods/log', 'pods/exec'] verbs: ['get', 'list', 'watch', 'create'] - apiGroups: ['batch'] resources: ['jobs/status'] verbs: ['get', 'list', 'watch'] - apiGroups: ['monitoring.coreos.com'] resources: ['servicemonitors'] verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'] - apiGroups: [''] resources: ['events'] verbs: ['list'] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kotsadm-rolebinding namespace: labels: kots.io/backup: velero kots.io/kotsadm: 'true' roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kotsadm-role subjects: - kind: ServiceAccount name: kotsadm ```
And proceed with the KOTS Admin Console step. ### KOTS Admin Console Once you have the plugin installed, you can install the KOTS Admin Console. If you are `cluster-admin`: ```bash kubectl kots install gitguardian ``` If not: ```bash kubectl kots install --ensure-rbac=false gitguardian ``` You will be prompted to choose a namespace to deploy the application and a password to access the KOTS Admin Console. ![Namespace and password prompt](/img/self-hosting/installation/replicated_choose_namespace_and_password.png) Once the installation of the KOTS Admin Console is finished, a port forward will be set up, and you will be able to access the KOTS Admin Console on http://localhost:8800. :::tip **KOTS Admin Console** By default, this is accessed on http://localhost:8800 using this command `kubectl kots admin-console --namespace=`, which is a wrapper around `kubectl port-forward`. You can configure an ingress if you want a public endpoint. ::: Launch ![End of existing cluster installation](/img/self-hosting/installation/replicated_end_existing_install.png) ### Application 1. Enter the password provided at the end of the cluster installation. ![Admin console password](/img/self-hosting/installation/replicated_password_form.png) 2. Upload the license downloaded on the portal ([see instructions on how to download the license file](../license-management#download)). ![License upload](/img/self-hosting/installation/replicated_license_upload.png) 3. Configure the application. You need to fill in all the required fields: - **Application Hostname**: Enter the Fully Qualified Domain Name (FQDN) for the GitGuardian application. - **Admin User Fields**: These fields are used to create the first GitGuardian user. You'll need to change the password upon the first login. - **Databases**: You must select an external PostgreSQL and Redis, see [Configure your database](./databases/database-config). When utilizing Redis Sentinel for high availability, ensure that the Redis master password matches with the Redis sentinel's password and that you're using the correct Sentinel port (default: 26379). ![Admin console application configuration](/img/self-hosting/installation/replicated_configure_app.png) Additional configuration options include: - **Scaling**: Adjust the number of replicas for each application component. For more details, visit the [Scaling](../management/infrastructure-management/scaling) page. - **Prometheus**: Activate an exporter for [Prometheus](../management/application-management/metrics). - **Ingress TLS Certificate**: This is for the GitGuardian Application. You can either use auto-generated self-signed certificates or upload your own. For self-signed or private CA certificates, disable SSL verification for the GitHub webhook. Learn more on the [Configure TLS certificates](../security/tls-certificates) page. - **Load Balancer**: Change the Service type can be changed from ClusterIP to [LoadBalancer](../management/infrastructure-management/load-balancer) if needed. - **Custom Certificate Authority**: Provide a [custom CA](../security/custom-ca) if necessary. - **HTTP(s) Proxy**: Refer to the [proxy](../management/infrastructure-management/proxy-server) section if needed. 4. Check if preflight checks pass. :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the installation **must not continue** until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../system-requirements)**. ::: ![Admin console preflights](/img/self-hosting/installation/replicated_preflights.png) 5. Launch The first installation of the application requires a few minutes to create all database objects. Once the process is completed, you will be able to log in to the dashboard using the administrator user you defined. ### Save the Data Encryption Key :::caution GitGuardian encrypts all sensitive information in the database using an encryption key (aka Django Secret Key). In case of disaster recovery, this key will be needed to restore your data. ::: You should save it and keep it in **a secure location**. Use the following command to display the key: ```shell kubectl get secrets gim-secrets --namespace= -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ### Troubleshooting If you encounter issues during the installation process, you can generate a support bundle for the GitGuardian team to diagnose and resolve problems more efficiently. See the [support bundle documentation](../troubleshoot/support#kots-based-installation) for detailed instructions. ## Next Steps After successful installation: - Access your GitGuardian instance using the hostname you configured - Log in with the administrator credentials you set up (change the temporary password on first login) - Configure [email settings](../management/application-management/email-configuration) for notifications - Set up [SSO](../../platform/enterprise-administration/saml-sso-configuration) and [SCIM](../../platform/enterprise-administration/scim-configuration) integration (optional) - [Integrate your first repositories](/platform/getting-started/integrate) to begin secret detection --- ## Install using OpenShift GitGuardian has been tested with OpenShift 4. Several requirements specific to OpenShift are required for installing GitGuardian application on OpenShift clusters. ## Deactivate securityContext GitGuardian Self-Hosted enforces `securityContext` directives by default. These settings can conflict with the `securityContext` requirements for some OpenShift security context constraints (SCCs) and must therefore be disabled. :::tip Security note Disabling our default `securityContext` does not mean a `securityContext` will not be set--it just means the SCC is responsible for setting the `securityContext`. ::: With Helm, the `securityContext` must be disabled in the values: ```yaml securityContext: enabled: false loki-minio: podSecurityContext: enabled: false containerSecurityContext: enabled: false loki: loki: podSecurityContext: fsGroup: null runAsGroup: null runAsUser: null ggscout: securityContext: enabled: false ``` ## Use OpenShift Route instead of Ingress OpenShift proposes `Route` instead of regular Kubernetes `Ingress`. Helm installations do not enable Ingress by default. The `Route` can be defined as: ```yaml apiVersion: route.openshift.io/v1 kind: Route metadata: name: gitguardian-helm spec: host: path: / port: targetPort: http tls: certificate: | insecureEdgeTerminationPolicy: Redirect key: | termination: edge to: kind: Service name: nginx weight: 100 wildcardPolicy: None ``` Where: - `` is the full qualified domain name of your instance - `` is the TLS Certificate - `` is the TLS Certificate's private key Note that if your GitGuardian instance has been created before October 2023, the service name is called `gitguardian` instead of `nginx` ## Handle resource quotas per Project When setting resource quotas per Project, it's essential to ensure that the quotas are sufficient for all your pods. With Helm installations, all resource requests and limits, including those for ephemeral storage, can be fully configured. Refer to our [Scaling GitGuardian](../management/infrastructure-management/scaling#additional-tuning-ephemeral-storage) page for more details. :::tip Ephemeral Storage Ephemeral Storage is used to clone repositories during Historical Scans. Ensure that your `scanner` pods are allocated sufficient space to handle the largest repositories. ::: --- ## License management License management is essential for GitGuardian self-hosted installations, involving both initial license acquisition and ongoing synchronization. This page covers how to download and manage licenses across different installation methods (Helm-based and KOTS-based), including both airgap and non-airgap environments. :::warning Handle the license file as sensitive information; it includes credentials for GitGuardian's registry and image repository. ::: :::info Some features are gated behind dedicated license fields that are disabled by default, such as [Public Monitoring for self-hosted](../public-monitoring/self-hosted) (available from 2026.7). To enable one of these, contact GitGuardian to update your license, then synchronize it using the steps below. ::: ## Download The method to obtain your license varies depending on your installation type: ### Helm-Based Installation For Helm installations, the license is included in the Helm chart you download. You will receive registry access credentials from the GitGuardian team at support@gitguardian.com. These credentials include: - A username (typically your email address) - A password for accessing the Helm chart registry You will use these credentials to authenticate with the registry using: ```bash helm registry login registry.replicated.com --username your.name@yourcompany.com ``` ### KOTS Embedded Cluster Installation For KOTS embedded cluster installations, the license is included directly in the installer bundle. You only need the license ID provided by the GitGuardian team - no manual download is required. ### KOTS Existing Cluster Installation For KOTS installations on existing clusters, you will need to manually download the license file. You will need 2 pieces of information: - the portal URL, which will usually be sent by email. - the password, which ideally will be sent on a different channel (via SMS for example). Once connected to the portal, you will be able to download the license file: ![Download portal](/img/self-hosting/replicated_download_license.png) ## Synchronization for Helm-based installation With Helm, the license data is provided during the installation or the upgrade. ### Airgap installation GitGuardian teams will send you the information to upload a new license manually. ### Non-Airgap, after 2025.3 GitGuardian will automatically synchronize the license information with your application. As a result, you no longer need to manually sync your license after installation or upgrades. ### Non-Airgap, before 2025.3 If you need to sync the license, you would need to use the `helm upgrade` command and specify the same version as the one currently installed to prevent unwanted upgrades to the latest version. To find the release name and the version currently installed, use `helm ls`: ```bash helm ls NAME UPDATED STATUS CHART APP VERSION 2025-03-20 12:40 deployed gitguardian-2025.3.0 2025.3.0 ``` Here, the version installed is `2025.3.0`. To synchronize the license manually, you would run the following command, using the version installed in your environment: ```bash helm upgrade -n oci://registry.replicated.com/gitguardian/gitguardian --version 2025.3.0 -f local-values.yaml ``` Replace `` with the name used during the initial installation. If needed, specify the Kubernetes namespace with `-n` (the default namespace is used if not specified). ## Synchronization for KOTS-based installation GitGuardian may update some information on your license, such as changing the expiration date, modifying the number of seats, etc. ### Airgap installation GitGuardian teams will send you the information to upload a new license in the Admin console. ### Non-Airgap From the 2025.3.0 release onward, GitGuardian will automatically synchronize the license information with your application. As a result, you no longer need to manually sync your license. Once the license has been updated automatically (for non-air gap environments), you will still need to manually deploy the updated configuration to your instance. ![Deploying the updated configuration](/img/self-hosting/security/kots-deploy.png) --- ## Admin Area This section serves as a comprehensive dashboard for administrators, providing essential tools and insights for managing your GitGuardian Self-Hosted instance. It enables effective monitoring of system health, user management, and configuration of instance settings. :::info When installing GitGuardian as Self-Hosted, there can only be one workspace per instance. ::: ## Health Check A page dedicated to monitoring the overall health and performance of your GitGuardian instance. This ensures that all systems are functioning correctly and efficiently, highlighting potential issues before they impact your workflow. More information on the [Checking environment health](../../troubleshoot/health-check) page. ## Users Provides a comprehensive list of all users within your GitGuardian instance. It allows for detailed user management, including adding new users and monitoring user activity. You have the ability to: - **Force a Password Reset:** Ensure security by forcing a password reset for any user. - **Promote a User to Admin:** Grant admin privileges to users, giving them access to the admin area. - **Revoke Admin Rights:** Remove admin privileges from users as needed. :::warning The `admin` privilege is specifically designed to control access to the Admin Area access. To adjust workspace access levels (`manager`, `member`, or `restricted`), navigate to the members settings section within your workspace. Detailed information is available on the **[workspace setting](../../../platform/enterprise-administration/workspace-settings)** page. ::: ## License Manage your GitGuardian license here. This includes viewing your current license details, updating license information, and understanding your license utilization to ensure compliance and optimal usage. More information on the [License Management](../../license-management) page. For [embedded cluster](../../installation/installation-embedded-cluster) configurations, gain direct access to the KOTS admin area from here. Further details are provided on the [Access to the KOTS Admin Console](../infrastructure-management/admin-console.md) page. ## Support Bundle A support bundle gathers logs, cluster information, and diagnostic data that help the GitGuardian support team troubleshoot your instance. To generate a bundle, configure the following options and click **Generate new support bundle**: - **Upload bundle directly to GitGuardian:** Send the bundle to GitGuardian automatically once generated, instead of downloading it and sharing it manually. - **Ticket ID:** Optionally associate the bundle with an existing support ticket so it is routed to the right case. - **Log collection period:** Choose how far back to collect logs (for example, the last 24 hours). For detailed configuration, RBAC requirements, and alternative generation methods (CLI or offline clusters), see the [Support bundle](../../troubleshoot/support) page. ## Settings The Settings section allows for comprehensive customization of your GitGuardian instance to meet organizational requirements. It includes: - **Signup Restrictions:** Control user access by allowing entry only through invitation or Single Sign-On (SSO) mechanisms, ensuring secure and regulated user addition. Further details can be found on the [Security recommendations and information](../../security/recommendations#signup-restrictions) page. - **Preferences:** A table of preferences provides flexibility, enabling fine-tuning of your GitGuardian instance for enhanced usability and efficiency. Additional information is available on the [Configure preferences](../application-management/preferences) page. - **Certificate-based authentication:** Verify and Troubleshoot [certificate-based authentication](../infrastructure-management/cert-based-auth) page. - **Machine Learning**: Enrich past incidents using [Machine Learning](./machine-learning) - **Honeytoken Configuration:** Integrate with your AWS organization to generate and monitor honeytokens, bolstering your security measures. Learn more on the [Honeytoken for self-hosted](../../../honeytoken/self-hosted) page. - **Public Monitoring:** Configure the connection that enables public secret scanning on your instance (available from 2026.7). Learn more on the [Public Monitoring for self-hosted](../../../public-monitoring/self-hosted) page. - **Email Configuration:** Choose between Sendgrid or SMTP for email services. For setup instructions, visit the [Configure the email system](../application-management/email-configuration) page. ## Encryption Key Rotation Enhance your security posture by periodically rotating encryption keys. This section provides tools and procedures for updating the encryption keys used to secure your data, helping to safeguard against unauthorized access. Detailed instructions are available on the [Database Security](../../security/database-security#update-postgresql-data-encryption-key) page. ## Tasks ### Worker tasks The Worker Tasks page allows you to monitor task activity and worker usage, helping you identify performance issues and optimize scaling for your GitGuardian self-hosted instance. ![Worker Tasks Overview](/img/self-hosting/management/application-management/admin_area_worker_tasks.png) ### Periodic tasks The Periodic Tasks page allows you to adjust schedules and fine-tune periodic tasks to enhance the performance of your GitGuardian self-hosted instance. It is important to exercise caution and avoid making changes without proper guidance. For assistance or additional support, it is recommended to contact the **[support team](mailto:support@gitguardian.com)** directly. ![Periodic Tasks Overview](/img/self-hosting/management/application-management/admin_area_periodic_tasks.png) --- ## Use the API As for the GitGuardian SaaS version, you can enable the API for your Self-Hosted environment. The base URL of the API routes will be different for the Self-Hosted environment than the SaaS one. You should use `[your_domain_name]/exposed`. For example, if your dashboard URL is `https://gitguardian.mycorp.local`, the URL to use for the API will be `https://gitguardian.mycorp.local/exposed/`. If you want to check the status of the API, you should use the following query: ```bash curl -H "Authorization: Token ${TOKEN}" \ https://gitguardian.mycorp.local/exposed/v1/health ``` :::tip If you are not certain of your API URL, you can find your dashboard, in the **API** part, in the Quota section: ![API URL](/img/self-hosting/management/application-management/api_url.png) ::: You can find more information about how to use the API [in the GitGuardian documentation](/platform/gitguardian-suite/api). --- ## Configure the email system In order to receive alerts from your GitGuardian instance, you need to setup an email sending system. You can either pick a classic SMTP configuration or use [SendGrid](https://sendgrid.com/). 1. Go to the Admin area of ​​your GitGuardian instance. You must be an admin to access it. ![Admin area CTA](/img/self-hosting/management/application-management/admin_area_cta.png) 2. Navigate to Settings > Email > Configuration ### SMTP Configuration You need to fill in the following information: - Server Host - Server Port - Username - Password - SSL activation ![Email configuration SMTP](/img/self-hosting/management/application-management/email_configuration_smtp.png) :::info For SMTP server with a self-signed certificate, add it to the trusted list to ensure communication (refer to **[custom CA](../../security/custom-ca.md)**). The DNS name must match the certificate's name. Alternatively, starting **2024.2.1** release, you can enable bypassing TLS verification for the SMTP server by executing the following command: ```bash kubectl exec --namespace deployments/webapp-internal-api -c app -- python manage.py set_preferences --email__is_bypass_tls_smtp_enabled=True ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ::: ### SendGrid A SendGrid API key in necessary to send emails with SendGrid. You need to generate one from the [SendGrid Website](https://app.sendgrid.com/settings/api_keys). ![Email configuration Sendgrid](/img/self-hosting/management/application-management/email_configuration_sendgrid.png) ### Checking your configuration Once you have picked a method and saved your configuration, you can test it by pressing the `Send test email` button. Shortly after that, you will receive an email on the address you used to set up your GitGuardian instance. If you did not receive any mail, check the app logs for any errors and reach out to us. --- ## Machine Learning(Application-management) This section outlines the machine learning features implemented in GitGuardian, detailing how they work and how to activate them for Self-Hosted. Once activated, you can [enrich past incidents](#enrich-past-incidents) with machine learning analysis. For more details about the machine learning capabilities, see the [Machine Learning Secret Detection documentation](../../../secrets-detection/secrets-detection-engine/machine_learning). ## System Requirements The ML Secret Engine requires **3 vCPU and 2.5 GiB RAM per replica**. For detailed scaling guidelines, performance metrics, and infrastructure recommendations, see the [Scaling documentation](../infrastructure-management/scaling#ml-secret-engine-scaling-considerations). :::info From **2025.7.0** version, Machine Learning is activated by default. ::: ### KOTS-Based Installation To enable this feature, set a positive number of replicas for both the ML engine and workers in your configuration: ![ML Secret Engine in KOTS](/img/self-hosting/management/application-management/ml_secretengine_kots.png) ### Helm-Based Installation :::info For those using GitGuardian in an air-gapped environment, the names of the images required for machine learning can be found **[here](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. ::: For Helm-based installations, consult the [Helm Values Documentation](../infrastructure-management/helm-values) for detailed configuration options. Ensure you configure a positive number of replicas for the ML engine and workers (the default value is 1, so no override of this value will get you the correct resources). Example minimal configuration: ```yaml secretEngine: replicas: 1 celeryWorkers: ml-api-priority: replicas: 1 ``` We strongly recommend using Horizontal Pod Autoscaling (HPA) for the `ml-api-priority` worker, especially when performing a backfill on all your incidents. For more information, refer to our [Autoscaling Guide](../infrastructure-management/autoscaling). #### Lower the priority of ML As Secret ML Engine has high hardware requirements, you may want to lower its priority to ensure all other pods are scheduled before. This can be done with a cluster-wide Resource called `PriorityClass`. Declare a `PriorityClass` in your cluster: ```yaml --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: ml-priority labels: {{- include "gim.labels" $ | nindent 4 }} value: -10 # see how to set this value with your cluster administrator globalDefault: false description: "Lower priority class for ML secretEngine pods that can be preempted." ``` Then, simply use that priorityClass in GitGuardian values: ```yaml secretEngine: priorityClassName: ml-priority ``` ## Enrich Past Incidents This backfill process applies two ML-powered features to your past incidents: - **[False Positive Remover](../../../secrets-detection/secrets-detection-engine/machine_learning#false-positive-remover)** - automatically detects and tags incidents likely to be false positives - **[Secret Enricher](../../../secrets-detection/secrets-detection-engine/machine_learning#secret-enricher)** - enriches generic incidents with precise secret types (e.g., "Redis Credentials" instead of "Generic Database Assignment") When you activate Machine Learning on your GitGuardian instance for the first time, all real-time incidents will be automatically analyzed by the ML engine, and the [Auto-ignore false positive playbook](../../../platform/automate-with-playbooks/available-playbooks.md#auto-ignore-false-positives) will be enabled by default. Here are the steps to enrich past incidents: 1. Navigate to the Admin area of your GitGuardian instance. You must have admin privileges to proceed. 2. In the Admin area, navigate to **Settings > Machine Learning**. 3. Click on **Backfill Incidents** to apply the ML model to past incidents. ![ML backfill past incidents](/img/self-hosting/management/application-management/ml_backfill_past_incidents.png) After the backfill process is completed, a confirmation message will appear, along with a link that redirects you to your incident page, filtered by the 'false positives' tag. ![ML backfill past incidents completed](/img/self-hosting/management/application-management/ml_backfill_past_incidents_completed.png) :::caution - The backfill process **cannot be canceled** once started. - The duration of this process depends on the number of incidents being analyzed, ranging from a few minutes to several days. - During the backfill process, **real-time incidents processing will be delayed**. Therefore, it is recommended to schedule this task outside of business hours to minimize disruptions. ::: --- ## Applicative metrics ## Export Application Metrics to Prometheus Applicative metrics are gathered thanks to [Prometheus](https://prometheus.io/), a software used for event monitoring and alerting, which permits scraping the data captured in the application. :::info The Prometheus exporter is not supported for [embedded clusters](../../installation/choose-embedded-existing#what-is-an-embedded-cluster-installation). ::: ### Metrics available The Prometheus exporter gives access to the following metrics, grouped by area. #### Users and incidents | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_active_users_total` | Gauge | All users in the instance | _None_ | | `gim_issues_total` | Gauge | All incidents | Severity, Status | | `gim_occurrences_total` | Gauge | All occurrences | Hidden, Status | #### Scanning activity | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_commits_total` | Gauge | Commits processed | Account, Scan type | | `gim_repo_scan_active_statuses_total` | Gauge | Count of historical scans | scan_feature, status | | `gim_check_runs_created` | Counter | GitHub check runs created | plan, account_id | | `gim_check_runs_timed_out` | Counter | GitHub check runs that timed out | plan, account_id | | `gim_check_runs_runtime_bucket` | Histogram | GitHub check run duration | status | | `gim_check_runs_error_codes` | Counter | GitHub check run errors by code | error_code | #### Infrastructure | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_postgres_used_disk_bytes` | Gauge | Disk space used by PostgreSQL | _None_ | | `gim_redis_used_memory_bytes` | Gauge | Memory used by Redis | _None_ | | `gim_redis_available_memory_bytes` | Gauge | Memory available for Redis | _None_ | #### Celery workers and queues | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_celery_queue_length` | Gauge | Tasks waiting in queue | queue_name | | `gim_celery_active_consumer_count` | Gauge | Active consumers in broker queue | queue_name | | `gim_celery_worker_tasks_active` | Gauge | Tasks currently being processed | _None_ | | `gim_celery_task_sent_total` | Counter | Tasks sent to a queue | name, queue_name, team | | `gim_celery_task_started_total` | Counter | Tasks started by a worker | name, queue_name, team | | `gim_celery_task_succeeded_total` | Counter | Tasks completed successfully | name, queue_name, team | | `gim_celery_task_failed_total` | Counter | Tasks that failed | name, exception, queue_name, team | | `gim_celery_task_retried_total` | Counter | Tasks retried | name, queue_name, team | | `gim_celery_task_queue_time_bucket` | Histogram | Time spent waiting in queue | name, queue_name, team | | `gim_celery_task_runtime_bucket` | Histogram | Task execution duration | name, queue_name, team | #### HTTP requests | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_http_request_started_total` | Counter | HTTP requests initiated | api, method, view_name | | `gim_http_request_success_total` | Counter | Successful HTTP requests | api, method, view_name | | `gim_http_request_failure_total` | Counter | Failed HTTP requests | api, method, status_code, view_name | | `gim_http_request_exception_total` | Counter | HTTP requests that raised an exception | api, method, view_name, exception | | `gim_http_request_view_duration_seconds` | Histogram | HTTP request duration per view | api, method, view_name | #### Health checks | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_health_check_result_count` | Gauge | Health check results | service_name, status | | `gim_outdated_health_check_count` | Gauge | Health checks older than the periodic range | service_name | | `gim_health_check_skipped_total` | Counter | Health checks skipped | reason, service_name | | `gim_health_check_duration_metric` | Histogram | Health check execution duration | service_name | #### Periodic tasks | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_periodic_task_period_seconds` | Gauge | Expected periodicity of a task | task_name, queue_name | | `gim_periodic_task_not_run_for_seconds` | Gauge | Time since a task was last run | task_name, queue_name | #### Public API | Metric | Type | Description | Dimensions | | --- | --- | --- | --- | | `gim_public_api_quota_total` | Gauge | Maximum allowed API usage | Account | | `gim_public_api_usage_total` | Gauge | Current API usage | Account | | `gim_public_api_token_total` | Gauge | Active API tokens | Account, Type | #### Recommended monitoring ##### System health | Metric | What to watch for | | ------ | ----------------- | | `gim_celery_queue_length` | Queue backlog growing over time is the first sign of system saturation. | | `gim_celery_active_consumer_count` | Drop in workers signals availability issues. | | `gim_postgres_used_disk_bytes` | Monitor disk pressure before it becomes critical. | | `gim_redis_used_memory_bytes` / `gim_redis_available_memory_bytes` | High ratio indicates cache memory pressure. | | `gim_periodic_task_not_run_for_seconds` | Compare against `gim_periodic_task_period_seconds` to detect stalled tasks. | ##### API and integrations | Metric | What to watch for | | ------ | ----------------- | | `gim_http_request_failure_total` | Filter by `status_code` to spot error rate spikes (especially 5xx). | | `gim_http_request_view_duration_seconds` | Track API latency (P95/P99) to detect slowdowns. | | `gim_health_check_result_count` | Filter by `status=not_ok` to detect broken integrations. | ##### Example PromQL queries ```promql # Celery queue saturation (tasks per worker) gim_celery_queue_length / gim_celery_active_consumer_count # HTTP 5xx error rate over the last 5 minutes rate(gim_http_request_failure_total{status_code=~"5.."}[5m]) # API latency P95 over the last 5 minutes histogram_quantile(0.95, rate(gim_http_request_view_duration_seconds_bucket[5m])) # Redis memory utilization (%) gim_redis_used_memory_bytes / (gim_redis_used_memory_bytes + gim_redis_available_memory_bytes) * 100 # Detect stalled periodic tasks (not run for 2x their expected period) gim_periodic_task_not_run_for_seconds > 2 * gim_periodic_task_period_seconds ``` ##### Example alerting rules Below are starter [Prometheus alerting rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) you can adapt to your environment: ```yaml groups: - name: gitguardian rules: - alert: CeleryQueueBacklog expr: gim_celery_queue_length > 100 for: 5m annotations: summary: "Queue {{ $labels.queue_name }} has {{ $value }} pending tasks" - alert: RedisMemoryPressure expr: > gim_redis_used_memory_bytes / (gim_redis_used_memory_bytes + gim_redis_available_memory_bytes) > 0.85 for: 10m - alert: PeriodicTaskStalled expr: gim_periodic_task_not_run_for_seconds > 2 * gim_periodic_task_period_seconds for: 5m - alert: HighHTTPErrorRate expr: rate(gim_http_request_failure_total{status_code=~"5.."}[5m]) > 0.1 for: 5m ``` ##### Visualizing metrics with Grafana GitGuardian does not ship pre-built Grafana dashboards, but all `gim_*` metrics are standard Prometheus metrics and work with any Grafana instance connected to your Prometheus server. To get started: 1. Add your Prometheus server as a [Grafana data source](https://grafana.com/docs/grafana/latest/datasources/prometheus/). 2. Create panels using the PromQL queries above. 3. Organize panels into rows: **System health** (queues, Redis, Postgres, periodic tasks) and **API & Integrations** (error rates, health checks). ### Enable or disable Application metrics Applicative metrics are deactivated by default. Two steps are needed to activate Application Metrics: - authorize collection of metrics by the application - activate Prometheus export #### Authorize metrics collection To authorize the metrics collection, you should go to the **Preferences section** in the **Admin Area**, check the `prometheus_metrics_active` feature flag and save settings. ![Activate Applicative Metrics](/img/self-hosting/management/application-management/activate_applicative_metrics.png) To disable it, you should uncheck this parameter and save settings. #### Install Prometheus Operator Metrics are collected by Prometheus using the [Prometheus Operator](https://prometheus-operator.dev/). For Existing Clusters, you should manually install it ([installation documentation](https://prometheus-operator.dev/docs/getting-started/installation/)). #### Activate Prometheus export using KOTS To create exporter resources and allow automatic discovery, you should go in the **KOTS Admin Console** and check the **Activate Prometheus Exporter** checkbox in the Prometheus section of the configuration section. ![Activate Applicative Metrics](/img/self-hosting/management/application-management/activate_prometheus_exporter.png) Then save the configuration, and **Deploy** the application to apply the new configuration. To disable it, you should uncheck this parameter, save configuration, and apply it through a new deployment. #### Activate Prometheus export using Helm Applicative metrics exporter can be enabled by setting `observability.exporters.webAppExporter.enabled=true` in values file. ```yaml observability: exporters: webAppExporter: enabled: true ``` Please note that Helm application also features a [Celery Exporter](https://github.com/danihodovic/celery-exporter) allowing to monitor several Celery metrics like "count of active tasks by queue". The [full list of metrics is available here](https://github.com/danihodovic/celery-exporter#metrics). You can activate Celery Exporter in your values file: ```yaml observability: exporters: webAppExporter: enabled: true statefulAppExporter: enabled: true ``` If you use Prometheus Operator, you may want to use the Service Monitor provided for automatic discovery of the exporter by Prometheus: ```yaml observability: exporters: webAppExporter: enabled: true statefulAppExporter: enabled: true serviceMonitors: enabled: true ``` Otherwise, you can manually scrape exporters. - Applicative metrics can be scrapped from the app-exporter service at: `http://app-exporter:9808/metrics` - Celery metrics can be scrapped from the celery-exporter service at: `http://celery-exporter:9808/metrics` ### How to collect metrics On Existing Clusters, Prometheus must be installed and configured manually. If the [Kube-Prometheus](https://github.com/coreos/kube-prometheus) Operator is used, all the applicative metrics will be automatically listed thanks to the Discovery service of Kube-Prometheus Operator. Otherwise, a manual configuration may be needed. Applicative metrics discovery is possible through the `app-monitoring` headless service. This service exposes an `exporter` pod serving metrics at http://_exporter-xxxxx-xxxxx_:9808/metrics ## Usage data GitGuardian collects usage data to improve the user experience and support. It can be easily deactivated by adjusting the `custom_telemetry_active` setting found in the [preferences](./preferences#on-premise) section in the Admin area. :::info Why keep usage data enable? - **Continuous Product Improvement**: usage data greatly helps us understand how our application is used in various environments. This allows us to specifically target areas needing improvements and direct our testing efforts. This ensures that our product evolves to meet our users' needs effectively while contributing to better quality and stability. - **Targeted and Efficient Support**: in case of technical problems, usage data enables GitGuardian to identify and resolve issues much more quickly. This means reduced downtime for you and a better overall user experience. - **Security and Privacy**: we want to reassure you that data privacy and security are our top priority. We do not collect any personal or sensitive data. Our goal is solely to improve user experience and the performance of our product. ::: Here are the categories and metrics we collect: - **Replicated** - Various deployment-related metrics such as cloud status, version, and uptime - **System** - SSO Provider - Network Gateway Type - Custom CA and proxy status - Prometheus Application metrics activation status - **Users & Teams** - Number of pending invitees, registered users with different access levels, active users. - **Billing** - Number of [contributing developers](/platform/user-account/plan-usage) counted towards your license, and the number excluded from the count - The same two counts broken down per VCS type (Azure DevOps, Bitbucket Cloud, Bitbucket Data Center, Gerrit, GitHub, GitHub Enterprise, GitLab) These are aggregate counts of distinct commit author email addresses. The email addresses themselves are never transmitted. - **Historical Scan** - Number of historical scans canceled, failed, and finished - Percentile durations of historical scans - Number of secrets found per day and source scans per day in historical scans - Number of historical scans considered too large - **Integrations** - Number of instances, installations, projects, sites for VCS and Other Data Sources - Number of monitored and unmonitored sources, along with source size percentiles and estimated users per VCS - **Secret** - Number of deactivated detectors per category, registered and unregistered feedbacks, and various metrics related to secret validity checks and incidents - **Public API** - Number of calls for ggshield secrets scans, including different modes and repositories - Number of active personal access tokens and service accounts - Number of public API calls --- ## Non-VCS Sources This section outlines how to activate and configure workers for non-VCS (Version Control System) integrations in Self-Hosted GitGuardian. These integrations allow you to scan messaging platforms, documentation tools, ticketing systems, and container registries for secrets. By default, all workers for these integrations are deactivated (number of replicas set to 0). **Worker Compatibility:** - **Can use default VCS workers** (but dedicated workers recommended): Slack, Microsoft Teams, Confluence, Jira, and ServiceNow can optionally use the same workers as VCS sources (`worker-scanners`, `worker-worker`, `worker-long`). - **Require dedicated workers**: All other integrations (OneDrive, SharePoint, Container Registries, Package Registries) must use their own specialized workers and cannot share VCS workers We recommend using dedicated workers for all integrations to avoid queue congestion and ensure optimal performance. ## Available Integrations ### Messaging Integrations Monitor messaging platforms for secrets in conversations and shared content. **Available sources:** - [Microsoft Teams](../../../internal-monitoring/integrate-sources/messaging-integrations/microsoft-teams) - [Slack](../../../internal-monitoring/integrate-sources/messaging-integrations/slack) **Required workers:** - `worker-realtime-ods` - Processes real-time scans and events - `worker-scanners-ods` - Handles historical scans for messaging platforms - `worker-scanners-slack` - Dedicated worker for Slack historical scans only - `worker-long-ods` - Processes long-running tasks for messaging platforms - `worker-long-ods-io` - Handles IO-intensive long-running tasks ### Documentation Integrations Scan documentation platforms and file storage services for leaked secrets. **Available sources:** - [Confluence Cloud](../../../internal-monitoring/integrate-sources/documentation-integrations/confluence-cloud) - [Confluence Data Center](../../../internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center) - [Microsoft OneDrive](../../../internal-monitoring/integrate-sources/file-storage-integrations/microsoft-onedrive) - [Microsoft SharePoint Online](../../../internal-monitoring/integrate-sources/file-storage-integrations/microsoft-sharepoint-online) **Required workers:** - `worker-realtime-ods` - Processes real-time scans and events - `worker-scanners-ods` - Handles historical scans for documentation platforms - `worker-scanners-ods-highdisk` - Required for high storage tasks (Microsoft OneDrive and SharePoint scanning) - `worker-long-ods` - Processes long-running tasks for documentation platforms - `worker-long-ods-io` - Handles IO-intensive long-running tasks - `apache-tika` - Required when scanning Microsoft OneDrive and SharePoint for office document formats ### Ticketing Integrations Monitor ticketing systems for secrets in issues, comments, and attachments. **Available sources:** - [Jira Cloud](../../../internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud) - [Jira Data Center](../../../internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center) - [ServiceNow](../../../internal-monitoring/integrate-sources/ticketing-integrations/servicenow) **Required workers:** - `worker-realtime-ods` - Processes real-time scans and events - `worker-scanners-ods` - Handles historical scans for ticketing platforms - `worker-long-ods` - Processes long-running tasks for ticketing platforms - `worker-long-ods-io` - Handles IO-intensive long-running tasks ### Container Registry Integrations Scan container images and registries for embedded secrets. **Available sources:** - [Amazon ECR](../../../internal-monitoring/integrate-sources/container-registries-integrations/amazon-ecr) - [Azure Container Registry](../../../internal-monitoring/integrate-sources/container-registries-integrations/azure-container-registry) - [Docker Hub](../../../internal-monitoring/integrate-sources/container-registries-integrations/docker-hub) - [Google Artifact Registry](../../../internal-monitoring/integrate-sources/container-registries-integrations/google-artifact-registry) - [JFrog Container Registry](../../../internal-monitoring/integrate-sources/container-registries-integrations/jfrog-container-registry) **Required workers:** - `worker-container-registries` - Dedicated worker for container registry scanning tasks ### Package Registry Integrations Scan package registry artifacts for secrets across multiple package ecosystems. **Available sources:** - [JFrog Package Registries](../../../internal-monitoring/integrate-sources/package-registries-integrations/jfrog-package-registry) **Required workers:** - `worker-scanners-db-less` - Dedicated worker for package registry scanning tasks :::info The `commit-cache` Redis instance is used for JFrog Package Registries scanning. If the `commit-cache` Redis instance is not configured, the main Redis instance will be used instead. ::: ## System Requirements ### Standard Workers Each standard worker type requires: **0.5 vCPU and 2 GiB RAM per replica** ### File scanner pod For binary and file scanning (OneDrive/SharePoint): **0.5 vCPU and 500 MiB RAM per replica** ### High Disk Workers For high storage requirements (OneDrive/SharePoint): **Additional disk space and I/O capacity** ## Configuration ### KOTS-Based Installation To enable non-VCS source integrations in KOTS: 1. Access the [KOTS Admin Console](../infrastructure-management/admin-console) 2. Navigate to the **Config** section 3. Locate the worker configuration sections under **Scaling**: - **Container registries Worker** - **Non-VCS Sources Workers** ![ODS worker](/img/self-hosting/management/application-management/replicated_scale_ods_workers.png) 4. Set a positive number of replicas for the required workers (change from 0 to 1 or higher) 5. If using OneDrive/SharePoint, enable and set replicas in the **File Scanner** section 6. Save the configuration ### Helm-Based Installation :::info For air-gapped environments, the names of the images required for file scanner can be found in the [Air-gap Installation documentation](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images). ::: For Helm-based installations, consult the [Helm Values Documentation](../infrastructure-management/helm-values) for detailed configuration options. Configure worker replicas in your `values.yaml` file. **Example minimal configuration for messaging integration:** ```yaml # File scanner (for OneDrive/SharePoint) apacheTika: replicas: 1 # Set to 0 if not using OneDrive/SharePoint # Celery Workers celeryWorkers: # Messaging, Documentation, and Ticketing workers scanners-ods: replicas: 1 scanners-slack: replicas: 1 # Only needed for Slack long-ods: replicas: 1 long-ods-io: replicas: 1 realtime-ods: replicas: 1 # Container registry workers container-registries: replicas: 1 # High disk workers (for OneDrive/SharePoint) scanners-ods-highdisk: replicas: 1 # Set to 0 if not using OneDrive/SharePoint ``` **Example configuration for documentation integration with OneDrive/SharePoint:** ```yaml apacheTika: replicas: 1 celeryWorkers: scanners-ods: replicas: 1 scanners-ods-highdisk: replicas: 1 # Required for OneDrive/SharePoint long-ods: replicas: 1 long-ods-io: replicas: 1 realtime-ods: replicas: 1 ``` **Example configuration for ticketing integration:** ```yaml celeryWorkers: scanners-ods: replicas: 1 long-ods: replicas: 1 long-ods-io: replicas: 1 realtime-ods: replicas: 1 ``` **Example configuration for container registries:** ```yaml celeryWorkers: container-registries: replicas: 1 ``` **Example configuration for package registries:** ```yaml celeryWorkers: scanners-db-less: replicas: 1 ``` ## Scaling After enabling the basic integrations, refer to the [Scaling](../infrastructure-management/scaling) documentation for detailed information on: - Configuring scaling settings based on your workload - Monitoring worker performance - Optimizing resource allocation - Handling increased throughput This page focuses on initial activation - the scaling documentation covers performance optimization and capacity planning. ## Notes - **Queue Isolation**: Using dedicated workers prevents non-VCS sources from interfering with VCS scanning performance - **File scanner**: Only required when scanning Microsoft OneDrive and SharePoint for file scanning (Office documents, PDFs, etc.) - **High Disk Workers**: The `worker-scanners-ods-highdisk` is specifically designed for tasks requiring significant storage, primarily Microsoft OneDrive and SharePoint scanning - **Slack Special Case**: Slack has its own dedicated historical scan worker (`worker-scanners-slack`) in addition to the standard ODS workers - **Container Isolation**: Container registry scanning uses completely separate workers (`worker-container-registries`) from other non-VCS sources - **Package Registry Isolation**: Package registry scanning requires dedicated `worker-scanners-db-less` workers and uses the `commit-cache` Redis instance --- ## Configure preferences In order to configure preferences to fine tune your GitGuardian instance, navigate to **Settings > General > Preferences**. :::warning Please be careful some preferences allow you to activate features in beta mode. If in doubt, please seek advice from [GitGuardian team](../../troubleshoot/support). ::: ## Table of Preferences ### General | Preference | Default Value | Description | | -------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `token_expire_in_days` | 7 | Lifespan, in days, of invitations and password reset links | | `presence_check_enabled` | true | Enable secret presence check. For more info, please refer to [Investigate incidents page](../../../internal-monitoring/remediate/investigate-incidents#secret-presence-checks) | | `presence_check_display_enabled` | true | Enable display of secret presence checks | | `background_presence_check_enabled` | true | Enable automatic secret presence check in background tasks | | `validity_check_enabled` | true | Enable secret validity check | | `background_validity_check_enabled` | true | Enable automatic secret validity check in background tasks | | `validity_check_for_invalid_secrets_enabled` | true | Whether to include invalid secrets in the periodic validity checks (useful because some secrets can be temporarily invalid). Disable to reduce load on workers. | ### SAML SSO For more info, please refer to the [SAML SSO page](../../../platform/enterprise-administration/saml-sso-configuration). | Preference | Default Value | Description | | --------------------------------- | ------------- | -------------------------------------------------------------------- | | `use_model_signature_settings` | true | Enable the manual configurations of the SAML signatures requirements | | `is_custom_nameid_format_enabled` | false | Enable the choice of NameID format | ### Bitbucket For more info, please refer to the [Bitbucket integration documentation](../../../internal-monitoring/integrate-sources/vcs-integrations/bitbucket). | Preference | Default Value | Description | | ------------------------- | ------------- | --------------------------------------------------------------------------------------------------- | | `min_delay_between_syncs` | 60 | Minimum delay, in minutes, between two consecutive synchronizations of a Bitbucket installation | | `auth_error_grace_period` | 0 | Minimum period, in minutes, of repeated authentication errors after which a token should be revoked | ### On Premise | Preference | Default Value | Description | | ------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `bitbucket_disable_admin_check` | false | Disable Bitbucket integration Admin Check when creating integration | | `prometheus_metrics_active` | false | Activate Prometheus Metrics Exporter on `/metrics`. For more info, please refer to [Applicative metrics page](/self-hosting/management/application-management/metrics) | | `custom_telemetry_active` | true | Enable sending telemetry metrics to GitGuardian | | `tls_client_force_second_factor_auth` | false | Multi-factor authentication option for Certificate-Based Authentication | | `version_update_notifications_active` | true | Enable version update notifications (sidebar card, license page, and email alerts) | | `support_bundle_admin_area_enabled` | true | Enable generating and uploading a support bundle from the Admin Area. For more info, please refer to the [Support page](/self-hosting/troubleshoot/support). | ### Notifier For more info, please refer to the [Custom webhook page](../../../platform/configure-alerting/notifiers-integrations/custom-webhook). | Preference | Default Value | Description | | ----------------------------------- | ------------- | ---------------------------------------------------------- | | `max_webhooks_per_integration_type` | 1000 | Maximum number of configured webhooks per integration type | ### Source Scanner (VCS) For more info, please refer to the [Historical scanning page](../../../internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning). | Preference | Default Value | Description | | ---------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `minutes_between_scans_per_source` | 0 | Minimum minutes between two scans on the same source. (0 = disabled) | | `vcs_clone_fetch_all_refs_enabled` | true | Fetch every reference the remote exposes during historical scans (pull/merge request refs, Git notes, GitLab keep-around refs, Gerrit change refs, etc.) on top of standard branches and tags. For more info, please refer to the [Historical scanning page](../../../internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning). | ### Sources Integrations For more info, please refer to the [Gerrit integration documentation](../../../internal-monitoring/integrate-sources/vcs-integrations/gerrit). | Preference | Default Value | Description | | ----------------------------------- | ------------- | ------------------------------------------------- | | `is_gerrit_enabled` | false | Enable the Gerrit integration. | | `is_gerrit_historical_scan_enabled` | false | Enable historical scans on Gerrit sources. | ### Source Scanner | Preference | Default Value | Description | | ------------------------------------------------ | ------------- | -------------------------------------------------------------------------------- | | `servicenow_data_source_recurrent_scan_interval` | 21600 | Minimum seconds between two recurrent scans on ServiceNow sources. | | `aws_ecr_recurrent_scan_interval` | 172800 | Minimum seconds between two recurrent scans on Amazon ECR sources. | | `azure_cr_recurrent_scan_interval` | 172800 | Minimum seconds between two recurrent scans on Azure Container Registry sources. | | `google_artifact_recurrent_scan_interval` | 172800 | Minimum seconds between two recurrent scans on Google Artifact Registry sources. | | `docker_hub_recurrent_scan_interval` | 172800 | Minimum seconds between two recurrent scans on Docker Hub sources. | | `jfrog_artifact_recurrent_scan_interval` | 172800 | Minimum seconds between two recurrent scans on JFrog Container Registry sources. | | `microsoft_teams_recurrent_scan_interval` | 21600 | Minimum seconds between two recurrent scans on Microsoft Teams sources. | | `microsoft_teams_recurrent_scan_window` | 1209600 | Time window, in seconds, for Microsoft Teams recurrent scans. | | `jfrog_package_registry_recurrent_scan_interval` | 28800 | Minimum seconds between two recurrent scans on JFrog Package Registry sources. | | `red_hat_quay_recurrent_scan_interval` | 172800 | Minimum seconds between two recurrent scans on Red Hat Quay sources. | | `sharepoint_online_recurrent_scan_interval` | 21600 | Minimum seconds between two recurrent scans on SharePoint Online sources. | | `microsoft_onedrive_recurrent_scan_interval` | 21600 | Minimum seconds between two recurrent scans on Microsoft OneDrive sources. | | `confluence_cloud_recurrent_scan_interval` | 21600 | Minimum seconds between two recurrent scans on Confluence Cloud sources. | | `jira_cloud_recurrent_scan_interval` | 21600 | Minimum seconds between two recurrent scans on Jira Cloud sources. | ### Container Registries | Preference | Default Value | Description | | --------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `enable_repository_scoped_layers_cache` | false | Include repository name in layers cache keys to scope cache per repository. This allows creating multiple secret occurrences instead of just one when we encounter the same layer with the same secret across different images. | ### Policy | Preference | Default Value | Description | | ---------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `is_repo_size_controlled` | false | Limit size of repositories for historical scan. (removed in _2024.9.0_) | | `repo_scan_size_limit` | 1073741824 | Maximum repository size for historical scan, in Byte. For more info, please refer to the following [page](../../../internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning). | | `repo_scan_pending_limit_in_hours` | 168 | Timeout, in hours, of the queue time of a repository's historical scan. For more info, please refer to the following [page](../../../internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning). | | `repo_scan_time_limit_in_sec` | 7200 | Timeout, in seconds, for historical scan of repository. For more info, please refer to the following [page](../../../internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning). | | `maximum_scan_size` | 1048576 | Maximum document size for secrets detection scan via API, in bytes. | | `repo_scan_max_commit_length` | 1073741824 | Maximum total length of a commit to scan, in Byte, larger commits are truncated (-1 = unlimited). | | `displayed_content_max_size` | 10485760 | Maximum displayed content size, in Byte. Introduced in 2023.11. | | `displayed_content_max_lines` | 100000 | Maximum displayed content lines. Introduced in 2023.11. | | `skip_unchanged_scans` | True | This setting allows skipping the historical scan of a repository if it has not changed since the last scan. | ### Public API For more info, please refer to our [API documentation](../../../platform/gitguardian-suite/api). | Preference | Default Value | Description | | ----------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `maximum_multifile_documents` | 20 | Maximum number of files in a multi-file document for scanning via API | | `maximum_token_per_account` | 150 | Maximum number of API keys allowed per workspace | | `maximum_token_per_member` | 5 | Maximum number of personal access tokens allowed per member | | `quotas` | 10000000 | Monthly sliding quotas for API calls (removed in _2024.7.0_) | | `max_page_size` | 100 | Upper bound of the `per_page` parameter in the Public API which controls the number of data returned in [paginated endpoints](../../../api-docs/pagination.md). | ### GitHub For more info, please refer to the [GitHub integration documentation](../../../internal-monitoring/integrate-sources/vcs-integrations/github). | Preference | Default Value | Description | | --------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `is_actionable_checkrun_enabled` | false | Enables action buttons on checkruns (removed in _2024.2.0_) | | `check_runs_overrides_labels_ghe` | false | Enable overriding the check run settings with repository labels on GitHub Enterprise Server | | `enable_check_runs_scans` | true | Works alongside `check_runs_skip_too_large_pr`. When both feature flags are enabled, GitGuardian runs scan-based evaluations for check runs whose pull requests are too large for the basic real-time evaluation. Scan-based evaluations rely on a git clone and therefore consume far less rate limit quota. | | `check_runs_skip_too_large_pr` | true | Skip the real-time evaluation of check runs when their pull request is too large, so that very large pull requests do not consume the entire rate limit quota. Used alongside the `pr_max_commits_for_check_run`, `pr_max_files_for_check_run`, and `pr_max_changes_for_check_run` settings. | | `disable_check_run_softtimelimit_retry` | true | Check runs have a limited time to finish their real-time evaluation. By default, once this time is reached, the evaluation is retried with a longer time limit, which usually consumes a lot of rate limit quota. Enable this feature flag to disable the retry. | | `pr_max_commits_for_check_run` | 200 | Commit count threshold above which the check run is skipped. Set to 0 to disable this threshold. | | `pr_max_files_for_check_run` | 60000 | Updated file count threshold above which the check run is skipped. Set to 0 to disable this threshold. | | `pr_max_changes_for_check_run` | 300000 | Changed line count threshold above which the check run is skipped. Set to 0 to disable this threshold. | | `commit_collector_max_workers` | 4 | Maximum number of calls per worker for the commit collector. Higher number will make the commit collection faster, but is more prone to reach GitHub rate limits. Expected value between 1 and 4. | ### Health Checks For more info, please refer to the [Checking environment health page](../../troubleshoot/health-check). | Preference | Default Value | Description | | ------------------------------- | ------------- | ----------------------------------------------------------------------------- | | `periodic_enabled` | true | Enable periodic health checks. | | `periodic_interval` | 1h | Removed in _2024.7.0_, now configurable with `spread_periodic_range_minutes`. | | `spread_periodic_range_minutes` | 60 | Interval between two runs of periodic health checks (in minutes). | ### Teams For more info, please refer to the [teams page](../../../platform/collaboration-and-sharing/teams). | Preference | Default Value | Description | | ----------- | ------------- | ------------------------------------------------------------------------------------- | | `max_teams` | 500 | Maximum of team allowed on an account. ⚠️ Exceeding this limit may impact performance. | ### Remediation Tracking For more info, please refer to the [Remediation tracking page](../../../internal-monitoring/remediate/prioritize-incidents#impacted-perimeter). | Preference | Default Value | Description | | ---------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------- | | `scan_after_push_force_rate_limit` | 300 | Rate limit in seconds for scan started by the file tracking engine. Applied per source, branch and scan type. | ### Custom tags | Preference | Default Value | Description | | --------------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- | | `max_custom_tag_keys_per_workspace` | 50 | The maximum number of custom tags keys per workspace. `oneword` custom tags count as 1 key | | `max_custom_tag_values_per_key_per_workspace` | 50 | The maximum number of custom tags values for a given key. `oneword` custom tags count as 1 value for the `oneword` key | | `max_custom_tags_per_resource` | 100 | The maximum number of custom tags linked to 1 resource (e.g. honeytoken, private incident, etc) | | ### Multi-Factor Authentication For more info, please refer to the [Account settings page](../../../platform/user-account/account-settings). | Preference | Default Value | Description | | -------------------- | ------------- | ----------------------------------------------------------------------------------------- | | `is_mfa_enabled` | false | Enable multi-factor authentication for the workspace. | | `sudo_mode_duration` | 30 | Duration, in minutes, of an elevated (sudo) session before re-authentication is required. | ### Background Presence Check Frequencies For more info, please refer to the [Investigate incidents page](../../../internal-monitoring/remediate/investigate-incidents#secret-presence-checks). | Preference | Default Value | Description | | ----------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- | | `ignored_old` | 0 | Frequency, in days, of automated checks for presence in git history for ignored secret incidents more than 1 year old | | `ignored_recent` | 178 | Frequency, in days, of automated checks for presence in git history for ignored secret incidents less than 1 year old | | `open_old` | 7 | Frequency, in days, of automated checks for presence in git history for open secret incidents more than 1 year old | | `open_recent` | 1 | Frequency, in days, of automated checks for presence in git history for open secret incidents less than 1 year old | | `resolved_old` | 178 | Frequency, in days, of automated checks for presence in git history for resolved secret incidents more than 1 year old | | `resolved_recent` | 30 | Frequency, in days, of automated checks for presence in git history for resolved secret incidents less than 1 year old | ### Background Validity Check Frequencies For more info, please refer to the [Validity checks page](../../../secrets-detection/customize-detection/validity-checks). | Preference | Default Value | Description | | ----------------- | ------------- | ---------------------------------------------------------------------------------------------------------- | | `ignored_old` | 178 | Frequency, in days, of automated secret validity checks for ignored secret incidents more than 1 year old | | `ignored_recent` | 30 | Frequency, in days, of automated secret validity checks for ignored secret incidents less than 1 year old | | `open_old` | 7 | Frequency, in days, of automated secret validity checks for open secret incidents more than 1 year old | | `open_recent` | 1 | Frequency, in days, of automated secret validity checks for open secret incidents less than 1 year old | | `resolved_old` | 178 | Frequency, in days, of automated secret validity checks for resolved secret incidents more than 1 year old | | `resolved_recent` | 30 | Frequency, in days, of automated secret validity checks for resolved secret incidents less than 1 year old | --- ## KOTS Admin Console The KOTS Admin Console is your central hub for managing your GitGuardian instance. Here, you can: - [Upgrade](./upgrade-kots) your GitGuardian platform to access the latest features and improvements. - [Back up](./backup) your GitGuardian data for safekeeping. - Re-sync your [license](../../license-management) to stay compliant and up-to-date. - Configure cluster-side settings, including: - [Scaling](./scaling) your instance to meet demand. - Configure [TLS certificates](../../security/tls-certificates). - Setting up [Ingress](./ingress.md) for external access. - Adjusting [Load Balancer](./load-balancer) settings for optimal distribution. - Configuring a [Proxy Server](./proxy-server) for network routing and security. - Change the periodicity of the [health checks](../../troubleshoot/health-check#integration-connectivity). :::info The KOTS Admin Console is not available with **[Helm Installation](../../installation/installation-existing-cluster-helm)**. For each management action, an alternative method will be described for Helm's environment. ::: ![KOTS admin](/img/self-hosting/management/infrastructure-management/replicated_kots_admin.png) ## Access The KOTS Admin Console is available on `http://${your-server-address}:8800`. If needed you can set up an SSH tunnel to access it locally on `http://localhost:8800`: ``` ssh -N -L 8800:localhost:8800 ${your-server-ip} ``` You can access it with the password given during the installation: - [for embedded cluster](../../installation/installation-embedded-cluster#embedded-cluster) - [for existing cluster](../../installation/installation-existing-cluster-kots#kots-admin-console) To reset the KOTS Admin Console password, execute the following command: ```bash kubectl kots reset-password ``` ## TLS Certificates To update the Certificate for the Console, please refer to [the TLS documentation](../../security/tls-certificates#kots-admin-console). ## Audit Logs To retrieve the audit logs for the Console, execute the following command: ```bash kubectl kots get versions gitguardian --namespace -o json ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). --- ## Autoscaling :::info This page only concerns installation on an existing cluster using **[KOTS](/self-hosting/installation/installation-existing-cluster-kots)** or **[Helm](/self-hosting/installation/installation-existing-cluster-helm)**. ::: ## Requirements for autoscaling You can use either **Kubernetes HPA (Horizontal Pod Autoscaler)** or **KEDA (Kubernetes Event-Driven Autoscaler)** for autoscaling. Both rely on the same metrics but have different requirements. - **HPA**: Kubernetes built-in, reads metrics from Metrics Server or external metrics pushed by Prometheus Adapter. A bit less responsive than KEDA. Cannot scale to zero replica. - **KEDA**: Reads events from a variety of sources (here Prometheus). Faster scaling. Can scale to zero replica. _Not available on KOTS-based installations._ ### Required components Depending on your chosen autoscaling method, you will need different components installed in your cluster: | Component | HPA | KEDA | |:----------------------------------------------------------------------------|:---:|:----:| | [Prometheus server](https://prometheus.io/) | Required | Required | | [Prometheus adapter](https://github.com/kubernetes-sigs/prometheus-adapter) | Required | Not required | | [KEDA controller](https://keda.sh/) | Not required | Required | HPA requires Prometheus adapter to expose these metrics to the Kubernetes metrics API, while KEDA can directly query Prometheus. ### Installing Prometheus server Both autoscaling methods need a Prometheus that scrapes the GitGuardian application metrics. Two setups are supported, depending on whether you run the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator) in your cluster. :::info Prerequisite: authorize metrics export Whichever option you pick, the GitGuardian application must be configured to expose its metrics first, otherwise Prometheus scrapes empty endpoints. See [Authorize metrics collection](../application-management/metrics.md#authorize-metrics-collection) to activate the application export. ::: :::info Which one should I pick? A standalone Prometheus server **does not read `ServiceMonitor` resources** — it only scrapes what its own configuration file lists. So the GitGuardian chart's built-in `ServiceMonitor` objects have no effect on a standalone server, and you must add a manual scrape configuration instead. - **Option A (recommended)** — if you already run, or are willing to install, [`kube-prometheus-stack`](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) (bundles the operator + a managed Prometheus). The GitGuardian chart ships the `ServiceMonitor` objects, so collection is just a matter of enabling them. - **Option B** — if you want a single self-contained Prometheus with no operator. You write the scrape configuration by hand. ::: Add the Prometheus Community Helm repository (used by both options): ```bash helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update ``` #### Option A (recommended): kube-prometheus-stack with ServiceMonitors For autoscaling you only need the **operator** (to process `ServiceMonitor` objects) and the **Prometheus** instance itself. Disable every other component to keep the install lightweight. Create a `kube-prometheus-stack-values.yaml`: ```yaml # Operator (prometheusOperator) and Prometheus stay enabled by default — # everything below is cluster-wide monitoring that autoscaling does not need. alertmanager: enabled: false grafana: enabled: false nodeExporter: enabled: false # disables the prometheus-node-exporter subchart kubeStateMetrics: enabled: false # disables the kube-state-metrics subchart defaultRules: create: false # skip the bundled Kubernetes alerting/recording rules # Skip scraping of Kubernetes control-plane and node components kubeApiServer: enabled: false kubelet: enabled: false kubeControllerManager: enabled: false coreDns: enabled: false kubeDns: enabled: false kubeEtcd: enabled: false kubeScheduler: enabled: false kubeProxy: enabled: false ``` ```bash helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \ --namespace monitoring \ --create-namespace \ -f kube-prometheus-stack-values.yaml ``` The managed Prometheus is then reachable in-cluster at `http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090`. Enable the GitGuardian `ServiceMonitor` objects in your `local-values.yaml`: ```yaml observability: exporters: statefulAppExporter: enabled: true serviceMonitors: enabled: true labels: # Must match the Helm release name of your kube-prometheus-stack install. # The stack's Prometheus only selects ServiceMonitors carrying this label. release: kube-prometheus-stack ``` :::caution The `release` label is mandatory By default, the stack's Prometheus has `serviceMonitorSelector: {matchLabels: {release: }}`. A `ServiceMonitor` **without that exact label is silently ignored** — no targets, no metrics, and the Prometheus Adapter ends up exposing nothing. Either set the label as shown above, or set `prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false` on the stack to make it select every `ServiceMonitor`. ::: After `helm upgrade` of the GitGuardian chart, confirm the targets are picked up (state `UP`) in the Prometheus UI under **Status > Targets**, or: ```bash kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 9090 # then browse http://localhost:9090/targets and look for serviceMonitor//... ``` #### Option B: Standalone Prometheus with manual scrape config Install the standalone server: ```bash helm install prometheus prometheus-community/prometheus \ --namespace monitoring \ --create-namespace \ --set alertmanager.enabled=false \ --set prometheus-pushgateway.enabled=false ``` The server is then reachable in-cluster at `http://prometheus-server.monitoring.svc.cluster.local:80`. Because the standalone server ignores `ServiceMonitor` objects, add a scrape job pointing at the GitGuardian metrics endpoints. The Celery queue-length metric (`gim_celery_queue_length`) is published by the **app exporter**, a single aggregating endpoint — so one static target is enough. Set this in the standalone Prometheus chart's values: ```yaml extraScrapeConfigs: | - job_name: "gim" static_configs: # Replace with the namespace your GitGuardian release is installed in - targets: ["app-exporter..svc.cluster.local:9808"] metric_relabel_configs: # The adapter rule maps metrics to a namespace (overrides.namespace), so the # series must carry a `namespace` label. A static target has none, so derive # it from the instance hostname: app-exporter..svc... -> - source_labels: [instance] regex: '.*\.([^.]+)\.svc.*' target_label: namespace action: replace replacement: '$1' ``` :::caution Update the placeholder hostname `` in `app-exporter..svc.cluster.local` is the **namespace** of your GitGuardian release — substitute the namespace you installed into. The `metric_relabel_configs` block then derives the `namespace` label from whatever you set, so keep the two consistent. ::: :::info The `app-exporter` service only exists when the aggregating exporter is enabled — set `observability.exporters.statefulAppExporter.enabled: true` in your GitGuardian values. For **Machine Learning Secret Engine** autoscaling you also need `bentoml_service_request_in_progress`, which is served by the secret engine itself rather than the app exporter. Add a second static target for it (port `3000` is the `secretEngine.port` default — change it only if you overrode that value): ```yaml - job_name: "gim-ml-secret-engine" metrics_path: /metrics static_configs: # Replace with your namespace, and 3000 if you changed secretEngine.port - targets: ["ml-secret-engine..svc.cluster.local:3000"] metric_relabel_configs: - source_labels: [instance] regex: '.*\.([^.]+)\.svc.*' target_label: namespace action: replace replacement: '$1' ``` ::: :::caution Do not enable `observability.serviceMonitors` Keep `observability.serviceMonitors.enabled: false` (the default) for this option. A standalone Prometheus install does **not** register the `monitoring.coreos.com` CRDs (those come with the Prometheus Operator). If you enable it, the GitGuardian chart tries to create `ServiceMonitor` objects whose CRD is absent and the `helm install`/`helm upgrade` **fails** with a `no matches for kind "ServiceMonitor"` error. The standalone server would ignore those objects anyway — collection here comes solely from the scrape config above. ::: ### Installing Prometheus adapter If you choose HPA for autoscaling, install [Prometheus Adapter](https://github.com/kubernetes-sigs/prometheus-adapter) to expose the Prometheus metrics to the Kubernetes metrics API. Point `prometheus.url`/`prometheus.port` at **the Prometheus you installed above** — this is the single most common misconfiguration. For **Option A** (kube-prometheus-stack): ```bash helm install prometheus-adapter prometheus-community/prometheus-adapter \ --namespace monitoring \ --set prometheus.url=http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local \ --set prometheus.port=9090 ``` For **Option B** (standalone server): ```bash helm install prometheus-adapter prometheus-community/prometheus-adapter \ --namespace monitoring \ --set prometheus.url=http://prometheus-server.monitoring.svc.cluster.local \ --set prometheus.port=80 ``` :::caution Adapter pointing at the wrong Prometheus If `prometheus.url` points at a service that does not exist (for example, you migrated from the standalone server to the stack but left the adapter on the old URL), the adapter stays `AVAILABLE=True` but exposes **zero** metrics. Verify with: ```bash kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq '.resources[].name' kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq '.resources[].name' ``` An empty `resources` list means the adapter reaches no matching series — check the URL first, then the [rules](#prometheus-adapter-configuration). ::: See the [Prometheus Adapter configuration](#prometheus-adapter-configuration) section below for the rules to add. ### Installing KEDA controller Install the [KEDA controller](https://github.com/kedacore/keda) to enable autoscaling. You can install it using the [KEDA Helm chart](https://github.com/kedacore/charts) with the following commands: ```bash helm repo add kedacore https://kedacore.github.io/charts helm install keda kedacore/keda \ --namespace keda \ --create-namespace ``` You must configure the Helm values of your GitGuardian chart to allow KEDA to connect to your Prometheus server: ```yaml autoscaling: keda: prometheus: metadata: # Use the Prometheus server address from your installation: # Option A (kube-prometheus-stack): http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090 # Option B (standalone server): http://prometheus-server.monitoring.svc.cluster.local:80 serverAddress: http://prometheus-server.monitoring.svc.cluster.local:80 # Optional. Custom headers to include in query customHeaders: X-Client-Id=cid,X-Tenant-Id=tid,X-Organization-Id=oid # Optional. Specify authentication mode (basic, bearer, tls) authModes: bearer # Optional. Specify TriggerAuthentication resource to use when authModes is specified. authenticationRef: name: keda-prom-creds ``` A `ScaledObject` and an `hpa` will be created in the GitGuardian namespace. ## Autoscaling workers Autoscaling allows for dynamic scaling of worker pods based on Celery task queue length as an external metric for scaling decisions, improving efficiency and performance while optimizing resource costs. To enable autoscaling based on Celery queue lengths, you need first to [authorize metrics collection](../application-management/metrics.md#authorize-metrics-collection) so the application exposes its metrics. If you use KEDA, configuring the Prometheus adapter is not necessary. ### Prometheus adapter configuration Configure Prometheus adapter to expose Celery queue lengths as external metrics. This is done by setting up a custom rule in the Prometheus Adapter configuration. The following rule should be added to your Prometheus Adapter Helm values to expose Celery queue lengths: ```yaml rules: external: - seriesQuery: '{__name__="gim_celery_queue_length",queue_name!=""}' metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (queue_name) resources: namespaced: true overrides: namespace: resource: namespace ``` If you use Machine Learning, you will also need this rule: ```yaml rules: external: - seriesQuery: '{__name__="bentoml_service_request_in_progress",exported_endpoint!=""}' resources: namespaced: false metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>) ``` ### Autoscaling Behavior The following behavior will be applied: - **Scaling Up**: If the length of a Celery queue exceeds 10 tasks per current worker replica, the number of replicas will be increased, provided the current number of replicas is below the specified maximum limit. - **Scaling Down**: If the number of tasks per current worker replica remains below 10 for a continuous period of 5 minutes, the number of replicas will be decreased, provided the current number of replicas is above the specified minimum limit. ![HPA behavior](/img/self-hosting/management/infrastructure-management/replicated_hpa_behavior.png) :::info Using KEDA, when the Celery queue is empty, the worker will transition to an idle state, resulting in the number of replicas being scaled down to zero. ::: ## Autoscaling web applications Web deployments (e.g. `public_api`, `internal_api`) scale on **request latency**, reading from your ingress controller's Prometheus metrics. GitGuardian ships a built-in latency query for a set of controllers; for any other controllers you provide your own KEDA trigger. :::caution Routing requirement Webapp autoscaling requires **Gateway API** routing (`routingApi: gateway-api`) — the actively developed mode that exposes the per-webapp metrics the autoscaler reads. It is **not** available with the default built-in nginx routing (`routingApi: ingress`), which fronts all traffic through a single in-chart nginx pod and exposes no per-webapp metrics. ::: ### Prerequisites In addition to [Prometheus and KEDA](#required-components), the built-in query reads metrics emitted by **your ingress controller**, which GitGuardian does **not** install or scrape. You must therefore: 1. **Enable the controller's Prometheus metrics**, on the controller's own chart — for example: - traefik: `metrics.prometheus.serviceMonitor.enabled=true` - istio / contour: their Envoy proxy metrics (no extra flag, but see the next point) 2. **Have Prometheus scrape them**, via a `ServiceMonitor`/`PodMonitor` (Prometheus Operator). Most controller charts ship one behind a flag (e.g. traefik `…metrics.serviceMonitor.enabled=true`); istio and Contour's Envoy are scraped with a `PodMonitor` on the proxy pods (path `/stats/prometheus`). With the standard `ServiceMonitor` setup, Prometheus renames the controller's `service` label to `exported_service` (label collision with the scrape target) — which is what the built-in queries match. If the expected series are missing, autoscaling has no data: check in Prometheus that the controller's request-duration metric exists before debugging the chart. ### Supported controllers The built-in latency query is selected by `ingress.controller`: | `ingress.controller` | Built-in latency query | |:---|:---:| | `istio` | ✅ | | `traefik` | ✅ | | `contour` | ✅ (requires the Gateway API *experimental* CRD channel — see below) | | `nginx-gateway-fabric` | ❌ (no per-route metrics in the OSS edition) | | `other` | ❌ (by design — bring your own trigger) | The built-in query covers `istio`, `traefik` and `contour`. Contour additionally requires the Gateway API **experimental** CRD channel (the upstream Kubernetes Gateway API SIG release channel). Any other data plane (`nginx-gateway-fabric`, Kong, Cilium, Envoy Gateway, `aws_alb`, …) has no built-in query — set `controller: other` and supply your own KEDA trigger like the one below. ### Built-in latency autoscaling (supported controllers) Set a latency threshold (in milliseconds); the chart builds the right Prometheus query for your controller automatically: ```yaml ingress: controller: istio # one of: istio, traefik, contour webapps: public_api: autoscaling: keda: { enabled: true } minReplicas: 1 maxReplicas: 5 metrics: targetLatency: 1000 # ms ``` ### Custom trigger for an unlisted controller (e.g. Gateway API with Kong / Cilium / Envoy Gateway) When your data plane has no built-in query, set `ingress.controller: other`, disable the built-in query with `targetLatency: null`, and provide your own KEDA trigger. Routing is unaffected — `other` renders standard Gateway API `HTTPRoute`s (or a plain `Ingress` with your `ingressClassName`). ```yaml ingress: routingApi: gateway-api controller: other gatewayApi: gatewayClassName: kong # your Gateway API controller webapps: public_api: autoscaling: keda: enabled: true triggers: - type: prometheus metricType: Value metadata: serverAddress: http://prometheus-server.monitoring.svc.cluster.local:80 query: 'sum(rate(kong_http_requests_total{service="gim.public-api.pnum-5051"}[1m]))' threshold: "20" minReplicas: 1 maxReplicas: 5 metrics: targetLatency: null # disables the built-in query ``` ### Overriding the built-in query You can also replace the built-in query with your own (e.g. scale on a different metric, percentile, or window): set `targetLatency: null` to drop the built-in query and define your trigger. Once `targetLatency` is null the `controller` value no longer affects autoscaling, so you can keep your real controller (e.g. `istio`) **or** set `controller: other` — both behave the same with a custom trigger. ```yaml ingress: controller: istio # or "other" — irrelevant for autoscaling once targetLatency is null webapps: public_api: autoscaling: keda: enabled: true triggers: - type: prometheus metricType: Value metadata: serverAddress: http://prometheus-server.monitoring.svc.cluster.local:80 # e.g. p99 instead of the default p95 latency query: 'histogram_quantile(0.99, sum(rate(istio_request_duration_milliseconds_bucket{destination_service_name="public-api"}[2m])) by (destination_service_name, le))' threshold: "800" minReplicas: 1 maxReplicas: 5 metrics: targetLatency: null ``` :::info `autoscaling.keda.triggers` are passed to KEDA as-is, so you are not limited to Prometheus — any [KEDA scaler](https://keda.sh/docs/latest/scalers/) (CPU, memory, Kafka, SQS, …) can be used. ::: ## KOTS-based installation KOTS-based installation only allows HPA autoscaling. Navigate under **Config > Scaling** in the [KOTS Admin Console](./admin-console), you will have access to the worker scaling options. For each worker, you can enable autoscaling by ticking the option `Enable Horizontal Pod Autoscaling`, then you will be able to specify the minimum and the maximum replicas. ![Worker Autoscaling configuration](/img/self-hosting/management/infrastructure-management/replicated_worker_autoscaling.png) ## Helm-based installation Customize Helm applications using your `local-values.yaml` file, submitted with the `helm` command. ### Autoscaling Workers You can enable worker autoscaling by setting the following Helm values (here, we enable HPA for the "worker" worker): ```yaml celeryWorkers: worker: autoscaling: hpa: enabled: true keda: enabled: false minReplicas: 1 maxReplicas: 10 ``` ### Autoscaling the Machine Learning Secret Engine For effective autoscaling of the **Machine Learning Secret Engine**, you must enable autoscaling for **both**: - **The ML Worker processing the Celery queue** (`ml-api-priority`): this worker is responsible for queuing and dispatching ML-related tasks. Without autoscaling, it could become a bottleneck, leading to delays in processing requests. - **The Secret Engine handling the computation** (`secretEngine`): enabling autoscaling for the Secret Engine ensures that it can scale in response to the demand for ML computations. To enable autoscaling, configure the following Helm values: ```yaml # ML Secret Engine secretEngine: autoscaling: hpa: enabled: true keda: enabled: false minReplicas: 1 maxReplicas: 2 celeryWorkers: # ML Worker ml-api-priority: autoscaling: hpa: enabled: true keda: enabled: false minReplicas: 1 maxReplicas: 2 ``` See [the values reference documentation](./helm-values) for further details. :::caution `autoscaling.hpa.enabled` and `autoscaling.keda.enabled` Helm parameters are mutually exclusive, you must choose between **hpa** (using Prometheus adapter) and **KEDA** controller. ::: --- ## Backup & Restore :::caution GitGuardian encrypts all sensitive information in the database using a data encryption key (also known as the Django Secret Key). In the event of a disaster, this key will be essential to restore your data. Regardless of the installation method (KOTS or Helm), **ensure the encryption key is securely stored** and accessible. Use the following command to display the key: ```shell kubectl get secrets gim-secrets --namespace= -o jsonpath='{.data.DJANGO_SECRET_KEY}' | base64 -d ``` ::: ## Backup To fully back up the GitGuardian application, you need to: - Back up the PostgreSQL database (⚠️ and the **data encryption key**). - Back up the KOTS config (for KOTS-based installations existing cluster). - Back up the Helm values file (for Helm-based installations existing cluster). We strongly recommend using externally managed databases and data stores, along with a robust strategy for snapshots and backups. An embedded cluster installation with an embedded PostgreSQL database is not recommended for production deployments and is intended for PoC/testing purposes only. For more information, see the [Choose your installation method](../../installation/choose-embedded-existing) page. ### Helm-based Installation Ensure you back up the values file you created during the [installation](../../installation/installation-existing-cluster-helm#customize-the-local-values-file). ### KOTS-based Installation To backup the KOTS config files, use: ```bash kubectl kots get config \ --namespace gitguardian \ --decrypt \ --appslug gitguardian > config.yaml ``` :::caution The backup configuration contains secrets. Ensure it is stored securely and access is strictly controlled. ::: If needed, specify the Kubernetes namespace with `--namespace` (the default namespace is used if not specified). KOTS offers a mechanism to simplify backups of your GitGuardian application. For detailed information on backup and restore, including Velero Version Compatibility, please refer to the [Replicated website](https://docs.replicated.com/enterprise/snapshots-understanding#velero-version-compatibility). ### ClickHouse If your installation uses [ClickHouse](./clickhouse/overview) for analytics features, it has its own backup mechanism and restore procedure: see [ClickHouse backup and restore](./clickhouse/backup-restore). Note that a complete disaster-recovery plan for ClickHouse-backed features may require restoring **both** ClickHouse and PostgreSQL to a consistent point in time. ## Restore Restoring the GitGuardian instance depends on the situation. Do you just want to go back in time to a previous database backup? Are you looking to roll back to a previous version of the application? Did you lose your database and/or Kubernetes cluster and need to restore the application and database from scratch? ### Database restore only To restore the PostgreSQL database, follow these steps: 1. Stop the application. 2. Flush the Redis cache. 3. Restore the PostgreSQL database. 4. Restart the application. ### Application version rollback :::danger Do not roll back or downgrade without consulting our **[support team](mailto:support@gitguardian.com)** first. Certain scenarios may require restoring the database from a pre-upgrade backup due to the complexity of reversing some database migrations. ::: ### Disaster Recovery In the event that you need to reinstall the application from scratch for disaster recovery, follow the appropriate installation procedure based on your setup: - [KOTS existing cluster](../../installation/installation-existing-cluster-kots) - [KOTS embedded cluster](../../installation/installation-embedded-cluster) - [Helm](../../installation/installation-existing-cluster-helm) #### Helm-Based Installation 1. Use your previously backed-up values file. 2. Ensure you specify the encryption key by either: - Using the inline parameter `miscEncryption.djangoSecretKey`, or - Referencing an existing secret with `miscEncryption.existingSecret`. #### KOTS-Based Installation 1. Follow the installation procedure for your KOTS setup. 2. Configure the installation with the essential settings. 3. Once the installation is complete, restore the KOTS configuration files using the following command: ```bash kubectl kots install gitguardian \ --namespace gitguardian \ --use-minimal-rbac \ --shared-password \ --license-file license.yaml \ --config-values config.yaml ``` - Replace `` with your desired password (used to access [KOTS Admin Console](./admin-console)). - Adjust the `namespace` if necessary. - Ensure you use the `config.yaml` file from your backup. - This command must be executed on a non-existent or empty namespace (i.e., no prior KOTS installation). 4. In the [KOTS Admin Console](./admin-console), verify that the configuration is correct and deploy the application. ![KOTS Admin Config](/img/self-hosting/management/infrastructure-management/replicated_kots_admin_config.png) --- ## Certificate-Based Authentication (legacy) :::warning Certificate-based authentication is deprecated and will be removed in a future release. This feature is no longer actively maintained. If you are currently using this feature, please contact **support@gitguardian.com** to discuss migration options. ::: Certificate-based authentication requires users to present a TLS client certificate to authenticate with GitGuardian. This method is essential to authenticate using a Common Access Card (CAC) or Personal Identity Verification (PIV). ## System Requirements You will need a Certificate Authority (CA) in PEM format to set up client authentication. GitGuardian supports one or multiple CAs (a bundle) for this purpose. These CA(s) will be used to validate the client certificates required for authenticating to the GitGuardian dashboard. Additionally, you must provide your own external user ID located in your client certificate, as well as the external user IDs of any users you want to invite to the GitGuardian platform. For example, the Department of Defense's Electronic Data Interchange Personal Identifier (EDIPI) found in the CN might look like `C=FR,O=DGSE,CN=hubert.bonisseur.delabath.117` where the EDIPI = `117`. ## Network requirements ### Outbound rules To ensure proper communication with the OCSP or CRL server(s), please configure the following network rules: | Port | Source | Destination | Description | | :---: | ------------: | ------------------------: | -----------------: | | 80 | All K8S nodes | _your OCSP/CRL server(s)_ | OCSP/CRL server(s) | ## Initial Setup Follow these steps to configure certificate-based authentication in your self-hosted instance: 1. **Initial Setup** 1. Follow [specific instructions](#configuration-parameters) depending on whether you are installing GitGuardian in an embedded or existing cluster. 1. Start with the mode set to `audit` for initial setup and verification. 1. Upload your CA that will validate client certificates. 1. Configure the regular expression to extract the external user ID from the client certificate's subject (or use the default one if that works for you). 2. **Authenticate for the first time** 1. Log in to your GitGuardian dashboard and provide your client certificate (or insert your CAC/PIV access card). 1. If you encounter an error during authentication, an error page will appear with the reason for the failure (e.g., Certificate invalid, revoked, etc.). Note that this error page will only display in `audit` mode. ![Certificate-based authentication audit error](/img/self-hosting/management/infrastructure-management/certificate_authentication_audit_error.png) 1. If your client certificate is valid, proceed to login with your login/password to the GitGuardian dashboard. 1. Then, enter the external user ID found in the CN of your client certificate when prompted. ![Certificate-based authentication External ID](/img/self-hosting/management/infrastructure-management/certificate_authentication_external_id.png) 3. **Verify and Enforce** 1. Navigate to the [admin area](../application-management/admin-area) under `Settings > Certificate-Based Authentication` to view client certificate and user mapping details. ![Certificate-based authentication admin area](/img/self-hosting/management/infrastructure-management/certificate_authentication_admin_area.png) 1. If the external user ID is not properly associated with a GitGuardian user, an error message will be displayed. Ensure that the regular expression correctly extracts the user’s external ID and that the user ID is correctly configured. ![Certificate-based authentication user mapping error](/img/self-hosting/management/infrastructure-management/certificate_authentication_user_mapping.png) 1. After confirming successful authentication and correct user mapping, switch to `enforce` mode via KOTS or Helm. 1. **Optional**: You can enable email/password authentication or Single Sign-On (SSO) alongside certificate-based authentication. This provides an additional security layer and allows for scalable user management through SAML SSO. ![Certificate-based authentication multi auth](/img/self-hosting/management/infrastructure-management/replicated_certificate_authentication_multi_auth.png) 4. **Integrate your first repositories and invite new user** 1. [Integrate your first repositories](../../../platform/getting-started/integrate) to get started with automated secrets detection and remediation. 1. Invite other team members along with their external user ID. 1. ⚠️ Only users with admin area access can invite users by providing the **external user ID**. They can also modify it in the `Settings > Members` page. ## Configuration Parameters For any installation (KOTS or Helm), configure the following parameters: - **Enable**: Enable certificate-based authentication. - **Mode**: Defines the application's behavior regarding client certificates. - `audit`: For setup only. Displays debugging information. ⚠️ Note: Public API routes are not functional with the audit mode. - `enforce`: For production. Requires a client certificate. - **Certificate Authority**: The CA that validates client certificates (also known as the CA bundle). - **CRL (optional)**: The certificate revocation list in PEM or DER format (OCSP used if not set). - **Regex**: The regular expression to extract the unique user identifier from the certificate Distinguished Name (DN), part of the certificate's subject. ### Existing Cluster :::caution When you activate this option, **TLS termination is done on the backend pods**. Enable SSL passthrough based on your exposure method ([Service Loadbalancer](./load-balancer) or [Ingress](./ingress)). Examples are provided below. ::: #### KOTS-Based Installation In the [KOTS Admin Console](./admin-console), enable **Use Certificate-Based Authentication** and configure the parameters. ![Certificate-based authentication KOTS](/img/self-hosting/management/infrastructure-management/replicated_certificate_authentication.png) #### Helm-Based Installation In [Helm values](./helm-values), configure the following block: ```yaml tls: clientAuth: enabled: true mode: enforce userRegex: '(?:.+,)?CN=[^.]+\.[^.]+\.[^.]+\.(\d+)(?:,.+)?' crt: '' key: '' caCrt: '' ocspCacheSize: '10m' existingSecret: '' existingSecretKeys: crt: 'server.crt' key: 'server.key' caCrt: 'ca.crt' # PEM format crl: url: '' cron: '0 0 * * *' persistence: storageClass: '' accessModes: - ReadWriteMany size: 1Gi labels: {} annotations: {} ``` Use [existing secrets](../../installation/helm-secrets#existing-secret) to store certificates. #### Annotations Example ##### Service Loadbalancer on DigitalOcean ```yaml service.beta.kubernetes.io/do-loadbalancer-tls-ports: '443' service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: 'true' ``` ##### Ingress Using NGINX Ingress Controller ```yaml ingress: tls: enabled: true annotations: nginx.ingress.kubernetes.io/ssl-passthrough: 'true' service: port: 443 ``` Add these in the annotations section of the [KOTS Admin Console](./admin-console) or in [Helm values](./helm-values). ![Loadbalancer annotations](/img/self-hosting/management/infrastructure-management/replicated_certificate_authentication_ingress_nginx.png) #### Notes about CRL usage in an existing cluster You may choose to perform revocation checks using CRL instead of OCSP server. This mode : - creates a Persistent Volume using a storageClass in the [accessMode](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes) of your choice. This configuration depends on your cluster. - fetches the CRL on a regular interval you define using a [cron expression](https://en.wikipedia.org/wiki/Cron) Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. ### Embedded Cluster In the [KOTS Admin Console](./admin-console), enable **Use Certificate-Based Authentication** and configure the parameters. ![Certificate-based authentication KOTS](/img/self-hosting/management/infrastructure-management/replicated_certificate_authentication.png) ## Troubleshooting If you encounter authentication issues, switching to `audit` mode is recommended. To diagnose the problem, you can review the logs from the `webapp-internal_api` pod. For additional details, refer to our [troubleshooting](../../troubleshoot/logs#viewing-logs-in-pods) page. To filter the logs for warnings, you can use the following command: ```bash kubectl logs webapp-internal-api-6b98b7b9bc-wcvpb | grep warning ``` **Common Issues**: 1. Invalid Client Certificate: ```json { "timestamp": "2024-08-16T14:57:54.713592Z", "level": "warning", "event": "Mutual tls authentication failed", "reason": "Missing or invalid certificate", "remote_auth_result": "FAILED:certificate revoked", "logger": "auth.mutual_tls.services.middlewares", "gg_service": "ward-runs-app", "gg_environment": "onprem", "gg_version": "2024.8.0" } ``` **Solution**: Verify the client certificate for validity. Check for issues such as expiration or revocation. 2. External User ID Cannot Be Mapped to a GitGuardian User: ```json { "timestamp": "2024-08-16T14:58:05.121226Z", "level": "warning", "event": "Mutual tls authentication failed", "reason": "Invalid User", "remote_user_dn": "CN=client3.0000000003,OU=Dev,O=GG,L=Paris,ST=Paris,C=FR", "external_user_id": "0000000003", "logger": "auth.mutual_tls.services.middlewares", "gg_service": "ward-runs-app", "gg_environment": "onprem", "gg_version": "2024.8.0" } ``` **Solution**: Ensure the regular expression correctly extracts the user’s external ID. Additionally, verify that the external user ID is properly associated with a GitGuardian user in the `Settings > Members` section of the GitGuardian dashboard. You must have [admin privileges](../application-management/admin-area#users) to access this setting. --- ## ClickHouse backup and restore ## How ClickHouse backup works A backup sidecar runs alongside ClickHouse, continuously watching for changes and taking scheduled full and incremental backups automatically: there is no separate cron job to configure. ```mermaid graph LR subgraph Pod["ClickHouse pod"] CH[ClickHouse] CB["clickhouse-backup(sidecar)"] end PVC[("Metadata volume")] SRC[("Object storageClickHouse's data")] DST[("Object storagebackup destination")] CH -->|FREEZE| PVC PVC -->|manifests + DDL| CB CB -->|upload| DST SRC -.->|server-side copyof data blobs| DST ``` Backups are: - **Application-consistent**: taken via ClickHouse's native `FREEZE` mechanism (zero-copy hardlinks), not a raw volume snapshot, so a backup never captures a table mid-write. - **Written to your object storage**: both the metadata/manifests and the underlying data blobs are copied to your configured bucket, under the path prefix you configure below. - **Deduplicated and chain-aware**: incremental backups only store what changed; retention policies remove whole backup chains rather than leaving orphaned increments. :::caution Never change permissions on the local backup path `FREEZE` works by creating **hard links** to the live table data, not copies. Permissions, ownership, and attributes on a hard link are a property of the underlying data itself: they're shared across every hard link pointing to it. Changing permissions on a file under the backup path changes them on the live data ClickHouse is actively reading and writing too, which can lead to data corruption. Never manually touch permissions there; let ClickHouse and the backup sidecar manage that path exclusively. ::: ## Backup sidecar configuration A backup sidecar is configured by default on the ClickHouse pod, via `clickhouse-server.sidecars`: the chart's mechanism for adding an extra container alongside the volumes ClickHouse itself uses. It runs [`clickhouse-backup`](https://github.com/Altinity/clickhouse-backup) in `server --watch` mode, which self-schedules full and incremental backups in-process; there is no separate cron job, and nothing else to deploy. ### Object storage destination The backup destination has **no default**: you must configure it before backups can run. This splits into two parts, both provider-specific: non-sensitive settings (bucket/container, region, path) go under `clickhouse.backupConfig` (see [Tunable settings](#tunable-settings) below for the rest of that map), while credentials (where a static key is required at all) are passed via a separately-created Kubernetes secret, never inline in your values file (the same pattern described in [Prerequisites](./overview#prerequisites)). The **target bucket** is set independently from ClickHouse's own data bucket (see [Object storage backends](./storage#object-storage-backends)): use a genuinely separate bucket, not just a different prefix in the same one (see the tip in that section for why). Pick your provider below. ```yaml clickhouse: backupConfig: REMOTE_STORAGE: 's3' S3_BUCKET: '' S3_REGION: '' S3_PATH: 'backups/metadata' S3_OBJECT_DISK_PATH: 'backups/objects' ``` **Target bucket:** `S3_BUCKET`. No credential entry needed: with IRSA (see [Object storage backends](./storage#configuration)), the ServiceAccount's token is automatically mounted into every container in the pod, including this sidecar. With Microsoft Entra Workload ID set up for the storage disk (see [Object storage backends](./storage#configuration)), the sidecar inherits it for free: the AKS mutating webhook injects the federated-token environment variables and projected token volume into **every container in the pod** by default, not just ClickHouse's own: no separate setup needed. Just add: ```yaml clickhouse: backupConfig: REMOTE_STORAGE: 'azblob' AZBLOB_ACCOUNT_NAME: '' AZBLOB_CONTAINER: '' AZBLOB_PATH: 'backups/metadata' AZBLOB_OBJECT_DISK_PATH: 'backups/objects' AZBLOB_USE_MANAGED_IDENTITY: 'true' ``` **Target bucket:** `AZBLOB_ACCOUNT_NAME` + `AZBLOB_CONTAINER`. No credential entry needed. `AZBLOB_USE_MANAGED_IDENTITY` is supported by `clickhouse-backup` since v2.7.1: our pinned 2.8.0 qualifies. Make sure the RBAC role granted to the managed identity (see [Object storage backends](./storage#configuration)) covers the container backups target, if different from ClickHouse's own. ```yaml clickhouse: backupConfig: REMOTE_STORAGE: 'gcs' GCS_BUCKET: '' GCS_PATH: 'backups/metadata' GCS_OBJECT_DISK_PATH: 'backups/objects' ``` The backup sidecar's GCS client does not accept HMAC keys (unlike ClickHouse's own disk, see [Object storage backends](./storage#object-storage-backends)): it needs its own native service account JSON key, passed as a Kubernetes secret rather than set inline in values, the same pattern described in [Prerequisites](./overview#prerequisites): create it directly, or sync it from your own secret store via an External Secrets Operator `SecretStore`/`ExternalSecret` or a Vault Secrets Operator. Whichever way you populate it, the secret must be named `clickhouse-backup-secret` and contain a `GCS_CREDENTIALS_JSON` key with the JSON key file's contents. If you create it directly: ```shell kubectl create secret generic clickhouse-backup-secret \ --namespace \ --from-file=GCS_CREDENTIALS_JSON= ``` **Target bucket:** `GCS_BUCKET`. Requires the credential above. Unlike ClickHouse's own disk (structurally blocked from Workload Identity, see [Object storage backends](./storage#object-storage-backends)), `clickhouse-backup`'s GCS client uses GCS's native API and supports `GCS_SA_EMAIL`: impersonating a GCP service account via [GKE Workload Identity Federation](https://cloud.google.com/kubernetes-engine/docs/concepts/workload-identity), without a JSON key. :::caution Not yet validated by us This path is sourced from `clickhouse-backup`'s own documentation (supported since v2.6.36; our pinned 2.8.0 qualifies) and GCP's Workload Identity Federation docs, but hasn't been tested end-to-end on a real GKE cluster. Validate it yourself before relying on it in production. ::: This requires a Workload Identity Federation setup specific to the backup sidecar (separate from ClickHouse's own disk, which still needs the static HMAC key pair regardless): 1. Workload Identity Federation enabled on your GKE cluster. 2. A dedicated Kubernetes ServiceAccount, annotated with a GCP service account's email. 3. An IAM policy binding allowing that ServiceAccount to impersonate the GCP service account. 4. A storage role granted to the GCP service account, scoped to the bucket. **Enable Workload Identity Federation** (if not already enabled on the cluster): ```bash gcloud container clusters update \ --zone \ --workload-pool=.svc.id.goog ``` **Create the GCP service account**: ```bash gcloud iam service-accounts create clickhouse-backup --project= ``` **Chart configuration**: annotate the ClickHouse ServiceAccount so it can impersonate the GCP service account: ```yaml clickhouse-server: serviceAccount: annotations: iam.gke.io/gcp-service-account: clickhouse-backup@.iam.gserviceaccount.com ``` **IAM policy binding**: allow the Kubernetes ServiceAccount to impersonate the GCP service account (replace ``): ```bash gcloud iam service-accounts add-iam-policy-binding \ clickhouse-backup@.iam.gserviceaccount.com \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:.svc.id.goog[/clickhouse]" ``` **Storage role**: grant the GCP service account access to the bucket: ```bash gcloud storage buckets add-iam-policy-binding gs:// \ --member=serviceAccount:clickhouse-backup@.iam.gserviceaccount.com \ --role=roles/storage.objectAdmin ``` With this in place: ```yaml clickhouse: backupConfig: REMOTE_STORAGE: 'gcs' GCS_BUCKET: '' GCS_PATH: 'backups/metadata' GCS_OBJECT_DISK_PATH: 'backups/objects' GCS_SA_EMAIL: 'clickhouse-backup@.iam.gserviceaccount.com' ``` **Target bucket:** `GCS_BUCKET`. No JSON key to create or store. `clickhouse-backup` talks to MinIO through its `s3` remote storage type too (same as AWS S3), just pointed at your MinIO endpoint with path-style addressing and a static access-key/secret-key pair, since MinIO has no IAM-equivalent identity to federate with: ```yaml clickhouse: backupConfig: REMOTE_STORAGE: 's3' S3_BUCKET: '' S3_REGION: 'us-east-1' # required by the S3 client even though MinIO ignores it S3_ENDPOINT: 'http://:' S3_PATH: 'backups/metadata' S3_OBJECT_DISK_PATH: 'backups/objects' S3_FORCE_PATH_STYLE: 'true' S3_DISABLE_SSL: 'true' # omit and use an https:// endpoint above instead if MinIO terminates TLS ``` Credentials are passed as a Kubernetes secret, never inline in your values file (the same pattern described in [Prerequisites](./overview#prerequisites)). Whichever way you populate it, the secret must be named `clickhouse-backup-secret` and contain `S3_ACCESS_KEY` and `S3_SECRET_KEY` keys: ```shell kubectl create secret generic clickhouse-backup-secret \ --namespace \ --from-literal=S3_ACCESS_KEY= \ --from-literal=S3_SECRET_KEY= ``` **Target bucket:** `S3_BUCKET`. Requires the credential above. ### Bucket lifecycle policies Lifecycle rules and bucket protections for **both** buckets are documented together in [Bucket lifecycle policies](./storage#bucket-lifecycle-policies): see the **Backup bucket** subsection for this one (versioning, Object Lock, replication, archive-tier caveats) and the **ClickHouse data bucket** subsection for ClickHouse's own data bucket. The two need different, in places opposite, rules. ### Tunable settings Beyond the object storage destination above, a handful of other sidecar settings are exposed under the same `clickhouse.backupConfig` map, with sensible defaults out of the box: override only the ones you need to change, without redeclaring the whole sidecar spec: ```yaml clickhouse: backupConfig: BACKUPS_TO_KEEP_REMOTE: '30' # only overriding retention here ``` | Setting | Purpose | Default | | :--- | :--- | :--- | | `WATCH_SCHEDULES` | Cron-driven full/incremental backup schedule, see [Understanding the backup schedule](#understanding-the-backup-schedule) below. | `name=ch-bkp,full=0 2 * * 0,increment=0 2 * * *,full_type=rebase,delete_previous_cycle=false` | | `BACKUPS_TO_KEEP_REMOTE` | Number of individual backups to keep in object storage: every full and every increment counts separately, see [Understanding the backup schedule](#understanding-the-backup-schedule) below. | `7` | | `REBASE_BEFORE_REMOVE_OLD_REMOTE` | Without this, `BACKUPS_TO_KEEP_REMOTE` isn't a hard cap: with incremental chains, `clickhouse-backup` won't delete a chain that a newer increment still depends on, so the retained count can grow past the limit. This rebases the oldest increment still inside the retention window onto a standalone full backup, making it independent of the older chain before it, which can then be deleted, keeping retention strict. | `true` | | `UPLOAD_CONCURRENCY` | Tables uploaded in parallel during a backup, and (same value) files per table uploaded in parallel. | `2` | | `DOWNLOAD_CONCURRENCY` | Same as `UPLOAD_CONCURRENCY`, for restore. | `2` | | `S3_CONCURRENCY` | Parallel chunks for a single file's S3 multipart transfer, a finer-grained level than `UPLOAD_CONCURRENCY`/`DOWNLOAD_CONCURRENCY`. | `2` | | `REBASE_CONCURRENCY` | Tables processed in parallel during a `rebase` operation (see `full_type=rebase` below). | `2` | | `LOG_LEVEL` | Sidecar log verbosity. | `info` | | `ALLOW_EMPTY_BACKUPS` | Without this, a fresh install with no tables yet is treated as a fatal error, crash-looping the sidecar. | `true` | The concurrency settings default to a conservative, fixed value rather than `clickhouse-backup`'s own auto-detection, which sizes off the node's total CPU count rather than this container's actual CPU limit: raise them if you've given the sidecar more CPU and want faster backups and restores. A few other settings are already configured by the chart with sensible defaults and aren't exposed for override; see `clickhouse-backup`'s own [configuration reference](https://github.com/Altinity/clickhouse-backup#configurable-parameters) for the exhaustive list of available settings. ### Understanding the backup schedule `WATCH_SCHEDULES` drives the backup cadence with cron expressions. One schedule has the form: ``` name=,full=[,increment=][,full_type=create|rebase][,delete_previous_cycle=true|false] ``` | Key | Required | Meaning | | :--- | :--- | :--- | | `name` | Yes | Prefix for this chain's backup names. Lets you run more than one independent schedule side by side, separated with `;`. | | `full` | Yes | Cron expression for the full backup. | | `increment` | No | Cron expression for the incremental backup. Omit for full-only backups. | | `full_type` | No (`create`) | `create` re-uploads all data for every full backup. `rebase` performs a server-side copy of the previous chain instead (no re-upload, much faster), but only once a previous backup already exists; the very first cycle always falls back to `create`. | | `delete_previous_cycle` | No (`false`) | `true` deletes every older backup of this chain as soon as a new full succeeds, keeping only the current cycle. `false` leaves older cycles in place, pruned only by `BACKUPS_TO_KEEP_REMOTE` above. | Cron expressions accept the standard 5-field syntax (minute, hour, day, month, weekday), an optional leading seconds field, and `@every`/`@daily`-style descriptors. The chart's default: ```yaml clickhouse: backupConfig: WATCH_SCHEDULES: 'name=ch-bkp,full=0 2 * * 0,increment=0 2 * * *,full_type=rebase,delete_previous_cycle=false' ``` This runs a full backup every Sunday at 2am (via `rebase` once a previous one exists, so no re-upload) and an incremental backup every day at 2am. On Sunday, the `full` and `increment` cron expressions fire on the same tick: the full backup always takes priority, so no separate increment runs that day. **Retention window:** with `delete_previous_cycle: false`, `BACKUPS_TO_KEEP_REMOTE` keeps the N most recent backups, counting each full and each increment as its own entry. At 7 entries a week (1 full + 6 increments), `BACKUPS_TO_KEEP_REMOTE: '7'` keeps roughly 1 week of history. ## Backup freshness Backup freshness is surfaced inside the product using ClickHouse's own system tables. Treat a backup as unhealthy if no valid full backup exists within your recovery point objective, or if no new backup has been taken recently. :::danger Container health does not reflect backup health The sidecar's watch loop retries a failed backup on the next scheduled tick instead of stopping: a persistent failure (bad credentials, an unreachable bucket, a full disk) logs an error on every attempt but never crashes the container. Pod status and restart count stay green throughout. See [ClickHouse monitoring and alerting](./monitoring) to set up an external signal that does catch this. ::: ## Restore Restoring ClickHouse data is a manual, deliberate operation: it is not triggered automatically. `clickhouse-backup` restores in place, on the same ClickHouse instance the sidecar runs alongside: it needs direct filesystem access to attach the backup's data parts, the same requirement that keeps it deployed as a sidecar in the first place (see [How ClickHouse backup works](#how-clickhouse-backup-works) above). There's no restore-into-a-separate-empty-instance workflow without standing up a whole second ClickHouse deployment. High level procedure: 1. **Snapshot the current state first**: `clickhouse-backup create_remote` on the affected table(s), even if that data is already degraded. Gives you a fallback distinct from your regular backup chain if the restore itself goes wrong. 2. **Identify** the backup to restore from: list remote backups, check it isn't flagged as broken, and that its backup chain is intact. 3. **Check version compatibility** before committing to a full restore: `clickhouse-backup download --schema ` pulls just the schema and metadata (lightweight, no table data), so you can inspect `clickhouse_version` in the resulting `metadata.json` against the currently running ClickHouse version. 4. **Stop writes** to the affected table(s): pause or scale down the producers writing to them. 5. **Restore into a different name first** (`--restore-database-mapping`/`--restore-table-mapping`), never straight into the live table. 6. **Verify** the restored copy (row counts, spot-check known values) before touching production. 7. **Cut over**: once the mapped copy checks out, restore again directly onto the live table name with `--rm` (`restore`/`restore_remote --rm `): `clickhouse-backup` drops the existing schema and reattaches from the backup. To just **test** that a backup works (not to respond to a real incident), restore into a throwaway table or database name instead, so a drill never touches production data. :::caution Known pitfall: repeated restore attempts If you retry a restore using the **same backup name** after a failed or interrupted attempt, the restore tool may resume from a stale local state and only restore the schema (DDL), silently skipping the actual data, with no error. If a restore looks empty or incomplete, clear the tool's local state before retrying, or use a distinct target each time. ::: ## Disaster recovery scope :::danger A ClickHouse-only restore is not a complete disaster recovery for every feature Some features that use ClickHouse also join that data with information stored in PostgreSQL (for example, an inventory of which machines belong to your organization). Restoring ClickHouse alone, into an environment whose PostgreSQL differs, produces **inconsistent results** in the product: the ClickHouse data and the PostgreSQL registry disagree with each other. **A complete disaster recovery for these features requires restoring both ClickHouse and PostgreSQL to a consistent point in time.** Plan your PostgreSQL backup strategy (see [Backup & Restore](../backup)) and your ClickHouse backup strategy together, and test a combined restore as part of your disaster-recovery drills. ::: ## Recovery objectives We do not currently publish a fixed Recovery Point Objective (RPO) or Recovery Time Objective (RTO) for ClickHouse: these depend on your backup cadence and data volume. We recommend running a restore drill against your own data volume to measure your actual RTO, and setting your backup cadence (frequency of full and incremental backups) to match the data-loss window you're willing to accept. --- ## ClickHouse monitoring and alerting ClickHouse itself and its backup sidecar each expose Prometheus metrics, off by default. The backup sidecar deserves the closer attention below: its watch loop retries a failed backup on the next scheduled tick instead of stopping, so a persistent failure never crashes the container or shows up in pod status (see [Backup freshness](./backup-restore#backup-freshness)). :::caution Requires Prometheus Operator's CRDs Both ClickHouse's own `ServiceMonitor` and the backup sidecar's render a `ServiceMonitor` resource. If Prometheus Operator's CRDs aren't installed in the cluster, enabling either one makes the release fail to install: leave both `false` until they are. ::: ## ClickHouse server metrics ClickHouse's own metrics (query performance, resource usage) are exposed on the standard `http-metrics` port. Two settings gate this, both `false` by default: ```yaml clickhouse-server: metrics: enabled: true serviceMonitor: enabled: true ``` `metrics.enabled` turns on the metrics endpoint itself; `metrics.serviceMonitor.enabled` additionally ships a matching `ServiceMonitor` for it: both are required to get a scraped target. ### Key metrics ClickHouse exposes multiple metrics; the ones below are the ones that map directly to a guardrail this chart configures by default (see [Scheduling and reliability](./sizing#scheduling-and-reliability) and [Other guardrails](./sizing#other-guardrails)), so a breach here means a specific, known threshold was hit, not a symptom to interpret from scratch. | Metric | Type | Meaning | | :--- | :--- | :--- | | `ClickHouseErrorMetric_TOO_MANY_SIMULTANEOUS_QUERIES` | Counter | A query was rejected outright for exceeding `MAX_CONCURRENT_QUERIES` (`32` by default). `ClickHouseMetrics_Query` (gauge) tracks the current concurrent count if you want to watch the trend before it gets there. | | `ClickHouseErrorMetric_TIMEOUT_EXCEEDED` | Counter | A query was killed for running past `MAX_EXECUTION_TIME` (`55` seconds by default). | | `ClickHouseMetrics_MemoryTracking` / `ClickHouseErrorMetric_MEMORY_LIMIT_EXCEEDED` | Gauge (bytes) / Counter | Server-wide memory currently tracked, and how many times a query was killed for exceeding `MAX_SERVER_MEMORY_USAGE_TO_RAM_RATIO` (`0.9` of the pod's memory limit by default). | | `ClickHouseAsyncMetrics_MaxPartCountForPartition` | Gauge | The active-part count of the single worst-case partition across every table. `PARTS_TO_DELAY_INSERT`/`PARTS_TO_THROW_INSERT` (`1000`/`3000` by default) check it before accepting an insert into that partition. ClickHouse's own guidance: values above `300` already indicate overload. | | `ClickHouseProfileEvents_DelayedInserts` / `ClickHouseProfileEvents_RejectedInserts` | Counter | Early warning (an insert was artificially slowed) vs. hard failure (an insert was rejected with `Too many parts`) for the same parts-per-partition guardrails above. | | `ClickHouseProfileEvents_ExternalAggregationCompressedBytes` / `ExternalSortCompressedBytes` | Counter (bytes) | Cumulative data spilled to disk because a query's `GROUP BY`/`ORDER BY` crossed `MAX_BYTES_RATIO_BEFORE_EXTERNAL_GROUP_BY`/`_SORT` (`0.4` by default). A rising rate means queries are increasingly falling back to the slower disk-spill path. | | `ClickHouseAsyncMetrics_DiskAvailable_default` | Gauge (bytes) | Free space on the metadata volume. Unlike the filesystem cache, this volume doesn't degrade gracefully if it fills (see [What happens if this volume fills up](./sizing#metadata-volume)). | :::tip Filesystem cache hit ratio has its own metrics Covered separately in [Filesystem cache](./sizing#filesystem-cache): `ClickHouseProfileEvents_CachedReadBufferReadFromCacheHits`/`...Misses` (the same counters behind that page's SQL query) and `ClickHouseMetrics_FilesystemCacheSize`/`...SizeLimit` for how full the cache currently is. ::: :::tip A rising rate on either of these is a hardware-sizing signal, not just an alert Sustained `ExternalAggregationCompressedBytes`/`...SortCompressedBytes` growth or `MEMORY_LIMIT_EXCEEDED` increases both point to RAM, not CPU, being the actual bottleneck for your aggregation workload. See [Hardware recommendations](./sizing#hardware-recommendations) for when to move from ClickHouse's general-purpose RAM/core ratio to their data-warehouse one. ::: ### Key thresholds These assume the chart's default guardrail values above; adjust the literal numbers if you've customized `clickhouse.serverConfig`. Critical means a query or insert has already failed because of it; warning means you're trending toward one. | Condition | Based on | Suggested threshold | Severity | | :--- | :--- | :--- | :--- | | A query was rejected for too many concurrent queries | `ClickHouseErrorMetric_TOO_MANY_SIMULTANEOUS_QUERIES` | Any increase | Critical | | A query was killed for running too long | `ClickHouseErrorMetric_TIMEOUT_EXCEEDED` | Any increase | Critical | | A query was killed for exceeding its memory limit | `ClickHouseErrorMetric_MEMORY_LIMIT_EXCEEDED` | Any increase | Critical | | An insert was rejected outright (`Too many parts`) | `ClickHouseProfileEvents_RejectedInserts` | Any increase | Critical | | An insert is being throttled, but not yet rejected | `ClickHouseProfileEvents_DelayedInserts` | Any increase | Warning | | A partition is approaching the insert-delay threshold | `ClickHouseAsyncMetrics_MaxPartCountForPartition` | Above 80% of `PARTS_TO_DELAY_INSERT` (`800` by default) for 15 minutes | Warning | | Queries are increasingly spilling to disk | Rate of `ExternalAggregationCompressedBytes` + `ExternalSortCompressedBytes` | Sustained non-zero rate for 30 minutes | Warning | | The metadata volume is projected to fill up | `ClickHouseAsyncMetrics_DiskAvailable_default` | `predict_linear(...[1d]) < 0` (projected to hit zero within 24h) | Critical | ### Recommended alerts An example implementing the thresholds above as a Prometheus Operator `PrometheusRule`: ```yaml apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: clickhouse-server namespace: labels: release: spec: groups: - name: clickhouse-server rules: - alert: ClickHouseTooManyConcurrentQueries expr: increase(ClickHouseErrorMetric_TOO_MANY_SIMULTANEOUS_QUERIES[5m]) > 0 for: 1m labels: severity: critical annotations: summary: 'A query was rejected for exceeding the concurrent query limit' description: 'MAX_CONCURRENT_QUERIES (32 by default) was hit. ClickHouseMetrics_Query shows the current concurrent count if you want to confirm the trend.' - alert: ClickHouseQueryTimeout expr: increase(ClickHouseErrorMetric_TIMEOUT_EXCEEDED[5m]) > 0 for: 1m labels: severity: critical annotations: summary: 'A query was killed for exceeding MAX_EXECUTION_TIME' description: 'MAX_EXECUTION_TIME is 55 seconds by default. Check slow query logs for what ran long.' - alert: ClickHouseQueryMemoryLimitExceeded expr: increase(ClickHouseErrorMetric_MEMORY_LIMIT_EXCEEDED[5m]) > 0 for: 1m labels: severity: critical annotations: summary: 'A query was killed for exceeding the server memory limit' description: 'MAX_SERVER_MEMORY_USAGE_TO_RAM_RATIO is 0.9 by default. ClickHouseMetrics_MemoryTracking shows the server-wide trend leading up to this.' - alert: ClickHouseInsertRejected expr: increase(ClickHouseProfileEvents_RejectedInserts[5m]) > 0 for: 1m labels: severity: critical annotations: summary: "An insert was rejected with 'Too many parts'" description: 'PARTS_TO_THROW_INSERT (3000 by default) was hit for at least one partition. ClickHouseAsyncMetrics_MaxPartCountForPartition shows the worst-case partition if you want to confirm which one.' - alert: ClickHouseInsertDelayed expr: increase(ClickHouseProfileEvents_DelayedInserts[5m]) > 0 for: 5m labels: severity: warning annotations: summary: 'Inserts are being throttled due to a high part count' description: 'PARTS_TO_DELAY_INSERT (1000 by default) was hit for at least one partition. Not yet a rejection, but merges are falling behind inserts. Left unaddressed, this trends toward ClickHouseInsertRejected.' - alert: ClickHouseMaxPartCountApproachingLimit expr: ClickHouseAsyncMetrics_MaxPartCountForPartition > 800 for: 15m labels: severity: warning annotations: summary: 'A partition is approaching the insert-delay threshold' description: 'Above 80% of PARTS_TO_DELAY_INSERT (1000 by default). Sustained high insert rate outpacing background merges. Consider batching inserts at the source.' - alert: ClickHouseExternalSpillIncreasing expr: rate(ClickHouseProfileEvents_ExternalAggregationCompressedBytes[30m]) > 0 or rate(ClickHouseProfileEvents_ExternalSortCompressedBytes[30m]) > 0 for: 30m labels: severity: warning annotations: summary: 'Queries are spilling GROUP BY/ORDER BY to disk' description: 'MAX_BYTES_RATIO_BEFORE_EXTERNAL_GROUP_BY/_SORT (0.4 by default) is being crossed repeatedly, a sign these queries are memory-constrained relative to their data volume.' - alert: ClickHouseMetadataDiskWillFillUp expr: predict_linear(ClickHouseAsyncMetrics_DiskAvailable_default[1d], 86400) < 0 for: 10m labels: severity: critical annotations: summary: 'The metadata volume is projected to fill up within 24 hours' description: 'Unlike the filesystem cache, this volume does not degrade gracefully when full: inserts and merges fail outright. See Metadata volume in the sizing guide.' ``` `ClickHouseInsertRejected` and its threshold choices mirror [Altinity's own `clickhouse-operator` reference alerting rules](https://github.com/Altinity/clickhouse-operator/blob/master/deploy/prometheus/prometheus-alert-rules-clickhouse.yaml) (`ClickHouseRejectedInsert`/`ClickHouseDelayedInsertThrottling`/`ClickHouseMaxPartCountForPartition`), and `ClickHouseMetadataDiskWillFillUp`'s `predict_linear` pattern mirrors their `ClickHouseDiskUsage` rule. Both are scoped down here to the settings this chart actually configures. Most of Altinity's other rules (replica lag, ZooKeeper/Keeper sessions, Kafka, `Distributed` tables) don't apply: this chart runs ClickHouse single-node, without replication, Kafka, or sharding. ## Backup sidecar metrics :::danger The backup sidecar fails silently: do not rely on the pod's Kubernetes status A failed backup does not crash the container, does not restart the pod, and does not turn any Kubernetes-level health indicator red. The `clickhouse` pod can show `Running`/`Ready` with `0` restarts while backups have been failing for days. The only reliable way to know is to build alerting on the Prometheus metrics below. ::: ### Metrics endpoint The backup sidecar exposes Prometheus-format metrics on its own REST API, on the `backup-rest` port (`7171`), at `/metrics`. Like every other route on that API, it requires the same HTTP Basic Auth credentials as the rest of the backup API (`API_USERNAME`/`API_PASSWORD`, see [Prerequisites](./overview#prerequisites)): an unauthenticated scrape gets a `401`. To check it manually before wiring up Prometheus: `API_USERNAME`/`API_PASSWORD` are already injected into the `clickhouse-backup` container itself (it needs them to enforce this same auth on incoming requests), so there's no need to pull them from the secret separately: ```shell kubectl exec -n -c clickhouse-backup -- \ sh -c 'curl -s -u "$API_USERNAME:$API_PASSWORD" http://localhost:7171/metrics' ``` ### Scraping with Prometheus Operator Set `clickhouse.backup.metrics.enabled: true` to have the chart ship a matching `ServiceMonitor` for the `backup-rest` port automatically: it sources both the username and password from the same `clickhouse-credentials` secret already used elsewhere (see [Prerequisites](./overview#prerequisites)): ```yaml clickhouse: backup: metrics: enabled: true ``` ### Key metrics Every scheduled tick (full or incremental) runs as a `create_remote` operation, whether or not that day's full backup also triggers a `rebase` (see [Understanding the backup schedule](./backup-restore#understanding-the-backup-schedule)): | Metric | Type | Meaning | | :--- | :--- | :--- | | `clickhouse_backup_last_create_remote_status` | Gauge | `0`=failed, `1`=success, `2`=unknown. The outcome of the most recent scheduled backup attempt, full or incremental. | | `clickhouse_backup_last_create_remote_finish` | Gauge (unix timestamp) | Timestamp of the most recent attempt, success or failure. Going stale means the watch loop itself has stopped ticking, not just that a backup failed. | | `clickhouse_backup_successful_create_remotes` / `clickhouse_backup_failed_create_remotes` | Counter | Running counters, useful for a failure-rate alert over a rolling window. | | `clickhouse_backup_last_rebase_status` / `clickhouse_backup_last_rebase_finish` | Gauge | Same shape, for the weekly `rebase` step that runs after a full backup once a previous chain already exists. Stays unset for the first ~2 weeks after a fresh install, since `full_type: rebase` only applies from the second full cycle onward. | | `clickhouse_backup_in_progress_commands` | Gauge | How many backup operations are currently running. Stuck above `0` for far longer than a backup normally takes usually means a hung operation. | | `clickhouse_backup_number_backups_remote` / `clickhouse_backup_last_backup_size_remote` | Gauge | Chain count and size currently on remote storage, a basic sanity check that the chain count/size hasn't unexpectedly collapsed. | ### Key thresholds These thresholds are metric-agnostic: they apply however the metrics above are collected, whether that's Prometheus, Datadog, Grafana Cloud, or any other monitoring solution. They assume the chart's default schedule (daily `create_remote`, weekly `rebase`); adjust them if you've customized `WATCH_SCHEDULES`. | Condition | Based on | Suggested threshold | Severity | | :--- | :--- | :--- | :--- | | No backup attempt (full or incremental) recently | Time since `clickhouse_backup_last_create_remote_finish` | More than 36 hours (1.5x the default daily cadence) | Critical | | The last backup attempt failed | `clickhouse_backup_last_create_remote_status` | Equal to `0` (failed) for 15 minutes straight | Critical | | No weekly full-backup rebase recently | Time since `clickhouse_backup_last_rebase_finish` | More than 10 days (only meaningful once a second full cycle has run, expect this to be stale for the first two weeks after a fresh install) | Warning | | A backup operation has been running too long | `clickhouse_backup_in_progress_commands` | Greater than `0` for 2 hours straight | Warning | | The most recent remote backup reports a size of zero | `clickhouse_backup_last_backup_size_remote` and `clickhouse_backup_number_backups_remote` | Size equal to `0` while at least one backup already exists remotely | Critical | ### Recommended alerts An example implementing the thresholds above as a Prometheus Operator `PrometheusRule`: ```yaml apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: clickhouse-backup namespace: labels: release: spec: groups: - name: clickhouse-backup rules: - alert: ClickHouseBackupStalled expr: time() - clickhouse_backup_last_create_remote_finish > 36 * 3600 for: 10m labels: severity: critical annotations: summary: 'No backup attempt (full or incremental) in over 36 hours' description: 'The clickhouse-backup sidecar has not attempted a backup in more than 36 hours (1.5x the default daily cadence). The watch loop may have stopped, or its config may be invalid. Pod status will not show this: check the sidecar logs directly.' - alert: ClickHouseBackupFailing expr: clickhouse_backup_last_create_remote_status == 0 for: 15m labels: severity: critical annotations: summary: 'The last backup attempt failed' description: 'clickhouse_backup_last_create_remote_status is 0 (failed). Check the sidecar logs for the error; clickhouse-backup retries on the next scheduled tick, it does not stop or crash on its own.' - alert: ClickHouseFullBackupStalled expr: time() - clickhouse_backup_last_rebase_finish > 10 * 24 * 3600 for: 10m labels: severity: warning annotations: summary: 'No weekly full-backup rebase in over 10 days' description: 'Only meaningful once a second full cycle has run. Expect this to be stale for the first two weeks after a fresh install, since full_type: rebase only applies from the second full backup onward.' - alert: ClickHouseBackupStuck expr: clickhouse_backup_in_progress_commands > 0 for: 2h labels: severity: warning annotations: summary: 'A backup operation has been running for over 2 hours' description: 'clickhouse_backup_in_progress_commands has stayed above 0 for 2 hours straight, longer than a scheduled full or incremental backup normally takes. Check the sidecar logs for a hung operation. Raise the threshold if your data volume makes 2 hours a normal backup duration.' - alert: ClickHouseBackupSizeZero expr: clickhouse_backup_last_backup_size_remote == 0 and clickhouse_backup_number_backups_remote > 0 for: 10m labels: severity: critical annotations: summary: 'The most recent remote backup reports a size of zero' description: 'At least one backup exists on remote storage, but the most recent one reports 0 bytes, likely a broken or empty backup rather than a real one. Check the sidecar logs and verify the backup with `clickhouse-backup list remote`.' ``` `ClickHouseBackupStalled`'s 36-hour window is deliberately generous (1.5x the 24-hour default cadence) to avoid flapping on a single delayed tick, matching the convention `clickhouse-backup`'s own maintainers use in their [reference alerting rules](https://github.com/Altinity/clickhouse-operator/blob/master/deploy/prometheus/prometheus-alert-rules-backup.yaml) for the ClickHouse Operator. `ClickHouseBackupSizeZero` mirrors the same reference rule set's `ClickHouseRemoteBackupSizeZero`. --- ## ClickHouse GitGuardian uses [ClickHouse](https://clickhouse.com/), an open-source column-oriented database, to power features that require fast analytics over large volumes of data (for example, machine and [endpoint](/endpoint-protection/home) secret occurrence analytics). PostgreSQL remains the primary datastore for the rest of the application; ClickHouse is only involved for the specific features that need it. :::info Mandatory from 2027.1 Starting with release **2027.1.0**, ClickHouse and its object storage backend become mandatory for every self-hosted deployment. See the [customer notice](/support/customer-notices/clickhouse-object-storage-self-hosted) for what changes and how to prepare. ::: ## Deployment model ClickHouse runs as a dedicated, in-cluster stateful component, and relies on **external object storage** (S3-compatible, Azure Blob Storage, or Google Cloud Storage) for durable data storage. It is not a fully externally managed database like PostgreSQL or Redis. See [ClickHouse storage](./storage) for details. ## Default topology ClickHouse is deployed as a **single node**. This is the simplest and lightest-footprint option, and is sufficient for the vast majority of deployments, though it is **not highly available**: there is no other replica to fail over to. ## Supported version GitGuardian pins the ClickHouse version shipped with each release to the same version running our SaaS offering, and validates it against our test suite before release. Do not attempt to run a different ClickHouse version than the one shipped with your release. ## Storage ClickHouse splits its storage into three parts: local **metadata** and **filesystem cache** volumes, and **object storage** holding the actual table data, where the bulk of the storage footprint lives and where `clickhouse-backup` writes to when backing up. See [ClickHouse storage](./storage) for the local volumes and provider-specific object storage configuration, [Sizing and hardening](./sizing) for hardware sizing, [Backup and restore](./backup-restore) for the backup runbook, and [Monitoring and alerting](./monitoring) to catch a failing backup that pod health won't show you. ## Required configuration A production-ready ClickHouse deployment requires all of the following to be configured: | What to configure | Details | Where | |---|---|---| | Compute sizing and hardening | Node & instance resources, scheduling, node stability | [Sizing and hardening](./sizing) | | ClickHouse credentials | Instance password | [Prerequisites](#prerequisites) | | Object storage configuration | S3 / Azure Blob / GCS backend, disk authentication | [Storage → Configuration](./storage#configuration) | | In-cluster volumes configuration | Metadata & cache volumes, storage class | [Storage → Local volumes](./storage#local-persistent-volumes) | | Backup configuration | Destination bucket, credentials secret, schedule & retention | [Backup and restore](./backup-restore#object-storage-destination) | ## Prerequisites Before installing, the ClickHouse admin password and the [backup sidecar](./backup-restore)'s local API password should be passed via a Kubernetes secret rather than set inline in values, the same pattern used throughout GitGuardian self-hosted. It can be created directly or synced from your own secret store. See [Helm sensitive information management](../../../installation/helm-secrets#existing-secret) for how to populate it. If you create it directly: ```shell kubectl create secret generic clickhouse-credentials \ --namespace \ --from-literal=admin-password= \ --from-literal=api-password= \ --from-literal=api-username= ``` :::caution All three keys are required: don't rename or omit any of them `clickhouse-credentials`, `admin-password`, `api-password`, and `api-username` are wired into the chart's defaults under those exact names: `admin-password` via `clickhouse-server.auth.existingSecret`/`existingSecretKey` (GitGuardian derives its own `CLICKHOUSE_PASSWORD` from the same secret), and `api-password`/`api-username` consumed directly by the backup sidecar and its `ServiceMonitor`. Missing or renaming any of the three breaks ClickHouse's own authentication, the backup sidecar, or GitGuardian's connection to it, unless you also override the corresponding values. ::: With the secret in place, enable ClickHouse itself: ```yaml clickhouse: enabled: true ``` This alone isn't enough for a working deployment: ClickHouse's object storage backend has no default and must be configured for your provider (see [ClickHouse storage](./storage)), and the backup destination needs the same before backups can run (see [Backup and restore](./backup-restore#object-storage-destination)). Follow both pages before considering ClickHouse installed. --- ## ClickHouse sizing and hardening ## Hardware recommendations Use the table below as a starting point for compute sizing, based on the number of active endpoints (machines) reporting data: | Tier | Endpoints | ClickHouse cores | ClickHouse RAM | Cache volume | | :--- | :--- | :--- | :--- | :--- | | **Small** | ~100 | 4 | 16 GiB | 30Gi | | **Medium** | ~1,000 | 6 | 24 GiB | 50Gi | | **Large** | ~10,000 | 8+ | 32 GiB+ | 100Gi | CPU is the main lever for the heavier aggregation queries: scale cores with data volume rather than over-provisioning RAM alone. Start with **4 GiB of RAM per core** (ClickHouse's own "general purpose" ratio), and move up to **8 GiB of RAM per core** (their "data warehousing" ratio) if you observe external `GROUP BY`/`ORDER BY` spill or memory-limit query rejections under normal load: both are concrete signs that RAM, not CPU, is the actual bottleneck for your aggregation workload (see [Key metrics](./monitoring#key-metrics) for the exact counters to watch). - **Node type**: a general-purpose or memory-optimized instance type with **4 to 8 GiB of RAM per core**. Avoid compute-optimized instance types: they tend to be under-provisioned on RAM for ClickHouse's aggregation workloads. - **Disk**: use **local NVMe or network-attached SSD** (high IOPS) for the metadata and cache volumes. Never use HDD-class storage or network filesystems (NFS/EFS/Azure Files); their latency characteristics are incompatible with ClickHouse's read/write patterns. - **Dedicated, stable node**: schedule ClickHouse on a dedicated, **on-demand** node (not spot/preemptible) to avoid disruption from node reclamation. Avoid co-locating noisy-neighbor workloads. - **Object storage**: elastic by design, not a sizing driver the way local disk is, since it scales independently of your cluster. ## Filesystem cache The local filesystem cache sits in front of object storage and only needs to hold your **working set** (the data actually touched by recent queries), not your entire historical dataset. Because analytics features typically read only the current state per machine or account, superseded historical data doesn't inflate the working set even as your total object storage footprint grows: the cache tracks your number of **active** endpoints, not your total accumulated history. That said, the cache remains one of the most effective levers for query performance, and it's always preferable to oversize it than to undersize it: growing it later means resizing a StatefulSet's persistent volume claim template, an operation Kubernetes doesn't support in place (see the caution below). Guidance for sizing the cache: - The chart defaults `clickhouse.serverConfig.CACHE_MAX_SIZE` to **`48Gi`**, backed by a **`50Gi` cache persistent volume** (the Medium tier above); the same setting applies regardless of which object storage provider you use. Use the **Cache volume** column in the table above as a starting point for your own tier, pairing `CACHE_MAX_SIZE` about `2Gi` below the volume size (see the margin guidance below). Adjust it upward based on observed read latency: consistently slow reads on previously-queried data are a sign the cache is undersized relative to your working set. - Revisit this sizing as your endpoint count grows. :::caution Resizing the cache volume later is a manual operation Kubernetes doesn't allow resizing a StatefulSet's persistent volume claim template in place, so growing the cache volume after installation (while fully possible) takes a manual procedure, not a simple values change. Size upfront using the table above based on your expected endpoint count, rather than starting small and expecting to resize easily later. If your environment is resource-constrained, we still recommend not going below `30Gi` (the Small tier) for the cache volume. ::: :::tip Measure the actual cache hit ratio `system.events` exposes the raw hit/miss counters behind the cache, a more precise signal than latency alone: ```sql SELECT round(sumIf(value, event = 'CachedReadBufferReadFromCacheHits') / (sumIf(value, event = 'CachedReadBufferReadFromCacheHits') + sumIf(value, event = 'CachedReadBufferReadFromCacheMisses')), 4) AS cache_hit_ratio FROM system.events; ``` A consistently low ratio is a concrete signal to grow `CACHE_MAX_SIZE` and the cache persistent volume above. ::: ```yaml clickhouse: serverConfig: CACHE_MAX_SIZE: '98Gi' # pairs with a 100Gi cache volume from the Large tier above ``` :::caution Size the cache persistent volume larger than CACHE_MAX_SIZE `CACHE_MAX_SIZE` is a soft limit that ClickHouse enforces itself through LRU eviction, not a hard guarantee against the underlying volume filling up. Always give the persistent volume headroom above it, never size it equal to or below: for example, `CACHE_MAX_SIZE: '28Gi'` on a `30Gi` volume is fine. If the volume does fill up regardless, ClickHouse doesn't fail queries or inserts; it logs a warning and skips caching that entry, falling back to reading directly from object storage. Left unaddressed, though, this permanently degrades reads on that data to the slower path instead of the cached one. ::: ## Metadata volume Unlike the cache, this volume isn't sized against your working set: its own footprint barely grows with data volume. The S3 disk's local metadata (a mapping file per object stored, tens of bytes each) and table definitions stay in the low megabytes even at large scale, regardless of endpoint count or retention. Start with a **minimum of 20Gi** anyway. The footprint itself doesn't need that much, but it's cheap headroom against the backup sidecar's `FREEZE` hardlinks, which briefly coexist on this same volume during a backup cycle (see [Backup and restore](./backup-restore)), and any local system tables you re-enable beyond the chart's defaults. :::caution What happens if this volume fills up Unlike the cache disk, ClickHouse doesn't degrade gracefully here: this is a load-bearing volume, not a best-effort cache. If it fills, inserts and merges fail with real errors instead of falling back elsewhere. Reserve free space on this disk yourself, via the `` disk's `keep_free_space_bytes` in your own `00-object-storage.xml` (see [ClickHouse storage](./storage#configuration)), so ClickHouse refuses new writes predictably once space runs low instead of running the disk down to 0 bytes free. ::: ## Scheduling and reliability The chart applies a set of guardrails by default, so ClickHouse fails predictably (clean rejections) instead of destabilizing the node under load. The ones below need input from you; see [Other guardrails](#other-guardrails) for the rest. ### Reserved resources Set `requests` equal to `limits` on both CPU and memory for the main ClickHouse container, so the scheduler reserves the full amount upfront instead of over-committing the node. Cap CPU below the node's allocatable capacity to leave headroom for the kubelet. Adjust the values below to match your sizing tier: ```yaml clickhouse-server: resources: requests: cpu: 8 memory: 32Gi limits: cpu: 8 memory: 32Gi ``` The `clickhouse-backup` sidecar in the same pod runs on its own, separate (and smaller) budget, so the pod as a whole doesn't reach Kubernetes' `Guaranteed` QoS class. This only pins the main container's resources. ### Node stability You need to prevent your Kubernetes autoscaler, if any, from consolidating or evicting the node while ClickHouse is running on it, which would otherwise detach and reattach its volume mid-operation: ```yaml clickhouse-server: podAnnotations: karpenter.sh/do-not-disrupt: 'true' # adjust the annotation for your own cluster autoscaler if not using Karpenter ``` Where possible, pin ClickHouse to dedicated, on-demand node(s) reserved for it: this keeps it off spot/preemptible capacity (a reclaimed spot node means an abrupt eviction and a volume re-attach) and away from noisy-neighbor workloads competing for the same CPU/memory: ```yaml clickhouse-server: nodeSelector: workload: clickhouse tolerations: - key: workload operator: Equal value: clickhouse effect: NoSchedule ``` This assumes a dedicated node pool that you have provisioned as **on-demand** (not spot/preemptible), labeled `workload: clickhouse` and tainted `workload=clickhouse:NoSchedule`; adjust the label and taint to match your own cluster's convention. The `nodeSelector` only pins ClickHouse to that pool, it doesn't select the pool's capacity type, so keeping it off spot depends on the pool itself being on-demand. On a dedicated, non-shared node you can also give the ClickHouse pod a high `priorityClassName`. There it's largely belt-and-suspenders (nothing of consequence competes for the node), but it's a zero-cost extra hardening guardrail: even a dedicated node still runs DaemonSets (CNI, log/metrics agents), and priority decides who the kubelet evicts first if the node comes under resource pressure. `infrastructure-critical` is **not** a built-in Kubernetes class (the only native ones, `system-node-critical` and `system-cluster-critical`, are reserved for control-plane/system pods), so you must create it in your cluster beforehand (the chart doesn't): ```yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: infrastructure-critical value: 1000000 # above your default workloads, well below the system-* classes (~2e9) globalDefault: false description: 'High scheduling priority for infrastructure-critical workloads' ``` Then reference it on the ClickHouse pod: ```yaml clickhouse-server: priorityClassName: infrastructure-critical ``` :::caution Make sure your reserved node pool has capacity in the PV's zone The metadata and cache volumes (network-attached SSD) are zone-locked once provisioned. If ClickHouse's node is lost and your reserved node pool can't provision replacement capacity in that same zone, the pod stays `Pending` indefinitely: it cannot reschedule to a node in a different zone without a new volume. Make sure the node pool you dedicate to ClickHouse spans (or can scale in) every zone your cluster provisions volumes in. ::: ### Other guardrails Beyond node-level scheduling, the chart also configures a set of server-side guardrails by default (memory and concurrency limits, disk headroom, query spill and timeout thresholds, and insert deduplication) so ClickHouse fails predictably instead of destabilizing under load. These ship with sensible defaults and don't need any configuration from you. If you observe symptoms like disk spill, memory pressure, or query rejections under high dashboard concurrency, please reach out to our **[support team](mailto:support@gitguardian.com)** to evaluate a configuration better suited to your workload. --- ## ClickHouse storage ClickHouse's storage splits into three parts: - **Object storage**: the bucket you provide (S3-compatible, Azure Blob Storage, or GCS), holding the actual table data. This is where the bulk of the storage footprint lives. - **Filesystem cache**: a local persistent volume acting as an LRU cache in front of object storage, for fast reads of recently accessed data (the same pattern used by ClickHouse Cloud). - **Metadata**: a separate local persistent volume holding table structure and part manifests for the data held in object storage. ```mermaid graph LR CH[ClickHouse] META[("Metadata volume(local PVC)")] CACHE[("Filesystem cache volume(local PVC)")] S3[("Object storageS3 / Azure Blob / GCS")] CH --> META CH -->|reads/writes| CACHE CACHE -.->|cache miss / fill| S3 ``` This page covers the two local volumes first, then the object storage backends and their configuration. ## Local persistent volumes The metadata and cache volumes are both provisioned locally, independently of your object storage backend, and kept apart from each other: as shown in the diagram above, ClickHouse writes to both, but only the cache ever talks to object storage. ### Metadata volume The chart already provisions the metadata volume via `persistence` (`enabled`, `20Gi`, `ReadWriteOnce`), mounted at ClickHouse's data directory, where it holds table structure and part manifests for the data held in object storage. In your values you only set the storage class (the chart leaves it unset, so your cluster's default StorageClass applies, which may not be SSD-backed) and, if needed, adjust the size: ```yaml clickhouse-server: persistence: storageClass: gp3 # set an SSD/NVMe-backed class, see Storage class below size: 20Gi # optional; defaults to 20Gi, see Metadata volume sizing below ``` The `size` is illustrative, see [Metadata volume](./sizing#metadata-volume) for sizing guidance; unlike the cache, its footprint barely grows with data volume. ### Filesystem cache Provisioned as a **second, separate** volume via `extraVolumeClaimTemplates` + `extraVolumeMounts`, mounted at `/cache`, kept apart from the metadata volume so a full cache doesn't starve the metadata disk (and vice versa). Point your object storage backend's cache disk `` at this mount (shown in each backend's [configuration](#configuration) below): ```yaml clickhouse-server: extraVolumeClaimTemplates: - metadata: name: cache spec: accessModes: - ReadWriteOnce storageClassName: gp3 # adapt to your provider, use an SSD/NVMe-backed class, see Storage class below resources: requests: storage: 50Gi # must stay above CACHE_MAX_SIZE (see Filesystem cache below); 50Gi pairs with the chart's default 48Gi extraVolumeMounts: - name: cache mountPath: /cache ``` The `storage` above is illustrative, see [Filesystem cache](./sizing#filesystem-cache) for sizing guidance: it only needs to hold your working set, not your full dataset, and should be sized above `CACHE_MAX_SIZE`. ### Storage class Use the same class of storage for both volumes: high IOPS is required for metadata as well as the cache: | Class | Examples | Notes | | :--- | :--- | :--- | | **Network-attached SSD** (recommended) | AWS EBS `gp3` / `io2`, Azure Premium SSD (`Premium_LRS`), GCP `pd-ssd` / `pd-balanced` | Survives node loss or reschedule: the volume follows the pod to a new node. | | **Local NVMe** | AWS instance store (`i3` / `i4i` instance types), an on-prem local-volume StorageClass | Fastest option, but pinned to the node it was provisioned on, see the caution below. | | Not supported | HDD-class (`st1` / `sc1`, `pd-standard`, Standard HDD), network filesystems (NFS, EFS, Azure Files, Filestore) | Latency is incompatible with ClickHouse's read/write patterns. | :::caution Local NVMe pins the pod to its node A local-path StorageClass ties the volume to the specific node it was provisioned on: unlike network-attached storage, it cannot simply follow the pod to a different node. If your cluster autoscaler consolidates or drains that node, the pod cannot be rescheduled without losing the volume. If you use local NVMe, prevent your autoscaler from disrupting the node (see [Node stability](./sizing#node-stability)), and plan to restore from backup rather than expect a simple reschedule if the node is lost anyway. ::: ## Object storage backends ClickHouse stores its table data on an object storage bucket that you provide. Each provider below has a single supported authentication path: credential-less on AWS S3 and Azure (no static keys to create, store, or rotate), and static access-key/secret-key credentials on GCS and MinIO: GCS because credential-less access isn't possible for ClickHouse's own disk (see the GCS tab for why), MinIO because it has no cloud identity provider to federate with in the first place. :::tip Use a dedicated bucket, and a separate one for backups Use a bucket dedicated to ClickHouse: don't share it with unrelated data. The [backup sidecar](./backup-restore) writes to a bucket of its own too: **use a genuinely separate bucket for it, not just a different prefix inside ClickHouse's own data bucket.** A shared bucket means a single failure (a bad lifecycle policy, an over-permissioned credential, an accidental deletion) can take out your live data and your backups together, defeating the point of having a backup at all. ::: :::tip Outbound network access If your cluster restricts egress (NetworkPolicies, an egress firewall or proxy), ClickHouse and the backup sidecar both need outbound access to your object storage endpoint. With a credential-less setup, they also need to reach your cloud provider's identity token-exchange endpoint to trade the projected token for short-lived credentials: AWS STS (`sts.amazonaws.com`, or your region's STS endpoint) for IRSA, Microsoft Entra ID (`login.microsoftonline.com`) for Workload Identity. ::: ### Bucket lifecycle policies ClickHouse's own data bucket and the [backup sidecar's bucket](./backup-restore) need **different, in places opposite** lifecycle rules and protections. Both are covered here. Read the subsection for each bucket you're configuring. #### ClickHouse data bucket Don't apply a lifecycle rule to the bucket (or prefix) backing a ClickHouse disk that **transitions or expires objects**: ClickHouse expects every object it wrote to remain immediately readable indefinitely. A transition to an archive storage tier (S3 Glacier/Deep Archive and equivalents, including S3 Intelligent-Tiering's optional Archive Access tiers) makes the object unreadable until restored, which can make ClickHouse fail to start or throw errors reading existing parts; an expiration rule deletes data ClickHouse still expects to find, risking data loss. Only ClickHouse itself (via `TTL` / `DROP PARTITION`) or an informed administrator should ever remove these objects. The one lifecycle rule that **is** safe: aborting incomplete multipart uploads after a few days. This only cleans up orphaned upload fragments left behind by interrupted uploads (never live data), and prevents them from accumulating unnoticed in your bucket. :::tip Don't add versioning or Object Lock to this bucket either ClickHouse deletes and rewrites objects continuously as part of normal operation (merges, `TTL`, `DROP PARTITION`). Neither adds a real disaster-recovery benefit here (that's what the [backup bucket](#backup-bucket) is for), and both work against normal operation instead: versioning piles up delete markers with no purge plan of their own, and Object Lock blocks ClickHouse's own legitimate deletes outright, not just accidental ones. ::: #### Backup bucket The same core rule as the data bucket applies here too, for the same reason: don't let a lifecycle rule transition or expire objects that `clickhouse-backup` still manages. It tracks its own retention (`BACKUPS_TO_KEEP_REMOTE`) and chain dependencies (`REBASE_BEFORE_REMOVE_OLD_REMOTE`, see [Tunable settings](./backup-restore#tunable-settings)) directly, and expects every backup inside that window to stay immediately readable and to be deleted on its own terms, not S3's. An external expiration rule deletes backups it still expects to find; a transition to an archive tier can break a `rebase`'s server-side copy from a still-referenced older chain. The same multipart-abort rule above is safe here too. Beyond that baseline, this bucket exists specifically to survive a disaster that takes out ClickHouse's own bucket, so hardening it further is worth the extra cost and complexity that isn't justified on the data bucket: - **Versioning**: recommended. Defense in depth against a compromised credential or a bug deleting backups outright, on top of `clickhouse-backup`'s own retention logic. - **Object Lock** (Governance or Compliance mode): worth it if you have a ransomware or compliance requirement to defend against, but set the retention period **shorter** than your effective `BACKUPS_TO_KEEP_REMOTE` window. Otherwise it blocks `clickhouse-backup`'s own routine pruning too, not just malicious deletes. We haven't verified how it handles a blocked delete, so the safe design goal is that the two windows never actually collide. - **Cross-region or cross-account replication**: recommended for a real disaster-recovery posture. A separate bucket already protects against a shared misconfiguration or credential; replicating it further protects against losing the account or region it lives in. - **Archive-tier transition**: only safe for backups you've explicitly exported outside of `clickhouse-backup`'s own tracked path (a manual copy to a bucket or prefix it doesn't manage). Never transition objects inside the bucket or prefix it actively manages: the same read-availability assumption that rules this out on the data bucket applies here. ### Configuration On AWS EKS, ClickHouse authenticates to S3 using **IAM Roles for Service Accounts (IRSA)**: there is no access key to create, store, or rotate. This requires: 1. An IAM OIDC identity provider registered for your EKS cluster (most EKS clusters already have one for other workloads); see [AWS's IAM roles for service accounts documentation](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) if you need to set one up. 2. A dedicated Kubernetes ServiceAccount for ClickHouse, created by the chart, annotated with an IAM role ARN. 3. An IAM role that trusts your cluster's OIDC provider, scoped to that ServiceAccount. 4. A permission policy granting only the S3 access ClickHouse and its backup sidecar need. **Chart configuration**: create a dedicated ServiceAccount for ClickHouse and annotate it with the role ARN: ```yaml clickhouse-server: serviceAccount: annotations: eks.amazonaws.com/role-arn: 'arn:aws:iam:::role/' ``` **Trust policy**: scoped to the ServiceAccount above (replace ``, ``, and ``): ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam:::oidc-provider/" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { ":sub": "system:serviceaccount::clickhouse", ":aud": "sts.amazonaws.com" } } } ] } ``` **Permission policy**: scoped to the bucket dedicated to ClickHouse: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:ListBucket", "s3:GetBucketLocation", "s3:ListBucketMultipartUploads"], "Resource": [ "arn:aws:s3:::", "arn:aws:s3:::" ] }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": [ "arn:aws:s3:::/*", "arn:aws:s3:::/*" ] } ] } ``` :::tip Scope the policy to ClickHouse's own bucket and, since IRSA gives a single role to the whole pod, the separate backup bucket too (see the tip above): the policy grants read/write/delete on both, so neither should be shared with unrelated data. `` must match the one you set in the disk `` below; `` is the one you'll set in the backup sidecar's own destination config (see [Backup and restore](./backup-restore#object-storage-destination)). ::: With the ServiceAccount in place, the disk configuration uses the environment-provided credentials: no `extraEnvVars` needed, since the ServiceAccount's IRSA token is automatically mounted into every container in the pod, including the backup sidecar. You only need to declare the raw disk itself, named `object_disk`; the filesystem cache in front of it, and the storage policy that puts new tables on it, are already configured by the chart: ```yaml clickhouse-server: configdFiles: 00-object-storage.xml: | 1073741824 s3 https://.s3..amazonaws.com// true ``` :::caution Name the file so it sorts before object-cache.xml ClickHouse loads `config.d` files in alphabetical order, and the chart's own cache configuration (`object-cache.xml`) expects the `object_disk` disk above to already exist by the time it's parsed. Name your file `00-object-storage.xml`, as shown above; anything that sorts before `object-cache.xml` works, but this is the convention used throughout this page. ::: **Target bucket:** set by the `` portion of the `` URL above: this is ClickHouse's own data bucket, independent from the bucket the [backup sidecar](./backup-restore) writes to. On AKS, ClickHouse authenticates to Azure Blob Storage using **Microsoft Entra Workload ID**: the same OIDC-federation model as IRSA, under Azure's naming. This requires: 1. Workload Identity and the OIDC issuer enabled on your AKS cluster (on AKS Automatic clusters this is preconfigured; on AKS Standard, enable it explicitly). 2. A dedicated Kubernetes ServiceAccount for ClickHouse, created by the chart, annotated with a managed identity's client ID, with the pod itself labeled to opt in. 3. A **federated identity credential** linking that managed identity to your cluster's OIDC issuer and the ServiceAccount's subject. 4. An Azure RBAC role assignment granting only the Blob Storage access ClickHouse and its backup sidecar need. **Enable Workload Identity on the cluster** (AKS Standard only, skip on AKS Automatic): ```bash az aks update \ --resource-group \ --name \ --enable-oidc-issuer \ --enable-workload-identity export AKS_OIDC_ISSUER="$(az aks show --name \ --resource-group \ --query "oidcIssuerProfile.issuerUrl" --output tsv)" ``` **Create a managed identity** for ClickHouse: ```bash az identity create \ --name clickhouse-workload-identity \ --resource-group export IDENTITY_CLIENT_ID="$(az identity show \ --name clickhouse-workload-identity \ --resource-group \ --query 'clientId' --output tsv)" ``` **Chart configuration**: create a dedicated ServiceAccount for ClickHouse, annotated with the managed identity's client ID, and label the pod to opt in to the mutating webhook that injects the federated token: ```yaml clickhouse-server: serviceAccount: annotations: azure.workload.identity/client-id: '' podLabels: azure.workload.identity/use: 'true' ``` **Federated identity credential**: links the managed identity to the ServiceAccount's subject (replace ``): ```bash az identity federated-credential create \ --name clickhouse-federated-credential \ --identity-name clickhouse-workload-identity \ --resource-group \ --issuer "${AKS_OIDC_ISSUER}" \ --subject system:serviceaccount::clickhouse \ --audience api://AzureADTokenExchange ``` **Role assignment**: grant the managed identity access to the storage account, scoped to a container if you use a dedicated one: ```bash az role assignment create \ --assignee-object-id "$(az identity show --name clickhouse-workload-identity \ --resource-group --query principalId --output tsv)" \ --assignee-principal-type ServicePrincipal \ --role "Storage Blob Data Contributor" \ --scope ``` With this in place, the disk configuration uses the workload identity instead of a static account key. You only need to declare the raw disk itself, named `object_disk`; the filesystem cache in front of it, and the storage policy that puts new tables on it, are already configured by the chart: ```yaml clickhouse-server: configdFiles: 00-object-storage.xml: | 1073741824 azure_blob_storage https://.blob.core.windows.net true ``` :::caution Name the file so it sorts before object-cache.xml ClickHouse loads `config.d` files in alphabetical order, and the chart's own cache configuration (`object-cache.xml`) expects the `object_disk` disk above to already exist by the time it's parsed. Name your file `00-object-storage.xml`, as shown above; anything that sorts before `object-cache.xml` works, but this is the convention used throughout this page. ::: **Target bucket:** Azure's equivalent of a bucket is a **container** within a storage account, set here by `` (the account) and `` (the container); independent from the container the [backup sidecar](./backup-restore) writes to. ClickHouse has no native GCS disk type: it accesses GCS through its **`s3` disk type** pointed at GCS's S3-compatible interoperability endpoint (`storage.googleapis.com`), as documented by [ClickHouse itself](https://clickhouse.com/docs/integrations/gcs). Unlike S3 and Azure, this is the only supported authentication path for ClickHouse's own GCS disk: provide a GCS bucket and an **HMAC key pair** for a service account with access to it. :::danger Why credential-less isn't possible here GCS's XML API [does accept OAuth 2.0 bearer tokens](https://docs.cloud.google.com/storage/docs/authentication) (the constraint isn't on GCS's side), but ClickHouse's S3 client only ever speaks AWS-style HMAC request signing: it has no code path to send a bearer token to any S3-compatible endpoint. On AWS, IRSA still works because STS's `AssumeRoleWithWebIdentity` *converts* the federated token into temporary, HMAC-signable AWS credentials before ClickHouse ever sees them; GCP has no equivalent exchange that turns a Workload Identity Federation token into an [HMAC key](https://docs.cloud.google.com/storage/docs/authentication/hmackeys): those are always static and manually created. A static HMAC key pair is therefore required for ClickHouse's own GCS access regardless of your cluster's identity setup. The [backup sidecar](./backup-restore) is a separate program using GCS's native API, not the S3-compatible one: it may be able to use Workload Identity Federation even though ClickHouse's own disk can't; see [Backup and restore](./backup-restore#object-storage-destination) for that path. ::: **Storage configuration:** you only need to declare the raw disk itself, named `object_disk`; the filesystem cache in front of it, and the storage policy that puts new tables on it, are already configured by the chart: ```yaml clickhouse-server: configdFiles: 00-object-storage.xml: | 1073741824 s3 https://storage.googleapis.com/// true ``` :::caution Name the file so it sorts before object-cache.xml ClickHouse loads `config.d` files in alphabetical order, and the chart's own cache configuration (`object-cache.xml`) expects the `object_disk` disk above to already exist by the time it's parsed. Name your file `00-object-storage.xml`, as shown above; anything that sorts before `object-cache.xml` works, but this is the convention used throughout this page. ::: **Target bucket:** set by the `` portion of the `` URL above: this is ClickHouse's own data bucket, independent from the bucket the [backup sidecar](./backup-restore) writes to. GCS supports S3-style batch delete (`support_batch_delete: true`): no special handling needed when dropping tables. The HMAC access key ID is not sensitive on its own (like an AWS access key ID) and can be a literal value. **Credentials:** the configuration above references one environment variable, `GCS_HMAC_SECRET_ACCESS_KEY`, that must be injected into the ClickHouse pod from a Kubernetes secret. Create the secret as described in [Helm sensitive information management](../../../installation/helm-secrets), then reference it: ```yaml clickhouse-server: extraEnvVars: - name: GCS_HMAC_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: clickhouse-gcs-credentials key: secret-access-key ``` :::caution The backup sidecar needs a different credential `clickhouse-backup`'s GCS client does not accept HMAC keys: it only reads a native GCP service account JSON key. See [Backup and restore](./backup-restore) for the credential the sidecar needs in addition to the HMAC key pair above. ::: MinIO isn't a cloud provider, so there's no IAM-equivalent identity to federate with: ClickHouse always authenticates to it with a **static access-key/secret-key pair**, the same way it does for GCS. Unlike GCS, MinIO speaks the same S3 API the [backup sidecar](./backup-restore) already expects, so a single access-key/secret-key pair can cover both ClickHouse's own disk and the backup sidecar: no separate credential type needed for the backup path. **Storage configuration:** you only need to declare the raw disk itself, named `object_disk`; the filesystem cache in front of it, and the storage policy that puts new tables on it, are already configured by the chart: ```yaml clickhouse-server: configdFiles: 00-object-storage.xml: | 1073741824 s3 http://:/// ``` :::caution Name the file so it sorts before object-cache.xml ClickHouse loads `config.d` files in alphabetical order, and the chart's own cache configuration (`object-cache.xml`) expects the `object_disk` disk above to already exist by the time it's parsed. Name your file `00-object-storage.xml`, as shown above; anything that sorts before `object-cache.xml` works, but this is the convention used throughout this page. ::: **Target bucket:** set by the `` portion of the `` URL above: this is ClickHouse's own data bucket, independent from the bucket the [backup sidecar](./backup-restore) writes to. :::tip TLS If your MinIO deployment terminates TLS with a self-signed or internal CA certificate, add that CA to the ClickHouse pod's trust store rather than disabling certificate verification. If MinIO is only reachable over your cluster's internal network, a plain `http://` endpoint (as shown above) avoids the problem entirely. ::: **Credentials:** the configuration above references one environment variable, `MINIO_SECRET_ACCESS_KEY`, that must be injected into the ClickHouse pod from a Kubernetes secret. Create the secret as described in [Helm sensitive information management](../../../installation/helm-secrets), then reference it: ```yaml clickhouse-server: extraEnvVars: - name: MINIO_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: clickhouse-minio-credentials key: secret-access-key ``` ## Credentials AWS S3 and Azure authenticate credential-less by default (IRSA and Microsoft Entra Workload ID respectively, see the tabs above), so there's no long-lived secret to store in your cluster for either. GCS and MinIO are the exceptions: ClickHouse's own disk always needs a static access-key/secret-key pair for both, regardless of cluster identity setup: GCS because ClickHouse's S3 client can't consume a federated token (see the GCS tab), MinIO because it has no cloud identity provider to federate with in the first place. That static credential is passed the same way as other sensitive GitGuardian configuration, see [Helm sensitive information management](../../../installation/helm-secrets). --- ## Cluster management ## Overview An overview of your cluster is available under the "Cluster Management" tab in the Admin Console. ![Cluster Overview](/img/self-hosting/management/infrastructure-management/replicated_cluster_management.png) Some key pieces of information: - Nodes in the cluster. - CPU, RAM, and disk availability on each node. Nodes don't need to be of the same size. Here, you can also find instructions to add a new node. You can also drain nodes. ## Adding worker nodes to Embedded cluster If you want more processing power, you can scale your instance vertically by using a more powerful machine. But it is not always practical because it needs to be done before the installation, and it also means a big machine will always be running. Usually, a better solution is to scale horizontally by adding worker nodes to the cluster. This solution is more flexible and allows to add and remove processing capabilities when needed. A common use case is the initial historical scan. If you have a lot of repositories, adding more CPUs can speed up this process a lot. **For nodes to communicate together, you need to open `30000` and [the following ports](https://docs.k0sproject.io/v0.13.1/networking/#needed-open-ports-protocols) between them.** You can add a node at anytime ([installation](../../installation/installation-embedded-cluster-v2) included). 1. Connect with SSH to your other node. 2. Run the following to download the installer: ```bash LICENSE_ID=your_license curl -f https://replicated.app/embedded/gitguardian/stable -H "Authorization: $LICENSE_ID" -o gitguardian.tgz tar -xvzf gitguardian.tgz ``` 3. Go to the [KOTS Admin Console](./admin-console). Go to the "Cluster Management" tab. Click on "Add node" 4. Select roles to assign to the node 1. `management` is used for control-plane/worker nodes (for high availability). 2. The other roles are to be set depending on which kind of workload you intend to run. 3. If you just need processing power and you don't know the exact usage, just select all roles (except `management`) 5. It will show you a command to add a node. ![Add Node Command](/img/self-hosting/management/infrastructure-management/replicated_v2_add_node_command.png) 6. Run it on your new node. 7. Run the join command ![Node added](/img/self-hosting/management/infrastructure-management/replicated_v2_add_node_success.png) --- ## Gateway API :::info This page only concerns Helm-based installations on an existing cluster. See [Ingress](./ingress) for the default routing model. ::: GitGuardian's Helm chart can route external traffic through the [Kubernetes Gateway API](https://gateway-api.sigs.k8s.io/) instead of the legacy `Ingress` resource. This is opt-in: existing installations keep using `Ingress` by default. Gateway API is the modern, future-proof, and standardized successor to `Ingress` for Kubernetes traffic routing: instead of relying on controller-specific annotations as the NGINX `Ingress` does, it expresses routing through portable, role-oriented resources. Adopting it also enables capabilities such as latency-based autoscaling of the web application. :::warning Controller requirement Every `HTTPRoute` emitted by the chart uses the **`RegularExpression`** path match type. **Your Gateway API controller MUST support `RegularExpression` matchers**, otherwise the resources are rejected and traffic does not flow. Validated controllers: **Istio (≥ 1.25)**, **NGINX Gateway Fabric**, **Traefik (≥ v3)**. Verify your controller's support before enabling Gateway API mode. ::: ## When should you use Gateway API? Gateway API is the right choice when: - Your platform team has standardized on Gateway API and wants GitGuardian to follow the same model as the rest of the cluster. - You operate a **multi-tenant cluster** with a shared `Gateway` managed by a different team, and you want GitGuardian's routes to attach to it rather than provisioning a dedicated entry point. - Your data plane (Istio, Envoy Gateway, Kong, NGINX Gateway Fabric, …) is moving away from the `Ingress` resource and Gateway API gives you cleaner role separation between platform and application teams. If none of the above applies, the default Ingress mode is the simpler choice. ## Prerequisites To use Gateway API mode you need: - **Kubernetes ≥ 1.25** - **Gateway API CRDs ≥ v1.0** (channel: standard) [installed cluster-wide](https://gateway-api.sigs.k8s.io/guides/getting-started/introduction/) - A **Gateway API conformant controller with `RegularExpression` path match support** — see the warning above for validated controllers. - A **`GatewayClass`** that the controller reconciles, ready to be referenced by your `Gateway` ### Verifying cluster compatibility Run the following checks before switching to Gateway API mode. **Confirm the CRDs are installed:** ```bash kubectl get crd gateways.gateway.networking.k8s.io \ httproutes.gateway.networking.k8s.io \ gatewayclasses.gateway.networking.k8s.io ``` All three CRDs must exist. If they do not, install them following your controller's documentation (most controllers ship them or document the exact `kubectl apply` URL). **Confirm a `GatewayClass` is available and accepted:** ```bash kubectl get gatewayclass NAME CONTROLLER ACCEPTED AGE istio istio.io/gateway-controller True 28d ``` You should see at least one entry with `ACCEPTED=True`. Note the `NAME` column — this is the value you will set in `ingress.gatewayApi.gatewayClassName`. **Confirm the controller is healthy:** ```bash kubectl get pods -A -l 'app.kubernetes.io/component in (controller, gateway-api)' ``` The exact label depends on your controller; if in doubt, check that the namespace it runs in (`istio-system`, `envoy-gateway-system`, `kong`, `projectcontour`, …) has all pods in `Running` state. ## Configuration Two values control routing in your `values.yaml` file, and they are intentionally orthogonal: - `ingress.routingApi`: `ingress` (default) or `gateway-api`. Selects the routing API used to expose GitGuardian. - `ingress.controller`: the data plane that fulfills the routes. Used in both modes for autoscaling metrics; in Ingress mode it also picks the routing manifest format. ### Common fields The following fields keep the same meaning in both modes: | Field | Purpose | |---|---| | `ingress.enabled` | Master switch for external exposure. | | `ingress.controller` | Data plane name. Drives autoscaling metric selection (HPA / KEDA). In Gateway API mode it does not influence routing. | | `ingress.tls.enabled` | Enables TLS on the public listeners and the HTTP → HTTPS redirect. | | `ingress.tls.existingSecret` | Name of the `Secret` containing the TLS certificate. | | `hostname` / `domain` | Public hostnames used by the chart (app, API, receiver). | ### Gateway API specific fields These fields are only consumed when `routingApi: gateway-api`: | Field | Purpose | |---|---| | `ingress.routingApi` | Set to `gateway-api` to enable this mode. Default is `ingress`. | | `ingress.gatewayApi.gatewayClassName` | Name of the `GatewayClass` the chart references. Required only when `gateway.create=true`. Run `kubectl get gatewayclass` to find available classes in your cluster. | | `ingress.gatewayApi.gateway.create` | `true` lets the chart create and own the `Gateway` alongside the Helm release. `false` makes the chart attach its `HTTPRoute` resources to a `Gateway` managed elsewhere (multi-tenant model). | | `ingress.gatewayApi.gateway.name` | Name of the `Gateway`. The Gateway the chart creates if `create=true`, or the existing Gateway to attach to if `create=false`. | | `ingress.gatewayApi.gateway.namespace` | Namespace of the existing `Gateway`. Required only when `create=false` and the Gateway lives in a different namespace than GitGuardian. | | `ingress.gatewayApi.gateway.httpListenerPort` | Port for the HTTP listener on the chart-managed Gateway. Default `80`. Ignored when `create=false`. | | `ingress.gatewayApi.gateway.httpsListenerPort` | Port for the HTTPS listener on the chart-managed Gateway. Default `443`. Ignored when `create=false`. | ### Example: chart-managed Gateway The simplest setup. The chart creates the `Gateway` in the GitGuardian namespace; the controller provisions a load balancer for it. ```yaml ingress: enabled: true routingApi: gateway-api controller: istio tls: enabled: true existingSecret: gitguardian-tls gatewayApi: gatewayClassName: istio gateway: create: true name: gitguardian httpListenerPort: 80 httpsListenerPort: 443 ``` ### Example: attaching to an existing Gateway (multi-tenant) The chart only emits `HTTPRoute` resources pointing at a `Gateway` that already exists in the cluster. Typical when a platform team operates one shared `Gateway` for many applications. ```yaml ingress: enabled: true routingApi: gateway-api controller: istio tls: enabled: true # Leave empty if the certificate is managed at the Gateway level # by your platform team. existingSecret: '' gatewayApi: gatewayClassName: istio gateway: create: false name: shared-gateway namespace: gateway-system ``` Three things must hold on the platform team's side for the attachment to succeed: 1. The target `Gateway`'s `spec.listeners[].allowedRoutes.namespaces` must allow routes coming from the GitGuardian namespace. Set it to `From: All`, or use `From: Selector` with a label that matches the GitGuardian namespace. 2. If TLS is enabled and you reference a `Secret` from the chart, that `Secret` must be reachable by the `Gateway` (typically in the `Gateway`'s namespace). When the certificate is fully managed at the `Gateway` level, leave `ingress.tls.existingSecret` empty. 3. The `Gateway` must expose listeners with the names the chart's routes target via `sectionName`: - A listener named `http` is always required (used by the HTTP → HTTPS redirect route when TLS is enabled, or by all routes when TLS is disabled). - A listener named `https` is required when `ingress.tls.enabled=true`. ## Limitations **Body size limits** are not part of the Gateway API standard. The chart does not set one in Gateway API mode, so the effective cap is your controller's default (≈1 MB on NGF). To match the legacy mode, attach a controller-specific policy to the `gim-exposed` HTTPRoute with a **25 MB** limit. Example on NGINX Gateway Fabric: ```yaml apiVersion: gateway.nginx.org/v1alpha1 kind: ClientSettingsPolicy metadata: name: gim-exposed-body-limit namespace: spec: targetRef: group: gateway.networking.k8s.io kind: HTTPRoute name: gim-exposed body: maxSize: 25m ``` For Istio, Contour, Envoy Gateway or Traefik, use the equivalent native mechanism (e.g. `EnvoyFilter`, route-level setting, middleware) on the same HTTPRoute. ### NGINX Gateway Fabric specifics - **Per-route timeouts.** NGF ignores `spec.rules[].timeouts` (routes show `Accepted=True reason=UnsupportedField`). To restore them, apply a `ProxySettingsPolicy` (NGF ≥ 2.6) to the affected HTTPRoute — for example to keep the 3600 s ceiling on the billing-metrics export, target `gim-app` with `proxyReadTimeout: 3600s`. - **In-app-agent SSE.** The chart automatically skips the `X-Accel-Buffering: no` header on NGF (NGF rejects it from its allowlist). NGINX does not buffer streaming responses by default, so SSE flows correctly. ### AWS Load Balancer Controller is not supported The **AWS Load Balancer Controller** Gateway API mode (`gateway.k8s.aws/alb`) is **not** supported: the chart's `HTTPRoute`s use a `ResponseHeaderModifier` filter for security headers, which it rejects (only `RequestRedirect` is supported), so the `Gateway` never becomes `Programmed`. On Amazon EKS, use a validated controller such as **Istio** instead. ## Upgrading from Ingress to Gateway API Switching `routingApi` from `ingress` to `gateway-api` is potentially **traffic-impacting**: the chart stops creating `Ingress` resources and creates `Gateway`/`HTTPRoute` resources instead. Whether it requires a maintenance window or a DNS cutover depends on your cluster's setup. ### Step 1 — Identify your scenario Two possible paths: - **A. Attach to an existing shared `Gateway`** managed by your platform team. The `Gateway` and its load balancer already exist; GitGuardian only adds `HTTPRoute` resources to it. See [Example: attaching to an existing Gateway](#example-attaching-to-an-existing-gateway-multi-tenant). - **B. Create a new `Gateway` from the chart.** The chart provisions a dedicated `Gateway`, and your Gateway API controller provisions the underlying load balancer for it. See [Example: chart-managed Gateway](#example-chart-managed-gateway). Scenario A is the model the Gateway API was designed for: the cluster admin owns the `Gateway` (entry point, listeners, certificates, load balancer) and application teams own their `HTTPRoute` resources. This **separation of concerns** is a core best practice — the cluster admin keeps full control over how traffic enters the cluster, while application teams remain free to manage their own routing without touching infrastructure. If your organization can support it, prefer scenario A. Scenario B remains a valid choice when GitGuardian is the only application using Gateway API in the cluster, when you do not (yet) have a shared `Gateway`, or when GitGuardian must own its public entry point for organizational reasons. It is also a convenient stepping stone when migrating from `Ingress` before extracting the `Gateway` to the platform team's ownership later. ### Step 2 — Determine the public-address impact Whether the public IP / hostname of GitGuardian will change depends on your scenario. **Scenario A — Attach to an existing Gateway.** The address is the one of the shared `Gateway`. Switching from your current `Ingress` to that `Gateway` will change the public address that GitGuardian is reachable at — unless the existing `Ingress` controller and the shared `Gateway` happen to be backed by the same load balancer, which is uncommon. Plan a **DNS cutover and a maintenance window**. **Scenario B — Chart-managed `Gateway`.** Whether a new load balancer is provisioned depends on your Gateway API controller: - Some controllers provision **one `Service` of type `LoadBalancer` per `Gateway`** (Istio in Gateway API mode, Envoy Gateway, Kong, Contour Gateway Provisioner). With these, the new `Gateway` gets a new address — plan a DNS cutover and a maintenance window. - Some controllers can **reuse a single shared load balancer** across multiple `Gateway` resources, or even share it with the legacy `Ingress` data path (Traefik in Gateway API mode is a frequent example, depending on configuration). With these, the public address may be preserved and the cutover is closer to a regular Helm upgrade. Check your controller's documentation before assuming the behavior — this is the single most important question to answer before scheduling the migration. Useful command once a `Gateway` is deployed: ```bash kubectl get gateway -n -o jsonpath='{.status.addresses}' ``` If the address differs from the one your DNS currently points at, you are in the "new load balancer" situation. ### Step 3 — Plan the cutover **If the address changes** (most cases): The goal is to rehearse the switch end-to-end in a non-production environment first — apply the same `values.yaml` change and confirm the routes work — so that production cutover is a known quantity rather than a discovery. Once that is done: 1. Deploy the new Gateway API controller alongside the existing Ingress controller if possible (in staging, or as a parallel release in a separate namespace), so DNS records and certificates can be prepared against the future address. 2. Lower the TTL on your DNS records ahead of the cutover so rollback is quick. 3. Switch the GitGuardian release to `routingApi: gateway-api`. The chart removes the `Ingress` resources and creates the routes against the `Gateway`. 4. Update DNS to the new `Gateway` address (`kubectl get gateway -o jsonpath='{.status.addresses}'`). 5. If a corporate reverse proxy or CDN sits in front of GitGuardian, update its origin to the new address. **If the address is preserved** (controller reuses the same load balancer): The cutover is closer to a regular Helm upgrade, but the goal is still to rehearse it in a non-production environment first so the switch is a known quantity. Once that is done: 1. Switch the GitGuardian release to `routingApi: gateway-api`. The chart swaps the `Ingress` resources for `Gateway`/`HTTPRoute` resources; traffic continues to flow through the same load balancer. 2. Confirm with `kubectl get httproute -n ` and `kubectl describe gateway ` that all routes are `Accepted=True` and the `Gateway` is `Programmed=True`. ### TLS certificate The TLS `Secret` referenced by `ingress.tls.existingSecret` must live in a namespace reachable by the `Gateway` — usually the `Gateway`'s own namespace. If you currently keep the certificate in the GitGuardian namespace and you switch to a `Gateway` in another namespace, replicate the `Secret` (or rely on a tool like `cert-manager` or `reflector` to copy it). ### Autoscaling In Gateway API mode, built-in latency queries are available for `controller: istio`, `traefik` and `contour` — they reuse the same metrics as in Ingress mode, so no HPA/KEDA reconfiguration is needed when migrating (Contour additionally requires the experimental Gateway API CRD channel). For any other data plane (NGINX Gateway Fabric, Kong, Cilium, Envoy Gateway, …), set `controller: other` and provide your own KEDA trigger. See [Autoscaling web applications](./autoscaling.md#autoscaling-web-applications) for the support matrix and configuration examples (built-in query, `other` + custom trigger, and overriding the query). ### Rollback To roll back, set `routingApi` back to `ingress` and re-apply. The chart will recreate the `Ingress` resources. The `Gateway`/`HTTPRoute` resources are removed by Helm; in scenario B the underlying cloud load balancer is released by the controller. DNS records have to be reverted manually if they were changed. ## Troubleshooting The Gateway API exposes status conditions on every resource. Most issues surface there. ```bash # Gateway listeners and assigned address kubectl get gateway -n kubectl describe gateway -n # Routes and their attachment status kubectl get httproute -n kubectl describe httproute -n ``` Common cases: - **`Accepted=False`** on `HTTPRoute` with a `NotAllowedByListeners` reason — the shared `Gateway` does not allow routes from the GitGuardian namespace. Update the `Gateway`'s `spec.listeners[].allowedRoutes.namespaces`. - **`Programmed=False`** on `Gateway` — the controller has not finished provisioning the underlying load balancer. Check the controller's logs. - **No traffic reaches GitGuardian** but routes are accepted — confirm DNS points at the new `Gateway`'s address, and that the cloud load balancer's security groups allow inbound traffic on the listener ports. - **TLS handshake failures** — confirm the `Secret` referenced by `ingress.tls.existingSecret` exists in a namespace reachable by the `Gateway` (usually the `Gateway`'s namespace). --- ## Helm Chart Values Changelog Track changes in GitGuardian's Helm chart values across releases. **Latest Version**: [2026.8.0](./helm-values/2026.8.0) **Resources**: [Helm installation guide](../../installation/installation-existing-cluster-helm) | [Upgrade procedures](./upgrade-helm) ## 2026.8.0 vs 2026.7.0 **New:** - Added the opt-in `clickhouse` component (`clickhouse.enabled`, default `false`): sizing guardrails and backup settings under `clickhouse.*`, and the vendored subchart's raw values under `clickhouse-server.*`. It requires object storage you provide. See [ClickHouse](./clickhouse/overview). - Added `global.emptyDir.sizeLimit` to set a default `sizeLimit` on every chart-managed `emptyDir` volume (empty emits no `sizeLimit`, which is the Kubernetes default of unbounded). Per-volume overrides: `secretEngine.emptyDir.modelDir.sizeLimit` (the ML model bundle, by far the largest of the machine-learning volumes), `secretEngine.emptyDir.bentomlTmp.sizeLimit`, `secretEngine.emptyDir.bentomlProm.sizeLimit`, and `logCollector.emptyDir.sizeLimit`. Set these if your platform caps `emptyDir` volumes. - Added the optional `celeryWorkers.incidents-disk` worker, which consumes the `incidents_disk` queue to recompute secret locations on dedicated pods with their own ephemeral storage (`5Gi` request). Disabled by default (`replicas: 0`); when disabled, the queue falls back to the `scanners` worker. Autoscaling metric `{"incidents_disk":10}`. **Updated:** - Added the `core_aspm` queue to `celeryWorkers.long.queues` (and the matching `core_aspm: 10` autoscaling metric). ## 2026.7.0 vs 2026.6.0 **New:** - Added the optional `celeryWorkers.public-monitoring` worker, which consumes the Public Monitoring queues (`public_monitoring`, `public_monitoring_historical_scan`, `public_monitoring_realtime_scan`). It is gated by the `is_public_monitoring_enabled` license field (effectively disabled until licensed); when enabled it defaults to 1 replica, `1Gi` memory request / `2Gi` limit. - Added the opt-in `mcpServer` deployment. Set `mcpServer.enabled: true` to deploy the MCP server (default `false`). When enabled it runs 1 replica, exposes an ingress under the `/mcp-server` path of the application host, enables the OAuth proxy, and uses latency-based autoscaling (`mcpServer.autoscaling.metrics.targetLatency`). With the `aws_alb` controller it requires AWS Load Balancer Controller 2.14 or later. - Added `inAppAnalytics.ephemeralStorage` (`enabled`, `size`, `storageClass`, `annotations`, `labels`; default `enabled: false`, `size: 20Gi`) to attach a dedicated ephemeral volume to the in-app analytics pod, moving Spark scratch and spill data off the node's local `/tmp` disk. Prevents daily analytics job failures caused by node ephemeral-storage limits on large workspaces. See [In-app analytics ephemeral storage](./scaling#in-app-analytics-ephemeral-storage). - Added `logCollector.collectMigrationLogs` (default `true`) to also collect logs from the pre-deploy and post-deploy hook Jobs. The collector is injected as a native sidecar, which requires Kubernetes 1.29 or later. Disable it on older clusters. **Updated:** - Added the `validity_check_batch` autoscaling metric to `celeryWorkers.batch`. ## 2026.6.0 vs 2026.5.0 **New:** - Added Gateway API support for ingress. New `ingress.routingApi` (`ingress` (default) or `gateway-api`) selects between the Kubernetes Ingress / IngressRoute / VirtualService / HTTPProxy / Route templates and Gateway API `HTTPRoute` + `Gateway`. When `gateway-api` is selected, configure `ingress.gatewayApi.gatewayClassName` and `ingress.gatewayApi.gateway.*` (`create`, `name`, `namespace`, `httpListenerPort`, `httpsListenerPort`); only the `istio`, `contour`, and `traefik` controllers are supported in this mode. See [Gateway API](./gateway-api). - Added the optional `celeryWorkers.check-run-scanners` worker — consumes the `check_run_scan` queue to run scan-based (PR-scoped) check-runs on dedicated pods, separate from the historical-scan `scanners` worker. Disabled by default (`replicas: 0`); when disabled, the `check_run_scan` queue falls back to the `scanners` worker. Autoscaling metric `{"check_run_scan":10}`, `terminationGracePeriodSeconds: 1800`. - Added the optional `celeryWorkers.premium-scanners-retry` worker — consumes the `premium_repo_scan_retry` queue and retries failed large-repository scans on a dedicated high-memory pod. Disabled by default (`replicas: 0`); when disabled, retries fall back to the regular scanner workers. Defaults: `120Gi` memory request/limit, autoscaling metric `{"premium_repo_scan_retry":1}`, `terminationGracePeriodSeconds: 86400`. See [Premium scan retry worker](./scaling#premium-scan-retry-worker). - Added the `premium_repo_scan_retry` queue so retries are processed by the standard `celeryWorkers.scanners` worker when the dedicated worker is disabled. - Added `tls.customCa.resources` to set resource requests/limits on the `init-custom-ca` init container (default: requests `cpu: 50m` / `memory: 64Mi`, limits `memory: 128Mi`). **Updated:** - `webapps.internal_api_long.nginx.location` now also routes `issues/{id}/occurrences/` and `public-monitoring/perimeter/all-developers/` to the long-request internal API webapp (previously only the `report/` endpoint). ## 2026.5.0 vs 2026.4.0 **New:** - Added dedicated `celeryWorkers.automatic-severities` worker (replicas: 1, autoscaling up to 3, requests 1Gi / limits 2Gi memory) — moves the `automatic_severities` queue out of the `long` worker into its own scalable worker. - Added `celery` queue to `celeryWorkers.worker.queues` (and matching `celery: 10` autoscaling metric). - Added `endpoints` queue to `celeryWorkers.long.queues` (and matching `endpoints: 10` autoscaling metric). - Added `inAppAnalytics.annotations` and `inAppAnalytics.podLabels` for finer-grained metadata on analytics workloads. - Added `tls.certManager.issuer.group` (default: `cert-manager.io`) to support external issuers (e.g. AWS PCA). - Added `logCollector.supportBundle.logLevel` (`info` / `error`, default: `info`) to filter Loki queries when generating a support bundle. **Updated:** - Default value of `inAppAnalytics.enabled` changed from `false` to `true`. **Removed:** - Removed `automatic_severities` from `celeryWorkers.long.queues` (moved into the dedicated `celeryWorkers.automatic-severities` worker above). ## 2026.4.0 (Required) vs 2026.3.0 **New:** - Added `global.labels` for common labels applied to all resources (replaces `commonLabels`). - Added `global.tolerations` for common tolerations applied to all workloads (replaces `commonTolerations`). - Added `global.nodeSelector` for a global node selector applied to all GIM pods (component-level `nodeSelector` takes full precedence). [Learn more about node scheduling](./scaling#node-affinity-scheduling). - Added `global.image.imagePullPolicy` for global image pull policy. - Added `autoscaling.keda.additionalPromqlLabelSelectors` for custom PromQL label selectors in KEDA queries. - Added `nginx.extraEnv`, `nginx.extraVolumes`, `nginx.extraVolumeMounts` for Nginx customization. - Added `inAppAnalytics.terminationGracePeriodSeconds` (default: 7200s) for analytics job graceful shutdown. - Added `networkPolicy.mode` (`dryrun` / `enforce`), `networkPolicy.allowedNamespaces`, and `networkPolicy.extraPolicies` for granular network policy control. See [Network policies](./network-policies). - Added `replicated.supportBundle.enabled`, `replicated.supportBundle.admissionPolicy`, `replicated.supportBundle.credentials`, and `replicated.supportBundle.resources` for enhanced support bundle configuration. **Updated:** - Added `onPrem.replicatedRbac.mode` (`full` / `minimal` / `disabled`) replacing the previous boolean `enabled`. - Added `core_default`, `sources_default`, `incidents_default` to `celeryWorkers.worker.queues`. - Added `code_fixing` to `celeryWorkers.scanners.queues`. - Added `hmsl`, `core_long`, `sources_long`, `incidents_long`, `ml_backpopulate` to `celeryWorkers.long.queues`. **Removed:** - Removed `commonLabels` and `commonTolerations` (replaced by `global.labels` / `global.tolerations`). - Removed `global.security.allowInsecureImages` and `global.compatibility.openshift.adaptSecurityContext`. - Removed `onPrem.replicatedRbac.enabled` (replaced by `mode`). - Removed `sentry` section. - Removed `externalSecrets` section. Manage `ExternalSecret` resources yourself and use `existingSecrets` instead. - Removed `logCollector.networkPolicy.enabled` in favor of top-level `networkPolicy.enabled`. ## 2026.3.0 vs 2026.2.0 **Updated:** - Added `ml_backpopulate` to `celeryWorkers.long.queues` default value. ## 2026.2.0 vs 2026.1.0 **New:** - Added `hookMethod` parameter to handle `helm` and `argocd` hooks annotations. - Added `replicated.replicaCount` coming with Replicated SDK HA feature. - Added `replicated.highAvailability.podAntiAffinityPreset` coming with Replicated SDK HA feature. - Added `replicated.highAvailability.podDisruptionBudget.enabled` coming with Replicated SDK HA feature. - Added `replicated.highAvailability.podDisruptionBudget.minAvailable` coming with Replicated SDK HA feature. - Introduced new `celeryWorkers.check-runs` worker type dedicated to Check Run tasks (default: 0 replicas). **Updated:** - Updated `loki.loki.compactor.retention_delete_delay` from `168h` to `2h` to better reflect Loki configuration. - Added `sources_default`, `incidents_default` and `individual_validity_check` to `celeryWorkers.worker.queues`. - Added `individual_validity_check` to `celeryWorkers.worker.autoscaling.metrics`. - Added `code_fixing` to `celeryWorkers.scanners.queues`. - Added `hmsl`, `sources_long` and `incidents_long` to `celeryWorkers.long.queues`. ## 2026.1.0 (Required) vs 2025.12.0 **New:** - Added `webappDefaults` and `celeryWorkerDefaults` sections to centralize common configuration (e.g., `nodeSelector`, `tolerations`, `priorityClassName`). Individual webapp/worker configurations are still fully supported and take priority over defaults - you can override any default value by specifying it directly under `webapps.[name]` or `celeryWorkers.[name]`, even if not explicitly listed in the values reference. - Added new Celery queues: `core_default` and `core_long`. **Removed:** - Removed `apacheTika.javaOpts` parameter. ## 2025.12.0 vs 2025.11.0 **New:** - Added `extra_hostnames` parameter to allow additional hostnames on Nginx proxy. - Added `network.ipFamily` parameter to select IP class (IPv4/IPv6) for `Service` resources. [Learn more](./ipv6-networking). - Introduced new worker type `business-contribution` under `celeryWorkers` key value. - Added new global `podDisruptionBudget.enabled` parameter to deploy PDB globally. - Introduced section `inAppAnalytics` parameter to configure the In App Analytics feature (in beta). - Added new `podDisruptionBudget` parameter to control PDB globally. **Updated:** - Tagged `experimental.ingressRoutes` explicitly as deprecated feature. ## 2025.11.0 vs 2025.10.0 **New:** - Added default `RuntimeDefault` value to MinIO pod security `loki-minio.containerSecurityContext.seccompProfile.type`. - Introduced `update_sources_state` and `nhi_ingestion` parameters to `celeryWorkers.long.autoscaling.metrics`. - Added `replicatedRbac` section to control replicated RBAC. **Updated:** - replicated-sdk now inherits from `global.imagePullSecrets`, removing the need to use `replicated.imagePullSecrets` if secret is defined globally. - Default `logCollector.supportBundle.since` changed from `6h` to `12h`. - Changed `celeryWorkers.long.queues` value to add `update_sources_state` and `nhi_ingestion`. **Removed:** - Deleted `replicatedSdk` key as it is enabled by default now. ## 2025.10.0 (Required) vs 2025.9.0 **Updated:** - Containers are now using readOnlyRootFilesystem by default (`containerSecurityContext`). - Updated `loki-minio.image.repository` from `gitguardian/wolfi/minio-bitnami` to `gitguardian/wolfi/minio`. - Updated `loki-minio.image.tag` from `0.20250723` to `0.20250907`. - The parameter `loki-minio.image.pullPolicy` has been renamed to `loki-minio.image.imagePullPolicy`. - Added `automatic_severities` to `celeryWorkers.long.queues` to allow long-running tasks to complete gracefully before the 24-hour timeout. - Added `NO_PROXY` to `replicated.extraEnv` default to fix license verification when using a proxy. **Removed:** - `loki-minio.podSecurityContext.enabled` boolean has been removed. To disable `podSecurityContext` you now need to use empty object such as `podSecurityContext: {}`. - `loki-minio.containerSecurityContext.enabled` boolean has been removed. To disable `containerSecurityContext` you now need to use empty object such as `containerSecurityContext: {}`. - `loki-minio.networkPolicy` section has been removed since it is not supported anymore. - `loki-minio.console` section has been removed since it is not relevant anymore. - `loki-minio.ServiceAccount` section has been removed since it is now enabled by default. ## 2025.9.0 vs 2025.8.0 **New:** - Introduced `apacheTika` parameter to configure the new file scanner service for Non-VCS sources (disabled by default). - Introduced `celeryWorkers.scanners-ods-highdisk` parameter to configure workers dedicated to high storage tasks like Microsoft OneDrive and SharePoint scanning (default: 0). [Learn more about Non-VCS Sources](../application-management/non-vcs-sources.md). **Updated:** - Updated `logCollector.supportBundle.since` default value from `3d` to `6h` to make support bundle lighter. **Removed:** - `postgresql.plugins.pgvector.enabled` has been removed since it is now enabled by default, pgvector is now required. [Learn more about PostgreSQL requirements](../../system-requirements.md#postgresql). ## 2025.8.0 vs 2025.7.0 :::caution Upgrading to 2025.8 **Air gap deployment?** This release introduces a new `image.registry` parameter in Helm values to support the Log Collector system. This parameter specifies the location of the GitGuardian images for the [Log Collector](../../troubleshoot/logs#log-collector) components (Loki, MinIO, Fluent Bit) and is separate from the main `imageRegistry` parameter. Follow the [upgrade instructions](../infrastructure-management/upgrade-helm#upgrading-to-20258) to update your helm values file. ::: **New:** - Introduced a new `image.registry` parameter in Helm values to support the Log Collector system. This parameter specifies the location of the GitGuardian images for the [Log Collector](/self-hosting/troubleshoot/logs#log-collector) components (Loki, MinIO, Fluent Bit) and is separate from the main `imageRegistry` parameter. Follow the [upgrade instructions](/self-hosting/management/infrastructure-management/upgrade-helm#upgrading-to-20258) to update your helm values file. - Introduced `celeryWorkers.scanners-slack` parameter to configure workers dedicated to Slack scanning (default: 0). [Learn more about Slack Scanning considerations](./scaling.md#slack-scanning-considerations). - Added `commonTolerations` parameter that allows you to apply consistent tolerations across all workloads in the GitGuardian deployment. **Removed:** - `beat.replicas` has been removed and is now hardcoded in the chart to 1. ## 2025.7.0 (Required) vs 2025.6.0 **New:** - Added `priorityClassName` parameter for ML Secret Engine and several priority class configuration. [Learn more](../application-management/machine-learning#lower-the-priority-of-ml). This is also available for other pods and as a global parameter (`global.priorityClassName`). **Updated:** - Changed the default value of `celeryWorkers.ml-api-priority.replicas` from `0` to `1`. [Learn more](../application-management/machine-learning#helm-based-installation). ## 2025.6.0 vs 2025.5.0 **New:** - Added `global.fipsEnabled` parameter to enable FIPS compliant images. [Learn more about FIPS compliance](../../security/recommendations). - Added pod anti-affinity configuration (`podAntiAffinityPreset`) and `nodeSelector` and `tolerations` parameters across all components for improved workload placement control and high availability. [Learn more about scaling](./scaling#node-affinity-scheduling). - Enhanced logCollector with additional configuration options (`logCollector.env`, `logCollector.envFrom`, `logCollector.pipelines`). [Learn more about additional pipelines](../../troubleshoot/logs#additional-pipelines). - Enhanced migration job resource configuration with separate specifications for pre-deploy, post-deploy, and upgrade path check jobs. **Removed:** - `migration.resources` has been replaced with job-specific resource configurations for better resource management. ## 2025.5.0 vs 2025.4.0 :::caution Upgrading to 2025.5 **Air gap deployment?** We've renamed images in this release. See below changes and find all image and tag names on the **[Air Gap Install page](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. ::: **New:** - Added support for configuring the proxy via an existing Kubernetes secret using `proxy.existingSecret` and `proxy.existingSecretKeys.*`. **Updated:** - **FIPS:** This release uses Chainguard images without FIPS-approved cryptographic modules. If you would like to use Chainguard images with FIPS, please contact our [support team](mailto:support@gitguardian.com). This change involves renaming the following images: - `gitguardian/prm-static-chainguard-fips` to `gitguardian/prm-static-chainguard` - `gitguardian/prm-app-fips` to `gitguardian/prm-app-chainguard` - Use `proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/bash:latest` image instead of `proxy.replicated.com/proxy/gitguardian/docker.io/nginxinc/nginx-unprivileged:stable` for Custom CA injection (See `tls.customCa.image.*`). - The `securityContext.enabled` (bool) parameter has been replaced by a new `securityContext` (object) parameter, which now allows specifying the full Pod Security Context. **Removed:** - `experimental.chainguard` has been deprecated as GitGuardian images are now using Chainguard by default. [Lean more about Chainguard](../../security/recommendations). ## 2025.4.0 (Required) vs 2025.3.0 :::caution Upgrading to 2025.4 **Air gap deployment?** We've added new images in this release. Find all image and tag names on the **[Air Gap Install page](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. ::: **New:** - Our self-hosted deployments now include a log collection system, leveraging Loki, MinIO, and Fluent Bit under the hood. This log collection system is now enabled by default for all installation types (Helm or KOTS). [Learn more about the log collector](../../troubleshoot/logs#log-collector). - The PostgreSQL `pgvector` extension is now required by default (`postgresql.plugins.pgvector.enabled`). Please follow the [installation instructions](../../system-requirements#postgresql) to enable vector similarity search capabilities for upcoming machine learning features. **Updated:** - Added default `support-bundle` Role and optional ClusterRole creation (configurable via `replicated.supportBundle.rbac.clusterRole.create`). - Added `global.compatibility.openshift.adaptSecurityContext` configuration to support OpenShift's restricted-v2 Security Context Constraints (SCC). Values include `auto` (default), `force`, and `disabled` for flexible security context adaptation. ## 2025.3.0 vs 2025.2.0 :::caution Upgrading to 2025.3 We've updated the path and names of our images in this release. Follow the [upgrade instructions](./upgrade-helm#upgrading-to-20253) to update your tooling for downloading and uploading GitGuardian images to your private registry. Find all image and tag names on the **[Air Gap Install page](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. ::: **Updated:** - Change registry URL from `proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com` to `proxy.replicated.com/proxy/gitguardian/docker.io` and rename paths and images name from: - `/prm/static-chainguard` to `/gitguardian/prm-static-chainguard-fips` - `/prm/app-chainguard` to `/gitguardian/prm-app-chainguard-fips` - `/prm/helm-tooling` to `/gitguardian/prm-helm-tooling` - `/services/nginx-unprivileged` to `/nginxinc/nginx-unprivileged` - `/ml-detector/ml-secret-engine/app-chainguard` to `/gitguardian/ml-secret-engine-app-chainguard-fips` - Change registry URL from `registry.replicated.com` to `proxy.replicated.com/proxy/gitguardian/docker.io` and rename paths and images name from `/gitguardian/replicated-sdk` to `/replicated/replicated-sdk`. - The `nhi-scout` parameter has been renamed to `ggscout`. - Added `celeryWorkers.*.autoscaling.keda.idleReplicaCount` parameter to allow specifying the number of replicas when there is no activity on the Celery Worker (default: `0`). ## 2025.2.0 vs 2025.1.0 **New:** - Enhanced the `webapps..autoscaling` settings to support both Horizontal Pod Autoscaler (HPA) and KEDA autoscaling options, including enabling/disabling and setting triggers. [Learn more](./autoscaling). - Added `migration.podAnnotations` parameter for GitGuardian migration pods. **Updated:** - `nhiScout.enabled` parameter has been moved to `nhi-scout.enabled`. [Learn more](../../../ggscout-docs/self-hosted-configuration). ## 2025.1.0 (Required) vs 2024.12.0 :::caution Upgrading to 2024.12 The ReplicatedSDK image is now pulled from the Replicated registry instead of Docker Hub. For airgap installations, ensure you update your automation processes for pulling and pushing images to your private registry. For more information, refer to the [Airgap Installation page](../../installation/airgap-installation-existing-cluster-helm). ::: **New:** - Introduced `secretEngine` parameter to configure the new ML Secret Engine service. (Disabled by default). [Learn more](../application-management/machine-learning#helm-based-installation). - Introduced `celeryWorkers.ml-api-priority` parameter to configure ML Secret Engine dedicated worker (Disabled by default). - Introduced `nhiScout.enabled` parameter to enable NHI Scout deployment (Disabled by default). [Learn more](../../../ggscout-docs/self-hosted-configuration) - Introduced `nhi-scout` parameter to configure NHI Scout. - Added `replicated.image.registry` parameter to use the Replicated registry (`registry.replicated.com`) instead of Docker Hub by default. **Updated:** - Changed the default value of `replicated.image.repository` from `replicated/replicated-sdk` to `gitguardian/replicated-sdk`. ## 2024.12.0 vs 2024.11.0 :::caution Upgrading to 2024.12 This release includes breaking changes. Upgrade to **2024.12.0** using the **[upgrade notes](./upgrade-helm)**. ::: **New:** - Ability to deploy `Ingress` objects with the support of several Ingress controllers. For details, see the [Ingress documentation](./ingress). **Updated:** - `front.ingress` has been renamed to `ingress` for improved consistency and standardization across the Helm chart. - `istio` have been moved under the `ingress`. - The default memory value for `migration.resources` has been increased from `100Mi` to `200Mi`. ## 2024.11.0 vs 2024.10.0 :::caution Upgrading to 2024.11 This release includes breaking changes. ::: **New:** - Removed `settings.healthCheck.periodicInterval` parameter since health checks are now distributed over time rather than executing them simultaneously. This parameter is replaced by `spread_periodic_range_minutes` in the [admin area](../application-management/preferences#health-checks). - Added `replicated.privateCASecret` parameter to specify a custom CA when using a proxy. [Learn more](./proxy-server#helm-based-installation). - Replace the legacy parameter `replicated.images.replicated-sdk` with the new parameters `replicated.image.repository` and `replicated.image.tag` ## 2024.10.0 (Required) vs 2024.9.0 **New:** - Added two new worker types `long-ods` (non-VCS sources such as Slack, Jira Cloud, Confluence, ...) and `long-ods-io` (long tasks specialized in Input/Output). - Added the support of CRL (instead of default OCSP) for certificate-based authentication. **Updated:** - Decreased the default value of `celeryWorkers.realtime-ods.replicas` from `2` to `0`. ## 2024.9.0 vs 2024.8.0 **New:** - Added a new `autoscaling` object to configure autoscaling settings. - Enhanced the `celeryWorkers..autoscaling` settings to support both Horizontal Pod Autoscaler (HPA) and KEDA autoscaling options, including enabling/disabling and setting triggers. [Learn more](./autoscaling). - Introduced a new setting `replicated.supportBundle.logs.maxLines` to specify the maximum number of lines included in support bundle logs. - Added `experimental.tini`, a new option to enable `tini` for terminating zombie processes on workers. ## 2024.8.0 vs 2024.7.0 **New:** - Introduced `tls.clientAuth` to support authentication using Common Access Card (CAC) or Personal Identity Verification (PIV). For detailed information, refer to the documentation [here](./cert-based-auth). ## 2024.7.0 (Required) vs 2024.6.0 :::caution Upgrading to 2024.7 This release includes breaking changes. ::: **New:** - Added `settings.healthCheck.periodicInterval` allowing you to change the frequency of [health checks](../../troubleshoot/health-check#integration-connectivity). **Updated:** - Renamed `front.ingress.tls.secretName` to `front.ingress.tls.existingSecret`. - Renamed `tls.customCa.caCert` to `tls.customCa.caCrt`. - Renamed `tls.customCa.existingSecretCaCertKey` to `tls.customCa.existingSecretKeys.caCrt` and set the Default to `""`. - Renamed `redis.main.existingSecretKeys.sentinel.password` to `redis.main.existingSecretKeys.sentinelPassword`. - Renamed `redis.main.existingSecretKeys.sentinel.url` to `redis.main.existingSecretKeys.sentinelUrl`. - Updated default value `front.nginx.resources` from `{"requests":{"cpu":"200m","memory":"500Mi"}}` to `{"requests":{"cpu":"100m","memory":"200Mi"}}` ## 2024.6.0 vs 2024.5.0 **Updated:** - Added new task `background_validity_check` to `celeryWorkers.long.queues`. ## 2024.5.0 vs 2024.4.0 :::caution Upgrading to 2024.5 This release includes breaking changes. ::: **New:** - Introduce `externalSecrets.refreshInterval`option to give the ability to customize the refresh interval for external secrets. - Added `istio.gateway.enabled` parameter to be able to disable Istio Gateway handling when Istio is enabled. - Added `redis.main.existingSecretKeys.url` and `redis.main.existingSecretKeys.password`. - Added `redis.commitCache.existingSecretKeys.url` and `redis.commitCache.existingSecretKeys.password`. - Added `migration.labels` and `migration.podLabels` for migrations resources. **Updated:** - Replaced `postgresql.existingSecretKeys.tls` with `postgresql.tls.existingSecretKeys` and set the Default to `""` for - `password` instead of `POSTGRES_PASSWORD`. - `crt` instead of ``"pg_client.crt"`. - `key` instead of `"pg_client.key"`. - `caCrt` instead of `"pg_server.ca_crt"`. - Replaced `redis.main.existingSecretKeys.tls` with `redis.main.tls.existingSecretKeys` and set the Default values to `""` for - `crt` instead of ``"redis_client.crt"`. - `key` instead of `"redis_client.key"`. - `caCrt` instead of `"redis_server.ca_crt"`. - Replaced `redis.commitCache.existingSecretKeys.tls` with `redis.commitCache.tls.existingSecretKeys` and set the Default values to `""` for - `crt` instead of ``"redis_client.crt"`. - `key` instead of `"redis_client.key"`. - `caCrt` instead of `"redis_server.ca_crt"`. - Rename `celeryWorkers.realtime_ods` to `celeryWorkers.realtime-ods`. - Set the Default for `miscEncryption.existingSecretKeys` attributes to `""` for - `djangoSecretKey` instead of `"DJANGO_SECRET_KEY"`. - `dbEncryptionKeys` instead of `"ENCRYPTION_KEYS"`. - `x509Cert` instead of `"SP_X509_CERT"`. - `x509PrivateKey` instead of `"SP_PRIVATE_KEY"`. - Added `"existingSecret":"","existingSecretKeys":{"password":""}` in `onPrem.adminUser` offering the option to specify the admin password in a secret. - Rename Default value for `tls.customCa.existingSecretCaCertKey ` to `"ca.crt"` instead of `"custom-ca.pem"`. - Added `report` to `celeryWorkers.worker.queues`. **Removed:** - Removed `argoCd.enabled` originally used to inject Argo CD phase annotations in Kubernetes resources but, since Argo CD supports Helm hooks annotations by mapping them onto its own hook annotations, it is not used anymore in 2024.5.0. ## 2024.4.0 (Required) vs 2024.3.0 **New:** - Added `commonLabels` to add custom labels to differentiate multiple GitGuardian deployments within the same Kubernetes cluster. - Introduce `ephemeralStorage` option for all `celeryWorkers` to support [Generic Ephemeral Inline Volumes](./scaling#generic-ephemeral-inline-volumes). - Introduced new `celeryWorkers.realtime-ods` worker for Other Data Sources (ODS) real time scanning. **Updated:** - Modified `celeryWorkers.worker.queues` and moved `realtime_ods,realtime_retry_ods` tasks into new `celeryWorkers.realtime-ods.queue`. ## 2024.3.0 vs 2024.2.0 **Updated:** - Decreased the default value of `celeryWorkers.scanners_ods.replicas` from `2` to `0`. ## 2024.2.0 vs 2024.1.0 **New:** - Added `redis.main.sentinel` configuration options for managing Redis Sentinel settings. - Introduced new settings for `redis.main.existingSecretKeys.sentinel.url` and `redis.main.existingSecretKeys.sentinel.password`. - Added `miscEncryption.dbEncryptionKeys` and `miscEncryption.existingSecretKeys.dbEncryptionKeys` for database encryption key management. - Introduced new `celeryWorkers.scanners_ods` worker for Other Data Sources (ODS) scanning. **Removed:** - Removed `observability.exporters.celeryExporter`. ## 2024.1.0 (Required) vs 2023.12.0 **New:** - Expanded `nodeSelector` and `tolerations` settings across multiple services: `front.nginx`, `webapps.internal_api`, `webapps.internal_api_long`, `webapps.public_api`, `webapps.hook`, `webapps.app_exporter`, `celeryWorkers.worker`, `celeryWorkers.email`, `celeryWorkers.scanners`, and `celeryWorkers.long`. - New `replicated.isAirgap` setting to manage air-gapped environments. - Introduced `tls.customCa.image` configuration for custom CA management. - Added new settings related to Kubernetes Roles and RoleBindings: `rbac.enabled`, `serviceAccount.create`, `serviceAccount.name`, `migration.serviceAccount.create`, and `migration.serviceAccount.name`. **Updated:** - Added new tasks `realtime_ods,realtime_retry_ods` to `celeryWorkers.worker.queues` to support additional task types. - Enabled `experimental.chainguard` by default, changing from `false` to `true`, to utilize Chainguard images for backend and frontend services. --- ## Helm Chart Values 2025.10.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2025.10.0](https://img.shields.io/badge/Version-2025.10.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webapps (*object*) | Backend deployments configuration | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api.nodeSelector (*object*) | Node selection constraint for Internal APIDefault: `{}` | | webapps.internal_api.tolerations (*list*) | Schedule Internal API pods with matching taintsDefault: `[]` | | webapps.internal_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api_long.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api_long.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api_long.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api_long.nodeSelector (*object*) | Node selection constraint for Internal long APIDefault: `{}` | | webapps.internal_api_long.tolerations (*list*) | Schedule Internal long API pods with matching taintsDefault: `[]` | | webapps.internal_api_long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api_long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.public_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.public_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.public_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.public_api.nodeSelector (*object*) | Node selection constraint for Public APIDefault: `{}` | | webapps.public_api.tolerations (*list*) | Schedule Public API pods with matching taintsDefault: `[]` | | webapps.public_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.public_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.hook.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.hook.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.hook.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.hook.nodeSelector (*object*) | Node selection constraint for HookDefault: `{}` | | webapps.hook.tolerations (*list*) | Schedule Hook pods with matching taintsDefault: `[]` | | webapps.hook.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.hook.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.app_exporter.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.app_exporter.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.app_exporter.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.app_exporter.nodeSelector (*object*) | Node selection constraint for App ExporterDefault: `{}` | | webapps.app_exporter.tolerations (*list*) | Schedule App Exporter pods with matching taintsDefault: `[]` | | webapps.app_exporter.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.app_exporter.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.worker.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.worker.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.worker.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.worker.nodeSelector (*object*) | Node selection constraint for Default WorkerDefault: `{}` | | celeryWorkers.worker.tolerations (*list*) | Schedule Default Worker pods with matching taintsDefault: `[]` | | celeryWorkers.worker.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.worker.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.worker.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.email.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.email.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.email.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.email.nodeSelector (*object*) | Node selection constraint for Email WorkerDefault: `{}` | | celeryWorkers.email.tolerations (*list*) | Schedule Email Worker pods with matching taintsDefault: `[]` | | celeryWorkers.email.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.email.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.email.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.scanners.nodeSelector (*object*) | Node selection constraint for Scanner WorkerDefault: `{}` | | celeryWorkers.scanners.tolerations (*list*) | Schedule Scanner Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workers We want to let the long tasks terminate before they are killed (24h timeout)Default: `"celery_long,background_validity_check,automatic_severities"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long.autoscaling.minReplicas (*int*) | HPA minReplicasDefault: `1` | | celeryWorkers.long.autoscaling.maxReplicas (*int*) | HPA maxReplicasDefault: `10` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"automatic_severities":10,"background_validity_check":10,"celery_long":10}` | | celeryWorkers.long.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long.ephemeralStorage (*object*) | Schedule Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods-highdisk.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.scanners-ods-highdisk.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods-highdisk.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods-highdisk.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods-highdisk.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.realtime-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.realtime-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.realtime-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.realtime-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.realtime-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.realtime-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.realtime-ods.ephemeralStorage (*object*) | Realtime ODS worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long-ods.ephemeralStorage (*object*) | Schedule Non-VCS Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods-io.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods-io.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods-io.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.long-ods-io.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods-io.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods-io.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.container-registries.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.container-registries.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.container-registries.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.container-registries.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.container-registries.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.container-registries.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.container-registries.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-slack.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-slack.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-slack.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.scanners-slack.nodeSelector (*object*) | Node selection constraint for Slack WorkerDefault: `{}` | | celeryWorkers.scanners-slack.tolerations (*list*) | Schedule Slack Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-slack.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-slack.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.ml-api-priority.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.ml-api-priority.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.ml-api-priority.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.ml-api-priority.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.9.0"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.0.3"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"6h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20251015"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.5.3"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Specifies the Loki retention delayDefault: `"168h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use new Ingress routes instead of legacy nginxDefault: `false` | --- ## Helm Chart Values 2025.11.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2025.11.0](https://img.shields.io/badge/Version-2025.11.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webapps (*object*) | Backend deployments configuration | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api.nodeSelector (*object*) | Node selection constraint for Internal APIDefault: `{}` | | webapps.internal_api.tolerations (*list*) | Schedule Internal API pods with matching taintsDefault: `[]` | | webapps.internal_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api_long.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api_long.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api_long.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api_long.nodeSelector (*object*) | Node selection constraint for Internal long APIDefault: `{}` | | webapps.internal_api_long.tolerations (*list*) | Schedule Internal long API pods with matching taintsDefault: `[]` | | webapps.internal_api_long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api_long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.public_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.public_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.public_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.public_api.nodeSelector (*object*) | Node selection constraint for Public APIDefault: `{}` | | webapps.public_api.tolerations (*list*) | Schedule Public API pods with matching taintsDefault: `[]` | | webapps.public_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.public_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.hook.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.hook.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.hook.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.hook.nodeSelector (*object*) | Node selection constraint for HookDefault: `{}` | | webapps.hook.tolerations (*list*) | Schedule Hook pods with matching taintsDefault: `[]` | | webapps.hook.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.hook.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.app_exporter.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.app_exporter.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.app_exporter.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.app_exporter.nodeSelector (*object*) | Node selection constraint for App ExporterDefault: `{}` | | webapps.app_exporter.tolerations (*list*) | Schedule App Exporter pods with matching taintsDefault: `[]` | | webapps.app_exporter.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.app_exporter.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.worker.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.worker.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.worker.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.worker.nodeSelector (*object*) | Node selection constraint for Default WorkerDefault: `{}` | | celeryWorkers.worker.tolerations (*list*) | Schedule Default Worker pods with matching taintsDefault: `[]` | | celeryWorkers.worker.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.worker.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.worker.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.email.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.email.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.email.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.email.nodeSelector (*object*) | Node selection constraint for Email WorkerDefault: `{}` | | celeryWorkers.email.tolerations (*list*) | Schedule Email Worker pods with matching taintsDefault: `[]` | | celeryWorkers.email.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.email.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.email.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.scanners.nodeSelector (*object*) | Node selection constraint for Scanner WorkerDefault: `{}` | | celeryWorkers.scanners.tolerations (*list*) | Schedule Scanner Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workers We want to let the long tasks terminate before they are killed (24h timeout)Default: `"celery_long,background_validity_check,automatic_severities,update_sources_state,nhi_ingestion"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long.autoscaling.minReplicas (*int*) | HPA minReplicasDefault: `1` | | celeryWorkers.long.autoscaling.maxReplicas (*int*) | HPA maxReplicasDefault: `10` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"automatic_severities":10,"background_validity_check":10,"celery_long":10,"nhi_ingestion":10,"update_sources_state":10}` | | celeryWorkers.long.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long.ephemeralStorage (*object*) | Schedule Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods-highdisk.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.scanners-ods-highdisk.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods-highdisk.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods-highdisk.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods-highdisk.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.realtime-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.realtime-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.realtime-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.realtime-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.realtime-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.realtime-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.realtime-ods.ephemeralStorage (*object*) | Realtime ODS worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long-ods.ephemeralStorage (*object*) | Schedule Non-VCS Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods-io.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods-io.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods-io.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.long-ods-io.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods-io.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods-io.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.container-registries.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.container-registries.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.container-registries.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.container-registries.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.container-registries.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.container-registries.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.container-registries.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-slack.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-slack.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-slack.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.scanners-slack.nodeSelector (*object*) | Node selection constraint for Slack WorkerDefault: `{}` | | celeryWorkers.scanners-slack.tolerations (*list*) | Schedule Slack Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-slack.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-slack.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.ml-api-priority.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.ml-api-priority.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.ml-api-priority.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.ml-api-priority.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.enabled (*bool*) | Controls the RBAC from the Replicated SDKDefault: `true` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.11.1"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.0.3"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"12h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20251015"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.5.8"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Specifies the Loki retention delayDefault: `"168h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use new Ingress routes instead of legacy nginxDefault: `false` | --- ## Helm Chart Values 2025.12.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2025.12.0](https://img.shields.io/badge/Version-2025.12.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames to be served by nginxDefault: `[]` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webapps (*object*) | Backend deployments configuration | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api.nodeSelector (*object*) | Node selection constraint for Internal APIDefault: `{}` | | webapps.internal_api.tolerations (*list*) | Schedule Internal API pods with matching taintsDefault: `[]` | | webapps.internal_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api_long.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api_long.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api_long.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api_long.nodeSelector (*object*) | Node selection constraint for Internal long APIDefault: `{}` | | webapps.internal_api_long.tolerations (*list*) | Schedule Internal long API pods with matching taintsDefault: `[]` | | webapps.internal_api_long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api_long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.public_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.public_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.public_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.public_api.nodeSelector (*object*) | Node selection constraint for Public APIDefault: `{}` | | webapps.public_api.tolerations (*list*) | Schedule Public API pods with matching taintsDefault: `[]` | | webapps.public_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.public_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.hook.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.hook.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.hook.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.hook.nodeSelector (*object*) | Node selection constraint for HookDefault: `{}` | | webapps.hook.tolerations (*list*) | Schedule Hook pods with matching taintsDefault: `[]` | | webapps.hook.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.hook.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.app_exporter.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.app_exporter.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.app_exporter.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.app_exporter.nodeSelector (*object*) | Node selection constraint for App ExporterDefault: `{}` | | webapps.app_exporter.tolerations (*list*) | Schedule App Exporter pods with matching taintsDefault: `[]` | | webapps.app_exporter.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.app_exporter.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.worker.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.worker.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.worker.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.worker.nodeSelector (*object*) | Node selection constraint for Default WorkerDefault: `{}` | | celeryWorkers.worker.tolerations (*list*) | Schedule Default Worker pods with matching taintsDefault: `[]` | | celeryWorkers.worker.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.worker.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.worker.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.email.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.email.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.email.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.email.nodeSelector (*object*) | Node selection constraint for Email WorkerDefault: `{}` | | celeryWorkers.email.tolerations (*list*) | Schedule Email Worker pods with matching taintsDefault: `[]` | | celeryWorkers.email.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.email.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.email.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.scanners.nodeSelector (*object*) | Node selection constraint for Scanner WorkerDefault: `{}` | | celeryWorkers.scanners.tolerations (*list*) | Schedule Scanner Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workers We want to let the long tasks terminate before they are killed (24h timeout)Default: `"celery_long,background_validity_check,automatic_severities,update_sources_state,nhi_ingestion"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long.autoscaling.minReplicas (*int*) | HPA minReplicasDefault: `1` | | celeryWorkers.long.autoscaling.maxReplicas (*int*) | HPA maxReplicasDefault: `10` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"automatic_severities":10,"background_validity_check":10,"celery_long":10,"nhi_ingestion":10,"update_sources_state":10}` | | celeryWorkers.long.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long.ephemeralStorage (*object*) | Schedule Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods-highdisk.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.scanners-ods-highdisk.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods-highdisk.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods-highdisk.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods-highdisk.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.realtime-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.realtime-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.realtime-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.realtime-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.realtime-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.realtime-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.realtime-ods.ephemeralStorage (*object*) | Realtime ODS worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long-ods.ephemeralStorage (*object*) | Schedule Non-VCS Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods-io.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods-io.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods-io.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.long-ods-io.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods-io.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods-io.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.container-registries.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.container-registries.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.container-registries.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.container-registries.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.container-registries.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.container-registries.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.container-registries.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-slack.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-slack.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-slack.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.scanners-slack.nodeSelector (*object*) | Node selection constraint for Slack WorkerDefault: `{}` | | celeryWorkers.scanners-slack.tolerations (*list*) | Schedule Slack Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-slack.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-slack.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.business-contribution.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.business-contribution.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.business-contribution.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.business-contribution.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.business-contribution.nodeSelector (*object*) | Node selection constraint for Business Contrib WorkerDefault: `{}` | | celeryWorkers.business-contribution.tolerations (*list*) | Schedule Business Contrib Worker pods with matching taintsDefault: `[]` | | celeryWorkers.business-contribution.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.business-contribution.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.ml-api-priority.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.ml-api-priority.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.ml-api-priority.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.ml-api-priority.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp Analytics (in beta)Default: `{"enabled":false,"labels":{},"nodeSelector":{},"podAnnotations":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `false` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.enabled (*bool*) | Controls the RBAC from the Replicated SDKDefault: `true` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.12.1"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.0.3"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"12h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20251015"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.6.2"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Specifies the Loki retention delayDefault: `"168h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2025.7.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2025.7.0](https://img.shields.io/badge/Version-2025.7.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | postgresql.plugins.pgvector.enabled (*bool*) | Enable pgvector pluginDefault: `true` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webapps (*object*) | Backend deployments configuration | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api.nodeSelector (*object*) | Node selection constraint for Internal APIDefault: `{}` | | webapps.internal_api.tolerations (*list*) | Schedule Internal API pods with matching taintsDefault: `[]` | | webapps.internal_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api_long.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api_long.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api_long.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api_long.nodeSelector (*object*) | Node selection constraint for Internal long APIDefault: `{}` | | webapps.internal_api_long.tolerations (*list*) | Schedule Internal long API pods with matching taintsDefault: `[]` | | webapps.internal_api_long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api_long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.public_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.public_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.public_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.public_api.nodeSelector (*object*) | Node selection constraint for Public APIDefault: `{}` | | webapps.public_api.tolerations (*list*) | Schedule Public API pods with matching taintsDefault: `[]` | | webapps.public_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.public_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.hook.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.hook.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.hook.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.hook.nodeSelector (*object*) | Node selection constraint for HookDefault: `{}` | | webapps.hook.tolerations (*list*) | Schedule Hook pods with matching taintsDefault: `[]` | | webapps.hook.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.hook.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.app_exporter.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.app_exporter.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.app_exporter.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.app_exporter.nodeSelector (*object*) | Node selection constraint for App ExporterDefault: `{}` | | webapps.app_exporter.tolerations (*list*) | Schedule App Exporter pods with matching taintsDefault: `[]` | | webapps.app_exporter.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.app_exporter.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.worker.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.worker.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.worker.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.worker.nodeSelector (*object*) | Node selection constraint for Default WorkerDefault: `{}` | | celeryWorkers.worker.tolerations (*list*) | Schedule Default Worker pods with matching taintsDefault: `[]` | | celeryWorkers.worker.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.worker.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.worker.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.email.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.email.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.email.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.email.nodeSelector (*object*) | Node selection constraint for Email WorkerDefault: `{}` | | celeryWorkers.email.tolerations (*list*) | Schedule Email Worker pods with matching taintsDefault: `[]` | | celeryWorkers.email.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.email.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.email.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.scanners.nodeSelector (*object*) | Node selection constraint for Scanner WorkerDefault: `{}` | | celeryWorkers.scanners.tolerations (*list*) | Schedule Scanner Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workersDefault: `"celery_long,background_validity_check"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long.autoscaling.minReplicas (*int*) | HPA minReplicasDefault: `1` | | celeryWorkers.long.autoscaling.maxReplicas (*int*) | HPA maxReplicasDefault: `10` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"background_validity_check":10,"celery_long":10}` | | celeryWorkers.long.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long.ephemeralStorage (*object*) | Schedule Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.realtime-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.realtime-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.realtime-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.realtime-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.realtime-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.realtime-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.realtime-ods.ephemeralStorage (*object*) | Realtime ODS worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long-ods.ephemeralStorage (*object*) | Schedule Non-VCS Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods-io.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods-io.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods-io.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.long-ods-io.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods-io.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods-io.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.container-registries.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.container-registries.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.container-registries.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.container-registries.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.container-registries.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.container-registries.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.container-registries.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.ml-api-priority.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.ml-api-priority.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.ml-api-priority.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.ml-api-priority.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | beat (*object*) | Asynchronous tasks scheduler | | beat.replicas (*int*) | Asynchronous tasks scheduler replicas countDefault: `1` | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.7.1"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"seccompProfile":{"type":"RuntimeDefault"}}` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.0.3"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"3d"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio-bitnami"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20250524"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.pullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.enabled (*bool*) | Enable pod Security Context for MinIODefault: `true` | | loki-minio.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.enabled (*bool*) | Enable container Security Context for MinIODefault: `true` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.5.1"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Specifies the Loki retention delayDefault: `"168h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use new Ingress routes instead of legacy nginxDefault: `false` | --- ## Helm Chart Values 2025.8.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2025.8.0](https://img.shields.io/badge/Version-2025.8.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | postgresql.plugins.pgvector.enabled (*bool*) | Enable pgvector pluginDefault: `true` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webapps (*object*) | Backend deployments configuration | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api.nodeSelector (*object*) | Node selection constraint for Internal APIDefault: `{}` | | webapps.internal_api.tolerations (*list*) | Schedule Internal API pods with matching taintsDefault: `[]` | | webapps.internal_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api_long.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api_long.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api_long.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api_long.nodeSelector (*object*) | Node selection constraint for Internal long APIDefault: `{}` | | webapps.internal_api_long.tolerations (*list*) | Schedule Internal long API pods with matching taintsDefault: `[]` | | webapps.internal_api_long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api_long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.public_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.public_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.public_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.public_api.nodeSelector (*object*) | Node selection constraint for Public APIDefault: `{}` | | webapps.public_api.tolerations (*list*) | Schedule Public API pods with matching taintsDefault: `[]` | | webapps.public_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.public_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.hook.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.hook.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.hook.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.hook.nodeSelector (*object*) | Node selection constraint for HookDefault: `{}` | | webapps.hook.tolerations (*list*) | Schedule Hook pods with matching taintsDefault: `[]` | | webapps.hook.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.hook.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.app_exporter.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.app_exporter.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.app_exporter.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.app_exporter.nodeSelector (*object*) | Node selection constraint for App ExporterDefault: `{}` | | webapps.app_exporter.tolerations (*list*) | Schedule App Exporter pods with matching taintsDefault: `[]` | | webapps.app_exporter.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.app_exporter.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.worker.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.worker.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.worker.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.worker.nodeSelector (*object*) | Node selection constraint for Default WorkerDefault: `{}` | | celeryWorkers.worker.tolerations (*list*) | Schedule Default Worker pods with matching taintsDefault: `[]` | | celeryWorkers.worker.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.worker.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.worker.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.email.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.email.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.email.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.email.nodeSelector (*object*) | Node selection constraint for Email WorkerDefault: `{}` | | celeryWorkers.email.tolerations (*list*) | Schedule Email Worker pods with matching taintsDefault: `[]` | | celeryWorkers.email.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.email.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.email.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.scanners.nodeSelector (*object*) | Node selection constraint for Scanner WorkerDefault: `{}` | | celeryWorkers.scanners.tolerations (*list*) | Schedule Scanner Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workersDefault: `"celery_long,background_validity_check"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long.autoscaling.minReplicas (*int*) | HPA minReplicasDefault: `1` | | celeryWorkers.long.autoscaling.maxReplicas (*int*) | HPA maxReplicasDefault: `10` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"background_validity_check":10,"celery_long":10}` | | celeryWorkers.long.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long.ephemeralStorage (*object*) | Schedule Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.realtime-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.realtime-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.realtime-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.realtime-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.realtime-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.realtime-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.realtime-ods.ephemeralStorage (*object*) | Realtime ODS worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long-ods.ephemeralStorage (*object*) | Schedule Non-VCS Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods-io.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods-io.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods-io.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.long-ods-io.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods-io.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods-io.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.container-registries.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.container-registries.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.container-registries.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.container-registries.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.container-registries.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.container-registries.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.container-registries.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-slack.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-slack.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-slack.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.scanners-slack.nodeSelector (*object*) | Node selection constraint for Slack WorkerDefault: `{}` | | celeryWorkers.scanners-slack.tolerations (*list*) | Schedule Slack Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-slack.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-slack.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.ml-api-priority.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.ml-api-priority.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.ml-api-priority.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.ml-api-priority.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.8.0"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"seccompProfile":{"type":"RuntimeDefault"}}` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-cluster-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.0.3"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"3d"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio-bitnami"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20250723"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.pullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.enabled (*bool*) | Enable pod Security Context for MinIODefault: `true` | | loki-minio.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.enabled (*bool*) | Enable container Security Context for MinIODefault: `true` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.5.3"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Specifies the Loki retention delayDefault: `"168h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use new Ingress routes instead of legacy nginxDefault: `false` | --- ## Helm Chart Values 2025.9.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2025.9.0](https://img.shields.io/badge/Version-2025.9.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webapps (*object*) | Backend deployments configuration | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api.nodeSelector (*object*) | Node selection constraint for Internal APIDefault: `{}` | | webapps.internal_api.tolerations (*list*) | Schedule Internal API pods with matching taintsDefault: `[]` | | webapps.internal_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.internal_api_long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.internal_api_long.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.internal_api_long.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.internal_api_long.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.internal_api_long.nodeSelector (*object*) | Node selection constraint for Internal long APIDefault: `{}` | | webapps.internal_api_long.tolerations (*list*) | Schedule Internal long API pods with matching taintsDefault: `[]` | | webapps.internal_api_long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api_long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.public_api.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.public_api.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.public_api.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.public_api.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.public_api.nodeSelector (*object*) | Node selection constraint for Public APIDefault: `{}` | | webapps.public_api.tolerations (*list*) | Schedule Public API pods with matching taintsDefault: `[]` | | webapps.public_api.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.public_api.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.hook.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.hook.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.hook.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.hook.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.hook.nodeSelector (*object*) | Node selection constraint for HookDefault: `{}` | | webapps.hook.tolerations (*list*) | Schedule Hook pods with matching taintsDefault: `[]` | | webapps.hook.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.hook.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webapps.app_exporter.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webapps.app_exporter.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webapps.app_exporter.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webapps.app_exporter.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webapps.app_exporter.nodeSelector (*object*) | Node selection constraint for App ExporterDefault: `{}` | | webapps.app_exporter.tolerations (*list*) | Schedule App Exporter pods with matching taintsDefault: `[]` | | webapps.app_exporter.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.app_exporter.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.worker.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.worker.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.worker.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.worker.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.worker.nodeSelector (*object*) | Node selection constraint for Default WorkerDefault: `{}` | | celeryWorkers.worker.tolerations (*list*) | Schedule Default Worker pods with matching taintsDefault: `[]` | | celeryWorkers.worker.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.worker.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.worker.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.email.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.email.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.email.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.email.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.email.nodeSelector (*object*) | Node selection constraint for Email WorkerDefault: `{}` | | celeryWorkers.email.tolerations (*list*) | Schedule Email Worker pods with matching taintsDefault: `[]` | | celeryWorkers.email.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.email.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.email.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.scanners.nodeSelector (*object*) | Node selection constraint for Scanner WorkerDefault: `{}` | | celeryWorkers.scanners.tolerations (*list*) | Schedule Scanner Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners.ephemeralStorage (*object*) | Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workersDefault: `"celery_long,background_validity_check"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long.autoscaling.minReplicas (*int*) | HPA minReplicasDefault: `1` | | celeryWorkers.long.autoscaling.maxReplicas (*int*) | HPA maxReplicasDefault: `10` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"background_validity_check":10,"celery_long":10}` | | celeryWorkers.long.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long.ephemeralStorage (*object*) | Schedule Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-ods-highdisk.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.scanners-ods-highdisk.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.scanners-ods-highdisk.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-ods-highdisk.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-ods-highdisk.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-ods-highdisk.ephemeralStorage (*object*) | Non-VCS Historical Scan worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.realtime-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.realtime-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.realtime-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.realtime-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.realtime-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.realtime-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.realtime-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.realtime-ods.ephemeralStorage (*object*) | Realtime ODS worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.long-ods.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.long-ods.ephemeralStorage (*object*) | Schedule Non-VCS Long Worker ephemeral storageDefault: `{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.long-ods-io.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.long-ods-io.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.long-ods-io.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.long-ods-io.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.long-ods-io.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.long-ods-io.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.container-registries.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.container-registries.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.container-registries.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.container-registries.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.container-registries.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.container-registries.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.container-registries.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.scanners-slack.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.scanners-slack.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.scanners-slack.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.scanners-slack.nodeSelector (*object*) | Node selection constraint for Slack WorkerDefault: `{}` | | celeryWorkers.scanners-slack.tolerations (*list*) | Schedule Slack Worker pods with matching taintsDefault: `[]` | | celeryWorkers.scanners-slack.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.scanners-slack.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | celeryWorkers.ml-api-priority.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | celeryWorkers.ml-api-priority.autoscaling.keda.idleReplicaCount (*int*) | Having this to zero means it can downscale to zero in some case. To disable this, set it's value to ~.Default: `0` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.ml-api-priority.nodeSelector (*object*) | Node selection constraint for Long WorkerDefault: `{}` | | celeryWorkers.ml-api-priority.tolerations (*list*) | Schedule Long Worker pods with matching taintsDefault: `[]` | | celeryWorkers.ml-api-priority.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | celeryWorkers.ml-api-priority.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engineDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.8.0"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"seccompProfile":{"type":"RuntimeDefault"}}` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.0.3"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"6h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio-bitnami"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20250723"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.pullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.enabled (*bool*) | Enable pod Security Context for MinIODefault: `true` | | loki-minio.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.enabled (*bool*) | Enable container Security Context for MinIODefault: `true` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.5.3"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Specifies the Loki retention delayDefault: `"168h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use new Ingress routes instead of legacy nginxDefault: `false` | --- ## Helm Chart Values 2026.1.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.1.0](https://img.shields.io/badge/Version-2026.1.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames to be served by nginxDefault: `[]` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | WebApps default deployments configuration, Webapps can override any of these values in their own section | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* /api/v1/accounts/\\d+/report/"` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers. Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":10,"initialDelaySeconds":20,"periodSeconds":30,"timeoutSeconds":15},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workers We want to let the long tasks terminate before they are killed (24h timeout)Default: `"celery_long,background_validity_check,automatic_severities,update_sources_state,nhi_ingestion,core_long"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"automatic_severities":10,"background_validity_check":10,"celery_long":10,"nhi_ingestion":10,"update_sources_state":10}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"enabled":false,"labels":{},"nodeSelector":{},"podAnnotations":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `false` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.enabled (*bool*) | Controls the RBAC from the Replicated SDKDefault: `true` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.12.2"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.2"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20251015"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.6.3"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Specifies the Loki retention delayDefault: `"168h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2026.2.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.2.0](https://img.shields.io/badge/Version-2026.2.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames to be served by nginxDefault: `[]` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | Backend deployments configuration | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* /api/v1/accounts/\\d+/report/"` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":10,"initialDelaySeconds":20,"periodSeconds":30,"timeoutSeconds":15},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default,sources_default,incidents_default,individual_validity_check"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"honeytoken":10,"individual_validity_check":10,"realtime":10,"realtime_retry":10,"reports":10}` | | celeryWorkers.check-runs.queues (*string*) | Queues consumed by Check Run workersDefault: `"check_run"` | | celeryWorkers.check-runs.replicas (*int*) | Check Run workers replicas countDefault: `0` | | celeryWorkers.check-runs.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan,code_fixing"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workers We want to let the long tasks terminate before they are killed (24h timeout)Default: `"celery_long,background_validity_check,automatic_severities,update_sources_state,nhi_ingestion,hmsl,core_long,sources_long,incidents_long"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"automatic_severities":10,"background_validity_check":10,"celery_long":10,"nhi_ingestion":10,"update_sources_state":10}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"enabled":false,"labels":{},"nodeSelector":{},"podAnnotations":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `false` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.enabled (*bool*) | Controls the RBAC from the Replicated SDKDefault: `true` | | replicated.replicaCount (*int*) | Number of Replicated SDK replicasDefault: `2` | | replicated.highAvailability.podAntiAffinityPreset (*string*) | antiAffinity for Replicated SDK, applies only if replicaCount > 1Default: `"soft"` | | replicated.highAvailability.podDisruptionBudget.enabled (*bool*) | Enable podDisruptionBudget for Replicated SDKDefault: `true` | | replicated.highAvailability.podDisruptionBudget.minAvailable (*int*) | podDisruptionBudget minAvailable for Replicated SDKDefault: `1` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.16.0"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"latest"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"latest"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | hookMethod (*string*) | Hook Method (helm/argocd/none)Default: `"helm"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.2"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20251015"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.6.5"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Delay after which chunks will be fully deleted during retention.Default: `"2h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2026.3.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.3.0](https://img.shields.io/badge/Version-2026.3.0-informational?style=flat-square) | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"compatibility":{"openshift":{"adaptSecurityContext":"auto"}},"fipsEnabled":false,"image":{"registry":null},"imagePullSecrets":[],"imageRegistry":"","priorityClassName":""}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.compatibility.openshift.adaptSecurityContext (*string*) | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)Default: `"auto"` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames to be served by nginxDefault: `[]` | | commonLabels (*object*) | Custom labels to add to all resources (includes commonMatchLabels) Format: `name: value`Default: `{}` | | commonTolerations (*list*) | Common tolerations applied to all workloadsDefault: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | externalSecrets.enabled (*bool*) | Enable [External secrets](https://external-secrets.io)Default: `false` | | externalSecrets.refreshInterval (*string*) | Specify the refreshInterval for externalSecretsDefault: `"15s"` | | externalSecrets.path (*string*) | External Secret PathDefault: `""` | | externalSecrets.secretStoreRef.kind (*string*) | [External secrets](https://external-secrets.io) ClassDefault: `"SecretStore"` | | externalSecrets.secretStoreRef.name (*string*) | [External secrets](https://external-secrets.io) NameDefault: `"vault"` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"prometheus":{}}}` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | Backend deployments configuration | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* /api/v1/accounts/\\d+/report/"` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":30,"heartbeatThreshold":120,"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":5},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default,sources_default,incidents_default,individual_validity_check"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"core_default":10,"honeytoken":10,"incidents_default":10,"individual_validity_check":10,"realtime":10,"realtime_retry":10,"reports":10,"sources_default":10}` | | celeryWorkers.check-runs.queues (*string*) | Queues consumed by Check Run workersDefault: `"check_run"` | | celeryWorkers.check-runs.replicas (*int*) | Check Run workers replicas countDefault: `0` | | celeryWorkers.check-runs.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan,code_fixing"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"code_fixing":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workers We want to let the long tasks terminate before they are killed (24h timeout)Default: `"celery_long,background_validity_check,automatic_severities,update_sources_state,nhi_ingestion,hmsl,core_long,sources_long,incidents_long,ml_backpopulate"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"automatic_severities":10,"background_validity_check":10,"celery_long":10,"core_long":10,"hmsl":10,"incidents_long":10,"ml_backpopulate":10,"nhi_ingestion":10,"sources_long":10,"update_sources_state":10}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"enabled":false,"labels":{},"nodeSelector":{},"podAnnotations":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `false` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.enabled (*bool*) | Controls the RBAC from the Replicated SDKDefault: `true` | | replicated.replicaCount (*int*) | Number of Replicated SDK replicasDefault: `2` | | replicated.highAvailability.podAntiAffinityPreset (*string*) | antiAffinity for Replicated SDK, applies only if replicaCount > 1Default: `"soft"` | | replicated.highAvailability.podDisruptionBudget.enabled (*bool*) | Enable podDisruptionBudget for Replicated SDKDefault: `true` | | replicated.highAvailability.podDisruptionBudget.minAvailable (*int*) | podDisruptionBudget minAvailable for Replicated SDKDefault: `1` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.18.0"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `false` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | sentry.enabled (*bool*) | Enable Sentry tracingDefault: `false` | | sentry.apm.enabled (*bool*) | Enable Sentry APMDefault: `false` | | sentry.dsn (*string*) | Sentry Data Source Name URLDefault: `"https://sentry.io"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"5.3"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"5.3"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Use default network policy. If enabled, you must ensure ingress traffic is allowed to nginxDefault: `false` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | hookMethod (*string*) | Hook Method (helm/argocd/none)Default: `"helm"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.2"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy.enabled (*bool*) | Enable Network Policy for log CollectorDefault: `true` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20251015"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.6.7"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Delay after which chunks will be fully deleted during retention.Default: `"2h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2026.4.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.4.0](https://img.shields.io/badge/Version-2026.4.0-informational?style=flat-square) Here is the reference for the customizable values for Helm installation. See [Helm installation documentation](/self-hosting/installation/installation-existing-cluster-helm) for more information. ## Values | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"fipsEnabled":false,"image":{"imagePullPolicy":"IfNotPresent","registry":null},"imagePullSecrets":[],"imageRegistry":"","labels":{},"nodeSelector":{},"priorityClassName":"","tolerations":[]}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | global.labels (*object*) | Common labels to add to all resources Format: `name: value`Default: `{}` | | global.tolerations (*list*) | Common tolerations applied to all workloads Example for ARM/Graviton nodes: tolerations: - key: graviton operator: ExistsDefault: `[]` | | global.nodeSelector (*object*) | Global node selector applied to all pods (component-level nodeSelector takes full precedence)Default: `{}` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames to be served by nginxDefault: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/16/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"additionalPromqlLabelSelectors":"","prometheus":{}}}` | | autoscaling.keda.additionalPromqlLabelSelectors (*string*) | Optional comma-terminated PromQL label selectors inserted at the start of every `{` in built-in KEDA Prometheus queries when your metrics need extra matchers (e.g. `cluster="prod",`). Leave empty to keep the default queries.Default: `""` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | Backend deployments configuration | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* /api/v1/accounts/\\d+/report/"` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":30,"heartbeatThreshold":120,"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":5},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default,sources_default,incidents_default,individual_validity_check"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"core_default":10,"honeytoken":10,"incidents_default":10,"individual_validity_check":10,"realtime":10,"realtime_retry":10,"reports":10,"sources_default":10}` | | celeryWorkers.check-runs.queues (*string*) | Queues consumed by Check Run workersDefault: `"check_run"` | | celeryWorkers.check-runs.replicas (*int*) | Check Run workers replicas countDefault: `0` | | celeryWorkers.check-runs.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan,code_fixing"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"code_fixing":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workers We want to let the long tasks terminate before they are killed (24h timeout)Default: `"celery_long,background_validity_check,automatic_severities,update_sources_state,nhi_ingestion,hmsl,core_long,sources_long,incidents_long,ml_backpopulate"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"automatic_severities":10,"background_validity_check":10,"celery_long":10,"core_long":10,"hmsl":10,"incidents_long":10,"ml_backpopulate":10,"nhi_ingestion":10,"sources_long":10,"update_sources_state":10}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"enabled":false,"labels":{},"nodeSelector":{},"podAnnotations":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `false` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.mode (*string*) | Controls the RBAC mode for the Replicated SDK. - `full`: default, grants all permissions required by the SDK (get/list/watch on core resources, create/update secrets) - `minimal`: read-only permissions scoped to specific resource names. Some SDK features (e.g. status informers, custom metrics reporting) may not work. Reserved for environments with strict RBAC policies that prohibit runtime secret creation and broad resource access. - `disabled`: no Role or RoleBinding created for the SDK. The ServiceAccount is still created.Default: `"full"` | | replicated.replicaCount (*int*) | Number of Replicated SDK replicasDefault: `2` | | replicated.highAvailability.podAntiAffinityPreset (*string*) | antiAffinity for Replicated SDK, applies only if replicaCount > 1Default: `"soft"` | | replicated.highAvailability.podDisruptionBudget.enabled (*bool*) | Enable podDisruptionBudget for Replicated SDKDefault: `true` | | replicated.highAvailability.podDisruptionBudget.minAvailable (*int*) | podDisruptionBudget minAvailable for Replicated SDKDefault: `1` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.19.1"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.enabled (*bool*) | Enable/Disable Support Bundle related file generation entirelyDefault: `true` | | replicated.supportBundle.rbac.createPodRole (*bool*) | Add pod create/get/delete permissions to the GIM ServiceAccount role, allowing the application to spawn support-bundle pods. Set to false to prevent in-cluster support bundle generation entirely.Default: `true` | | replicated.supportBundle.rbac.serviceAccount.create (*bool*) | Default: `true` | | replicated.supportBundle.rbac.serviceAccount.existingServiceAccountName (*string*) | Use an existing ServiceAccount instead of creating one If set, this takes precedence over create: trueDefault: `""` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.admissionPolicy.enabled (*bool*) | Create a ValidatingAdmissionPolicy to restrict support bundle pod creation. Only effective when rbac.enabledDefault: `true` | | replicated.supportBundle.credentials.existingSecret (*string*) | Use an existing Secret instead of creating one. The secret must contain the keys: 'license-id' and 'upload-domain'. If set, the chart will not create the 'support-bundle-credentials' secret.Default: `""` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | replicated.supportBundle.resources (*object*) | Resource requests/limits for the support bundle pod containersDefault: `{"initContainer":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"mainContainer":{"limits":{"cpu":"100m","memory":"64Mi"},"requests":{"cpu":"10m","memory":"32Mi"}}}` | | replicated.supportBundle.resources.initContainer.requests.cpu (*string*) | CPU request for the bundle generation init containerDefault: `"100m"` | | replicated.supportBundle.resources.initContainer.requests.memory (*string*) | Memory request for the bundle generation init containerDefault: `"128Mi"` | | replicated.supportBundle.resources.initContainer.limits.cpu (*string*) | CPU limit for the bundle generation init containerDefault: `"500m"` | | replicated.supportBundle.resources.initContainer.limits.memory (*string*) | Memory limit for the bundle generation init containerDefault: `"512Mi"` | | replicated.supportBundle.resources.mainContainer.requests.cpu (*string*) | CPU request for the HTTP server containerDefault: `"10m"` | | replicated.supportBundle.resources.mainContainer.requests.memory (*string*) | Memory request for the HTTP server containerDefault: `"32Mi"` | | replicated.supportBundle.resources.mainContainer.limits.cpu (*string*) | CPU limit for the HTTP server containerDefault: `"100m"` | | replicated.supportBundle.resources.mainContainer.limits.memory (*string*) | Memory limit for the HTTP server containerDefault: `"64Mi"` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"5.3"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"5.3"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Enable network policies for GIM namespace isolation. When enabled, ingress from outside the GIM namespace is denied by default, and only explicitly allowed namespaces can reach GIM pods. Start with mode=dryrun to verify your config, then switch to mode=enforce.Default: `false` | | networkPolicy.mode (*string*) | Network policy mode dryrun: all policies are deployed but a temporary allow-all prevents any blocking — verify your config first enforce: the allow-all is removed and policies actively block unauthorized ingressDefault: `"dryrun"` | | networkPolicy.allowedNamespaces (*list*) | List of namespace names allowed to reach GIM pods Include your ingress controller namespace, monitoring, and any other namespace that needs access. Example: ["ingress-nginx", "monitoring"]Default: `[]` | | networkPolicy.extraPolicies (*list*) | Extra NetworkPolicy resources to create alongside the default ones Each entry is rendered as a full NetworkPolicy spec — full flexibility for custom rules.Default: `[]` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | hookMethod (*string*) | Hook Method (helm/argocd/none)Default: `"helm"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.4"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy (*DEPRECATED*) | Use `networkPolicy.enabled` instead. Will be removed in a future release.Default: `{"enabled":false}` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20260330"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.6.10"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Delay after which chunks will be fully deleted during retention.Default: `"2h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2026.5.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.5.0](https://img.shields.io/badge/Version-2026.5.0-informational?style=flat-square) Here is the reference for the customizable values for Helm installation. See [Helm installation documentation](/self-hosting/installation/installation-existing-cluster-helm) for more information. ## Values | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"fipsEnabled":false,"image":{"imagePullPolicy":"IfNotPresent","registry":null},"imagePullSecrets":[],"imageRegistry":"","labels":{},"nodeSelector":{},"priorityClassName":"","tolerations":[]}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | global.labels (*object*) | Common labels to add to all resources Format: `name: value`Default: `{}` | | global.tolerations (*list*) | Common tolerations applied to all workloads Example for ARM/Graviton nodes: tolerations: - key: graviton operator: ExistsDefault: `[]` | | global.nodeSelector (*object*) | Global node selector applied to all pods (component-level nodeSelector takes full precedence)Default: `{}` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames to be served by nginxDefault: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/18/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"additionalPromqlLabelSelectors":"","prometheus":{}}}` | | autoscaling.keda.additionalPromqlLabelSelectors (*string*) | Optional comma-terminated PromQL label selectors inserted at the start of every `{` in built-in KEDA Prometheus queries when your metrics need extra matchers (e.g. `cluster="prod",`). Leave empty to keep the default queries.Default: `""` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | Backend deployments configuration | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* /api/v1/accounts/\\d+/report/"` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":30,"heartbeatThreshold":120,"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":5},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default,sources_default,incidents_default,individual_validity_check"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"core_default":10,"honeytoken":10,"incidents_default":10,"individual_validity_check":10,"realtime":10,"realtime_retry":10,"reports":10,"sources_default":10}` | | celeryWorkers.check-runs.queues (*string*) | Queues consumed by Check Run workersDefault: `"check_run"` | | celeryWorkers.check-runs.replicas (*int*) | Check Run workers replicas countDefault: `0` | | celeryWorkers.check-runs.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan,code_fixing"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"code_fixing":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workersDefault: `"background_validity_check,update_sources_state,nhi_ingestion,endpoints,hmsl,core_long,sources_long,incidents_long,ml_backpopulate"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"background_validity_check":10,"core_long":10,"endpoints":10,"hmsl":10,"incidents_long":10,"ml_backpopulate":10,"nhi_ingestion":10,"sources_long":10,"update_sources_state":10}` | | celeryWorkers.automatic-severities.queues (*string*) | Queues consumed by automatic severities workersDefault: `"automatic_severities"` | | celeryWorkers.automatic-severities.replicas (*int*) | Automatic severities workers replicas countDefault: `1` | | celeryWorkers.automatic-severities.autoscaling.maxReplicas (*int*) | Autoscaling metrics thresholdDefault: `3` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"annotations":{},"enabled":true,"labels":{},"nodeSelector":{},"podAnnotations":{},"podLabels":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `true` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.annotations (*object*) | Additional annotationsDefault: `{}` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podLabels (*object*) | Additional pod labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.mode (*string*) | Controls the RBAC mode for the Replicated SDK. - `full`: default, grants all permissions required by the SDK (get/list/watch on core resources, create/update secrets) - `minimal`: read-only permissions scoped to specific resource names. Some SDK features (e.g. status informers, custom metrics reporting) may not work. Reserved for environments with strict RBAC policies that prohibit runtime secret creation and broad resource access. - `disabled`: no Role or RoleBinding created for the SDK. The ServiceAccount is still created.Default: `"full"` | | replicated.replicaCount (*int*) | Number of Replicated SDK replicasDefault: `2` | | replicated.highAvailability.podAntiAffinityPreset (*string*) | antiAffinity for Replicated SDK, applies only if replicaCount > 1Default: `"soft"` | | replicated.highAvailability.podDisruptionBudget.enabled (*bool*) | Enable podDisruptionBudget for Replicated SDKDefault: `true` | | replicated.highAvailability.podDisruptionBudget.minAvailable (*int*) | podDisruptionBudget minAvailable for Replicated SDKDefault: `1` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.19.4"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.enabled (*bool*) | Enable/Disable Support Bundle related file generation entirelyDefault: `true` | | replicated.supportBundle.rbac.createPodRole (*bool*) | Add pod create/get/delete permissions to the GIM ServiceAccount role, allowing the application to spawn support-bundle pods. Set to false to prevent in-cluster support bundle generation entirely.Default: `true` | | replicated.supportBundle.rbac.serviceAccount.create (*bool*) | Default: `true` | | replicated.supportBundle.rbac.serviceAccount.existingServiceAccountName (*string*) | Use an existing ServiceAccount instead of creating one If set, this takes precedence over create: trueDefault: `""` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.admissionPolicy.enabled (*bool*) | Create a ValidatingAdmissionPolicy to restrict support bundle pod creation. Only effective when rbac.enabledDefault: `true` | | replicated.supportBundle.credentials.existingSecret (*string*) | Use an existing Secret instead of creating one. The secret must contain the keys: 'license-id' and 'upload-domain'. If set, the chart will not create the 'support-bundle-credentials' secret.Default: `""` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | replicated.supportBundle.resources (*object*) | Resource requests/limits for the support bundle pod containersDefault: `{"initContainer":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"mainContainer":{"limits":{"cpu":"100m","memory":"64Mi"},"requests":{"cpu":"10m","memory":"32Mi"}}}` | | replicated.supportBundle.resources.initContainer.requests.cpu (*string*) | CPU request for the bundle generation init containerDefault: `"100m"` | | replicated.supportBundle.resources.initContainer.requests.memory (*string*) | Memory request for the bundle generation init containerDefault: `"128Mi"` | | replicated.supportBundle.resources.initContainer.limits.cpu (*string*) | CPU limit for the bundle generation init containerDefault: `"500m"` | | replicated.supportBundle.resources.initContainer.limits.memory (*string*) | Memory limit for the bundle generation init containerDefault: `"512Mi"` | | replicated.supportBundle.resources.mainContainer.requests.cpu (*string*) | CPU request for the HTTP server containerDefault: `"10m"` | | replicated.supportBundle.resources.mainContainer.requests.memory (*string*) | Memory request for the HTTP server containerDefault: `"32Mi"` | | replicated.supportBundle.resources.mainContainer.limits.cpu (*string*) | CPU limit for the HTTP server containerDefault: `"100m"` | | replicated.supportBundle.resources.mainContainer.limits.memory (*string*) | Memory limit for the HTTP server containerDefault: `"64Mi"` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.group (*string*) | [Cert-Manager](https://cert-manager.io) Issuer GroupDefault: `"cert-manager.io"` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"5.3"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"5.3"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Enable network policies for GIM namespace isolation. When enabled, ingress from outside the GIM namespace is denied by default, and only explicitly allowed namespaces can reach GIM pods. Start with mode=dryrun to verify your config, then switch to mode=enforce.Default: `false` | | networkPolicy.mode (*string*) | Network policy mode dryrun: all policies are deployed but a temporary allow-all prevents any blocking — verify your config first enforce: the allow-all is removed and policies actively block unauthorized ingressDefault: `"dryrun"` | | networkPolicy.allowedNamespaces (*list*) | List of namespace names allowed to reach GIM pods Include your ingress controller namespace, monitoring, and any other namespace that needs access. Example: ["ingress-nginx", "monitoring"]Default: `[]` | | networkPolicy.extraPolicies (*list*) | Extra NetworkPolicy resources to create alongside the default ones Each entry is rendered as a full NetworkPolicy spec — full flexibility for custom rules.Default: `[]` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.controller (*string*) | Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istioDefault: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path typeDefault: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the IngressDefault: `""` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | hookMethod (*string*) | Hook Method (helm/argocd/none)Default: `"helm"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.4"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy (*DEPRECATED*) | Use `networkPolicy.enabled` instead. Will be removed in a future release.Default: `{"enabled":false}` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | logCollector.supportBundle.logLevel (*string*) | Log levels for support-bundle Loki queries: `info` (all levels) or `error` (error|fatal|critical labels only). Requires JSON logs with `level`; streams without that label are omitted when set to `error`.Default: `"info"` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20260512"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.7.2"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Delay after which chunks will be fully deleted during retention.Default: `"2h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2026.6.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.6.0](https://img.shields.io/badge/Version-2026.6.0-informational?style=flat-square) Here is the reference for the customizable values for Helm installation. See [Helm installation documentation](/self-hosting/installation/installation-existing-cluster-helm) for more information. ## Values | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"fipsEnabled":false,"image":{"imagePullPolicy":"IfNotPresent","registry":null},"imagePullSecrets":[],"imageRegistry":"","labels":{},"nodeSelector":{},"priorityClassName":"","tolerations":[]}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | global.labels (*object*) | Common labels to add to all resources Format: `name: value`Default: `{}` | | global.tolerations (*list*) | Common tolerations applied to all workloads Example for ARM/Graviton nodes: tolerations: - key: graviton operator: ExistsDefault: `[]` | | global.nodeSelector (*object*) | Common nodeSelector for all componentsDefault: `{}` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames accepted by the routing layer. Only effective on `/api/v1/receiver` (the `hook` webapp skips Host validation); other paths still require the canonical `hostname` above.Default: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/18/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"additionalPromqlLabelSelectors":"","prometheus":{}}}` | | autoscaling.keda.additionalPromqlLabelSelectors (*string*) | Optional comma-terminated PromQL label selectors inserted at the start of every `{` in built-in KEDA Prometheus queries when your metrics need extra matchers (e.g. `cluster="prod",`). Leave empty to keep the default queries.Default: `""` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | Backend deployments configuration | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* \"(?x)\n /api/v1/accounts/\\d+/\n (\n report/\n | issues/\\d+/occurrences/\n | public-monitoring/perimeter/all-developers/\n )\n\""` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":30,"heartbeatThreshold":120,"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":5},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default,sources_default,incidents_default,individual_validity_check"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"core_default":10,"honeytoken":10,"incidents_default":10,"individual_validity_check":10,"realtime":10,"realtime_retry":10,"reports":10,"sources_default":10}` | | celeryWorkers.check-runs.queues (*string*) | Queues consumed by Check Run workersDefault: `"check_run"` | | celeryWorkers.check-runs.replicas (*int*) | Check Run workers replicas countDefault: `0` | | celeryWorkers.check-runs.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan,code_fixing"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"code_fixing":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.check-run-scanners.queues (*string*) | Queues consumed by scan-based check-run workersDefault: `"check_run_scan"` | | celeryWorkers.check-run-scanners.replicas (*int*) | Scan-based check-run workers replicas count (0 = fall back to scanners)Default: `0` | | celeryWorkers.check-run-scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run_scan":10}` | | celeryWorkers.premium-scanners-retry.queues (*string*) | Queues consumed by the VCS scan retry workersDefault: `"premium_repo_scan_retry"` | | celeryWorkers.premium-scanners-retry.replicas (*int*) | VCS scan retry workers replicas count (0 disables the dedicated worker)Default: `0` | | celeryWorkers.premium-scanners-retry.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"premium_repo_scan_retry":1}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workersDefault: `"background_validity_check,update_sources_state,nhi_ingestion,endpoints,hmsl,core_long,sources_long,incidents_long,ml_backpopulate"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"background_validity_check":10,"core_long":10,"endpoints":10,"hmsl":10,"incidents_long":10,"ml_backpopulate":10,"nhi_ingestion":10,"sources_long":10,"update_sources_state":10}` | | celeryWorkers.automatic-severities.queues (*string*) | Queues consumed by automatic severities workersDefault: `"automatic_severities"` | | celeryWorkers.automatic-severities.replicas (*int*) | Automatic severities workers replicas countDefault: `1` | | celeryWorkers.automatic-severities.autoscaling.maxReplicas (*int*) | Autoscaling metrics thresholdDefault: `3` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"annotations":{},"enabled":true,"labels":{},"nodeSelector":{},"podAnnotations":{},"podLabels":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `true` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.annotations (*object*) | Additional annotationsDefault: `{}` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podLabels (*object*) | Additional pod labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.mode (*string*) | Controls the RBAC mode for the Replicated SDK. - `full`: default, grants all permissions required by the SDK (get/list/watch on core resources, create/update secrets) - `minimal`: read-only permissions scoped to specific resource names. Some SDK features (e.g. status informers, custom metrics reporting) may not work. Reserved for environments with strict RBAC policies that prohibit runtime secret creation and broad resource access. - `disabled`: no Role or RoleBinding created for the SDK. The ServiceAccount is still created.Default: `"full"` | | replicated.replicaCount (*int*) | Number of Replicated SDK replicasDefault: `2` | | replicated.highAvailability.podAntiAffinityPreset (*string*) | antiAffinity for Replicated SDK, applies only if replicaCount > 1Default: `"soft"` | | replicated.highAvailability.podDisruptionBudget.enabled (*bool*) | Enable podDisruptionBudget for Replicated SDKDefault: `true` | | replicated.highAvailability.podDisruptionBudget.minAvailable (*int*) | podDisruptionBudget minAvailable for Replicated SDKDefault: `1` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.19.6"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.enabled (*bool*) | Enable/Disable Support Bundle related file generation entirelyDefault: `true` | | replicated.supportBundle.rbac.createPodRole (*bool*) | Add pod create/get/delete permissions to the GIM ServiceAccount role, allowing the application to spawn support-bundle pods. Set to false to prevent in-cluster support bundle generation entirely.Default: `true` | | replicated.supportBundle.rbac.serviceAccount.create (*bool*) | Default: `true` | | replicated.supportBundle.rbac.serviceAccount.existingServiceAccountName (*string*) | Use an existing ServiceAccount instead of creating one If set, this takes precedence over create: trueDefault: `""` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.admissionPolicy.enabled (*bool*) | Create a ValidatingAdmissionPolicy to restrict support bundle pod creation. Only effective when rbac.enabledDefault: `true` | | replicated.supportBundle.credentials.existingSecret (*string*) | Use an existing Secret instead of creating one. The secret must contain the keys: 'license-id' and 'upload-domain'. If set, the chart will not create the 'support-bundle-credentials' secret.Default: `""` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | replicated.supportBundle.resources (*object*) | Resource requests/limits for the support bundle pod containersDefault: `{"initContainer":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"mainContainer":{"limits":{"cpu":"100m","memory":"64Mi"},"requests":{"cpu":"10m","memory":"32Mi"}}}` | | replicated.supportBundle.resources.initContainer.requests.cpu (*string*) | CPU request for the bundle generation init containerDefault: `"100m"` | | replicated.supportBundle.resources.initContainer.requests.memory (*string*) | Memory request for the bundle generation init containerDefault: `"128Mi"` | | replicated.supportBundle.resources.initContainer.limits.cpu (*string*) | CPU limit for the bundle generation init containerDefault: `"500m"` | | replicated.supportBundle.resources.initContainer.limits.memory (*string*) | Memory limit for the bundle generation init containerDefault: `"512Mi"` | | replicated.supportBundle.resources.mainContainer.requests.cpu (*string*) | CPU request for the HTTP server containerDefault: `"10m"` | | replicated.supportBundle.resources.mainContainer.requests.memory (*string*) | Memory request for the HTTP server containerDefault: `"32Mi"` | | replicated.supportBundle.resources.mainContainer.limits.cpu (*string*) | CPU limit for the HTTP server containerDefault: `"100m"` | | replicated.supportBundle.resources.mainContainer.limits.memory (*string*) | Memory limit for the HTTP server containerDefault: `"64Mi"` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.group (*string*) | [Cert-Manager](https://cert-manager.io) Issuer GroupDefault: `"cert-manager.io"` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"5.3"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"5.3"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.customCa.resources (*object*) | Resource requests and limits for the `init-custom-ca` init containerDefault: `{"limits":{"memory":"128Mi"},"requests":{"cpu":"50m","memory":"64Mi"}}` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Enable network policies for GIM namespace isolation. When enabled, ingress from outside the GIM namespace is denied by default, and only explicitly allowed namespaces can reach GIM pods. Start with mode=dryrun to verify your config, then switch to mode=enforce.Default: `false` | | networkPolicy.mode (*string*) | Network policy mode dryrun: all policies are deployed but a temporary allow-all prevents any blocking — verify your config first enforce: the allow-all is removed and policies actively block unauthorized ingressDefault: `"dryrun"` | | networkPolicy.allowedNamespaces (*list*) | List of namespace names allowed to reach GIM pods Include your ingress controller namespace, monitoring, and any other namespace that needs access. Example: ["ingress-nginx", "monitoring"]Default: `[]` | | networkPolicy.extraPolicies (*list*) | Extra NetworkPolicy resources to create alongside the default ones Each entry is rendered as a full NetworkPolicy spec — full flexibility for custom rules.Default: `[]` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.routingApi (*string*) | Routing API used to expose the application: - "ingress" -> Kubernetes Ingress v1 / IngressRoute / VirtualService / HTTPProxy / Route (templates/exposure/) - "gateway-api" -> Gateway API HTTPRoute + Gateway (templates/exposure-gateway-api/)Default: `"ingress"` | | ingress.controller (*string*) | Data plane / ingress controller in use in the cluster. Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istio. Drives which exposure/* template is picked (when routingApi=ingress) AND which Prometheus metric is used for HPA/KEDA latency-based autoscaling. With routingApi=gateway-api, only istio / contour / traefik are supported.Default: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path type (only used when routingApi=ingress and experimental.ingressRoutes=false)Default: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the Ingress (only used when routingApi=ingress)Default: `""` | | ingress.gatewayApi (*object*) | Gateway API configuration (only used when routingApi=gateway-api)Default: `{"gateway":{"create":false,"httpListenerPort":80,"httpsListenerPort":443,"name":"gitguardian","namespace":""},"gatewayClassName":""}` | | ingress.gatewayApi.gatewayClassName (*string*) | GatewayClass nameDefault: `""` | | ingress.gatewayApi.gateway.create (*bool*) | Create the Gateway resource or use an existing oneDefault: `false` | | ingress.gatewayApi.gateway.name (*string*) | Name of the Gateway (created or existing)Default: `"gitguardian"` | | ingress.gatewayApi.gateway.namespace (*string*) | Namespace of the Gateway (empty = same as release namespace)Default: `""` | | ingress.gatewayApi.gateway.httpListenerPort (*int*) | HTTP listener port (only used when create=true)Default: `80` | | ingress.gatewayApi.gateway.httpsListenerPort (*int*) | HTTPS listener port (only used when create=true)Default: `443` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | hookMethod (*string*) | Hook Method (helm/argocd/none)Default: `"helm"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.4"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy (*DEPRECATED*) | Use `networkPolicy.enabled` instead. Will be removed in a future release.Default: `{"enabled":false}` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | logCollector.supportBundle.logLevel (*string*) | Log levels for support-bundle Loki queries: `info` (all levels) or `error` (error|fatal|critical labels only). Requires JSON logs with `level`; streams without that label are omitted when set to `error`.Default: `"info"` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20260604"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.7.2"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Delay after which chunks will be fully deleted during retention.Default: `"2h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2026.7.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.7.0](https://img.shields.io/badge/Version-2026.7.0-informational?style=flat-square) Here is the reference for the customizable values for Helm installation. See [Helm installation documentation](/self-hosting/installation/installation-existing-cluster-helm) for more information. ## Values | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"fipsEnabled":false,"image":{"imagePullPolicy":"IfNotPresent","registry":null},"imagePullSecrets":[],"imageRegistry":"","labels":{},"nodeSelector":{},"priorityClassName":"","tolerations":[]}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | global.labels (*object*) | Common labels to add to all resources Format: `name: value`Default: `{}` | | global.tolerations (*list*) | Common tolerations applied to all workloads Example for ARM/Graviton nodes: tolerations: - key: graviton operator: ExistsDefault: `[]` | | global.nodeSelector (*object*) | Common nodeSelector for all componentsDefault: `{}` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames accepted by the routing layer. Only effective on `/api/v1/receiver` (the `hook` webapp skips Host validation); other paths still require the canonical `hostname` above.Default: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/18/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"additionalPromqlLabelSelectors":"","prometheus":{}}}` | | autoscaling.keda.additionalPromqlLabelSelectors (*string*) | Optional comma-terminated PromQL label selectors inserted at the start of every `{` in built-in KEDA Prometheus queries when your metrics need extra matchers (e.g. `cluster="prod",`). Leave empty to keep the default queries.Default: `""` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | Backend deployments configuration | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* \"(?x)\n /api/v1/accounts/\\d+/\n (\n report/\n | issues/\\d+/occurrences/\n | public-monitoring/perimeter/all-developers/\n )\n\""` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":30,"heartbeatThreshold":120,"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":5},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default,sources_default,incidents_default,individual_validity_check"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"core_default":10,"honeytoken":10,"incidents_default":10,"individual_validity_check":10,"realtime":10,"realtime_retry":10,"reports":10,"sources_default":10}` | | celeryWorkers.check-runs.queues (*string*) | Queues consumed by Check Run workersDefault: `"check_run"` | | celeryWorkers.check-runs.replicas (*int*) | Check Run workers replicas countDefault: `0` | | celeryWorkers.check-runs.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.public-monitoring.queues (*string*) | Queues consumed by Public Monitoring workersDefault: `"public_monitoring,public_monitoring_historical_scan,public_monitoring_realtime_scan"` | | celeryWorkers.public-monitoring.replicas (*int*) | Worker count when enabled (gated to 0 unless the license field below is true)Default: `1` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan,code_fixing"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"code_fixing":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.check-run-scanners.queues (*string*) | Queues consumed by scan-based check-run workersDefault: `"check_run_scan"` | | celeryWorkers.check-run-scanners.replicas (*int*) | Scan-based check-run workers replicas count (0 = fall back to scanners)Default: `0` | | celeryWorkers.check-run-scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run_scan":10}` | | celeryWorkers.premium-scanners-retry.queues (*string*) | Queues consumed by the VCS scan retry workersDefault: `"premium_repo_scan_retry"` | | celeryWorkers.premium-scanners-retry.replicas (*int*) | VCS scan retry workers replicas count (0 disables the dedicated worker)Default: `0` | | celeryWorkers.premium-scanners-retry.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"premium_repo_scan_retry":1}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workersDefault: `"background_validity_check,update_sources_state,nhi_ingestion,endpoints,hmsl,core_long,sources_long,incidents_long,ml_backpopulate"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"background_validity_check":10,"core_long":10,"endpoints":10,"hmsl":10,"incidents_long":10,"ml_backpopulate":10,"nhi_ingestion":10,"sources_long":10,"update_sources_state":10}` | | celeryWorkers.automatic-severities.queues (*string*) | Queues consumed by automatic severities workersDefault: `"automatic_severities"` | | celeryWorkers.automatic-severities.replicas (*int*) | Automatic severities workers replicas countDefault: `1` | | celeryWorkers.automatic-severities.autoscaling.maxReplicas (*int*) | Autoscaling metrics thresholdDefault: `3` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"annotations":{},"enabled":true,"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"20Gi","storageClass":""},"labels":{},"nodeSelector":{},"podAnnotations":{},"podLabels":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `true` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.annotations (*object*) | Additional annotationsDefault: `{}` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podLabels (*object*) | Additional pod labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | inAppAnalytics.ephemeralStorage.enabled (*bool*) | Enable ephemeral storageDefault: `false` | | inAppAnalytics.ephemeralStorage.annotations (*object*) | Additional annotationsDefault: `{}` | | inAppAnalytics.ephemeralStorage.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.ephemeralStorage.storageClass (*string*) | Storage classDefault: `""` | | inAppAnalytics.ephemeralStorage.size (*string*) | SizeDefault: `"20Gi"` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.mode (*string*) | Controls the RBAC mode for the Replicated SDK. - `full`: default, grants all permissions required by the SDK (get/list/watch on core resources, create/update secrets) - `minimal`: read-only permissions scoped to specific resource names. Some SDK features (e.g. status informers, custom metrics reporting) may not work. Reserved for environments with strict RBAC policies that prohibit runtime secret creation and broad resource access. - `disabled`: no Role or RoleBinding created for the SDK. The ServiceAccount is still created.Default: `"full"` | | mcpServer (*object*) | MCP Server (opt-in: requires `enabled: true`)Default: `{"annotations":{},"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"metrics":{"targetLatency":1000},"minReplicas":1},"enabled":false,"extraEnv":[],"gunicorn":{"maxRequests":1000,"port":8000,"timeout":120,"workers":1},"image":{"imagePullPolicy":"IfNotPresent","name":"gitguardian/mcp-server","registry":"ghcr.io","tag":"0.6.10"},"ingress":{"enabled":true},"labels":{},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":10,"timeoutSeconds":5},"mcpOAuthProxyEnabled":true,"nodeSelector":{},"podAnnotations":{},"podAntiAffinityPreset":"soft","podLabels":{},"priorityClassName":"","readinessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":10,"periodSeconds":5,"successThreshold":1,"timeoutSeconds":3},"replicas":1,"resources":{"limits":{"cpu":"1000m","memory":"1500Mi"},"requests":{"cpu":"250m","memory":"1Gi"}},"sentry":{"dsn":"","enabled":false,"profilesSampleRate":"0.1","tracesSampleRate":"0.1"},"service":{"annotations":{},"port":8000,"type":"ClusterIP"},"tolerations":[]}` | | mcpServer.enabled (*bool*) | Toggle deployment of the MCP serverDefault: `false` | | mcpServer.replicas (*int*) | Number of replicas (only effective when `enabled` is true)Default: `1` | | mcpServer.labels (*object*) | Additional labels for the MCP server DeploymentDefault: `{}` | | mcpServer.annotations (*object*) | Additional annotations for the MCP server DeploymentDefault: `{}` | | mcpServer.podLabels (*object*) | Additional pod labelsDefault: `{}` | | mcpServer.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | mcpServer.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | mcpServer.mcpOAuthProxyEnabled (*bool*) | Enable the MCP OAuth proxy behaviour (MCP_OAUTH_PROXY_ENABLED env var in gg-mcp)Default: `true` | | mcpServer.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | mcpServer.tolerations (*list*) | Schedule MCP server pods with matching taintsDefault: `[]` | | mcpServer.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | mcpServer.extraEnv (*list*) | Additional environment variablesDefault: `[]` | | replicated.replicaCount (*int*) | Number of Replicated SDK replicasDefault: `2` | | replicated.highAvailability.podAntiAffinityPreset (*string*) | antiAffinity for Replicated SDK, applies only if replicaCount > 1Default: `"soft"` | | replicated.highAvailability.podDisruptionBudget.enabled (*bool*) | Enable podDisruptionBudget for Replicated SDKDefault: `true` | | replicated.highAvailability.podDisruptionBudget.minAvailable (*int*) | podDisruptionBudget minAvailable for Replicated SDKDefault: `1` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.19.7"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.enabled (*bool*) | Enable/Disable Support Bundle related file generation entirelyDefault: `true` | | replicated.supportBundle.rbac.createPodRole (*bool*) | Add pod create/get/delete permissions to the GIM ServiceAccount role, allowing the application to spawn support-bundle pods. Set to false to prevent in-cluster support bundle generation entirely.Default: `true` | | replicated.supportBundle.rbac.serviceAccount.create (*bool*) | Default: `true` | | replicated.supportBundle.rbac.serviceAccount.existingServiceAccountName (*string*) | Use an existing ServiceAccount instead of creating one If set, this takes precedence over create: trueDefault: `""` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.admissionPolicy.enabled (*bool*) | Create a ValidatingAdmissionPolicy to restrict support bundle pod creation. Only effective when rbac.enabledDefault: `true` | | replicated.supportBundle.credentials.existingSecret (*string*) | Use an existing Secret instead of creating one. The secret must contain the keys: 'license-id' and 'upload-domain'. If set, the chart will not create the 'support-bundle-credentials' secret.Default: `""` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | replicated.supportBundle.resources (*object*) | Resource requests/limits for the support bundle pod containersDefault: `{"initContainer":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"mainContainer":{"limits":{"cpu":"100m","memory":"64Mi"},"requests":{"cpu":"10m","memory":"32Mi"}}}` | | replicated.supportBundle.resources.initContainer.requests.cpu (*string*) | CPU request for the bundle generation init containerDefault: `"100m"` | | replicated.supportBundle.resources.initContainer.requests.memory (*string*) | Memory request for the bundle generation init containerDefault: `"128Mi"` | | replicated.supportBundle.resources.initContainer.limits.cpu (*string*) | CPU limit for the bundle generation init containerDefault: `"500m"` | | replicated.supportBundle.resources.initContainer.limits.memory (*string*) | Memory limit for the bundle generation init containerDefault: `"512Mi"` | | replicated.supportBundle.resources.mainContainer.requests.cpu (*string*) | CPU request for the HTTP server containerDefault: `"10m"` | | replicated.supportBundle.resources.mainContainer.requests.memory (*string*) | Memory request for the HTTP server containerDefault: `"32Mi"` | | replicated.supportBundle.resources.mainContainer.limits.cpu (*string*) | CPU limit for the HTTP server containerDefault: `"100m"` | | replicated.supportBundle.resources.mainContainer.limits.memory (*string*) | Memory limit for the HTTP server containerDefault: `"64Mi"` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.group (*string*) | [Cert-Manager](https://cert-manager.io) Issuer GroupDefault: `"cert-manager.io"` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"5.3"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"5.3"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.customCa.resources (*object*) | Resource requests and limits for the `init-custom-ca` init containerDefault: `{"limits":{"memory":"128Mi"},"requests":{"cpu":"50m","memory":"64Mi"}}` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Enable network policies for GIM namespace isolation. When enabled, ingress from outside the GIM namespace is denied by default, and only explicitly allowed namespaces can reach GIM pods. Start with mode=dryrun to verify your config, then switch to mode=enforce.Default: `false` | | networkPolicy.mode (*string*) | Network policy mode dryrun: all policies are deployed but a temporary allow-all prevents any blocking — verify your config first enforce: the allow-all is removed and policies actively block unauthorized ingressDefault: `"dryrun"` | | networkPolicy.allowedNamespaces (*list*) | List of namespace names allowed to reach GIM pods Include your ingress controller namespace, monitoring, and any other namespace that needs access. Example: ["ingress-nginx", "monitoring"]Default: `[]` | | networkPolicy.extraPolicies (*list*) | Extra NetworkPolicy resources to create alongside the default ones Each entry is rendered as a full NetworkPolicy spec — full flexibility for custom rules.Default: `[]` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.routingApi (*string*) | Routing API used to expose the application: - "ingress" -> Kubernetes Ingress v1 / IngressRoute / VirtualService / HTTPProxy / Route (templates/exposure/) - "gateway-api" -> Gateway API HTTPRoute + Gateway (templates/exposure-gateway-api/)Default: `"ingress"` | | ingress.controller (*string*) | Data plane / ingress controller in use in the cluster. Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istio. Drives which exposure/* template is picked (when routingApi=ingress) AND which Prometheus metric is used for HPA/KEDA latency-based autoscaling. With routingApi=gateway-api, only istio / contour / traefik are supported. "other" = any controller without a built-in integration (Kong, Cilium, …): generic routing, no built-in autoscaling query (use keda.triggers).Default: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path type (only used when routingApi=ingress and experimental.ingressRoutes=false)Default: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the Ingress (only used when routingApi=ingress)Default: `""` | | ingress.gatewayApi (*object*) | Gateway API configuration (only used when routingApi=gateway-api)Default: `{"gateway":{"create":false,"httpListenerPort":80,"httpsListenerPort":443,"name":"gitguardian","namespace":""},"gatewayClassName":""}` | | ingress.gatewayApi.gatewayClassName (*string*) | GatewayClass nameDefault: `""` | | ingress.gatewayApi.gateway.create (*bool*) | Create the Gateway resource or use an existing oneDefault: `false` | | ingress.gatewayApi.gateway.name (*string*) | Name of the Gateway (created or existing)Default: `"gitguardian"` | | ingress.gatewayApi.gateway.namespace (*string*) | Namespace of the Gateway (empty = same as release namespace)Default: `""` | | ingress.gatewayApi.gateway.httpListenerPort (*int*) | HTTP listener port (only used when create=true)Default: `80` | | ingress.gatewayApi.gateway.httpsListenerPort (*int*) | HTTPS listener port (only used when create=true)Default: `443` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | hookMethod (*string*) | Hook Method (helm/argocd/none)Default: `"helm"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.collectMigrationLogs (*bool*) | Also collect logs from the pre-deploy and post-deploy hook Jobs. The collector is injected as a native sidecar (initContainer with restartPolicy: Always), which requires Kubernetes >= 1.29 so the hook Job can still complete. Leave disabled on older clusters.Default: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.4"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy (*DEPRECATED*) | Use `networkPolicy.enabled` instead. Will be removed in a future release.Default: `{"enabled":false}` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | logCollector.supportBundle.logLevel (*string*) | Log levels for support-bundle Loki queries: `info` (all levels) or `error` (error|fatal|critical labels only). Requires JSON logs with `level`; streams without that label are omitted when set to `error`.Default: `"info"` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20260604"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.7.3"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Delay after which chunks will be fully deleted during retention.Default: `"2h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## Helm Chart Values 2026.8.0 [//]: # (DO NOT EDIT !) [//]: # (This file was generated by Helm-Docs from ward-run-app:.platform/chart/values-onprem.yaml [//]: # (To modify this content, edit ward-run-app:.platform/chart/values-onprem.yaml and use `inv helm.docs` to generate a new file) ![Version: 2026.8.0](https://img.shields.io/badge/Version-2026.8.0-informational?style=flat-square) Here is the reference for the customizable values for Helm installation. See [Helm installation documentation](/self-hosting/installation/installation-existing-cluster-helm) for more information. ## Values | Key | Description | |-----|-------------| | global (*object*) | Global configurationDefault: `{"emptyDir":{"sizeLimit":""},"fipsEnabled":false,"image":{"imagePullPolicy":"IfNotPresent","registry":null},"imagePullSecrets":[],"imageRegistry":"","labels":{},"nodeSelector":{},"priorityClassName":"","tolerations":[]}` | | global.imageRegistry (*string*) | Global Docker image registryDefault: `""` | | global.image.registry (*string*) | Use the same value as `global.imageRegistry` here (for compatibility)Default: `nil` | | global.imagePullSecrets (*list*) | Global Docker registry secret names as an arrayDefault: `[]` | | global.fipsEnabled (*bool*) | Enable the use of FIPS compliant imagesDefault: `false` | | global.priorityClassName (*string*) | Default priority class for all componentsDefault: `""` | | global.labels (*object*) | Common labels to add to all resources Format: `name: value`Default: `{}` | | global.tolerations (*list*) | Common tolerations applied to all workloads Example for ARM/Graviton nodes: tolerations: - key: graviton operator: ExistsDefault: `[]` | | global.emptyDir.sizeLimit (*string*) | Default sizeLimit for every chart-managed emptyDir volume. Empty emits no sizeLimit (Kubernetes default: unbounded). Per-volume keys override this.Default: `""` | | global.nodeSelector (*object*) | Common nodeSelector for all componentsDefault: `{}` | | hostname (*string*) | Hostname for the GitGuardian application (without https://)Default: `"gitguardian.example.com"` | | extra_hostnames (*list*) | Additional hostnames accepted by the routing layer. Only effective on `/api/v1/receiver` (the `hook` webapp skips Host validation); other paths still require the canonical `hostname` above.Default: `[]` | | network.ipFamily (*string*) | IP family mode for the deployment ("ipv4", "ipv6", "dualstack")Default: `"ipv4"` | | postgresql (*object*) | PostgreSQL Database configurationDefault: *Not set* | | postgresql.host (*string*) | PostgreSQL Database host nameDefault: `""` | | postgresql.port (*int*) | PostgreSQL Database host portDefault: `5432` | | postgresql.username (*string*) | PostgreSQL Database user nameDefault: `""` | | postgresql.password (*string*) | PostgreSQL Database user password Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.mode (*string*) | PostgreSQL Database SSL mode Possible values: disable, allow, prefer, require, verify-ca, verify-full See: [PostgreSQL SSL Mode Descriptions](https://www.postgresql.org/docs/18/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS)Default: `"allow"` | | postgresql.tls.crt (*string*) | PostgreSQL Database Client certificate Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.key (*string*) | PostgreSQL Database Client certificate private key Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.caCrt (*string*) | PostgreSQL Database Custom Certificate Authority Should preferably be set in existing secret (see: `postgresql.existingSecret`)Default: `""` | | postgresql.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store PostgreSQL Database Client certificateDefault: `""` | | postgresql.tls.existingSecretKeys.key (*string*) | Existing secret key where to store PostgreSQL Database Client certificate private keyDefault: `""` | | postgresql.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store PostgreSQL Database Custom Certificate AuthorityDefault: `""` | | postgresql.existingSecret (*string*) | Secret used to store PostgreSQL password and Certificates (preferred method)Default: `""` | | postgresql.existingSecretKeys (*object*) | Keys used for PostgreSQL Database secrets when using an existing secret | | postgresql.existingSecretKeys.password (*string*) | Existing secret key where to store PostgreSQL Database user passwordDefault: `""` | | redis (*object*) | Redis Database configuration You can either provide a full qualified URI or fill each parts in dedicated fields Redis is used as a broker and result backend for celery and as a Commit CacheDefault: *Not set* | | redis.main.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.main.existingSecret`) This values is not used if using Redis SentinelDefault: `""` | | redis.main.user (*string*) | Redis Instance user (if `redis.main.url` is not specified) / Redis Sentinel master nameDefault: `""` | | redis.main.password (*string*) | Redis Instance password (if `redis.main.url` is not specified) / Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.host (*string*) | Redis Instance host name (if `redis.main.url` is not specified) This values is not used if using Redis SentinelDefault: `""` | | redis.main.port (*int*) | Redis Instance host port (if `redis.main.url` is not specified)Default: `6379` | | redis.main.sentinel (*object*) | Redis Sentinel dedicated parameters (works along with `redis.main.url`)Default: `{"enabled":false,"masterServiceName":"","password":"","url":"","user":""}` | | redis.main.sentinel.enabled (*bool*) | Redis Sentinel enablerDefault: `false` | | redis.main.sentinel.url (*string*) | Redis Sentinel instances list. Format: sentinel-1:26379,sentinel-2:26379 Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.user (*string*) | Redis Sentinel master userDefault: `""` | | redis.main.sentinel.password (*string*) | Redis Sentinel master password Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.sentinel.masterServiceName (*string*) | Redis Sentinel master service nameDefault: `""` | | redis.main.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.main.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.main.url` or `redis.main.host`)Default: `false` | | redis.main.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `redis.main.url`Default: `false` | | redis.main.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.main.existingSecret`)Default: `""` | | redis.main.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.main.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.main.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.main.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.main.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.main.existingSecretKeys.url (*string*) | Redis urlDefault: `""` | | redis.main.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | redis.main.existingSecretKeys.sentinelUrl (*string*) | Redis Sentinel instances listDefault: `""` | | redis.main.existingSecretKeys.sentinelPassword (*string*) | Redis Sentinel passwordDefault: `""` | | redis.commitCache.enabled (*bool*) | Enable a separate Redis instance dedicated to the Commit Cache feature. Commit Cache feature allows to not scan already scanned commit by saving in Redis scan results. If not enabled, main Redis instance will be used for the Commit CacheDefault: `false` | | redis.commitCache.url (*string*) | Full qualified URI of Redis Instance Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.user (*string*) | Redis Instance user name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.password (*string*) | Redis Instance user password (if `redis.commitCache.url` is not specified) Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.host (*string*) | Redis Instance host name (if `redis.commitCache.url` is not specified)Default: `""` | | redis.commitCache.port (*int*) | Redis Instance host port (if `redis.commitCache.url` is not specified)Default: `6379` | | redis.commitCache.tls (*object*) | Redis Instance TLS configurationDefault: *Not set* | | redis.commitCache.tls.enabled (*bool*) | Enable redis TLS (mandatory, whether using `redis.commitCache.url` or `redis.commitCache.host`)Default: `false` | | redis.commitCache.tls.requireServerCert (*bool*) | Enable redis server certificate check If true, you must provide a `rediss://` URL Scheme for `REDIS_URL`Default: `false` | | redis.commitCache.tls.crt (*string*) | Redis Instance Client certificate Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.key (*string*) | Redis Instance Client certificate private key Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.caCrt (*string*) | Redis Instance Custom Certificate Authority Should preferably be set in existing secret (see: `redis.commitCache.existingSecret`)Default: `""` | | redis.commitCache.tls.existingSecretKeys.crt (*string*) | Existing secret key where to store Redis Instance Client certificateDefault: `""` | | redis.commitCache.tls.existingSecretKeys.key (*string*) | Existing secret key where to store Redis Instance Client certificate private keyDefault: `""` | | redis.commitCache.tls.existingSecretKeys.caCrt (*string*) | Existing secret key where to store Redis Instance Custom Certificate AuthorityDefault: `""` | | redis.commitCache.existingSecret (*string*) | Secret used to store Redis Instance URL or password and Certificates (preferred method)Default: `""` | | redis.commitCache.existingSecretKeys (*object*) | Keys used for Redis secrets when using an existing secret | | redis.commitCache.existingSecretKeys.url (*string*) | Redis url can be set directly, or it will be recomposed from host, user, ...Default: `""` | | redis.commitCache.existingSecretKeys.password (*string*) | Redis password (You can't use this parameter with Argo CD, use `url` parameter instead)Default: `""` | | miscEncryption (*object*) | Encryption keys configuration Django Secret Key, X509 certificate and key are auto-generated during installation if not setDefault: *Auto-generated* | | miscEncryption.djangoSecretKey (*string*) | Encryption key for sensitive database fields. Auto-generated at first install if empty (preferred method) **IMPORTANT** The key should be kept in a safe place at it is **required to access all sensitive information** in the databaseDefault: *Auto-generated* | | miscEncryption.dbEncryptionKeys (*string*) | DB encryption secrets (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecret (*string*) | Secret used to store encryption secretsDefault: `""` | | miscEncryption.existingSecretKeys (*object*) | Keys used for encryption secrets when using an existing secret | | miscEncryption.existingSecretKeys.djangoSecretKey (*string*) | Existing secret key where to store Django Secret Key Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.dbEncryptionKeys (*string*) | Existing secret key where to store DB encryption keys (optional, only needed for djangoSecretKey key rotation)Default: `""` | | miscEncryption.existingSecretKeys.x509Cert (*string*) | Existing secret key where to store certificate for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | miscEncryption.existingSecretKeys.x509PrivateKey (*string*) | Existing secret key where to store certificate private key for SAML/SSO auth Auto-generated at first install if empty (preferred method)Default: `""` | | autoscaling (*object*) | Autoscaling configurationDefault: `{"keda":{"additionalPromqlLabelSelectors":"","prometheus":{}}}` | | autoscaling.keda.additionalPromqlLabelSelectors (*string*) | Optional comma-terminated PromQL label selectors inserted at the start of every `{` in built-in KEDA Prometheus queries when your metrics need extra matchers (e.g. `cluster="prod",`). Leave empty to keep the default queries.Default: `""` | | autoscaling.keda.prometheus (*object*) | Prometheus scaler configgurationDefault: `{}` | | front (*object*) | Frontend configuration The Frontend serves the Dashboard and acts as a proxy for other web deployments | | front.nginx.replicas (*int*) | Dashboard Frontend replicas countDefault: `1` | | front.nginx.nodeSelector (*object*) | Node selection constraint for FrontendDefault: `{}` | | front.nginx.tolerations (*list*) | Schedule Frontend pods with matching taintsDefault: `[]` | | front.nginx.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | front.nginx.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | front.nginx.resources (*object*) | Dashboard Frontend resourcesDefault: `{"requests":{"cpu":"100m","memory":"200Mi"}}` | | front.service.type (*string*) | Service type. Can be ClusterIP, NodePort or LoadBalancerDefault: `"ClusterIP"` | | front.service.port (*int*) | Dashboard Frontend Service portDefault: `80` | | front.service.annotations (*object*) | Dashboard Frontend Service annotationsDefault: `{}` | | webappDefaults (*object*) | Backend deployments configuration | | webappDefaults.autoscaling.hpa.enabled (*bool*) | Enable Horizontal Pod AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | webappDefaults.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | webappDefaults.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | webappDefaults.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | webappDefaults.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"targetLatency":1000}` | | webappDefaults.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | webappDefaults.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | webappDefaults.tolerations (*list*) | Schedule pods with matching taintsDefault: `[]` | | webappDefaults.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | webapps.internal_api.name (*string*) | Default: `"internal-api"` | | webapps.internal_api.component (*string*) | Default: `"app"` | | webapps.internal_api.replicas (*int*) | Internal API replicas countDefault: `1` | | webapps.internal_api.nginx.location (*string*) | Default: `"/api/v1/"` | | webapps.internal_api.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api.gunicorn.workers (*int*) | Default: `3` | | webapps.internal_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api.readinessProbe.periodSeconds (*int*) | Default: `5` | | webapps.internal_api.readinessProbe.timeoutSeconds (*int*) | Default: `3` | | webapps.internal_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.internal_api_long.name (*string*) | Default: `"internal-api-long"` | | webapps.internal_api_long.component (*string*) | Default: `"app"` | | webapps.internal_api_long.replicas (*int*) | Internal API for long requests replicas countDefault: `1` | | webapps.internal_api_long.nginx.location (*string*) | Default: `"~* \"(?x)\n /api/v1/accounts/\\d+/\n (\n report/\n | issues/\\d+/occurrences/\n | public-monitoring/perimeter/all-developers/\n )\n\""` | | webapps.internal_api_long.nginx.keepalive_timeout (*string*) | Default: `"3600s"` | | webapps.internal_api_long.gunicorn.port (*int*) | Default: `5050` | | webapps.internal_api_long.gunicorn.worker_class (*string*) | Default: `"gthread"` | | webapps.internal_api_long.gunicorn.workers (*int*) | Default: `4` | | webapps.internal_api_long.gunicorn.timeout (*int*) | Default: `300` | | webapps.internal_api_long.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.internal_api_long.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.internal_api_long.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.internal_api_long.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.internal_api_long.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.internal_api_long.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.internal_api_long.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.internal_api_long.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.public_api.name (*string*) | Default: `"public-api"` | | webapps.public_api.component (*string*) | Default: `"api"` | | webapps.public_api.replicas (*int*) | Public API (used for ggshield scans) replicas countDefault: `1` | | webapps.public_api.nginx.location (*string*) | Default: `"/exposed"` | | webapps.public_api.nginx.locationDirectives[0] (*string*) | Default: `"client_max_body_size 25m;"` | | webapps.public_api.gunicorn.port (*int*) | Default: `5051` | | webapps.public_api.gunicorn.workers (*int*) | Default: `5` | | webapps.public_api.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.public_api.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.public_api.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.public_api.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.public_api.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.public_api.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.public_api.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.public_api.readinessProbe.failureThreshold (*int*) | Default: `3` | | webapps.hook.name (*string*) | Default: `"hook"` | | webapps.hook.component (*string*) | Default: `"receiver"` | | webapps.hook.replicas (*int*) | VCS Webhooks Receivers replicas countDefault: `1` | | webapps.hook.nginx.location (*string*) | Default: `"/api/v1/receiver"` | | webapps.hook.gunicorn.port (*int*) | Default: `5050` | | webapps.hook.resources.requests.cpu (*string*) | Default: `"100m"` | | webapps.hook.resources.requests.memory (*string*) | Default: `"500Mi"` | | webapps.hook.readinessProbe.enabled (*bool*) | Default: `false` | | webapps.app_exporter.name (*string*) | Default: `"app-exporter"` | | webapps.app_exporter.replicas (*string*) | Prometheus exporter replicas count Will be set to 1 if .Values.observability.exporter.statefulAppExporter.enabled is trueDefault: 0 | | webapps.app_exporter.internal (*bool*) | Default: `true` | | webapps.app_exporter.gunicorn.port (*int*) | Default: `9808` | | webapps.app_exporter.readinessProbe.enabled (*bool*) | Default: `true` | | webapps.app_exporter.readinessProbe.initialDelaySeconds (*int*) | Default: `15` | | webapps.app_exporter.readinessProbe.periodSeconds (*int*) | Default: `10` | | webapps.app_exporter.readinessProbe.timeoutSeconds (*int*) | Default: `5` | | webapps.app_exporter.readinessProbe.successThreshold (*int*) | Default: `1` | | webapps.app_exporter.readinessProbe.failureThreshold (*int*) | Default: `3` | | celeryWorkerDefaults (*object*) | Default configuration applied to all celery workers Workers can override any of these values in their own configuration. NOTE: Do NOT set terminationGracePeriodSeconds here - it has a dedicated fallback mechanism.Default: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"idleReplicaCount":0,"triggers":[]},"maxReplicas":10,"minReplicas":1},"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"1Gi","storageClass":""},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":30,"successThreshold":1,"timeoutSeconds":10},"metricsPort":9808,"nodeSelector":{},"podAntiAffinityPreset":"soft","priorityClassName":"","startupProbe":{"enabled":true,"failureThreshold":30,"heartbeatThreshold":120,"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":5},"tolerations":[]}` | | celeryWorkers (*object*) | Asynchronous Workers deployments configuration | | celeryWorkers.worker.queues (*string*) | Queues consumed by default workersDefault: `"celery,check_run,realtime,realtime_retry,honeytoken,reports,core_default,sources_default,incidents_default,individual_validity_check"` | | celeryWorkers.worker.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `2` | | celeryWorkers.worker.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"celery":10,"check_run":10,"core_default":10,"honeytoken":10,"incidents_default":10,"individual_validity_check":10,"realtime":10,"realtime_retry":10,"reports":10,"sources_default":10}` | | celeryWorkers.check-runs.queues (*string*) | Queues consumed by Check Run workersDefault: `"check_run"` | | celeryWorkers.check-runs.replicas (*int*) | Check Run workers replicas countDefault: `0` | | celeryWorkers.check-runs.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run":10}` | | celeryWorkers.email.queues (*string*) | Queues consumed by Messaging workersDefault: `"email,notifier"` | | celeryWorkers.email.replicas (*int*) | Messaging workers replicas countDefault: `2` | | celeryWorkers.email.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"email":10,"notifier":10}` | | celeryWorkers.public-monitoring.queues (*string*) | Queues consumed by Public Monitoring workersDefault: `"public_monitoring,public_monitoring_historical_scan,public_monitoring_realtime_scan"` | | celeryWorkers.public-monitoring.replicas (*int*) | Worker count when enabled (gated to 0 unless the license field below is true)Default: `1` | | celeryWorkers.scanners.queues (*string*) | Queues consumed by Historical Scan workersDefault: `"basic_repo_scan,premium_repo_scan,manual_repo_scan,code_fixing"` | | celeryWorkers.scanners.replicas (*int*) | Historical Scan workers replicas countDefault: `2` | | celeryWorkers.scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"basic_repo_scan":10,"code_fixing":10,"manual_repo_scan":10,"premium_repo_scan":10}` | | celeryWorkers.check-run-scanners.queues (*string*) | Queues consumed by scan-based check-run workersDefault: `"check_run_scan"` | | celeryWorkers.check-run-scanners.replicas (*int*) | Scan-based check-run workers replicas count (0 = fall back to scanners)Default: `0` | | celeryWorkers.check-run-scanners.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"check_run_scan":10}` | | celeryWorkers.premium-scanners-retry.queues (*string*) | Queues consumed by the VCS scan retry workersDefault: `"premium_repo_scan_retry"` | | celeryWorkers.premium-scanners-retry.replicas (*int*) | VCS scan retry workers replicas count (0 disables the dedicated worker)Default: `0` | | celeryWorkers.premium-scanners-retry.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"premium_repo_scan_retry":1}` | | celeryWorkers.long.queues (*string*) | Queues consumed by Long Tasks workersDefault: `"background_validity_check,update_sources_state,nhi_ingestion,endpoints,hmsl,core_long,sources_long,incidents_long,ml_backpopulate,core_aspm"` | | celeryWorkers.long.replicas (*int*) | Long Tasks workers replicas countDefault: `2` | | celeryWorkers.long.autoscaling.metrics (*object*) | HPA metrics thresholdDefault: `{"background_validity_check":10,"core_aspm":10,"core_long":10,"endpoints":10,"hmsl":10,"incidents_long":10,"ml_backpopulate":10,"nhi_ingestion":10,"sources_long":10,"update_sources_state":10}` | | celeryWorkers.automatic-severities.queues (*string*) | Queues consumed by automatic severities workersDefault: `"automatic_severities"` | | celeryWorkers.automatic-severities.replicas (*int*) | Automatic severities workers replicas countDefault: `1` | | celeryWorkers.automatic-severities.autoscaling.maxReplicas (*int*) | Autoscaling metrics thresholdDefault: `3` | | celeryWorkers.incidents-disk.queues (*string*) | Queues consumed by the locations recompute workersDefault: `"incidents_disk"` | | celeryWorkers.incidents-disk.replicas (*int*) | Locations recompute workers replicas count (0 = fall back to scanners)Default: `0` | | celeryWorkers.incidents-disk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"incidents_disk":10}` | | celeryWorkers.scanners-ods.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan"` | | celeryWorkers.scanners-ods.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan":10}` | | celeryWorkers.scanners-ods-highdisk.queues (*string*) | Queues consumed by non-VCS Historical Scan workersDefault: `"ods_scan_highdisk"` | | celeryWorkers.scanners-ods-highdisk.replicas (*int*) | Non-VCS Historical Scan workers replicas countDefault: `0` | | celeryWorkers.scanners-ods-highdisk.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ods_scan_highdisk":10}` | | celeryWorkers.realtime-ods.queues (*string*) | Queues consumed by default workersDefault: `"realtime_ods,realtime_retry_ods"` | | celeryWorkers.realtime-ods.replicas (*int*) | Default workers (incl. realtime scans) replicas countDefault: `0` | | celeryWorkers.realtime-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"realtime_ods":10,"realtime_retry_ods":10}` | | celeryWorkers.long-ods.queues (*string*) | Queues consumed by none-VCS Long Tasks workersDefault: `"long_ods"` | | celeryWorkers.long-ods.replicas (*int*) | Non-VCS Long Tasks workers replicas countDefault: `0` | | celeryWorkers.long-ods.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `15` | | celeryWorkers.long-ods.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods":10}` | | celeryWorkers.long-ods-io.replicas (*int*) | Number of replica for Non-VCS workers specialized in IO operationsDefault: `0` | | celeryWorkers.long-ods-io.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.long-ods-io.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"long_ods_io":10}` | | celeryWorkers.container-registries.replicas (*int*) | Number of replica for Container Registries scansDefault: `0` | | celeryWorkers.container-registries.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | celeryWorkers.container-registries.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"container_registries":10}` | | celeryWorkers.scanners-slack.replicas (*int*) | Number of replica for Slack scansDefault: `0` | | celeryWorkers.scanners-slack.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `4` | | celeryWorkers.scanners-slack.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"slack_scan":6}` | | celeryWorkers.business-contribution.replicas (*int*) | Number of replica for Business Contrib WorkerDefault: `0` | | celeryWorkers.business-contribution.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `5` | | celeryWorkers.business-contribution.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"business_contribution":10}` | | celeryWorkers.business-contribution.prefetchMultiplier (*int*) | Prefetch multiplier for Business Contrib WorkerDefault: `100` | | celeryWorkers.ml-api-priority.replicas (*int*) | Number of replica for ML API priority workerDefault: `1` | | celeryWorkers.ml-api-priority.autoscaling.metrics (*object*) | Autoscaling metrics thresholdDefault: `{"ml_api_priority":10}` | | celeryWorkers.ml-api-priority.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | beat (*object*) | Asynchronous tasks scheduler | | beat.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | beat.resources (*object*) | Asynchronous tasks scheduler resourcesDefault: `{"requests":{"cpu":"10m","memory":"200Mi"}}` | | secretEngine (*object*) | ML Secret EngineDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":1,"metrics":{"bentoml_service_request_in_progress":10},"minReplicas":1},"emptyDir":{"bentomlProm":{"sizeLimit":""},"bentomlTmp":{"sizeLimit":""},"modelDir":{"sizeLimit":""}},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":1,"tolerations":[]}` | | secretEngine.replicas (*int*) | Number of replicasDefault: `1` | | secretEngine.nodeSelector (*object*) | Node selection constraint for secret-engineDefault: `{}` | | secretEngine.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | secretEngine.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | secretEngine.labels (*object*) | Additional labelsDefault: `{}` | | secretEngine.pdb.enabled (*bool*) | Activate PodDisruptionBudget on secret engine Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | secretEngine.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | secretEngine.autoscaling.hpa.enabled (*bool*) | Enable HPA on secret engineDefault: `false` | | secretEngine.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | secretEngine.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | secretEngine.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `1` | | secretEngine.autoscaling.metrics (*object*) | MetricsDefault: `{"bentoml_service_request_in_progress":10}` | | secretEngine.emptyDir.modelDir.sizeLimit (*string*) | sizeLimit for the `model-dir` emptyDir holding the ML model bundle, by far the largest of the three (>650Mi as of 1.11.0). Size it accordingly if your platform caps emptyDir volumes. Empty falls back to `global.emptyDir.sizeLimit`.Default: `""` | | secretEngine.emptyDir.bentomlTmp.sizeLimit (*string*) | sizeLimit for the `bentoml-tmp` emptyDir. Empty falls back to `global.emptyDir.sizeLimit`.Default: `""` | | secretEngine.emptyDir.bentomlProm.sizeLimit (*string*) | sizeLimit for the `bentoml-prom` emptyDir. Empty falls back to `global.emptyDir.sizeLimit`.Default: `""` | | inAppAnalytics (*object*) | InApp AnalyticsDefault: `{"annotations":{},"enabled":true,"ephemeralStorage":{"annotations":{},"enabled":false,"labels":{},"size":"20Gi","storageClass":""},"labels":{},"nodeSelector":{},"podAnnotations":{},"podLabels":{},"priorityClassName":"","tolerations":[]}` | | inAppAnalytics.enabled (*bool*) | Enable InApp AnalyticsDefault: `true` | | inAppAnalytics.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | inAppAnalytics.tolerations (*list*) | Schedule with matching taintsDefault: `[]` | | inAppAnalytics.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | inAppAnalytics.annotations (*object*) | Additional annotationsDefault: `{}` | | inAppAnalytics.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.podLabels (*object*) | Additional pod labelsDefault: `{}` | | inAppAnalytics.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | inAppAnalytics.ephemeralStorage.enabled (*bool*) | Enable ephemeral storageDefault: `false` | | inAppAnalytics.ephemeralStorage.annotations (*object*) | Additional annotationsDefault: `{}` | | inAppAnalytics.ephemeralStorage.labels (*object*) | Additional labelsDefault: `{}` | | inAppAnalytics.ephemeralStorage.storageClass (*string*) | Storage classDefault: `""` | | inAppAnalytics.ephemeralStorage.size (*string*) | SizeDefault: `"20Gi"` | | apacheTika (*object*) | Apache TikaDefault: `{"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"minReplicas":1,"targetCPUUtilizationPercentage":60,"targetMemoryUtilizationPercentage":60},"labels":{},"nodeSelector":{},"pdb":{"enabled":false,"minAvailable":"50%"},"priorityClassName":"","replicas":0,"tolerations":[]}` | | apacheTika.replicas (*int*) | Number of replicasDefault: `0` | | apacheTika.nodeSelector (*object*) | Node selection constraint for apache-tikaDefault: `{}` | | apacheTika.tolerations (*list*) | Schedule secret-engine pods with matching taintsDefault: `[]` | | apacheTika.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | apacheTika.labels (*object*) | Additional labelsDefault: `{}` | | apacheTika.pdb.enabled (*bool*) | Activate PodDisruptionBudget on apache-tika Note: `podDisruptionBudget.enabled` must be trueDefault: `false` | | apacheTika.pdb.minAvailable (*string*) | Minimum percentage of available replicasDefault: `"50%"` | | apacheTika.autoscaling.hpa.enabled (*bool*) | Enable HPA on apache-tikaDefault: `false` | | apacheTika.autoscaling.keda.enabled (*bool*) | Enable Keda AutoscalerDefault: `false` | | apacheTika.autoscaling.keda.triggers (*list*) | Additional Keda triggersDefault: `[]` | | apacheTika.autoscaling.targetCPUUtilizationPercentage (*int*) | Autoscaling CPU thresholdDefault: `60` | | apacheTika.autoscaling.targetMemoryUtilizationPercentage (*int*) | Autoscaling Memory thresholdDefault: `60` | | apacheTika.autoscaling.minReplicas (*int*) | Minimum number of workers created by autoscalerDefault: `1` | | apacheTika.autoscaling.maxReplicas (*int*) | Maximum number of workers created by autoscalerDefault: `10` | | onPrem.adminUser (*object*) | GitGuardian Admin User A temporary password has to be set in secret "gim-secrets" under ADMIN_PASSWORD key. You'll be asked to change this password on your connectionDefault: `{"email":"admin@example.com","existingSecret":"","existingSecretKeys":{"password":""},"firstname":"Admin"}` | | onPrem.replicatedRbac.mode (*string*) | Controls the RBAC mode for the Replicated SDK. - `full`: default, grants all permissions required by the SDK (get/list/watch on core resources, create/update secrets) - `minimal`: read-only permissions scoped to specific resource names. Some SDK features (e.g. status informers, custom metrics reporting) may not work. Reserved for environments with strict RBAC policies that prohibit runtime secret creation and broad resource access. - `disabled`: no Role or RoleBinding created for the SDK. The ServiceAccount is still created.Default: `"full"` | | mcpServer (*object*) | MCP Server (opt-in: requires `enabled: true`)Default: `{"annotations":{},"autoscaling":{"hpa":{"enabled":false},"keda":{"enabled":false,"triggers":[]},"maxReplicas":10,"metrics":{"targetLatency":1000},"minReplicas":1},"enabled":false,"extraEnv":[],"gunicorn":{"maxRequests":1000,"port":8000,"timeout":120,"workers":1},"image":{"imagePullPolicy":"IfNotPresent","name":"gitguardian/mcp-server","registry":"ghcr.io","tag":"0.7.0"},"ingress":{"enabled":true},"labels":{},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":10,"timeoutSeconds":5},"mcpOAuthProxyEnabled":true,"nodeSelector":{},"podAnnotations":{},"podAntiAffinityPreset":"soft","podLabels":{},"priorityClassName":"","readinessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":10,"periodSeconds":5,"successThreshold":1,"timeoutSeconds":3},"replicas":1,"resources":{"limits":{"cpu":"1000m","memory":"1500Mi"},"requests":{"cpu":"250m","memory":"1Gi"}},"sentry":{"dsn":"","enabled":false,"profilesSampleRate":"0.1","tracesSampleRate":"0.1"},"service":{"annotations":{},"port":8000,"type":"ClusterIP"},"tolerations":[]}` | | mcpServer.enabled (*bool*) | Toggle deployment of the MCP serverDefault: `false` | | mcpServer.replicas (*int*) | Number of replicas (only effective when `enabled` is true)Default: `1` | | mcpServer.labels (*object*) | Additional labels for the MCP server DeploymentDefault: `{}` | | mcpServer.annotations (*object*) | Additional annotations for the MCP server DeploymentDefault: `{}` | | mcpServer.podLabels (*object*) | Additional pod labelsDefault: `{}` | | mcpServer.podAnnotations (*object*) | Additional pod annotationsDefault: `{}` | | mcpServer.podAntiAffinityPreset (*string*) | Pod anti-affinity preset (hard or soft)Default: `"soft"` | | mcpServer.mcpOAuthProxyEnabled (*bool*) | Enable the MCP OAuth proxy behaviour (MCP_OAUTH_PROXY_ENABLED env var in gg-mcp)Default: `true` | | mcpServer.nodeSelector (*object*) | Node selection constraintDefault: `{}` | | mcpServer.tolerations (*list*) | Schedule MCP server pods with matching taintsDefault: `[]` | | mcpServer.priorityClassName (*string*) | priorityClassName (overrides global)Default: `""` | | mcpServer.extraEnv (*list*) | Additional environment variablesDefault: `[]` | | replicated.replicaCount (*int*) | Number of Replicated SDK replicasDefault: `2` | | replicated.highAvailability.podAntiAffinityPreset (*string*) | antiAffinity for Replicated SDK, applies only if replicaCount > 1Default: `"soft"` | | replicated.highAvailability.podDisruptionBudget.enabled (*bool*) | Enable podDisruptionBudget for Replicated SDKDefault: `true` | | replicated.highAvailability.podDisruptionBudget.minAvailable (*int*) | podDisruptionBudget minAvailable for Replicated SDKDefault: `1` | | replicated.image.registry (*string*) | Replicated SDK image registryDefault: `"proxy.replicated.com/proxy/gitguardian/docker.io"` | | replicated.image.repository (*string*) | Replicated SDK image repositoryDefault: `"replicated/replicated-sdk"` | | replicated.image.tag (*string*) | Replicated SDK image tagDefault: `"1.19.10"` | | replicated.imagePullSecrets (*list*) | Image pullsecretsDefault: `[{"name":"gim-replicated-registry"}]` | | replicated.extraEnv (*list*) | Replicated SDK env vars update this to use an existing Secret for proxy urls. gim-proxy is created automatically otherwise.Default: `[{"name":"HTTP_PROXY","valueFrom":{"secretKeyRef":{"key":"http_proxy","name":"gim-proxy"}}},{"name":"HTTPS_PROXY","valueFrom":{"secretKeyRef":{"key":"https_proxy","name":"gim-proxy"}}},{"name":"NO_PROXY","valueFrom":{"configMapKeyRef":{"key":"NO_PROXY","name":"gim-config"}}}]` | | replicated.isAirgap (*bool*) | Disable Replicated outbound connectionsDefault: `false` | | replicated.privateCASecret (*object*) | Specify secret containing Custom Certificate Authority certificate. See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/security/custom-ca#helm-based-installation)Default: `nil` | | replicated.supportBundle.enabled (*bool*) | Enable/Disable Support Bundle related file generation entirelyDefault: `true` | | replicated.supportBundle.rbac.createPodRole (*bool*) | Add pod create/get/delete permissions to the GIM ServiceAccount role, allowing the application to spawn support-bundle pods. Set to false to prevent in-cluster support bundle generation entirely.Default: `true` | | replicated.supportBundle.rbac.serviceAccount.create (*bool*) | Default: `true` | | replicated.supportBundle.rbac.serviceAccount.existingServiceAccountName (*string*) | Use an existing ServiceAccount instead of creating one If set, this takes precedence over create: trueDefault: `""` | | replicated.supportBundle.rbac.role.create (*bool*) | Create role (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.rbac.clusterRole.create (*bool*) | Create ClusterRole (optional) for Support Bundle generationDefault: `true` | | replicated.supportBundle.admissionPolicy.enabled (*bool*) | Create a ValidatingAdmissionPolicy to restrict support bundle pod creation. Only effective when rbac.enabledDefault: `true` | | replicated.supportBundle.credentials.existingSecret (*string*) | Use an existing Secret instead of creating one. The secret must contain the keys: 'license-id' and 'upload-domain'. If set, the chart will not create the 'support-bundle-credentials' secret.Default: `""` | | replicated.supportBundle.logs.maxLines (*int*) | Set the max number of lines in the support bundle logsDefault: `10000` | | replicated.supportBundle.resources (*object*) | Resource requests/limits for the support bundle pod containersDefault: `{"initContainer":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"mainContainer":{"limits":{"cpu":"100m","memory":"64Mi"},"requests":{"cpu":"10m","memory":"32Mi"}}}` | | replicated.supportBundle.resources.initContainer.requests.cpu (*string*) | CPU request for the bundle generation init containerDefault: `"100m"` | | replicated.supportBundle.resources.initContainer.requests.memory (*string*) | Memory request for the bundle generation init containerDefault: `"128Mi"` | | replicated.supportBundle.resources.initContainer.limits.cpu (*string*) | CPU limit for the bundle generation init containerDefault: `"500m"` | | replicated.supportBundle.resources.initContainer.limits.memory (*string*) | Memory limit for the bundle generation init containerDefault: `"512Mi"` | | replicated.supportBundle.resources.mainContainer.requests.cpu (*string*) | CPU request for the HTTP server containerDefault: `"10m"` | | replicated.supportBundle.resources.mainContainer.requests.memory (*string*) | Memory request for the HTTP server containerDefault: `"32Mi"` | | replicated.supportBundle.resources.mainContainer.limits.cpu (*string*) | CPU limit for the HTTP server containerDefault: `"100m"` | | replicated.supportBundle.resources.mainContainer.limits.memory (*string*) | Memory limit for the HTTP server containerDefault: `"64Mi"` | | ggscout.enabled (*bool*) | Enable ggscoutDefault: `false` | | ggscout.inventory.config.gitguardian.endpoint (*string*) | GitGuardian API endpoint (optional; if not specified, the current self-hosted GitGuardian instance URL will be used)Default: `"http://public-api:5051/exposed/v1"` | | ggscout.inventory.config.gitguardian.api_token (*string*) | GitGuardian API token for ggscout, please refer to [ggscout Helm configuration](https://docs.gitguardian.com/ggscout-docs/self-hosted-configuration#helm-based-installation)Default: `""` | | ggscout.inventory.config.sources (*object*) | For ggscout inventory sources configuration details, please refer to [ggscout Helm chart examples](https://github.com/GitGuardian/ggscout-helm-charts/tree/main/charts/ggscout/examples)Default: `{}` | | ggscout.caBundle.certs (*string*) | Specify CA certificates to inject (PEM format)Default: `""` | | ggscout.caBundle.existingSecret (*string*) | Specify the secret containing the CA certificate to injectDefault: `""` | | ggscout.caBundle.existingSecretKey (*string*) | Specify secret key under the CA certificate is storedDefault: `"ca.crt"` | | tls (*object*) | HTTPS TLS configuration You can manage the certificate manually or use [Cert-Manager](https://cert-manager.io) | | tls.certManager.enabled (*bool*) | Use [Cert-Manager](https://cert-manager.io) instead of a manual certificateDefault: `false` | | tls.certManager.certificatesSecret (*string*) | Name of the created cert-manager `Certificate` objectDefault: `"gitguardian-certificate"` | | tls.certManager.certificatesNamespace (*string*) | Namespace where certificate will be createdDefault: `.Release.Namespace` | | tls.certManager.issuer.group (*string*) | [Cert-Manager](https://cert-manager.io) Issuer GroupDefault: `"cert-manager.io"` | | tls.certManager.issuer.kind (*string*) | [Cert-Manager](https://cert-manager.io) Issuer ClassDefault: `"ClusterIssuer"` | | tls.certManager.issuer.name (*string*) | [Cert-Manager](https://cert-manager.io) Issuer NameDefault: `"gitguardian"` | | tls.customCa (*object*) | Custom Certificate Authority certificate for integrations (VCS, notifiers, webhooks, ...) | | tls.customCa.caCrt (*string*) | Certificates full chain in the PEM format Should preferably be set in existing secret (see: `tls.customCa.existingSecret`)Default: `""` | | tls.customCa.existingSecret (*string*) | Existing secret containing certificates full chain in the PEM formatDefault: `""` | | tls.customCa.existingSecretKeys.caCrt (*string*) | Key name of the certificate authority entryDefault: `""` | | tls.customCa.image (*object*) | Custom CA (used for init-containers only) image configurationDefault: `{"name":"gitguardian/wolfi/bash","pullSecrets":[],"registry":"proxy.replicated.com/proxy/gitguardian/ghcr.io","tag":"5.3"}` | | tls.customCa.image.registry (*string*) | Registry source to fetch the image Empty = from dockerhubDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | tls.customCa.image.name (*string*) | Image nameDefault: `"gitguardian/wolfi/bash"` | | tls.customCa.image.tag (*string*) | Image tagDefault: `"5.3"` | | tls.customCa.image.pullSecrets (*list*) | Image pullsecretsDefault: `[]` | | tls.customCa.resources (*object*) | Resource requests and limits for the `init-custom-ca` init containerDefault: `{"limits":{"memory":"128Mi"},"requests":{"cpu":"50m","memory":"64Mi"}}` | | tls.clientAuth (*object*) | Client (end user) authentication | | tls.clientAuth.enabled (*bool*) | Enable client authentication. This is required for Common Access CardDefault: `false` | | tls.clientAuth.mode (*string*) | Set client authentication mode (one of `enforce`, `audit`). `audit` mode must be used for initial setup.Default: `"enforce"` | | tls.clientAuth.userRegex (*string*) | Regex to extract the unique user identifier from the certificate DN. You must use a capture group using parenthesis to catch the user ID. Default regex will match 117 here: CN=hubert.bonisseur.delabath.117,O=DGSE,C=FRDefault: `"(?:.+,)?CN=[^.]+\\.[^.]+\\.[^.]+\\.(\\d+)(?:,.+)?"` | | tls.clientAuth.crt (*string*) | NGINX Server certificate (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.key (*string*) | NGINX Server key (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.caCrt (*string*) | NGINX Authority that validates user certificates (PEM) Should preferably be set in existing secret (see: `tls.clientAuth.existingSecret`)Default: `""` | | tls.clientAuth.crl (*object*) | Nginx CRL usage for clientAuthDefault: `{"cron":"0 0 * * *","persistence":{"accessModes":["ReadWriteMany"],"annotations":{},"labels":{},"size":"1Gi","storageClass":""},"url":""}` | | tls.clientAuth.crl.url (*string*) | Nginx CRL URL. Use a CRL instead of OCSP to check revokations status. Keep empty to use OCSP.Default: `""` | | tls.clientAuth.crl.cron (*string*) | Nginx CRL refresh cron expression. This example means daily at 00:00Default: `"0 0 * * *"` | | tls.clientAuth.crl.persistence.storageClass (*string*) | storageClass to use for the CRL PVCDefault: `""` | | tls.clientAuth.crl.persistence.accessModes (*list*) | accessModes to use for the CRL PVC. Use only ReadWriteMany (HA) if available.Default: `["ReadWriteMany"]` | | tls.clientAuth.crl.persistence.size (*string*) | PVC sizeDefault: `"1Gi"` | | tls.clientAuth.crl.persistence.labels (*object*) | PVC LabelsDefault: `{}` | | tls.clientAuth.crl.persistence.annotations (*object*) | PVC AnnotationsDefault: `{}` | | tls.clientAuth.existingSecret (*string*) | Existing secret nameDefault: `""` | | networkPolicy.enabled (*bool*) | Enable network policies for GIM namespace isolation. When enabled, ingress from outside the GIM namespace is denied by default, and only explicitly allowed namespaces can reach GIM pods. Start with mode=dryrun to verify your config, then switch to mode=enforce.Default: `false` | | networkPolicy.mode (*string*) | Network policy mode dryrun: all policies are deployed but a temporary allow-all prevents any blocking — verify your config first enforce: the allow-all is removed and policies actively block unauthorized ingressDefault: `"dryrun"` | | networkPolicy.allowedNamespaces (*list*) | List of namespace names allowed to reach GIM pods Include your ingress controller namespace, monitoring, and any other namespace that needs access. Example: ["ingress-nginx", "monitoring"]Default: `[]` | | networkPolicy.extraPolicies (*list*) | Extra NetworkPolicy resources to create alongside the default ones Each entry is rendered as a full NetworkPolicy spec — full flexibility for custom rules.Default: `[]` | | securityContext (*object*) | Specify Pod Security Context.Default: `{"enabled":true,"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | | containerSecurityContext (*object*) | Specify Container Security Context. Note: Enabled if `securityContext.enabled` is true.Default: `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` | | podDisruptionBudget.enabled (*bool*) | Deploy PodDisruptionBudget globally. Note: Some Deployments have their own enabler (like apacheTika or secretEngine)Default: `true` | | ingress.enabled (*bool*) | Enable ingress resourceDefault: `false` | | ingress.routingApi (*string*) | Routing API used to expose the application: - "ingress" -> Kubernetes Ingress v1 / IngressRoute / VirtualService / HTTPProxy / Route (templates/exposure/) - "gateway-api" -> Gateway API HTTPRoute + Gateway (templates/exposure-gateway-api/)Default: `"ingress"` | | ingress.controller (*string*) | Data plane / ingress controller in use in the cluster. Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istio. Drives which exposure/* template is picked (when routingApi=ingress) AND which Prometheus metric is used for HPA/KEDA latency-based autoscaling. With routingApi=gateway-api, only istio / contour / traefik are supported. "other" = any controller without a built-in integration (Kong, Cilium, …): generic routing, no built-in autoscaling query (use keda.triggers).Default: `"ingress-nginx"` | | ingress.path (*string*) | The routing path to the GitGuardian instance. You may need to set this to '/*' in order to use this with ALB ingress controllers.Default: `"/"` | | ingress.pathType (*string*) | Ingress Path type (only used when routingApi=ingress and experimental.ingressRoutes=false)Default: `"Prefix"` | | ingress.ingressClassName (*string*) | IngressClass that will be used to implement the Ingress (only used when routingApi=ingress)Default: `""` | | ingress.gatewayApi (*object*) | Gateway API configuration (only used when routingApi=gateway-api)Default: `{"gateway":{"create":false,"httpListenerPort":80,"httpsListenerPort":443,"name":"gitguardian","namespace":""},"gatewayClassName":""}` | | ingress.gatewayApi.gatewayClassName (*string*) | GatewayClass nameDefault: `""` | | ingress.gatewayApi.gateway.create (*bool*) | Create the Gateway resource or use an existing oneDefault: `false` | | ingress.gatewayApi.gateway.name (*string*) | Name of the Gateway (created or existing)Default: `"gitguardian"` | | ingress.gatewayApi.gateway.namespace (*string*) | Namespace of the Gateway (empty = same as release namespace)Default: `""` | | ingress.gatewayApi.gateway.httpListenerPort (*int*) | HTTP listener port (only used when create=true)Default: `80` | | ingress.gatewayApi.gateway.httpsListenerPort (*int*) | HTTPS listener port (only used when create=true)Default: `443` | | ingress.annotations (*object*) | Additional annotations for the Ingress resource.Default: `{}` | | ingress.labels (*object*) | Additional labels for the Ingress resource.Default: `{}` | | ingress.istio.revision (*string*) | Istio revision, if anyDefault: `""` | | ingress.istio.gateway.enabled (*bool*) | Enable Istio gateway handlingDefault: `false` | | ingress.istio.gateway.name (*string*) | Istio Gateway nameDefault: `"{{.Release.Name}}-{{.Release.Namespace}}"` | | ingress.istio.gateway.namespace (*string*) | Istio Gateway namespaceDefault: `"istio-system"` | | ingress.istio.gateway.selector (*string*) | Istio Gateway selectorDefault: `"ingressgateway"` | | ingress.tls.enabled (*bool*) | Enable TLS configuration for the hostname defined at ingress.hostname parameterDefault: `false` | | ingress.tls.existingSecret (*string*) | Existing secret containing TLS certificatesDefault: `""` | | ingress.tls.crt (*string*) | TLS certificate in PEM format Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | ingress.tls.key (*string*) | TLS private key Should preferably be set in existing secret (see: `ingress.tls.existingSecret`)Default: `""` | | observability.exporters (*object*) | Prometheus exporters configuration | | observability.exporters.webAppExporter.enabled (*bool*) | Enable GitGuardian Applicative metrics on Webapp pods and Celery WorkersDefault: `false` | | observability.exporters.statefulAppExporter.enabled (*bool*) | Enable Stateful metrics on Applicative Exporter See: [GitGuardian documentation](https://docs.gitguardian.com/self-hosting/management/application-management/metrics)Default: `false` | | observability.exporters.statefulAppExporter.resources (*object*) | Applicative Exporter resourcesDefault: `{"requests":{"cpu":"100m","memory":"500Mi"}}` | | observability.serviceMonitors.enabled (*bool*) | Enable ServiceMonitors for Prometheus Operator Note: this requires to install Prometheus Operator (not included in this chart) See: [Prometheus documentation](https://prometheus-operator.dev)Default: `false` | | rbac (*object*) | GitGuardian pods will use a limited role if enabledDefault: `{"enabled":true}` | | rbac.enabled (*bool*) | Creates a Role and bind it to GitGuardian ServiceAccount (see serviceAccount.name). See [GitGuardian doc](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm#kubernetes-application-rbac)Default: `true` | | serviceAccount (*object*) | GitGuardian Pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim"}` | | serviceAccount.create (*bool*) | create the serviceAccountDefault: `true` | | serviceAccount.name (*string*) | name of the serviceAccount (if serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim"` | | migration.nodeSelector (*object*) | Default: `{}` | | migration.tolerations (*list*) | Default: `[]` | | migration.labels (*object*) | Default: `{}` | | migration.podLabels (*object*) | Default: `{}` | | migration.podAnnotations (*object*) | Default: `{}` | | migration.preDeploy.resources (*object*) | Pre Deployment Job resourcesDefault: `{"limits":{"memory":"10Gi"},"requests":{"cpu":"500m","memory":"3Gi"}}` | | migration.postDeploy.resources (*object*) | Post Deployment Job resourcesDefault: `{"limits":{"memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}` | | migration.upgradePathCheck.resources (*object*) | upgradePathCheck Job resourcesDefault: `{"limits":{"memory":"1Gi"},"requests":{"cpu":"200m","memory":"500Mi"}}` | | migration.serviceAccount (*object*) | GitGuardian migration pods are using this ServiceAccountDefault: `{"annotations":{},"autoMount":true,"create":true,"labels":{},"name":"gim-migration"}` | | migration.serviceAccount.create (*bool*) | create the migration serviceAccountDefault: `true` | | migration.serviceAccount.name (*string*) | name of the serviceAccount (if migration.serviceAccount.create is false, it must exists prior to chart deployment)Default: `"gim-migration"` | | hookMethod (*string*) | Hook Method (helm/argocd/none)Default: `"helm"` | | proxy (*object*) | HTTP(s) proxy configuration You can configure a proxy server for outgoing traffic from the applicationDefault: *Not set* | | proxy.httpProxyUrl (*string*) | Url of the proxy server to be used for HTTP requestsDefault: `""` | | proxy.httpsProxyUrl (*string*) | Url of the proxy server to be used for HTTPS requestsDefault: `""` | | proxy.noProxyHostNames (*list*) | List of host names through which the traffic should not go via the proxyDefault: `[]` | | proxy.existingSecret (*string*) | Secret used to store proxy urls (preferred method)Default: `""` | | proxy.existingSecretKeys.httpProxyUrl (*string*) | Existing secret key where to store proxy http urlDefault: `""` | | proxy.existingSecretKeys.httpsProxyUrl (*string*) | Existing secret key where to store proxy https urlDefault: `""` | | logCollector.enabled (*bool*) | Enable logCollectorDefault: `true` | | logCollector.emptyDir.sizeLimit (*string*) | sizeLimit for the `logs` emptyDir shared by every log collector sidecar. Empty falls back to `global.emptyDir.sizeLimit`.Default: `""` | | logCollector.collectMigrationLogs (*bool*) | Also collect logs from the pre-deploy and post-deploy hook Jobs. The collector is injected as a native sidecar (initContainer with restartPolicy: Always), which requires Kubernetes >= 1.29 so the hook Job can still complete. Leave disabled on older clusters.Default: `true` | | logCollector.image.registry (*string*) | Fluent-bit image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | logCollector.image.name (*string*) | Fluent-bit image repositoryDefault: `"gitguardian/wolfi/fluent-bit"` | | logCollector.image.tag (*string*) | Fluent-bit image tagDefault: `"4.2.4"` | | logCollector.image.pullSecrets (*list*) | Fluent-bit image pull secretsDefault: `[]` | | logCollector.env (*list*) | - Environment variables to be passed to logCollectorDefault: `[]` | | logCollector.envFrom (*list*) | - Environment variables to be passed to logCollector from configMaps or SecretsDefault: `[]` | | logCollector.pipelines (*object*) | - Specify additional logCollector pipelinesDefault: `{}` | | logCollector.networkPolicy (*DEPRECATED*) | Use `networkPolicy.enabled` instead. Will be removed in a future release.Default: `{"enabled":false}` | | logCollector.resources.requests.cpu (*string*) | Specify CPU requestDefault: `"10m"` | | logCollector.resources.requests.memory (*string*) | Specify Memory requestDefault: `"32Mi"` | | logCollector.supportBundle.since (*string*) | lookback window for retrieving logsDefault: `"24h"` | | logCollector.supportBundle.limit (*int*) | Limit on number of logs to retrieve for each component (0 means disabled)Default: `0` | | logCollector.supportBundle.logLevel (*string*) | Log levels for support-bundle Loki queries: `info` (all levels) or `error` (error|fatal|critical labels only). Requires JSON logs with `level`; streams without that label are omitted when set to `error`.Default: `"info"` | | loki-minio.image.registry (*string*) | MinIO image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki-minio.image.repository (*string*) | MinIO image repositoryDefault: `"gitguardian/wolfi/minio"` | | loki-minio.image.tag (*string*) | MinIO image tagDefault: `"0.20260717"` | | loki-minio.image.digest (*string*) | MinIO image digestDefault: `""` | | loki-minio.image.imagePullPolicy (*string*) | MinIO image pull policyDefault: `"IfNotPresent"` | | loki-minio.image.pullSecrets (*list*) | MinIO image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki-minio.persistence.storageClass (*string*) | Storage class for MinIODefault: `""` | | loki-minio.persistence.size (*string*) | MinIO persistent storage sizeDefault: `"20Gi"` | | loki-minio.podSecurityContext.fsGroup (*int*) | Enable pod Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsUser (*int*) | Enable container Security Context for MinIODefault: `65532` | | loki-minio.containerSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki-minio.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki-minio.resources.requests.cpu (*string*) | Specify CPU request for MinIODefault: `"100m"` | | loki-minio.resources.requests.memory (*string*) | Specify Memory request for MinIODefault: `"512Mi"` | | loki.serviceAccount.create (*bool*) | Specifies whether a ServiceAccount should be createdDefault: `true` | | loki.rbac.sccEnabled (*bool*) | For OpenShift set sccEnabled to 'true' to use the SecurityContextConstraints.Default: `false` | | loki.imagePullSecrets (*list*) | Loki image pull secretsDefault: `[{"name":"gim-replicated-registry"}]` | | loki.loki.image.registry (*string*) | Loki image registryDefault: `"proxy.replicated.com/proxy/gitguardian/ghcr.io"` | | loki.loki.image.repository (*string*) | Loki image repositoryDefault: `"gitguardian/wolfi/loki"` | | loki.loki.image.tag (*string*) | Loki image tagDefault: `"3.7.6"` | | loki.loki.image.digest (*string*) | Loki image digestDefault: `""` | | loki.loki.image.pullPolicy (*string*) | Loki image pull policyDefault: `"IfNotPresent"` | | loki.loki.compactor.retention_delete_delay (*string*) | Delay after which chunks will be fully deleted during retention.Default: `"2h"` | | loki.loki.podSecurityContext.fsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsGroup (*int*) | Default: `65532` | | loki.loki.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.podSecurityContext.runAsUser (*int*) | Default: `65532` | | loki.loki.containerSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.privileged (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.readOnlyRootFilesystem (*bool*) | Default: `true` | | loki.loki.containerSecurityContext.allowPrivilegeEscalation (*bool*) | Default: `false` | | loki.loki.containerSecurityContext.capabilities.drop[0] (*string*) | Default: `"ALL"` | | loki.loki.containerSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | loki.singleBinary.replicas (*int*) | Number of replicasDefault: `1` | | loki.singleBinary.extraEnv[0].name (*string*) | Default: `"LOKI_ADDR"` | | loki.singleBinary.extraEnv[0].value (*string*) | Default: `"http://localhost:3100"` | | loki.singleBinary.persistence.size (*string*) | Size of persistent diskDefault: `"10Gi"` | | loki.singleBinary.persistence.storageClass (*string*) | Storage class to be usedDefault: `""` | | loki.singleBinary.resources.requests.cpu (*string*) | Specify CPU request for LokiDefault: `"100m"` | | loki.singleBinary.resources.requests.memory (*string*) | Specify Memory request for LokiDefault: `"256Mi"` | | clickhouse.enabled (*bool*) | Default: `false` | | clickhouse.serverConfig.CACHE_MAX_SIZE (*string*) | Default: `"48Gi"` | | clickhouse.serverConfig.MAX_CONCURRENT_QUERIES (*string*) | Default: `"32"` | | clickhouse.serverConfig.MAX_EXECUTION_TIME (*string*) | Default: `"55"` | | clickhouse.serverConfig.MAX_BYTES_RATIO_BEFORE_EXTERNAL_GROUP_BY (*string*) | Default: `"0.4"` | | clickhouse.serverConfig.MAX_BYTES_RATIO_BEFORE_EXTERNAL_SORT (*string*) | Default: `"0.4"` | | clickhouse.serverConfig.MAX_SERVER_MEMORY_USAGE_TO_RAM_RATIO (*string*) | Default: `"0.9"` | | clickhouse.serverConfig.PARTS_TO_DELAY_INSERT (*string*) | Default: `"1000"` | | clickhouse.serverConfig.PARTS_TO_THROW_INSERT (*string*) | Default: `"3000"` | | clickhouse.serverConfig.NON_REPLICATED_DEDUPLICATION_WINDOW (*string*) | Default: `"1000"` | | clickhouse.backup (*object*) | Ship a ServiceMonitor for the backup sidecar's Prometheus metrics (requires Prometheus Operator CRDs)Default: `{"metrics":{"enabled":false}}` | | clickhouse.backupConfig (*object*) | clickhouse-backup sidecar's provider-agnostic settings, see sidecars' own commentDefault: `{"ALLOW_EMPTY_BACKUPS":"true","BACKUPS_TO_KEEP_REMOTE":"7","DOWNLOAD_CONCURRENCY":"2","LOG_LEVEL":"info","REBASE_BEFORE_REMOVE_OLD_REMOTE":"true","REBASE_CONCURRENCY":"2","REMOTE_STORAGE":"s3","S3_CONCURRENCY":"2","UPLOAD_CONCURRENCY":"2","WATCH_SCHEDULES":"name=ch-bkp,full=0 2 * * 0,increment=0 2 * * *,full_type=rebase,delete_previous_cycle=false"}` | | clickhouse-server.serviceAccount.create (*bool*) | Default: `true` | | clickhouse-server.serviceAccount.name (*string*) | Default: `"clickhouse"` | | clickhouse-server.serviceAccount.annotations (*object*) | Default: `{}` | | clickhouse-server.metrics (*object*) | Ship a ServiceMonitor for ClickHouse's own Prometheus metrics (requires Prometheus Operator CRDs, requires metrics.enabled)Default: `{"enabled":false,"serviceMonitor":{"enabled":false}}` | | clickhouse-server.image.registry (*string*) | Default: `"proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com"` | | clickhouse-server.image.repository (*string*) | Default: `"cgr.dev/gitguardian.com/clickhouse-iamguarded"` | | clickhouse-server.image.tag (*string*) | Default: `"26.2"` | | clickhouse-server.image.pullSecrets[0].name (*string*) | Default: `"gim-replicated-registry"` | | clickhouse-server.commonAnnotations (*object*) | Default: `{}` | | clickhouse-server.podAnnotations (*object*) | Default: `{}` | | clickhouse-server.podLabels (*object*) | Default: `{}` | | clickhouse-server.priorityClassName (*string*) | Default: `""` | | clickhouse-server.nodeSelector (*object*) | Default: `{}` | | clickhouse-server.tolerations (*list*) | Default: `[]` | | clickhouse-server.podSecurityContext.enabled (*bool*) | Default: `true` | | clickhouse-server.podSecurityContext.runAsUser (*int*) | Default: `1001` | | clickhouse-server.podSecurityContext.runAsGroup (*int*) | Default: `1001` | | clickhouse-server.podSecurityContext.runAsNonRoot (*bool*) | Default: `true` | | clickhouse-server.podSecurityContext.seccompProfile.type (*string*) | Default: `"RuntimeDefault"` | | clickhouse-server.containerSecurityContext.enabled (*bool*) | Default: `true` | | clickhouse-server.initdbScripts."00-create-gim-db.sql" (*string*) | Default: `"CREATE DATABASE IF NOT EXISTS gim;\n"` | | clickhouse-server.persistence.enabled (*bool*) | Default: `true` | | clickhouse-server.persistence.size (*string*) | Default: `"20Gi"` | | clickhouse-server.persistence.accessModes[0] (*string*) | Default: `"ReadWriteOnce"` | | clickhouse-server.extraVolumeClaimTemplates[0].metadata.name (*string*) | Default: `"cache"` | | clickhouse-server.extraVolumeClaimTemplates[0].spec.accessModes[0] (*string*) | Default: `"ReadWriteOnce"` | | clickhouse-server.extraVolumeClaimTemplates[0].spec.resources.requests.storage (*string*) | Default: `"50Gi"` | | clickhouse-server.extraVolumeMounts[0].name (*string*) | Default: `"cache"` | | clickhouse-server.extraVolumeMounts[0].mountPath (*string*) | Default: `"/cache"` | | clickhouse-server.resources.requests.cpu (*int*) | Default: `4` | | clickhouse-server.resources.requests.memory (*string*) | Default: `"16Gi"` | | clickhouse-server.resources.limits.cpu (*int*) | Default: `4` | | clickhouse-server.resources.limits.memory (*string*) | Default: `"16Gi"` | | clickhouse-server.configdFiles (*object*) | Default: `{}` | | clickhouse-server.usersdFiles (*object*) | Default: `{}` | | clickhouse-server.extraEnvVars (*list*) | Default: `[]` | | experimental (*object*) | Experimental featuresDefault: *Not set* | | experimental.tini (*bool*) | Enable tini to terminate zombie processes on workersDefault: `true` | | experimental.ingressRoutes (*bool*) | Use Ingress routes instead of legacy nginx ⚠️ WARNING: This feature is deprecated and should not be used.Default: `false` | --- ## High availability Achieving a high-availability (HA) setup for the GitGuardian application requires configuring several components. ### Kubernetes cluster The foundation of a high-availability setup is a robust Kubernetes cluster. ### Existing cluster If you are using an existing cluster deployed via either [KOTS](../../installation/installation-existing-cluster-kots) or [Helm](../../installation/installation-existing-cluster-helm), ensure it is configured for **high availability**. Kubernetes provides support for high availability out-of-the-box, as long as the pods are distributed across multiple nodes. ### Embedded cluster :::caution High Availability (HA) on an embedded cluster isn't recommended nor supported by GitGuardian. For HA setups, leveraging a managed existing cluster is advised. ::: ## Rolling Updates Kubernetes natively supports rolling updates, which allows for seamless application updates without downtime. This feature is common to all installation types, ensuring that updates can be applied smoothly while maintaining high availability. ## Deployments & Pods Pod configurations are optimized to distribute across nodes evenly, minimizing the impact of a node failure. No additional configuration is required on your part. ## Databases & Datastores Both Redis and PostgreSQL require HA configurations. The embedded versions of these services don't support high availability, necessitating the use of external, HA-configured versions. ### ClickHouse [ClickHouse](./clickhouse/overview) runs as a [**single-node** topology](./clickhouse/sizing), which is not highly available: a node restart, upgrade, or failure takes it down until it recovers. --- ## Ingress routes (legacy) :::warning Ingress routes are a legacy experimental feature that is no longer recommended. Please use the standard **[nginx-based ingress configuration](./ingress)** instead. ::: :::info This page only concerns installation on an existing cluster using **[Helm](/self-hosting/installation/installation-existing-cluster-helm)**. ::: ## Overview We redesigned how we access the cluster using Ingress to get rid of our all-in-one nginx container. This option works for a limited number of Ingress Controller: ingress-nginx, traefik, contour, aws_alb, openshift, istio. Activation is optional and disabled by default. ![Ingress routes](/img/self-hosting/management/infrastructure-management/new_ingress_routes.png) ## Activation To activate Ingress routes, update the `values.yaml`: ```yaml experimental: # -- Use new Ingress routes instead of legacy nginx ingressRoutes: true ``` If you notice any unwanted behavior, please let us know and switch back to `ingressRoutes: false`. ## Ingress-NGINX Configuration If you are using `Ingress-NGINX` as your ingress controller, by default, it blocks custom directive injection via annotations. To allow GitGuardian to configure `Ingress-NGINX` using the `nginx.ingress.kubernetes.io/configuration-snippet` annotation, you must explicitly enable snippets in your deployment configuration. Here is an example of the necessary configuration to add to the `Ingress-NGINX` Helm chart values: ```yaml controller: allowSnippetAnnotations: true config: # configuration-snippet annotation is considered "Critical" annotations-risk-level: "Critical" ``` --- ## Ingress :::info This page only concerns installation on an existing cluster using **[KOTS](/self-hosting/installation/installation-existing-cluster-kots)** or **[Helm](/self-hosting/installation/installation-existing-cluster-helm)**. ::: ## Helm-based installation In your `values.yaml` file, add the following extract, adapted to your needs: ```yaml ingress: enabled: true # -- Ingress controller in use in the cluster. Mandatory if using istio or `experimental.ingressRoutes=true` # Supported: ingress-nginx / traefik / contour / aws_alb / openshift (Openshift Route) / istio controller: 'ingress-nginx' pathType: 'Prefix' path: '/' ingressClassName: 'my-class-name' annotations: kubernetes.io/ingress.class: # for ingress controllers that do not support ingressClassName labels: example.of.a.label: 'my-label' tls: enabled: true existingSecret: 'secret-containing-the-ingress-tls-certificates' istio: # -- Istio revision, if any revision: '' gateway: # -- Enable Istio gateway handling enabled: false # -- Istio Gateway name name: '' # -- Istio Gateway namespace namespace: '' # -- Istio Gateway selector selector: 'ingressgateway' ``` See **[TLS certificate](../../security/tls-certificates.md#helm-based-installation)** for help configuring TLS. :::tip Gateway API GitGuardian's Helm chart can also expose external traffic through the Kubernetes Gateway API instead of the legacy `Ingress` resource. This is useful in multi-tenant clusters or when your platform team has standardized on Gateway API. See **[Gateway API](./gateway-api.md)**. ::: :::note Legacy Feature The experimental Ingress routes feature is deprecated. For existing users, see **[Legacy Ingress routes](./ingress-routes-legacy)**. New deployments should use the standard nginx-based routing. ::: ## KOTS-based installation On existing clusters, a default Ingress is provided. This default Ingress is backed by a Kubernetes service (named `gitguardian`). The default ingress is customizable, allowing modifications to className, pathType, Annotations/Labels. **[TLS](../../security/tls-certificates.md)** will be enabled if you upload a certificate in **TLS certificates** section. In the [KOTS Admin Console](./admin-console), you may configure the following parameters: - **ClassName** of the resource to use - **PathType** and **Path** to route to the GitGuardian instance - **Annotations** and **Labels** specific to your ingress controller ![Ingress](/img/self-hosting/management/infrastructure-management/replicated_ingress.png) ## Using your own Ingress You have the option to disable the default Ingress and set up your own. Here's how you can go about it based on your installation type: ### Helm-based installation In the `values.yaml` file, set the `ingress.enabled` parameter to `false`. ### KOTS-based installation In the [KOTS Admin Console](./admin-console), simply use a Service. ![Ingress annotations](/img/self-hosting/management/infrastructure-management/replicated_custom_ingress.png) ### Custom ingress configuration If you opt to use your own Ingress, here are the fields you would need to modify: - `defaultBackend` - `ingressClassName` (use this for Ingress controllers that support it; otherwise, use the deprecated `kubernetes.io/ingress.class` annotation) - `rules` - `tls` To get more details on each of these fields, run the command `kubectl explain ingress.spec`. ### Protocol configuration The service backend is configured to listen only on HTTPS, and your Ingress needs to be set up accordingly. If you are utilizing the [NGINX Ingress controller](https://docs.nginx.com/nginx-ingress-controller/intro/overview/), this configuration is already handled in the included Ingress through the `nginx.ingress.kubernetes.io/backend-protocol: HTTPS` annotation. However, if you are using a different Ingress controller, you may need to add the necessary annotations in the provided text area. ### Sample configuration Below is an example of how a custom Ingress configuration might look: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: # for ingress controllers that do not support ingressClassName labels: kots.io/app-slug: gitguardian-seal kots.io/backup: velero name: gitguardian namespace: spec: ingressClassName: # for ingress controllers that support this field rules: - host: http: paths: - backend: service: name: gitguardian port: number: 443 path: / pathType: Prefix tls: - hosts: - secretName: # when using a kubernetes secret ``` --- ## IPv6 networking GitGuardian self-hosted supports IPv4, IPv6, and dual-stack networking configurations for maximum flexibility in modern cloud and on-premises environments. IPv6 is available exclusively for Helm-based installations. :::tip When to use IPv6 IPv6 support is useful when: - Your Kubernetes cluster is IPv6-only or dual-stack - You're migrating from IPv4 to IPv6 - Cloud provider requirements (some AWS regions encourage IPv6-only) - Corporate security policies require IPv6 ::: ## Quick start ### Helm values IPv6 support can activated via the Helm chart value `network.ipFamily`. | Your cluster setup | Use `network.ipFamily` | Notes | | --- | --- | --- | | **IPv4-only** (default) | `ipv4` | Backward compatible, no changes needed | | **IPv6-only** | `ipv6` | All services use IPv6 addresses only | | **Dual-stack** | `dualstack` or `ipv6` | See platform-specific notes below | ### Platform-specific considerations #### AWS EKS :::warning EKS dual-stack limitation AWS EKS does not support true dual-stack Kubernetes services. Even when your VPC is dual-stack, Kubernetes services must be **either** IPv4 **or** IPv6, not both. **Always use `ipFamily: 'ipv6'` on EKS**, even when your VPC is dual-stack. ::: Your pods in a dual-stack EKS VPC can still reach both IPv4 and IPv6 external services (databases, Redis, APIs), but Kubernetes services themselves will only have IPv6 addresses. #### Google GKE GKE fully supports dual-stack services where services receive both IPv4 and IPv6 addresses simultaneously. **Requirements:** - GKE cluster with `stack_type = "IPV4_IPV6"` - Advanced Datapath (Dataplane V2) enabled - Kubernetes 1.28+ You can use any `ipFamily` value (`ipv4`, `ipv6`, or `dualstack`) based on your needs. #### Azure AKS AKS supports dual-stack services similar to GKE. Services can have both IPv4 and IPv6 addresses. You can use any `ipFamily` value based on your needs. #### On-premises IPv6 support depends on your CNI plugin and cluster configuration: | CNI Plugin | IPv6 Support | | --- | --- | | Calico | ✅ Full support | | Cilium | ✅ Full support | | Flannel | ⚠️ Limited (IPv6-only, no dual-stack) | | Weave Net | ⚠️ Experimental | We recommend testing your cluster's IPv6 capabilities before deploying in production. ## Prerequisites ### Cluster requirements 1. **Kubernetes 1.28+** (required for stable dual-stack support) 2. **IPv6-enabled cluster**: Verify with: ```bash kubectl get nodes -o jsonpath='{.items[*].spec.podCIDRs}' ``` You should see IPv6 CIDRs like `2001:db8::/64` 3. **CNI plugin with IPv6 support**: AWS VPC CNI, Calico, Cilium, etc. ### PostgreSQL Your PostgreSQL must be IPv6-accessible: **Cloud providers:** - **AWS RDS**: Set `network_type = "DUAL"` - **Google Cloud SQL**: IPv6 is automatically available - **Azure Database for PostgreSQL**: Enable IPv6 in networking settings **Self-hosted**: Ensure `listen_addresses` includes IPv6: ```ini # postgresql.conf listen_addresses = '::' # Listen on all IPv4 and IPv6 addresses ``` And configure `pg_hba.conf` for IPv6 connections: ``` host all all 2001:db8::/32 md5 ``` ### Redis Your Redis must be IPv6-accessible: **Cloud providers:** - **AWS ElastiCache**: Set `network_type = "dual_stack"` - **Google Memorystore**: IPv6 is automatically available for certain tiers. However, Memorystore for Redis instances is not compatible with IPv6. - **Azure Cache for Redis**: Enable IPv6 in networking settings **Self-hosted**: Ensure Redis binds to IPv6: ```ini # redis.conf bind :: 0.0.0.0 ``` ### Network connectivity Different IPv6 cluster configurations have different connectivity capabilities: | Cluster Type | Can reach IPv4 services | Can reach IPv6 services | Common setup | | --- | --- | --- | --- | | **Dual-stack** | ✅ Yes | ✅ Yes | Most common, recommended | | **IPv6-only with NAT64/DNS64** | ✅ Yes (via translation) | ✅ Yes | AWS EKS default | | **IPv6-only without NAT64** | ❌ No | ✅ Yes | Rare, not recommended | :::info NAT64/DNS64 NAT64 and DNS64 enable IPv6-only pods to reach IPv4-only external services by translating IPv6 requests to IPv4. AWS EKS enables this by default for IPv6 clusters. ::: ## Configuration ### Helm values configuration Add the `network.ipFamily` configuration to your Helm values file: #### IPv4-only (default) ```yaml # No configuration needed - this is the default network: ipFamily: 'ipv4' ``` #### IPv6-only ```yaml network: ipFamily: 'ipv6' # PostgreSQL and Redis must be IPv6-accessible postgresql: host: '2001:db8::1234' # IPv6 address or hostname with AAAA record redis: main: host: '2001:db8::5678' ``` You must also configure Loki for IPv6. See [Loki IPv6 configuration](#loki-ipv6-configuration) below. #### Dual-stack (GKE/AKS) ```yaml network: ipFamily: 'dualstack' postgresql: host: 'postgres.example.com' # Must have A or AAAA DNS record redis: main: host: 'redis.example.com' ``` Loki IPv6 configuration is optional for dual-stack (components can use IPv4). ### Loki IPv6 configuration Loki requires explicit IPv6 configuration in IPv6-only clusters because it uses memberlist for service discovery between components. Add this to your Helm values: ```yaml loki: loki: commonConfig: ring: instance_enable_ipv6: true kvstore: store: "memberlist" compactor: compactor_ring: instance_enable_ipv6: true distributor: ring: instance_enable_ipv6: true extraMemberlistConfig: bind_addr: - '::' frontend: instance_enable_ipv6: true index_gateway: ring: instance_enable_ipv6: true ingester: lifecycler: enable_inet6: true pattern_ingester: enabled: true lifecycler: enable_inet6: true query_scheduler: scheduler_ring: instance_enable_ipv6: true ruler: ring: instance_enable_ipv6: true ``` | Requirement | Notes | | --- | --- | | **IPv6-only** | Required - components cannot communicate without it | | **Dual-stack** | Optional - components can fall back to IPv4 | ## Deployment :::tip Preflights When your external databases are IPv6-ready, test connectivity using our [preflights](../../installation/installation-existing-cluster-helm#run-preflight-checks-). ::: ### Upgrading existing IPv4 deployment #### To dual-stack (GKE/AKS - zero downtime) Dual-stack upgrades are seamless because existing IPv4 services continue working while IPv6 is added: ```yaml # values-ipv6.yaml network: ipFamily: 'dualstack' ``` ```bash helm upgrade gitguardian gitguardian/gitguardian \ --namespace gitguardian \ -f values.yaml \ -f values-ipv6.yaml ``` #### To IPv6-only (requires planning) :::caution Downtime required Migrating to IPv6-only requires service disruption as IP addresses change. ::: 1. **Backup your data** 2. **Migrate PostgreSQL and Redis to IPv6** 3. **Update Helm values**: ```yaml network: ipFamily: 'ipv6' postgresql: host: '2001:db8::1234' # New IPv6 address redis: main: host: '2001:db8::5678' # New IPv6 address ``` 4. **Deploy**: ```bash helm upgrade gitguardian gitguardian/gitguardian \ --namespace gitguardian \ -f values.yaml \ -f values-ipv6.yaml ``` 5. **Update DNS records** to AAAA records 6. **Test connectivity** ## Validation After deployment, verify IPv6 is working: ### Check service IP addresses ```bash kubectl get svc -n gitguardian -o wide ``` Services should show IPv6 addresses (e.g., `2001:db8:1234:5678::a`) or both IPv4 and IPv6 for dual-stack. ### Test connectivity ```bash # Get service IP and test health endpoint SERVICE_IP=$(kubectl get svc internal-api -n gitguardian -o jsonpath='{.spec.clusterIP}') kubectl run test-ipv6 --rm -it --image=curlimages/curl -- \ curl -v "http://[$SERVICE_IP]:5050/api/v1/health" ``` ### Check application logs ```bash kubectl logs -n gitguardian deployment/webapp-internal-api --tail=50 ``` Look for Gunicorn binding to `[::]` and no connection errors to PostgreSQL/Redis. ## Troubleshooting ### Services not getting IPv6 addresses **Symptoms**: Services show `` or only IPv4 addresses **Checklist**: 1. Verify cluster has IPv6 service CIDR: `kubectl cluster-info dump | grep -i service-cluster-ip-range` 2. Check `network.ipFamily` is set correctly in Helm values 3. For EKS, verify cluster was created with `ip_family = "ipv6"` ### PostgreSQL connection failures **Symptoms**: `could not translate host name to address` **Checklist**: 1. Test connectivity: `kubectl run test-pg --rm -it --image=postgres:16 -- psql -h 2001:db8::1234 -U gitguardian` 2. Verify DNS returns AAAA records (if using hostname) 3. Check PostgreSQL `listen_addresses` includes `::` 4. Verify `pg_hba.conf` allows your IPv6 subnet ### Redis connection failures **Symptoms**: `ConnectionError: Error connecting to Redis` **Checklist**: 1. Test connectivity: `kubectl run test-redis --rm -it --image=redis:7 -- redis-cli -h 2001:db8::5678 PING` 2. Check Redis `bind` config includes `::` 3. Use correct URL format: `redis://[2001:db8::5678]:6379` (brackets required for IPv6) ### Nginx fails to start **Symptoms**: `bind() to [::]:80 failed (99: Cannot assign requested address)` **Solution**: Your cluster doesn't support IPv6. Verify CNI plugin supports IPv6 or use `network.ipFamily: 'ipv4'`. ### Application crashes with port parsing error **Symptoms**: `'' is not a valid port number` **Solution**: Don't set both `redis.main.url` and `redis.main.host`. Use one or the other: - URL format: `redis.main.url: 'redis://[2001:db8::5678]:6379'` - Or host/port: `redis.main.host: '2001:db8::5678'` with `redis.main.port: 6379` ### Loki fails to start or components can't communicate **Symptoms**: `failed to join memberlist`, `no healthy instances in ring`, or `too many unhealthy instances in the ring` **Solution**: Ensure the complete [Loki IPv6 configuration](#loki-ipv6-configuration) is applied. The most commonly missed setting is `extraMemberlistConfig.bind_addr: ['::']`. After fixing configuration, restart Loki: ```bash kubectl rollout restart deployment/loki-backend -n gitguardian kubectl rollout restart statefulset/loki-write -n gitguardian kubectl rollout restart statefulset/loki-read -n gitguardian ``` ## Ingress and load balancers ### AWS Application Load Balancer (ALB) ```yaml ingress: controller: aws_alb annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/ip-address-type: dualstack alb.ingress.kubernetes.io/target-type: ip ``` ### Nginx Ingress Controller ```yaml controller: service: ipFamilyPolicy: PreferDualStack ipFamilies: [IPv4, IPv6] ``` ### Istio Gateway ```bash kubectl patch svc istio-ingressgateway -n istio-system \ -p '{"spec":{"ipFamilyPolicy":"PreferDualStack","ipFamilies":["IPv4","IPv6"]}}' ``` ## Performance considerations IPv6 has comparable performance to IPv4 with negligible latency difference. In IPv6-only clusters with NAT64/DNS64, expect ~5-10ms translation overhead when accessing IPv4-only external services. ## Security considerations - **Firewall rules**: Add `ip6tables` rules alongside your `iptables` rules - **Network policies**: Include IPv6 CIDRs in your Kubernetes NetworkPolicy `ipBlock` rules - **TLS/SSL**: Works identically to IPv4 (same certificates, protocols, and cipher suites) ## Backward compatibility All IPv6 changes are **100% backward compatible**. Existing IPv4 deployments continue working without changes—no Helm value changes or application code changes required unless you're enabling IPv6. ## Cost optimization | Platform | Potential savings | | --- | --- | | **AWS EKS** | $40-100/month (no NAT Gateway or public IPv4 costs) | | **GCP GKE** | Minimal impact (IPv6 addresses are free) | ## Additional resources - [Kubernetes IPv6/Dual-stack Documentation](https://kubernetes.io/docs/concepts/services-networking/dual-stack/) - [AWS EKS IPv6 Documentation](https://docs.aws.amazon.com/eks/latest/userguide/cni-ipv6.html) - [GCP GKE IPv6 Documentation](https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips#ipv6) - [PostgreSQL IPv6 Configuration](https://www.postgresql.org/docs/current/runtime-config-connection.html) - [Redis IPv6 Configuration](https://redis.io/docs/management/config/) ## Support When reporting IPv6-related issues, please provide: ```bash # Kubernetes version kubectl version --short # Cluster IP families kubectl cluster-info dump | grep -i service-cluster-ip-range # CNI plugin kubectl get pods -n kube-system | grep -i cni # Service configuration kubectl get svc internal-api -n gitguardian -o yaml # Pod logs kubectl logs deployment/webapp-internal-api -n gitguardian --tail=100 # Helm values (redact sensitive information) helm get values gitguardian -n gitguardian ``` --- ## Load balancer ## Existing clusters (Helm-based or KOTS-based) :::info This section only concerns installation on an existing cluster using **[KOTS](/self-hosting/installation/installation-existing-cluster-kots)** or **[Helm](/self-hosting/installation/installation-existing-cluster-helm)**. ::: ### Helm-based installation The Kubernetes cluster must include a LoadBalancer controller add-on (for AWS, this would be an ALB), which is not provided by our Helm charts. This setup is an alternative to using Ingress, which is not activated by default in the On-Prem values. Customers need to override these values to access the dashboard via a LoadBalancer. Switch the frontend serviceType from `ClusterIP` to `LoadBalancer` in your `local-values.yaml` file: ```yaml front: service: type: LoadBalancer annotations: # example when using an ELB on AWS service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:iam::12345678 ``` ### KOTS-based installation For existing clusters, the Service type can be changed from ClusterIP to LoadBalancer. This allows for the creation of a dedicated cloud load balancer (e.g., an AWS Application Load Balancer) specifically for the GitGuardian dashboard. Note: This modification does not impact the KOTS Admin Console, which remains accessible only through port forwarding, unless manually configured otherwise. #### Annotations Annotations enable service customization. For example, on AWS, you can add the following annotations in the KOTS Admin Console's annotations section: ``` service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:iam::12345678 ``` You can add those in the annotations section of the [KOTS Admin Console](./admin-console). ![Loadbalancer annotations](/img/self-hosting/management/infrastructure-management/replicated_loadbalancer_service.png) ## Embedded clusters ### Configure your instance to work behind a load balancer In case you plan to expose your embedded cluster behind a load balancer (allowing your cluster to run in private network), you may need to configure additional settings. The GitGuardian dashboard on an Embedded cluster installation is, by default, exposed using an HTTPs configuration that requires [SNI TLS extension](https://en.wikipedia.org/wiki/Server_Name_Indication). Unfortunately, some load balancers (such as AWS ones) are not able to deal with SNI enforced backends. In KOTS, check the parameter `Use NodePort Service` and choose to expose a port (for example `8080`). Then: - On the instance firewall/security group, allow connection from the load balancer to instance port `8080`. - On the load balancer: - Configure certificate(s) to terminate the TLS connection. Endpoint should match the hostname you use in the configuration. - Target the instance on port `8080`. - For instance health checks, you can target the `/health` endpoint. --- ## Network policies GitGuardian self-hosted ships built-in Kubernetes `NetworkPolicy` resources that isolate the GIM namespace from the rest of the cluster. When enabled, ingress from outside the namespace is **denied by default** and only namespaces you explicitly allow can reach GitGuardian pods. Network policies are available for Helm-based installations and configured entirely through Helm values under the top-level `networkPolicy.*` keys. Full value reference: [Helm values](./helm-values). :::info Kubernetes requirements `NetworkPolicy` objects are enforced by your **CNI plugin** (Calico, Cilium, AWS VPC CNI with policy enforcement, etc.). Make sure your cluster has a policy-enforcing CNI before enabling this feature — otherwise the policies are deployed but ignored. ::: ## Quick start The recommended rollout is a **two-step process**: deploy in `dryrun` first to validate your configuration, then switch to `enforce` to activate blocking. ### 1. Deploy in dryrun mode In `dryrun` mode, all policies are applied but a temporary allow-all rule prevents any traffic from being blocked. Use this phase to review the generated policies and identify every namespace that needs to talk to GIM. ```yaml networkPolicy: enabled: true mode: dryrun allowedNamespaces: - ingress-nginx - monitoring ``` Inspect the deployed policies and your traffic patterns (CNI logs, service mesh metrics, etc.) to confirm nothing legitimate would be blocked. ### 2. Switch to enforce mode Once you're confident, remove the safety net by switching to `enforce`: ```yaml networkPolicy: enabled: true mode: enforce allowedNamespaces: - ingress-nginx - monitoring ``` Ingress from any namespace not in `allowedNamespaces` is now actively blocked. ## Configuration reference | Value | Default | Description | | --- | --- | --- | | `networkPolicy.enabled` | `false` | Enable NetworkPolicy resources for the GIM namespace. | | `networkPolicy.mode` | `dryrun` | `dryrun`: policies are deployed with an allow-all safety net. `enforce`: the allow-all is removed and policies actively block unauthorized ingress. | | `networkPolicy.allowedNamespaces` | `[]` | Namespaces allowed to reach GIM pods. Include your ingress controller, monitoring stack, and any other workload that needs access. Example: `["ingress-nginx", "monitoring"]`. | | `networkPolicy.extraPolicies` | `[]` | Full `NetworkPolicy` spec entries rendered alongside the defaults. Use this for custom allow/deny rules outside of the `allowedNamespaces` model. | ### Custom policies Use `networkPolicy.extraPolicies` when you need rules that don't fit the `allowedNamespaces` pattern (e.g. egress restrictions, pod-selector-based rules). Each entry is rendered as a full `NetworkPolicy` spec: ```yaml networkPolicy: enabled: true mode: enforce allowedNamespaces: - ingress-nginx extraPolicies: - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-external-smtp spec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 10.0.0.0/24 ports: - protocol: TCP port: 587 ``` ## Troubleshooting - **Traffic blocked unexpectedly**: Go back to `mode: dryrun`, then add the missing namespace to `allowedNamespaces` before switching back to `enforce`. - **Policies deployed but not enforced**: Check that your CNI plugin supports `NetworkPolicy` enforcement. Run `kubectl get networkpolicies -n ` to confirm the resources exist. - **Ingress controller unable to reach GIM**: The namespace of your ingress controller (e.g. `ingress-nginx`, `istio-system`) must be listed in `allowedNamespaces`. --- ## HTTP Proxy GitGuardian allows you to configure an HTTP proxy for outgoing traffic from the application. This includes traffic to services like Replicated, Docker, messaging integrations, and other external connections. For more details, refer to our [Network Requirements](../../network-requirements#outbound-rules) page. :::caution - You must add `127.0.0.1,10.0.0.0/8` to the list of proxy exceptions `NO_PROXY` to permit the local and internal cluster traffic through the proxy (replace `10.0.0.0/8` with your internal subnet). - Verify the proxy FQDNs are resolvable and reachable within your Kubernetes cluster. - Specifying password in proxy URLs is supported. - GitGuardian can be deployed with both HTTP and HTTPS proxies. For the HTTPS proxy, it may be necessary to add a Certificate Authority (CA) so that the proxy's SSL certificate is trusted. This process ensures secure and reliable communication between the application and the proxy. For more information, please refer to the **[custom CA section](../../security/custom-ca)**. ::: ## Helm-based installation To configure a **proxy** for [outgoing](../../network-requirements#outbound-rules) HTTP(s) traffic, update your Helm `values` file accordingly. If you are using a custom Certificate Authority (CA), ensure it is configured both under `replicated.privateCASecret` and within the application configuration under `tls.customCa`. For more details, refer to the [Custom CA](../../security/custom-ca#helm-based-installation) documentation. :::info From **2025.5.0** version, proxy urls are always stored as Secret. ::: ### Using an existing secret :::info The secret must be present before the installation of GitGuardian. ::: The following example will set the `http_proxy` and `https_proxy` keys of the `gim-proxy` Kubernetes Secret. ```yaml proxy: noProxyHostNames: - 127.0.0.1 - 10.0.0.0/8 existingSecret: 'gim-proxy' existingSecretKeys: httpProxyUrl: 'http_proxy' # Secret should contain: http://username:password@proxy.company.com:8080 httpsProxyUrl: 'https_proxy' # Secret should contain: https://username:password@proxy.company.com:8080 replicated: privateCASecret: # optional if you are using a custom CA name: custom-ca-secret-name key: 'custom-ca.pem' extraEnv: - name: NO_PROXY valueFrom: configMapKeyRef: name: gim-config key: 'NO_PROXY' - name: HTTP_PROXY valueFrom: secretKeyRef: name: 'gim-proxy' key: 'http_proxy' # Example: http://username:password@proxy.company.com:8080 - name: HTTPS_PROXY valueFrom: secretKeyRef: name: 'gim-proxy' key: 'https_proxy' # Example: https://username:password@proxy.company.com:8080 ``` ### Using inline values :::info When using this method, GitGuardian chart will handle the Kubernetes Secret containing proxy urls for you. ::: ```yaml proxy: httpProxyUrl: 'http://proxy:8080' httpsProxyUrl: 'http://proxy:8080' noProxyHostNames: - 127.0.0.1 - 10.0.0.0/8 ``` ## KOTS-based installation In the [KOTS Admin Console](./admin-console), you can configure the URL(s) for the [outgoing](../../network-requirements#outbound-rules) HTTP(s) traffic to your proxy server: ![Services and components](/img/self-hosting/management/infrastructure-management/proxy.png) ## Embedded cluster-specific For embedded cluster installations, additional proxy configuration may be required at the cluster level to handle container image pulls and system-level communications. :::info The embedded cluster-level proxy configuration handles system-level traffic (container image pulls, Kubernetes API communications), while the application-level proxy configuration described above handles GitGuardian application traffic (integrations, notifications, etc.). Both may be needed depending on your environment. ::: For the embedded cluster installation method, you can configure proxy settings during installation. To configure an HTTP proxy without authentication during installation: ```bash LICENSE_ID=your_license curl -f https://replicated.app/embedded/gitguardian/stable -H "Authorization: $LICENSE_ID" -o gitguardian.tgz tar -xvzf gitguardian.tgz sudo ./gitguardian install --license license.yaml \ --http-proxy http://proxy.example.com:8080 \ --https-proxy http://proxy.example.com:8080 ``` When using a proxy that requires authentication, you can include credentials in the proxy URL: ```bash sudo ./gitguardian install --license license.yaml \ --http-proxy http://username:password@proxy.example.com:8080 \ --https-proxy http://username:password@proxy.example.com:8080 ``` However, **some Kubernetes components do not support authenticated proxies**. If you encounter issues with container image pulls (such as `ImagePullBackOff` errors), you may need to apply the workaround described below. **Workaround for Authenticated Proxy Issues** The embedded cluster creates proxy configuration in `/etc/systemd/system/k0scontroller.service.d/http-proxy.conf`. To work around authentication issues: 1. **Locate the proxy configuration file**: ```bash sudo cat /etc/systemd/system/k0scontroller.service.d/http-proxy.conf ``` 2. **Edit the file to prefix environment variables with `CONTAINERD_`**: ```bash sudo vi /etc/systemd/system/k0scontroller.service.d/http-proxy.conf ``` 3. **Modify the file to look like this**: ```ini [Service] Environment="CONTAINERD_HTTP_PROXY=http://username:password@proxy.example.com:8080" Environment="CONTAINERD_HTTPS_PROXY=http://username:password@proxy.example.com:8080" Environment="CONTAINERD_NO_PROXY=localhost,127.0.0.1,.cluster.local,.svc,10.244.0.0/16" ``` 4. **Restart the k0s controller service**: ```bash sudo systemctl daemon-reload sudo systemctl restart k0scontroller ``` 5. **Verify proxy configuration** by checking that pods can pull images and external connectivity works: ```bash sudo ./gitguardian shell kubectl get pods -A kubectl run test-pod --image=curlimages/curl --rm -it --restart=Never -- curl -I https://www.gitguardian.com ``` --- ## Scaling ## Application topology GitGuardian application consists of several Kubernetes resources. Here are key aspects based on the installation type: - **KOTS-based Installations**: Allows configuration of replicas, CPU, and memory requests/limits for main deployments/pods. - **Helm-based Installations**: Provides more comprehensive customization, including: - Creation of new classes of workers. - Customization of other resource types such as ephemeral storage, huge pages, etc. - Setting nodeSelector, tolerations, and additional configurations. For detailed insights into deployment/pod names, types, and their usage, visit the [GitGuardian Application Topology](../../troubleshoot/topology) page. ## Scaling for GitGuardian: Historical Scans, Real-Time Scans, Public API and ML Secret Engine When using GitGuardian for monitoring repositories, it's crucial to scale the resources appropriately for historical scans, real-time scans, and public API requests. This ensures efficient and timely processing regardless of the load. These recommendations are only for **[existing cluster installations](../../installation/choose-embedded-existing#what-is-an-existing-cluster-installation)**. ### General Guidelines :::tip Performing your first Historical Scans When you add a high number of sources, consider temporarily increasing the number of pods for the time of the initial historical scan. Afterward, you can decrease those pods' replicas and resources. ::: When performing [a historical scan](../../../internal-monitoring/integrate-sources/monitored-perimeter#historical-scanning) on a git repository, GitGuardian clones the repository on the pod's ephemeral storage and will traverse all branches and commits in search of potential secrets. The full scan is done by a single Pod and can last from a few seconds to many hours depending on the repository size. The more pods you'll add, the more historical scans can be done concurrently. When sizing your nodes, keep in mind that each Pod must have enough ephemeral storage and memory to run. **To improve performance and reduce scan times, it is recommended to use SSD disks for the ephemeral storage.** For real-time scans, these are triggered by `Push` events sent by the VCS to GitGuardian. These scans typically complete in under a second and should always be under 3 seconds. To handle peaks of pushes, you may want to increase the count of `worker-worker` Pods that are processing real-time scans. The public API, used mainly by [ggshield](../../../platform/gitguardian-suite/gitguardian-cli-ggshield), is deployed under the `webapp-public_api` pod. This pod is essential for enabling interactions between ggshield and GitGuardian. To ensure the public API can handle the expected traffic, you may need to adjust the number of `webapp-public_api` Pods. The `webapp-internal_api` pods handle internal requests for the Dashboard, while the `webapp-internal_api_long` pods manage longer-running operations, ensuring reliable performance and preventing timeouts during extended tasks. Adjust the number of pods and node capacity according to the size and number of repositories, expected volume of push events, and expected volume of API requests to ensure efficient and effective scanning and interactions. To avoid manual scaling, you may be interested in autoscaling to adapt dynamically to the load, see [Autoscaling](./autoscaling.md). #### Container Registry Scanning Considerations - **Replica Configuration**: By default, container registry replicas are set to 0, causing container registry scanning to fall back to using scanner workers. It is recommended to configure this to a non-zero replica count for dedicated container registry scanning performance. - **Cache Usage**: Consumes significant Redis memory and database storage (several GB). Consider scaling Redis or using a dedicated instance. - **Database Pressure**: Scanner pods can pressure the database, especially during initial scans. Scale carefully with the recommended minimum replica counts. - **Data Transfer Costs**: Scanning large registries can result in high network transfer costs. Start with a few repositories to evaluate costs before scaling to full scan. #### Check Runs Considerations - **Replica Configuration**: By default, check runs replicas are set to 0, causing check run processing to be handled by `worker-worker`. If you experience high volumes of GitHub check runs, you can enable dedicated `worker-check-runs` pods by setting `celeryWorkers.check-runs.replicas` to offload the `check_run` queue from `worker-worker`. #### Slack Scanning Considerations - **Replica Configuration**: By default, Slack scanners replicas are set to 0, causing Slack registry scanning to fall back to using scanner workers. It is recommended to configure this to a non-zero replica count for dedicated Slack registry scanning performance. Configuring a large number of replicas is unnecessary, as Slack scanning is restricted to one channel at a time due to Slack API rate limits. #### Binary Files Scanning Considerations Binary Files Scanning is currently only available for Microsoft Sharepoint Online and Microsoft OneDrive. When performing an historical scan on sources containing binary files, the files will be downloaded locally on the pod ephemeral storage. **To improve performance and reduce scan times, it is recommended to use SSD disks for the ephemeral storage and to provision enough ephemeral storage for these pods (100GB).** #### Package Registry Scanning Considerations - **Replica Configuration**: `scanners-db-less.replicas` must be set to a value greater than 0 for JFrog Package Registries, SharePoint, and OneDrive integrations. By default, replicas are set to 0. - **Cache Usage**: The `commit-cache` Redis instance is used for JFrog Package Registries scanning. If `commit-cache` is not configured, the main Redis instance will be used instead. #### Premium Scan Retry Worker :::info Only available for **[helm-based installations](../../installation/installation-existing-cluster-helm)**. ::: `premium-scanners-retry` is a **backup scanner** for larger repositories. When a scan fails on a standard `worker-scanners` pod — usually an out-of-memory (OOM) error on a large repo — the job is re-queued to `premium_repo_scan_retry` and retried on a higher-memory pod. This lets you size your base scanners for the common case instead of for your largest repository. You can activate this worker if some VCS scans are failing repeatedly with "Worker Error" failure. - **Disabled by default** (`replicas: 0`): consumes no resources until enabled. While disabled, `worker-scanners` consumes the `premium_repo_scan_retry` queue as a fallback, so no action is required. - **Resources**: defaults to a `120Gi` memory request **and** limit — intentional, sized for OOM recovery of jobs that already failed on standard pods. Pick a node that fits closely (e.g. ~128 GB allocatable) to avoid provisioning an oversized node. - **Scale to zero**: pair with [Horizontal Pod Autoscaling](./autoscaling) (metric on `premium_repo_scan_retry`, threshold `1`) so the large node is only provisioned when there is a scan to retry. ```yaml celeryWorkers: premium-scanners-retry: replicas: 1 # 0 disables the dedicated worker (retries fall back to worker-scanners) resources: requests: memory: 120Gi limits: memory: 120Gi ``` #### ML Secret Engine Scaling Considerations The ML Secret Engine requires specific resource allocation and scaling considerations. For detailed setup instructions, see the [Machine Learning documentation](../application-management/machine-learning). - **Per-pod resources**: 3 vCPU and 2.5 GiB RAM each. - **Instance recommendation**: Use AWS Gen 7 Intel (M7i) instances with amd64 architecture. CPU-only instances are far more cost-effective than GPU instances (g4dn/p3) for ML analysis. - **Scaling**: Use the sizing recommendations below (Small/Medium/Large) as baseline configuration. For dynamic scaling during backfills, consider configuring [Horizontal Pod Autoscaling (HPA)](./autoscaling) for the `ml-api-priority` worker. #### ClickHouse Some features require [ClickHouse](./clickhouse/overview), an optional in-cluster component with its own sizing considerations, distinct from the core system components above. See the dedicated [Sizing and hardening](./clickhouse/sizing) page for sizing tables and hardware recommendations. #### Analytics [Advanced Analytics](../../../platform/analytics/internal-monitoring) requires additional resources when enabled. The job executes once a day and has the following default resource configuration: - **Memory request**: 8 GB - **Memory limit**: 12 GB - **Database usage increase**: 15-20% (minimum 5-6 GB) - **Ephemeral storage**: the job runs a Spark pipeline that writes shuffle and spill data to `/tmp` on the node's local disk. On large workspaces this can exceed the node's ephemeral-storage limit and cause the daily job to fail. Plan for 5 to 20 GB of scratch space depending on your data volume. Plan your cluster and database capacity accordingly. Starting **2026.7.0**, you can move the Spark scratch space onto a dedicated, sized volume instead of the node's local disk. See [In-app analytics ephemeral storage](#in-app-analytics-ephemeral-storage). ### Small #### Core System Components For up to 2000 repositories, handling up to 500 pushes per hour, and up to 1000 API requests per hour: | Component | Required Capacity | Count | | :----------------------- | :--------------------------------------------------------------------------------------------- | :---- | | Kubernetes compute nodes | 4 vCPU 16 GB memory 50 GB ephemeral disk space, 10 GB persistent disk space | 3 | | PostgreSQL Master | 4 vCPU 8 GB memory 200 GB disk space | 1 | | Redis | 2 vCPU 2 GB memory 20 GB disk space | 1 | | **Total** | **18 vCPU 58 GB memory 150 GB ephemeral disk space, 250 GB persistent disk space** | **5** | If you plan to use global ephemeral storage, add 20 GB to the persistent disk space on each of your Kubernetes compute nodes. #### Historical Scans (up to 5GB in size) | Component | Required Capacity | Count | | :--------------------- | :----------------------------- | :---- | | `worker-scanners` Pods | Memory request and limit: 6 GB | 4 | #### Real-Time Scans (up to 500 pushes/h) | Component | Required Capacity | Count | | :------------------- | :------------------------ | :---- | | `worker-worker` Pods | Default resource settings | 2 | #### Public API (up to 1k requests/h) | Component | Required Capacity | Count | | :------------------------------- | :------------------------ | :---- | | `webapp-public_api` Pods | Default resource settings | 2 | | `nginx` (dashboard and API) Pods | Default resource settings | 2 | #### Dashboard (up to 200 active users) | Component | Required Capacity | Count | | :------------------------------ | :------------------------ | :---- | | `webapp-internal_api` Pods | Default resource settings | 2 | | `webapp-internal_api_long` Pods | Default resource settings | 2 | #### Machine learning (up to 500 events/h) | Component | Required Capacity | Count | | :---------------------------- | :------------------------ | :---- | | `ml-secret-engine` Pods | Default resource settings | 1 | | `worker-ml-api-priority` Pods | Default resource settings | 1 | #### Historical Scans and Real-Time Scans for Container registries | Component | Required Capacity | Count | | :--------------------------------- | :----------------------------- | :---- | | `worker-container-registries` Pods | Memory request and limit: 4 GB | 2 | #### Historical Scans for Slack | Component | Required Capacity | Count | | :--------------------------- | :------------------------ | :---- | | `worker-scanners-slack` Pods | Default resource settings | 1 | #### Historical Scans for Sharepoint / OneDrive | Component | Required Capacity | Count | | :---------------------------------- | :------------------------ | :---- | | `worker-scanners-ods-highdisk` Pods | Default resource settings | 1 | | `apacheTika` Pods | Default resource settings | 1 | #### Package Registry Scanning | Component | Required Capacity | Count | | :----------------------------- | :------------------------ | :---- | | `worker-scanners-db-less` Pods | Default resource settings | 1 | ### Medium #### Core System Components For up to 10000 repositories, handling up to 1000 pushes per hour, and up to 25000 API requests per hour: | Component | Required Capacity | Count | | :----------------------- | :---------------------------------------------------------------------------------------------- | :---- | | Kubernetes compute nodes | 8 vCPU 32 GB memory 50 GB ephemeral disk space, 10 GB persistent disk space | 5 | | PostgreSQL Master | 8 vCPU 32 GB memory 250 GB disk space | 1 | | Redis | 4 vCPU 8 GB memory 40 GB disk space | 1 | | **Total** | **52 vCPU 200 GB memory 250 GB ephemeral disk space, 340 GB persistent disk space** | **7** | If you plan to use global ephemeral storage, add 120 GB to the persistent disk space on each of your Kubernetes compute nodes. #### Historical Scans (up to 10GB in size) | Component | Required Capacity | Count | | :--------------------- | :------------------------------ | :---- | | `worker-scanners` Pods | Memory request and limit: 11 GB | 12 | #### Real-Time Scans (up to 1k pushes/h) | Component | Required Capacity | Count | | :------------------- | :------------------------ | :---- | | `worker-worker` Pods | Default resource settings | 4 | #### Public API (up to 25k requests/h) | Component | Required Capacity | Count | | :------------------------------- | :------------------------ | :---- | | `webapp-public_api` Pods | Default resource settings | 4 | | `nginx` (dashboard and API) Pods | Default resource settings | 2 | #### Dashboard (up to 500 active users) | Component | Required Capacity | Count | | :------------------------------ | :------------------------ | :---- | | `webapp-internal_api` Pods | Default resource settings | 4 | | `webapp-internal_api_long` Pods | Default resource settings | 2 | #### Machine learning (up to 1k events/h) | Component | Required Capacity | Count | | :---------------------------- | :------------------------ | :---- | | `ml-secret-engine` Pods | Default resource settings | 2 | | `worker-ml-api-priority` Pods | Default resource settings | 2 | #### Historical Scans for Slack | Component | Required Capacity | Count | | :--------------------------- | :------------------------ | :---- | | `worker-scanners-slack` Pods | Default resource settings | 2 | #### Historical Scans for Sharepoint / OneDrive | Component | Required Capacity | Count | | :---------------------------------- | :-------------------------------- | :---- | | `worker-scanners-ods-highdisk` Pods | Memory request, limit: 4GiB, 6GiB | 4 | | `apacheTika` Pods | Default resource settings | 2 | #### Package Registry Scanning | Component | Required Capacity | Count | | :----------------------------- | :------------------------ | :---- | | `worker-scanners-db-less` Pods | Default resource settings | 2 | ### Large #### Core System Components For up to 40000 repositories, handling up to 2000 pushes per hour, and up to 50000 API requests per hour: | Component | Required Capacity | Count | | :----------------------- | :---------------------------------------------------------------------------------------------- | :---- | | Kubernetes compute nodes | 8 vCPU 64 GB memory 50 GB ephemeral disk space, 10 GB persistent disk space | 7 | | PostgreSQL Master | 16 vCPU 64 GB memory 300 GB disk space | 1 | | Redis | 8 vCPU 16 GB memory 100 GB disk space | 1 | | **Total** | **80 vCPU 528 GB memory 350 GB ephemeral disk space, 470 GB persistent disk space** | **9** | If you plan to use global ephemeral storage, add 160 GB to the persistent disk space on each of your Kubernetes compute nodes. #### Historical Scans (up to 15GB in size) | Component | Required Capacity | Count | | :------------------------- | :------------------------------ | :---- | | `worker-scanners` Pods | Memory request and limit: 16 GB | 16 | | `worker-scanners-ods` Pods | Memory request and limit: 4 GB | 10 | Define specific `worker-scanners-ods` pods especially if you integrate large Slack or MS Teams instances (5k+ channels). It's better to isolate these workloads. Otherwise, it's fine to share the same queue and workers with the `worker-scanners` workload. #### Real-Time Scans (up to 2k pushes/h) | Component | Required Capacity | Count | | :------------------- | :------------------------ | :---- | | `worker-worker` Pods | Default resource settings | 8 | #### Public API (up to 50k requests/h) | Component | Required Capacity | Count | | :------------------------------- | :------------------------ | :---- | | `webapp-public_api` Pods | Default resource settings | 6 | | `nginx` (dashboard and API) Pods | Default resource settings | 2 | #### Dashboard (up to 1k active users) | Component | Required Capacity | Count | | :------------------------------ | :------------------------ | :---- | | `webapp-internal_api` Pods | Default resource settings | 6 | | `webapp-internal_api_long` Pods | Default resource settings | 2 | #### Machine learning (up to 2k events/h) | Component | Required Capacity | Count | | :---------------------------- | :------------------------ | :---- | | `ml-secret-engine` Pods | Default resource settings | 2 | | `worker-ml-api-priority` Pods | Default resource settings | 2 | #### Historical Scans for Slack | Component | Required Capacity | Count | | :--------------------------- | :------------------------ | :---- | | `worker-scanners-slack` Pods | Default resource settings | 2 | #### Historical Scans for Sharepoint / OneDrive | Component | Required Capacity | Count | | :---------------------------------- | :-------------------------------- | :---- | | `worker-scanners-ods-highdisk` Pods | Memory request, limit: 4GiB, 6GiB | 4 | | `apacheTika` Pods | Default resource settings | 2 | #### Package Registry Scanning | Component | Required Capacity | Count | | :----------------------------- | :------------------------ | :---- | | `worker-scanners-db-less` Pods | Default resource settings | 4 | ## Configure scaling settings You may size your infrastructure according to the above recommendations but you may also use Kubernetes autoscaling to adapt dynamically to the load, see [Autoscaling](./autoscaling.md). ### KOTS-based installation :::caution Ensure that you update the **[Kubernetes Application RBAC](../../installation/installation-existing-cluster-kots#kubernetes-application-rbac)** by adding the `patch` permission to the `servicemonitors` resource. ::: Navigate under **Config > Scaling** in the [KOTS Admin Console](./admin-console), you will have access to the worker scaling options. - **Front replicas**: Scale `nginx` pods. - **API replicas**: Scale `api` pods. - **Workers replicas**: Scale `workers` pods (including the `scanners` pods) :::info Changing these values doesn't affect the rollout upgrade strategy. Workers are configured to spread across nodes if there are multiple nodes. If you have configured your cluster for high availability, do not use less than 2 workers of each type. ::: **Non-VCS Sources Integration:** For non-VCS integrations (messaging, documentation, ticketing, and container registries), worker configuration varies by integration type: - Some integrations can optionally use generic VCS workers but benefit from dedicated workers - Others require their own specialized workers and cannot share VCS workers - By default, all non-VCS source workers are deactivated (replicas set to 0) For detailed configuration instructions, worker requirements, and activation steps, see the [Non-VCS Sources](../application-management/non-vcs-sources) documentation. This scaling page focuses on performance optimization after initial activation. ### Helm-based installation Customize Helm applications using your `local-values.yaml` file, submitted with the `helm` command. Configure deployments with `replicas`: `use webapps.[name].replicas` for web pods, `celeryWorkers.[name].replicas` for async workers and `secretEngine.replicas` for Machine Learning Secret Engine. Additionally, set resources `requests` and `limits` as needed. **Example** ```yaml migration: # Set resources for pre-deploy and post-deploy jobs resources: limits: cpu: 1000m memory: 500Mi front: nginx: # Set resources for nginx init containers init: resources: limits: cpu: 1000m memory: 500Mi replicas: 2 resources: limits: memory: 1Gi webapps: public_api: replicas: 5 resources: requests: cpu: 200m memory: 500Mi limits: memory: 4Gi celeryWorkers: scanners: replicas: 8 resources: requests: cpu: 200m memory: 4Gi limits: memory: 16Gi secretEngine: replicas: 2 ``` See [the values reference documentation](./helm-values) for further details. :::tip Scaling Recommendation For optimal performance, consider scaling the following pods to a minimum of 2 replicas each: `hook`, `internal-api-long`, `public-api`, `worker-email`, `worker-long`, and `worker-worker`. ::: ## Additional tuning ephemeral storage :::info Only available for **[helm-based installations](../../installation/installation-existing-cluster-helm)**. ::: In certain scenarios, optimizing ephemeral storage configurations becomes essential for achieving better performance and stability, particularly for `scanners` workers. This section outlines additional configurations for fine-tuning ephemeral storage, focusing on leveraging "On Demand" nodes with nvme disks and integrating Generic Ephemeral Inline Volumes. ### "On Demand" nodes with nvme disks In the following example, we specify that `scanners` workers only use "On Demand" VMs with nvme disks and that pods' ephemeral storage will use these disks ```yaml celeryWorkers: scanners: replicas: 8 localStoragePath: /nvme/disk # Used for pods ephemeral storage nodeSelector: # Must run on "On Demand" nodes with nvme disks eks.amazonaws.com/capacityType: ON_DEMAND local-nvme-ready: 'true' tolerations: - key: worker-highdisk operator: Equal value: 'true' effect: NoSchedule resources: requests: cpu: 200m memory: 16Gi limits: memory: 16Gi ``` ### Generic Ephemeral Inline Volumes In the following example, we leverage Kubernetes' Generic Ephemeral Inline Volumes within Helm charts. This feature facilitates dynamic provisioning and reclamation of storage, particularly beneficial when dealing with small limits on Ephemeral storage. Note that it's supported starting Kubernetes 1.23 ([learn more](https://docs.openshift.com/container-platform/4.15/storage/generic-ephemeral-vols.html)). ```yaml celeryWorkers: scanners: replicas: 8 resources: requests: cpu: 200m memory: 4Gi limits: memory: 16Gi # -- Worker ephemeral storage ephemeralStorage: enabled: true size: 2Gi ``` ### In-app analytics ephemeral storage The [in-app analytics](../../../platform/analytics/internal-monitoring) job runs a Spark pipeline that writes shuffle and spill data to `/tmp` on the node's local disk by default. On large workspaces this can exceed the node's ephemeral-storage limit and cause the daily job to fail. Starting **2026.7.0**, you can attach a dedicated Generic Ephemeral Inline Volume to the analytics pod. When enabled, GitGuardian mounts it at `/ephemeral` and points Spark's scratch space (`SPARK_LOCAL_DIRS`) at it instead of `/tmp`. ```yaml inAppAnalytics: ephemeralStorage: enabled: true size: 20Gi storageClass: '' # Optional: defaults to the cluster's default StorageClass ``` Size the volume according to your data volume. A range of 5 to 20 GB is a good starting point. ### Node Affinity Scheduling Use the nodeSelector parameter in Helm values to schedule worker pods on specific nodes, ensuring they run in designated zones or meet specific criteria ([learn more](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-your-chosen-node)). ```yaml celeryWorkers: long: nodeSelector: topology.kubernetes.io/zone: eu-central-1c scanners: nodeSelector: topology.kubernetes.io/zone: eu-central-1c worker: nodeSelector: topology.kubernetes.io/zone: eu-central-1c ``` ### Pod Anti-Affinity GitGuardian's Helm chart provides configurable pod anti-affinity settings to control how pods are distributed across your Kubernetes cluster nodes. This feature allows you to optimize availability and resource utilization by ensuring pods are spread evenly across different nodes and availability zones. **Default configuration:** By default, the chart applies a `podAntiAffinityPreset: soft` configuration for webApps and workers. This `soft` anti-affinity preference attempts to distribute pods across nodes but does not guarantee uniform distribution. The scheduler will try to place pods on different nodes when possible, but will still schedule pods even if the preferred distribution cannot be achieved. **Hardened Configuration:** For environments requiring guaranteed uniform pod distribution, you can specify `podAntiAffinityPreset: hard`. This configuration enforces strict anti-affinity rules that ensure pods are evenly distributed across: - Availability zones (topology key: `topology.kubernetes.io/zone`) - Individual nodes (topology key: `kubernetes.io/hostname`) To enable hard pod anti-affinity for the scanner worker component, configure your Helm values as follows: ```yaml celeryWorkers: scanners: replicas: 10 podAntiAffinityPreset: hard ``` This configuration will ensure that each scanner worker pod runs on a different node, providing maximum distribution and fault tolerance. **Node Capacity Requirements:** `hard` anti-affinity preset requires that you have sufficient nodes in your cluster to satisfy the desired number of replicas. If your cluster does not have enough nodes to accommodate all pods with the strict anti-affinity rules, some pods will remain in a "**Pending**" state until additional nodes become available. For example, if you configure 10 replicas with hard anti-affinity but only have 8 available nodes, 2 pods will remain pending until more nodes are added to the cluster. --- ## Upgrade Helm :::danger Do not roll back or downgrade without consulting our **[support team](mailto:support@gitguardian.com)** first. Certain scenarios may necessitate restoring the database from a pre-upgrade backup due to the complexity of reversing some database migrations. ::: :::caution Prior to upgrading, ensure you back up your PostgreSQL database. For detailed instructions, refer to the **[Backup](./backup.md)** page. ::: ## Upgrade path and required versions {#required-versions} Some releases are **required** and cannot be skipped. They carry database migrations and infrastructure changes that later releases build upon, so your instance has to pass through each of them. Required releases follow a quarterly cycle: **January, April, July, and October**. All other releases are optional. You can recognize a required release in the **[self-hosted release notes](/releases/self-hosted)**: its title ends with `Required`. If one or more required releases stand between your current version and the version you target, upgrade to each of them in order before reaching your target. Upgrading from 2025.6 to 2026.7, for instance, takes five successive upgrades: `2025.6` ➔ `2025.7` ➔ `2025.10` ➔ `2026.1` ➔ `2026.4` ➔ `2026.7` For every step of the path: 1. Review the [breaking changes](#breaking-changes) of the target version and the **[Helm values changelog](./helm-values)**, then update your values file accordingly. 2. Run the upgrade. 3. Wait for the application to be fully upgraded before starting the next step: all pods running and all jobs completed. :::note You cannot skip a required version by accident. Every upgrade starts with an `upgrade-path-check` job that validates the path and stops the upgrade before any change is applied if a required version is missing. ::: ## Run preflight checks :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the upgrade **must not continue** until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)** if needed. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../../system-requirements)**. ::: We strongly advise you to run our preflight script to ensure your existing cluster meets GitGuardian's requirements. Retrieve the script from our public repository [here](https://github.com/GitGuardian/ggtools/tree/main/helm-preflights) Specify an existing Kubernetes namespace using the `-n` option. If not specified, the script will run in your default namespace. Replace `` with your existing [helm release name](https://helm.sh/docs/intro/using_helm/#helm-install-installing-a-package). ```bash ./preflights.sh -r -n oci://registry.replicated.com/gitguardian/gitguardian -f local-values.yaml ``` ## Upgrading the GitGuardian application Log in to the registry with the following command: ```bash helm registry login registry.replicated.com --username your.name@yourcompany.com ``` Upgrade the GitGuardian application to the latest version in the Kubernetes cluster and namespace where it's installed: ```bash helm upgrade -n oci://registry.replicated.com/gitguardian/gitguardian -f local-values.yaml ``` Replace `` with the name used during the initial installation (use `helm ls` to find it). If needed, specify the namespace with `-n` (default namespace is used if not specified). This will upgrade your application to the latest version. To upgrade to a specific version, use the `--version` flag: ```bash helm upgrade -n oci://registry.replicated.com/gitguardian/gitguardian --version 2024.x.y -f local-values.yaml ``` ## Upgrading the GitGuardian application in Airgap Follow these steps to upgrade a Helm-based installation in an air-gapped environment: 1. Log in to the Helm registry: ```bash helm registry login registry.replicated.com --username your.name@yourcompany.com ``` 2. Download the Helm chart locally (replace with the desired version as needed): ```bash helm fetch oci://registry.replicated.com/gitguardian/gitguardian # this will download a file like gitguardian-.tgz ``` 3. Authenticate Docker to the Replicated proxy to pull images (replace ``): ```bash LICENSE_ID=""; \ echo "{\"auths\": {\"proxy.replicated.com\": {\"auth\": \"$(echo -n \"${LICENSE_ID}:${LICENSE_ID}\" | base64)\"}, \"registry.replicated.com\": {\"auth\": \"$(echo -n \"${LICENSE_ID}:${LICENSE_ID}\" | base64)\"}}}" > ~/.docker/config.json ``` 4. Pull the required images for the target release, then upload them to your private registry. Refer to the image list on the **[Airgap Install page](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. You can use `docker` or `skopeo` to transfer images. :::::info Image architecture All GitGuardian images are multi-architecture. You do not need to pass `--platform` when pulling them; the correct variant is selected automatically based on the host architecture. ::::: 5. Run preflight checks against the local chart archive: ```bash ./preflights.sh -r -n gitguardian-.tgz -f local-values.yaml ``` 6. Upgrade using the local chart archive: ```bash helm upgrade --timeout 30m -n gitguardian-.tgz -f local-values.yaml ``` Replace ``, ``, and `` accordingly. Ensure your `local-values.yaml` points to your private image registry as described in the **[Airgap Install page](../../installation/airgap-installation-existing-cluster-helm#upload-gitguardian-images)**. ## Updating application configuration Modify the application configuration with an updated values file using the `helm upgrade` command. Stick to the same version using the `--version` flag: ```bash helm upgrade -n oci://registry.replicated.com/gitguardian/gitguardian --version 2024.x.y -f local-values.yaml ``` Replace `` with the name used during the initial installation (use `helm ls` to find it). If needed, specify the Kubernetes namespace with `-n` (default namespace is used if not specified). ## Breaking changes Some versions need manual changes before you upgrade. Check every version between your current one and your target, including the ones you pass through on your [upgrade path](#required-versions). ### 2025.10 {#upgrading-to-202510} **If you are using an air gap deployment:** This release now uses a **non-Bitnami** chart and Docker image for the MinIO subchart (which supports the [log collector feature](../../troubleshoot/logs#log-collector)). This change implies minor modifications to your `values.yaml` file: Modify your Helm values file: - Update `loki-minio.image.repository` from `gitguardian/wolfi/minio-bitnami` to `gitguardian/wolfi/minio`. - Update `loki-minio.image.tag` from `0.20250723` to `0.20250907`. - Rename parameter `loki-minio.image.pullPolicy` to `loki-minio.image.imagePullPolicy`. ### 2025.8 {#upgrading-to-20258} **If you are using an air gap deployment:** This release introduces a new `image.registry` parameter in Helm values to support the [Log Collector](../../troubleshoot/logs#log-collector) system. This parameter specifies the location of the GitGuardian images for the Log Collector components (Loki, MinIO, Fluent Bit) and is separate from the main `imageRegistry` parameter. Add the `image.registry` to your Helm values file: ```yaml global: imageRegistry: docker.internal/example/path # Location of the GitGuardian images image: registry: docker.internal/example/path # Location of the GitGuardian images (same as imageRegistry) ``` Find all image and tag names on the **[Air Gap Install page](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. ### 2025.7 {#upgrading-to-20257} **[Machine Learning engine](../application-management/machine-learning) is now enabled by default.** Ensure your infrastructure meets the [ML requirements](../application-management/machine-learning#system-requirements). ### 2025.6 {#upgrading-to-20256} GitGuardian 2025.6 now requires Kubernetes 1.28 as the minimum supported version. However, **Kubernetes 1.28 is no longer receiving active or maintenance support** from the Kubernetes project (support ended in October 2024). We strongly recommend upgrading to **Kubernetes 1.32** for optimal security and stability. Kubernetes 1.32 is actively supported until December 2025 and will receive maintenance support until February 2026. For more information: - [Kubernetes end-of-life schedule](https://endoflife.date/kubernetes) - [GitGuardian system requirements](/self-hosting/system-requirements#kubernetes-for-existing-clusters) ### 2025.5 {#upgrading-to-20255} **Air gap deployment?** We've renamed images in this release. See below and find all image and tag names on the **[Air Gap Install page](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. This change involves renaming the following images: - `gitguardian/prm-static-chainguard-fips` to `gitguardian/prm-static-chainguard` - `gitguardian/prm-app-fips` to `gitguardian/prm-app-chainguard` ### 2025.4 {#upgrading-to-20254} **Please install the PostgreSQL `pgvector` extension** to enable vector similarity search. This is essential for upcoming features leveraging our internal machine learning engine. Follow the [installation instructions](../../system-requirements#postgresql) to ensure compatibility. **Air gap deployment?** We've added new images in this release. The new images are for the log collection system, which includes: - Fluent Bit (log collector) - Loki (log aggregation) - MinIO (object storage for logs) Find all image and tag names on the **[Air Gap Install page](../../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images)**. ### 2025.3 {#upgrading-to-20253} The 2025.3 release introduces a breaking change in the naming registry URL, including the path and image names. If you are downloading our images in a private registry (refer to our [air gap documentation](../../installation/airgap-installation-existing-cluster-helm)), make sure to update your tooling, as well as the image names and paths in your Helm values file. Change registry URL - **Old:** `proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com` - **New:** `proxy.replicated.com/proxy/gitguardian/docker.io` Image path and name changes - `/prm/static-chainguard` ➔ `/gitguardian/prm-static-chainguard-fips` - `/prm/app-chainguard` ➔ `/gitguardian/prm-app-chainguard-fips` - `/prm/helm-tooling` ➔ `/gitguardian/prm-helm-tooling` - `/services/nginx-unprivileged` ➔ `/nginxinc/nginx-unprivileged` - `/ml-detector/ml-secret-engine/app-chainguard` ➔ `/gitguardian/ml-secret-engine-app-chainguard-fips` Change registry URL - **Old:** `registry.replicated.com` - **New:** `proxy.replicated.com/proxy/gitguardian/docker.io` Image path and name changes - `/gitguardian/replicated-sdk` ➔ `/replicated/replicated-sdk` ## Additional notes ### Pod update strategy The goal is to find a balance between service continuity and available resources on the cluster. You can define which [update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) to use during an upgrade / update. This configuration is possible for celeryWorkers (`celeryWorkers.worker.updateStrategy`) and webapps (`webapps.app.updateStrategy`). If not defined, this default strategy applies: - If less than 3 replicas ```yaml type: RollingUpdate rollingUpdate: maxUnavailable: 50% maxSurge: 50% ``` - Else ```yaml type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25% ``` --- ## Upgrade Embedded cluster :::danger Do not roll back or downgrade without consulting our **[support team](mailto:support@gitguardian.com)** first. Certain scenarios may necessitate restoring the database from a pre-upgrade backup due to the complexity of reversing some database migrations. ::: :::caution Requirements Preflight checks are critical for a successful installation. The following rules apply: - :x: **Preflight Check Failures**: If preflight checks fail, the upgrade **must not continue** until the targeted environment meets all requirements. Please reach out to our **[support team](mailto:support@gitguardian.com)**. - :warning: **Preflight Check Warnings**: If preflight checks return warnings, the installation can proceed, but it is recommended that you address these warnings to comply with our **[recommendations](../../system-requirements)**. ::: ### Upgrading to 2026.3 If you are using an Embedded cluster V2 deployment (instances installed in 2025 or after), you must manually delete the `replicated` PodDisruptionBudget before upgrading to 2026.3: 1. Check your current version. This issue only affects instances running **2026.2.0**. If you are on an older version, you can upgrade directly to 2026.3.0 without any manual step. 2. Connect to the node via SSH and delete the PodDisruptionBudget: ```bash kubectl delete -n kotsadm pdb replicated ``` 3. Open the KOTS Admin Console and launch the upgrade to 2026.3.0 from the "Version History" tab. ### Upgrading to 2026.1 If you are using an embedded cluster deployment, this release introduces new subcharts for **PostgreSQL** and **Valkey** (formerly **Redis**): - **Valkey (formerly Redis) Upgrade**: The migration from Redis to Valkey is seamless and requires no action on your part. _Note that the application cache will be reset, without affecting the normal functioning of the application._ - **PostgreSQL Upgrade**: This operation requires a mandatory manual action before initiating the upgrade. Due to the way Kubernetes handles `StatefulSet` objects, the PostgreSQL `StatefulSet` cannot be upgraded automatically. Follow these steps to perform the migration safely. #### Step 1: Back up the database Before proceeding with the upgrade, you must back up your PostgreSQL database using the migration tool provided in the [postgresql-bitnami-migration](https://github.com/GitGuardian/ggtools/tree/main/postgresql-bitnami-migration) repository. 1. Download the backup script from the repository. 2. Run the backup script to create a database dump: ```bash ./backup.sh --namespace gitguardian --output dump.sql.gz ``` 3. Store the backup file (`dump.sql.gz`) in a safe location. #### Step 2: Delete the PostgreSQL StatefulSet Ensure the PostgreSQL `StatefulSet` is present in your namespace: ```bash kubectl get sts -n gitguardian ``` Delete the `StatefulSet` before starting the upgrade: ```bash kubectl delete sts postgresql -n gitguardian ``` #### Step 3: Run preflight checks and proceed with upgrade A preflight check during the upgrade will automatically verify that the StatefulSet deletion has been completed. If the preflight check passes, proceed with the upgrade through the KOTS Admin Console. #### Step 4: Restore the database After the upgrade is complete and all pods are running, restore the database using the restore script: ```bash ./restore.sh --namespace gitguardian --input dump.sql.gz ``` Verify that your settings and data have been preserved by checking the GitGuardian dashboard. For detailed instructions on the backup and restore scripts, refer to the [postgresql-bitnami-migration](https://github.com/GitGuardian/ggtools/tree/main/postgresql-bitnami-migration) repository. ### Upgrading the GitGuardian application :::caution Prior to upgrading, ensure you back up your PostgreSQL database. For detailed instructions, refer to the **[Backup](./backup.md)** page. ::: The GitGuardian application can be updated through the KOTS Admin Console in the "Version History" tab. First, you need to check for updates. This can be done manually or automatically. Then, you can deploy a newer version by clicking the "Deploy" button. :::tip On Embedded clusters V2, updating the application through the KOTS Admin Console also upgrades the Kubernetes cluster if needed. ::: You can find more information [on the KOTS documentation](https://kots.io/kotsadm/updating/updating-kots-apps/). ![Upgrade page](/img/self-hosting/management/infrastructure-management/replicated_upgrade_page.png) :::caution During upgrades, workers are stopped but new commits are still queued and will be processed after the upgrade. Upgrades do not stop the dashboard, but they introduce a temporary delay in message processing and alerting. **We advise running upgrades during a low-traffic period.** ::: ### Upgrading the GitGuardian application in Airgap In an air-gapped environment, your cluster has no direct internet access. To upgrade, you download the new air gap bundle on a machine that **does** have internet access, transfer it to your environment, then make the new version available to the KOTS Admin Console and deploy it. The exact steps depend on how your instance was installed. Follow the section that matches your deployment. #### Embedded cluster (instances installed in 2025 or after) On an Embedded cluster, **you do not need to install or upgrade KOTS separately**: KOTS is bundled with the GitGuardian application and is upgraded automatically when you deploy a new version. You only need to make the new air gap bundle available to the Admin Console. There are two ways to do this. Uploading from the command line is the **recommended** option: it is faster and lets you download the bundle directly on the node, without re-uploading it through the browser. **Option 1: Upload the new version from the command line (recommended)** 1. On a machine with internet access, download the new air gap bundle using the same command you used to install, replacing `your_license` with your license ID: ```bash LICENSE_ID=your_license curl -f "https://replicated.app/embedded/gitguardian/stable?airgap=true" -H "Authorization: $LICENSE_ID" -o gitguardian.tgz tar -xvzf gitguardian.tgz ``` This extracts the `gitguardian` binary and the `gitguardian.airgap` bundle. 2. Transfer both the `gitguardian` binary and the `gitguardian.airgap` bundle to the node where the Embedded cluster is running. 3. On the node, from the directory containing both files, upload the bundle to make the new version available in the Admin Console: ```bash sudo ./gitguardian update --airgap-bundle gitguardian.airgap ``` 4. Open the KOTS Admin Console, go to the **Version History** tab, and click **Deploy** next to the new version. **Option 2: Upload the new version from the Admin Console** 1. On a machine with browser access to the Admin Console, download the new air gap bundle using the same command as in Option 1 (step 1). 2. In the Admin Console, go to the **Version History** tab and click **Upload new version**, then select the `gitguardian.airgap` bundle. 3. Once the upload is processed, click **Deploy** next to the new version. :::tip On Embedded clusters, deploying a new version through the Admin Console also upgrades the Kubernetes cluster and KOTS if needed. No separate KOTS upgrade command is required. ::: :::note On **Embedded cluster legacy (kURL) installations (instances installed in 2024 or before)**, the upgrade works differently: download the latest air gap package and re-run the same installation command as outlined in the [installation guide](../../installation/installation-embedded-cluster#embedded-cluster), then upload the application bundle from the **Version History** tab of the Admin Console. ::: #### Existing cluster (KOTS) :::danger Deprecation Notice KOTS installation on existing clusters will be deprecated and unsupported after the June 2026 release (version 2026.6.0). Please migrate to the [Helm installation](../../installation/installation-existing-cluster-helm). ::: On an existing cluster, KOTS runs as an application in your cluster and must be upgraded separately from the GitGuardian application. 1. Upgrade the KOTS Admin Console by following the [air gap installation instructions](../../installation/airgap-installation-existing-cluster-kots#download-and-install-the-kots-admin-console): install the latest version of the KOTS plugin on your machine, download the latest KOTS bundle, and upload these images to your registry. Then, instead of running the installation command, upgrade the KOTS application running in the cluster: ```bash kubectl kots admin-console upgrade --namespace ``` If needed, specify the Kubernetes namespace with `--namespace` (the default namespace is used if not specified). 2. Download the latest application bundle from the download portal. Then go to your KOTS Admin Console on the **Version History** tab, click **Upload new version**, upload the bundle, and deploy it. ### Required versions [KOTS Admin Console](./admin-console) will show some versions as "Required". ![Required version](/img/self-hosting/management/infrastructure-management/required-version.png) If you have several versions to upgrade, you'll have to upgrade to each required version between your current version and your target version. After each deployment, you should wait for the application to be fully upgraded. To that extent, you can monitor pods' status and wait for all pods to be live and all jobs to be completed. ```bash watch kubectl get po -n ``` The application is restarted when all pods are in the running status: ```bash Every 2.0s: kubectl get po -n default gitguardian-example: Thu Jul 4 06:11:24 2024 NAME READY STATUS RESTARTS AGE beat-677d68bb9f-8f5lp 1/1 Running 0 23m kotsadm-56dd9b7866-cv4jc 1/1 Running 0 30m kotsadm-rqlite-0 1/1 Running 0 33m kurl-proxy-kotsadm-7cdfc47bf4-nr55l 1/1 Running 0 33m nginx-578786cd47-6ccfh 1/1 Running 0 23m nginx-578786cd47-cx899 1/1 Running 0 23m post-deploy-f77kq 0/1 Completed 0 23m postgresql-0 1/1 Running 0 29m pre-deploy-hnpbq 0/1 Completed 0 28m redis-master-0 1/1 Running 0 29m replicated-76bff7f9bb-zb2lb 1/1 Running 0 23m webapp-hook-5745c9995-6p7ph 1/1 Running 0 23m webapp-internal-api-55fdd98d4d-9x25r 1/1 Running 1 (22m ago) 23m webapp-internal-api-long-b98b68fb-x6q7s 1/1 Running 0 23m webapp-public-api-7d4b7f8956-2jvf4 1/1 Running 0 23m worker-email-755dd6db6b-4drhj 1/1 Running 0 23m worker-email-755dd6db6b-6lrhc 1/1 Running 0 23m worker-long-tasks-54875654d8-jl57k 1/1 Running 0 23m worker-long-tasks-54875654d8-mh47g 1/1 Running 0 23m worker-realtime-ods-7b844db9c6-6rcsl 1/1 Running 0 23m worker-realtime-ods-7b844db9c6-hb8lq 1/1 Running 0 23m worker-scanners-55fc98d756-mrqsx 1/1 Running 0 23m worker-scanners-55fc98d756-rz6xz 1/1 Running 0 23m worker-worker-85bff7dc8f-6zs98 1/1 Running 0 23m worker-worker-85bff7dc8f-vd5vx 1/1 Running 0 23m ``` :::info We have set a 30-day TTL (Time To Live) for `pre-deploy` and `post-deploy` jobs to allow for log retrieval if needed. It is recommended not to delete these pods, as they can be useful for troubleshooting. ::: ### Upgrading KOTS Please remember that regular upgrades of KOTS are necessary. GitGuardian releases are thoroughly tested with the [latest KOTS release](https://docs.replicated.com/release-notes/rn-app-manager). To ensure full functionality and compatibility, some features may not perform as expected on older versions of KOTS. We strongly recommend staying updated with the most recent releases. To check the KOTS plugin version, run the following command: ```bash kubectl kots version ``` If there is an update available, follow the instructions and run this command: ```bash curl https://kots.io/install | bash ``` For **existing cluster**, you will need to upgrade the KOTS application running in the cluster: :::warning KOTS installation on existing clusters will be deprecated and unsupported after the June 2026 release (version 2026.6.0). Please migrate to [Helm installation](../../installation/installation-existing-cluster-helm). ::: ```bash kubectl kots admin-console upgrade -n ``` For **Embedded cluster installations (instances installed in 2025 or after)**, KOTS is upgraded automatically with the GitGuardian application. For **Embedded cluster legacy (kURL) installations (instances installed in 2024 or before)**, simply re-run the same installation command as outlined in the [installation guide](../../installation/installation-embedded-cluster#embedded-cluster). ⚠️ During the upgrade you will be prompted (possibly more than once) with a Y/N question to drain the node and apply the upgrade. You should respond with Y to continue. Because this step deletes all pods on the node, there will be some brief downtime while the upgrade happens and you should plan accordingly. 🌐 If you are using an HTTP proxy, ensure that you follow the [instructions](../../installation/installation-embedded-cluster#configuring-proxy-settings). For further instructions on upgrading KOTS, refer to the [Replicated documentation](https://docs.replicated.com/enterprise/updating-embedded-cluster). :::info In some cases, the preflight checks may not detect the KOTS admin version change correctly, leading to failures even when using the required minimum KOTS version. To address this issue, follow these steps: 1. Navigate to the [KOTS Admin Console](./admin-console). 2. Go to **Config > Advanced Options**. 3. Adjust the number of email worker replicas (for example, from 2 to 1). 4. Deploy your configuration change. 5. Click the **Check for update** link. 6. Run the preflight checks again. 7. Once the preflight checks are completed, revert the change by restoring the number of email worker replicas to its original value. ::: ### Upgrading Kubernetes on Embedded Cluster legacy (kURL) (instances installed in 2024 or before) To upgrade your Kubernetes version for the embedded cluster, follow these steps: 1. Simply re-run the same installation command as outlined in the [installation guide](../../installation/installation-embedded-cluster#embedded-cluster). ⚠️ During the upgrade you will be prompted (possibly more than once) with a Y/N question to drain the node and apply the upgrade. You should respond with Y to continue. Because this step deletes all pods on the node, there will be some brief downtime while the upgrade happens and you should plan accordingly. 🌐 If you are using an HTTP proxy, ensure that you follow the [instructions](../../installation/installation-embedded-cluster#configuring-proxy-settings). 2. To verify the Kubernetes version, execute the following command: ```bash kubectl version ``` --- ## Network requirements Depending on the installation method, you'll have some network requirements, even for Airgap environments. :::tip IPv6 support GitGuardian self-hosted supports IPv4, IPv6, and dual-stack networking. For details, see [IPv6 networking](./management/infrastructure-management/ipv6-networking). ::: ## Services and components GitGuardian uses different components for its functioning: - **Nginx:** Web Server, - **Celery:** queue and task manager, - **Django:** framework used for the application, - **PostgreSQL:** database, - **Redis:** cache manager, - **Replicated:** management console (KOTS admin and Replicated SDK). ![Services and components](/img/self-hosting/components_map.png) After installing the GitGuardian application, you will see different pods created on your Kubernetes cluster. For detailed insights into deployment/pod names, types, and their usage, visit the [GitGuardian Application Topology](./troubleshoot/topology) page. ## External access Below domains to whitelist and ports to open are specific to the installation, upgrade, and usage of the application and its management. Ensure the relevant rules are correctly applied to your firewall. ### Inbound rules For you to communicate with GitGuardian application, certain inbound ports must be open. | Protocol | Port | Source | Destination | Description | | -------- | ---- | ------- | ------------- | ---------------------------- | | TCP | 443 | 0.0.0.0 | All K8S nodes | GitGuardian HTTPS entrypoint | | TCP | 8800 | 0.0.0.0 | All K8S nodes | KOTS Admin Console | > Note: The KOTS Admin Console is not applicable when using the Helm installation method. The source is based on the customer's service access policy. For example, the KOTS Admin Console might be limited to select internal IPs to prevent public access. **We recommend dropping all incoming traffic except the ports listed above**. ### Outbound rules For the GitGuardian application to communicate with external services, certain outbound ports must be open. If you are using an HTTP proxy, you may also need to [configure your proxy](./management/infrastructure-management/proxy-server) to allow traffic to the following domains. | Protocol | Port | Source | Destination | Description | | -------- | ---- | ------------- | -------------------------------- | --------------------------------- | | TCP | 443 | All K8S nodes | \*.replicated.com | Replicated Registry and Proxy | | TCP | 443 | All K8S nodes | replicated.app | Replicated API | | TCP | 443 | All K8S nodes | \*.docker.io | Docker hub Registry (auth & pull) | | TCP | 443 | All K8S nodes | production.cloudflare.docker.com | Docker hub Registry | > Note: The Docker hub registry is not applicable when using the Helm installation method. #### Embedded cluster legacy (kURL) (instances installed in 2024 or before) If you're using the Embedded installation method, there are some additional ports to open. | Protocol | Port | Source | Destination | Description | | -------- | ---- | ------------- | ------------------------ | -------------------------------- | | TCP | 443 | All K8S nodes | k8s.kurl.sh | Replicated K8S kurl installer | | TCP | 443 | All K8S nodes | s3.kurl.sh, kurl.sh | Replicated kurl installer | | TCP | 443 | All K8S nodes | kurl-sh.s3.amazonaws.com | Replicated kurl installer assets | Replicated maintains a current list of IP addresses associated with these domains. - For the range of IP addresses for `k8s.kurl.sh`, see [replicatedhq/ips](https://github.com/replicatedhq/ips/blob/main/ip_addresses.json#L34-L39) in GitHub. - The range of IP addresses for `s3.kurl.sh` is the same as for the `kurl.sh` domain. For the range of IP addresses for `kurl.sh`, see [replicatedhq/ips](https://github.com/replicatedhq/ips/blob/main/ip_addresses.json#L28-L31) in GitHub. - The kurl installer assets (tar.gz packages) are downloaded from Amazon S3 during installations with kURL. For information about dynamically scraping the IP ranges to allowlist for accessing these packages, see [AWS IP address ranges](https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html#aws-ip-download) in the AWS documentation. :::note Depending on your integrations and settings, additional domains or IP ranges may need to be whitelisted and/or allowed in your HTTP proxy if you are using one. Here is a list of features that will make outbound requests: - [Honeytoken](../honeytoken/self-hosted#network-requirements) - [Public Monitoring](../public-monitoring/self-hosted#network-requirements) - Secret validity checkers - VCS Integrations (GitHub, GitHub Enterprise Server, GitLab, Bitbucket...) - Messaging Integrations (Slack, Microsoft Teams...) - Documentation Integrations (Confluence...) - External notifiers (Slack, Jira...) - Custom webhook notifier - Email notifications (either SMTP or Sendgrid) ::: ## Nginx reverse proxy example for embedded installation If you want to set up a reverse proxy in front of your embedded installation, you need to configure and forward the SNI header properly. Here is an example configuration for an Nginx virtual host. `external_gitguardian_hostname` is the hostname to use in a browser to access the dashboard, and `internal_gitguardian_hostname` is the hostname used to reach the GitGuardian instance internally from the reverse proxy. This is also the hostname set up in the KOTS Admin Console. ```nginx server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name external_gitguardian_hostname; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; set $target_host internal_gitguardian_hostname; location / { proxy_set_header Host $target_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass https://$target_host; proxy_read_timeout 60; proxy_ssl_name $target_host; proxy_ssl_server_name on; proxy_ssl_protocols TLSv1.2 TLSv1.3; proxy_ssl_session_reuse off; } } ``` ## Architecture examples Here are some architecture examples that can help you install and configure your GitGuardian environment. ### Internal network ![Internal network graph](/img/self-hosting/network_flows_internal_network.png) If you have an internal network behind a firewall, you can easily connect to an internal VCS (eg: self-hosted GitLab). However, **if you want to connect to github.com, therefore requiring internet access, you will need to open wide incoming access to the HTTPS port of your GitGuardian instance**. :::note It is possible to restrict traffic to github.com IP addresses, but [this is not recommended by GitHub](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/about-githubs-ip-addresses). You can use a Web Application Firewall (WAF) or a proxy to monitor closely the incoming traffic on the GitGuardian instance. ::: In this scenario, the GitGuardian instance needs an open 443 egress port to get updates. ### Internal network with DMZ ![DMZ network graph](/img/self-hosting/network_flows_dmz.png) If in addition to an internal network, you have a DMZ and you want to integrate with github.com, you can put **the GitGuardian instance in the DMZ**. This makes it easier to access github.com but you will need to expose your internal VCS outside of your internal network so that the GitGuardian instance can access it. In this scenario, GitGuardian needs an open 443 egress port to get updates. ### Isolated network GitGuardian offers a fully offline solution, ensuring that your data remains within your environment at all times. ![Isolated network graph](/img/self-hosting/network_flows_isolated_network.png) In this scenario, **the GitGuardian instance is completely isolated from the Internet**. It is offline and airgapped. This means no github.com monitoring is possible, and [Public Monitoring](../public-monitoring/self-hosted) cannot run either, as it requires outbound access to GitGuardian's Public Monitoring service. This also means you don't need an open 443 egress port to get updates. For more details on installing GitGuardian in an airgap environment, refer to our [installation guide](./installation/airgap-installation-existing-cluster-helm). :::info This Airgap functionality is not available by default. Please contact your **[sales representative](mailto:support@gitguardian.com)** if you want to enable it. ::: --- ## SaaS vs Self-Hosted ## Core concepts ### SaaS vs Self-Hosted - **SaaS (Software-as-a-Service)** means the application is hosted and maintained by the vendor. Example: GitGuardian SaaS is hosted on GitGuardian's servers, [start for free](../platform/getting-started/account-creation)! - **Self-Hosted or On-Premise** means the application is hosted on the customer's servers. Example: GitGuardian Self-Hosted is deployed on the customer's servers, [choose your installation method](./installation/choose-embedded-existing.md). ### Deployment - **SaaS:** GitGuardian manages and controls the servers, databases, and infrastructure. - **Self-Hosted:** GitGuardian ensures compatibility with the customer’s environment. For more details about self-hosted, refer to the [System Requirements](./system-requirements.md) page. ### Versions and Upgrades - **SaaS:** GitGuardian controls version releases and can quickly address issues with hotfixes or rollbacks. ([SaaS Release Notes](/releases/saas)) - **Self-Hosted:** The customer decides when to deploy new versions. GitGuardian provides support when needed and sends newsletters with each new release. ([Self-Hosted Release Notes](/releases/self-hosted)) For more details about self-hosted, refer to the [Upgrade](./management/infrastructure-management/upgrade-helm) page. ### Maintenance - **SaaS:** GitGuardian monitors the platform and handles alerts. - **Self-Hosted:** GitGuardian has no direct visibility and includes self-monitoring capabilities within the platform, managed by the customer. For more details about self-hosted, refer to the [Health Checks](./troubleshoot/health-check.md) page. ### Support and Debugging - **SaaS:** GitGuardian has full access to data and logs, enabling quick bug identification and fixes. - **Self-Hosted:** GitGuardian relies on customer-provided data ("support bundle") to investigate issues, potentially lengthening the resolution process. For more details about self-hosted, refer to the [Support](./troubleshoot/support.md) page. ## Feature matrix The software running in our SaaS and Self-Hosted solutions is essentially the same. However, some features are not available in Self-Hosted versions due to significant differences in environments, requiring more effort for them to work in a self-hosted setup. The tables below highlight some of the differences between our SaaS and Self-Hosted offerings. - ✅ available - ⌛ coming soon - ❌ not available ### Secrets scanning sources For more details, refer to the [Secrets Scanning Integrations Overview](../internal-monitoring/integrate-sources/overview.md) page. | Scan source name | GitGuardian SaaS | GitGuardian Self-Hosted | Additional Details | | ---------------------------------------- | ---------------- | ----------------------- | ---------------------------------------------------- | | GitHub.com | ✅ | ✅ | | | GitHub Enterprise Server | ✅ | ✅ | | | GitLab.com | ✅ | ✅ | | | GitLab Self-Hosted Community Edition | ✅ | ✅ | | | GitLab Self-Hosted Premium/Ultimate Plan | ✅ | ✅ | | | Bitbucket Cloud | ✅ | ✅ (2025.2.0) | | | Bitbucket Server/Data Center | ✅ | ✅ | | | Slack | ✅ | ✅ (2024.3.0) | | | Microsoft Teams | ✅ | ✅ (2024.3.0) | | | Jira Cloud | ✅ | ✅ (2024.4.0) | Recurrent scanning instead of webhooks from 2026.6.0 | | Jira Data Center | ✅ | ✅ (2024.12.0) | | | ServiceNow | ✅ | ✅ (2025.5.0) | No historical scan | | Confluence Cloud | ✅ | ✅ (2024.7.0) | | | Confluence Data Center | ✅ | ✅ (2024.11.0) | | | Azure Container Registry | ✅ | ✅ (2025.6.0) | | | Google Artifact Registry | ✅ | ✅ (2025.6.0) | | | JFrog Container Registry | ✅ | ✅ (2025.6.0) | | | DockerHub | ✅ | ✅ (2025.6.0) | | | AWS Container Registry (ECR) | ✅ | ✅ (2025.8.0) | | | Microsoft SharePoint Online | ✅ | ✅ (2025.9.0) | | | Microsoft OneDrive | ✅ | ✅ (2025.9.0) | | | Bring Your Own Sources | ✅ | ✅ (2025.9.0) | | ### Alerting and Notifications For more details, refer to the [Alerting and Notifications](../platform/configure-alerting/alerting-and-notifications.md) page. | Notifier name | GitGuardian SaaS | GitGuardian Self-Hosted | | ---------------- | ---------------- | ----------------------- | | Slack | ✅ | ✅ | | PagerDuty | ✅ | ✅ | | Splunk | ✅ | ✅ | | Discord | ✅ | ✅ | | Jira Cloud | ✅ | ✅ (2024.5.0) | | Jira Data Center | ✅ | ✅ (2024.12.0) | | Microsoft Teams | ✅ | ✅ (2025.1.0) | ### Honeytoken For more details, refer to the [Honeytoken](../honeytoken/home.mdx) page. | Feature Name | GitGuardian SaaS | GitGuardian Self-Hosted | Additional Details | | ----------------------------------------------------------------------------- | ---------------- | ----------------------- | -------------------------------------------------------------------------------------------------------- | | Honeytoken | ✅ | ✅ | | | Honeytoken Deployment Jobs | ✅ | ✅ (2024.4.0) | | | [Honeytoken "Publicly Exposed" Detailed Location](../honeytoken/code-leakage) | ✅ | ❌ | The “Publicly Exposed” tag exists for both, but exact location on GitHub.com is available only for SaaS. | ### Other features | Feature Name | GitGuardian SaaS | GitGuardian Self-Hosted | Additional Details | | ------------ | ---------------- | ----------------------- | ------------------ | | [AI Filters](../platform/collaboration-and-sharing/search-and-filter#4-natural-language-search-ai-filters) | ✅ | ✅ (2026.6.0) | | | [Remediation Tracking](../internal-monitoring/remediate/prioritize-incidents.md#2-explore-with-the-incident-page) | ✅ | ✅ (2025.1.0) | | | [False Positive Remover (Machine Learning)](../secrets-detection/secrets-detection-engine/machine_learning#false-positive-remover) | ✅ | ✅ (2025.1.0) | | | [Secret Enricher (Machine Learning)](../secrets-detection/secrets-detection-engine/machine_learning#secret-enricher) | ✅ | ✅ (2025.3.0) | | | [Similar Incident Grouping (Machine Learning)](../internal-monitoring/remediate/investigate-incidents#ml-powered-similar-incident-grouping) | ✅ | ⌛ | Not supported on self-hosted yet but will be added in a future release. | | [Incident Prioritization Risk Score (Machine Learning)](../internal-monitoring/remediate/prioritize-incidents#risk-score-ml-powered-prioritization) | ✅ | ⌛ | Not supported on self-hosted yet but will be added in a future release. | | [Public Monitoring](../public-monitoring/self-hosted) | ✅ | ✅ (2026.7.0) | Detects secrets leaked on public sources. On self-hosted, requires outbound network access to reach GitGuardian's Public Monitoring service. | | [Secret "Publicly Leaked" Tag](../internal-monitoring/remediate/investigate-incidents#public-exposure-information) | ✅ | Partial | Self-hosted: "Source publicly visible" is always available; "Public incident linked" additionally requires the [Public Monitoring](../public-monitoring/self-hosted) feature (available from 2026.7.0); "Outside perimeter" is not available on self-hosted. SaaS: all three exposure types are visible with a [Public Monitoring](https://www.gitguardian.com/monitor-public-github-for-secrets) subscription. | | [Secrets Analyzer](../secrets-detection/secrets-detection-engine/secrets_analyzer) | ✅ | ✅ (2025.4.0) | | | [Advanced Analytics](../platform/analytics/internal-monitoring) | ✅ | ✅ (2025.12.0) | | | [Analytics Overview](../platform/analytics/overview) | ✅ | ⌛ | Coming soon... | | [Secrets Manager integration](../ggscout-docs/integrations) | ✅ | ✅ (2025.3.0) | ggscout is deployed on the GitGuardian Self-Hosted cluster | | [IP allowlist](../platform/enterprise-administration/ip-allowlist) | ✅ | ❌ | This feature is not available on self-hosted environments, as there are alternative methods to restrict access. | | [GG Bridge](../platform/deployment-model/ggbridge) | ✅ | ❌ | Not supported for self-hosted deployments. | | [GitGuardian Assistant](../platform/assistant/overview) | ✅ | ⌛ | | | [Generic Detectors for non-VCS sources](/releases/saas/2026/07/08/changelog) | ✅ | ⌛ | | | [GitGuardian MCP server](../ggmcp-docs/home) | ✅ | ✅ (2026.7.0) | | --- ## Custom Certificate Authorities GitGuardian provides the option to use a custom Certification Authority (CA) for some of the integration. Configuring this will permit the GitGuardian application to verify certificates signed by the custom CA. It is only supported with the following integrations: - GitHub Enterprise Server - GitLab Self-Managed - Azure DevOps - Bitbucket - Splunk alerting - Custom webhook alerting ## Prerequisites To use your CA certificates with the GitGuardian application, you will need to generate a `pem` file with the entire SSL certificate trust chain. ### Format your file with multiple pem certificates In case of multiple certificates, you should concatenate them into a single file, like the example below: ```bash -----BEGIN CERTIFICATE----- xxx (your first certificate) xxx -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- xxx (your second certificate) xxx -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- xxx (your third certificate) xxx -----END CERTIFICATE----- ``` ## Upload and deploy ### Helm-based installation Helm supports only the `pem` file format. To use a custom CA, specify it in the values file under the `tls.customCa` and `replicated.privateCASecret` sections. :::info For TLS certificates via cert-manager, see **[Configure TLS certificates using cert-manager](./tls-certificates#using-cert-manager)**. ::: Given the certificate is at a path `$HOME/gitguardian/custom-ca.pem`, first create the secret in your namespace with the following command: ```bash kubectl create secret generic custom-ca-secret-name --from-file $HOME/gitguardian/custom-ca.pem ``` Then specify the following in your values file: ```yaml tls: customCa: # Name of the secret containing certificate in the PEM format existingSecret: custom-ca-secret-name # Key name of the certificate entry existingSecretKeys: caCrt: 'custom-ca.pem' replicated: privateCASecret: name: custom-ca-secret-name key: 'custom-ca.pem' ``` Apply the configuration with: ```bash helm upgrade -n oci://registry.replicated.com/gitguardian/gitguardian --version 2024.x.y -f local-values.yaml` ``` Replace `` with the release name you specified during the initial installation (use `helm ls` to find it). If needed, specify the Kubernetes namespace with `-n` (default namespace is used if not specified). Stick to the same version using the `--version` flag. ### KOTS-based installation Connect to the Admin Console and navigate to the Custom Certificate Authority section. Check the **Use custom CA** setting. Depending on the type of file you generated, you'll have to check the corresponding option. You can now upload your CA certificate file: ![Configure your custom Certificate Authority](/img/self-hosting/security/installation_configure_custom_ca.png) Once uploaded, do not forget to save the configuration at the bottom of the page. **You'll also have to redeploy the application for the change to be taken into account.** Certificates will be then installed and used by the application. --- ## Database Security Maintaining the security of your database systems is paramount in protecting sensitive information and ensuring the integrity of your data. This guide provides comprehensive steps for updating the security settings of PostgreSQL and Redis databases, including password changes, encryption key rotation, and client certificate updates. Follow these procedures carefully to enhance the security posture of your databases. ## Update PostgreSQL Password Ensure the security of your PostgreSQL database by setting a new password. :::caution Ensure you back up your database before starting this procedure, which will incur minimal application downtime—from scaling down to full redeployment. ::: 1. Scale down the Dashboard, Public API and Webhook receivers. ```bash kubectl --namespace get deploy -o name \ | grep webapp \ | xargs kubectl --namespace scale deploy/% --replicas 0 ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). 2. Confirm all asynchronous and scheduled tasks have finished. ```bash kubectl exec --namespace -t deploy/worker-scanners \ -- celery -A ward_run_app inspect active ``` The output should indicate `- empty -` for each pod, signaling completion. ```bash app@(...):/app$ celery -A ward_run_app inspect active (...) -> workers@worker-worker-(...): OK - empty - -> long_tasks@worker-long-tasks-(...): OK - empty - -> scanner@worker-scanners-(...): OK - empty - -> email@worker-email-(...): OK - empty - -> email@worker-email-(...): OK - empty - -> scanner@worker-scanners-(...): OK - empty - -> long_tasks@worker-long-tasks-(...): OK - empty - -> workers@worker-worker-(...): OK - empty - ``` 3. Scale down all workers and scheduler pods. ```bash kubectl --namespace get deploy -o name \ | grep worker \ | xargs kubectl --namespace scale deploy/% --replicas 0 ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). 4. Configure your environment, update the namespace `gg_namespace` as needed. ```bash gg_namespace= pg_host=$(kubectl -n $gg_namespace get cm gim-config -o jsonpath="{.data.POSTGRES_HOST}") pg_port=$(kubectl -n $gg_namespace get cm gim-config -o jsonpath="{.data.POSTGRES_PORT}") pg_user=$(kubectl -n $gg_namespace get cm gim-config -o jsonpath="{.data.POSTGRES_USER}") pg_passwd=$(kubectl -n $gg_namespace get secret gim-secrets -o jsonpath="{.data.POSTGRES_PASSWORD}" | base64 -d) pg_db=$(kubectl -n $gg_namespace get cm gim-config -o jsonpath="{.data.POSTGRES_DB}") ``` 5. With your environment set, you're ready to launch a PostgreSQL shell. ```bash echo "Connection to $pg_user@$pg_host:$pg_port/$pg_db" kubectl -n $gg_namespace run postgresql-client --rm -it \ --restart='Never' --image docker.io/bitnamilegacy/postgresql:13 \ --env="PGPASSWORD=$pg_passwd" --command \ -- psql --host $pg_host -U $pg_user -d $pg_db -p $pg_port ``` 6. Inside the shell, update your password. ```sql ALTER USER WITH PASSWORD ''; ``` Replace `` with your username and `` with the desired password. ### KOTS-Based Installation 1. Navigate to the “Config” tab in the [KOTS Admin Console](../management/infrastructure-management/admin-console.md) and update the PostgreSQL password. 2. Save the configuration. 3. Deploy the updated configuration. ![Deploying the updated configuration](/img/self-hosting/security/kots-deploy.png) ### Helm-Based Installation :::caution Do not directly modify values within the Kubernetes secret `gim-secrets`, as such changes will be overridden by subsequent Helm upgrades. ::: 1. For secrets management, ensure updates are made in the appropriate location based on your setup. Look at your values file under the `postgresql` section to find how the password is stored. For further details, see [Helm sensitive information management](../installation/helm-secrets). - If you use a secret manager, change the required values in it. - If you use a secret inside the namespace, patch it: ```bash kubectl patch secret -n $gg_namespace gim-secrets \ -p "{\"data\":{\"POSTGRES_PASSWORD\":\"$(echo '' | base64)\"}}" ``` 2. Once the new password is set you can redeploy the application: `helm upgrade -n -f local-values.yaml` Replace `` with the release name you specified during the initial installation (use `helm ls` to find it). If needed, specify the Kubernetes namespace with `-n` (default namespace is used if not specified). Stick to the same version using the `--version` flag. ## Update Redis main Password (external cluster) The process for updating the Redis main password varies by installation method: - **Standard Redis Installation**: either create a new instance with identical settings or directly update the password in the existing instance's configuration file. - **AWS Elasticache**: use the AWS CLI or API to follow the [Rotate AUTH token](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html#auth-modifyng-token) guidelines. - **GCP Memorystore**: modify the AUTH string by [toggling AUTH from off to on](https://cloud.google.com/memorystore/docs/redis/about-redis-auth). - **Bitnami Helm chart**: in the Redis Helm Chart value file, change the value `global.redis.password` with the new password. Apply changes with `helm upgrade -f `. ### KOTS-Based Installation 1. Navigate to the “Config” tab in the [KOTS Admin Console](../management/infrastructure-management/admin-console.md) and update the PostgreSQL password. 2. Save the configuration. 3. Deploy the updated configuration. ![Deploying the updated configuration](/img/self-hosting/security/kots-deploy.png) ### Helm-Based Installation :::caution Do not directly modify values within the Kubernetes secret `gim-secrets`, as such changes will be overridden by subsequent Helm upgrades. ::: 1. For secrets management, ensure updates are made in the appropriate location based on your setup. Look at your values file under the `redis.main` section to find how the password is stored. For further details, see [Helm sensitive information management](../installation/helm-secrets). - If you use a secret manager, change the required values in it. - If you use a secret inside the namespace, patch it: ```bash kubectl patch secret -n \ -p "{\"data\":{\"REDIS_URL\":\"://:$(echo -n '' | base64)@:\"}}" ``` 2. Once the new password is set you can redeploy the application: `helm upgrade -n -f local-values.yaml` Replace `` with the release name you specified during the initial installation (use `helm ls` to find it). If needed, specify the Kubernetes namespace with `-n` (default namespace is used if not specified). Stick to the same version using the `--version` flag. ## Update Redis main Password (embedded cluster) Replace the value of the key `redis-password` in the secret `redis` by your new password. ```bash NEWPASSWORD=$(echo -n '' | base64) kubectl patch secret --namespace redis \ -p "{\"data\":{\"redis-password\":\"${NEWPASSWORD}\"}}" ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ## Update PostgreSQL client certificate (external cluster) :::info This procedure is intended for PostgreSQL configurations using mTLS (Mutual TLS). Please be aware that configuring PostgreSQL to utilize client certificates is not feasible with AWS RDS. ::: :::caution Ensure you back up your database before starting this procedure, which will incur minimal application downtime—from scaling down to full redeployment. ::: 1. Scale down the Dashboard, Public API and Webhook receivers. ```bash kubectl --namespace get deploy -o name \ | grep webapp \ | xargs kubectl --namespace scale deploy/% --replicas 0 ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). 2. Confirm all asynchronous and scheduled tasks have finished. ```bash $ kubectl exec --namespace -t deploy/worker-scanners \ -- celery -A ward_run_app inspect active ``` The output should indicate `- empty -` for each pod, signaling completion. ```bash app@(...):/app$ celery -A ward_run_app inspect active (...) -> workers@worker-worker-(...): OK - empty - -> long_tasks@worker-long-tasks-(...): OK - empty - -> scanner@worker-scanners-(...): OK - empty - -> email@worker-email-(...): OK - empty - -> email@worker-email-(...): OK - empty - -> scanner@worker-scanners-(...): OK - empty - -> long_tasks@worker-long-tasks-(...): OK - empty - -> workers@worker-worker-(...): OK - empty - ``` 3. Scale down all workers and scheduler pods. ```bash kubectl --namespace get deploy -o name \ | grep worker \ | xargs kubectl --namespace scale deploy/% --replicas 0 ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). 4. The process for updating the PostgreSQL client certificate varies by installation method: - **GCP Cloud SQL**: Create a new client certificate following the [procedure](https://cloud.google.com/sql/docs/postgres/configure-ssl-instance#new-client). ### KOTS-Based Installation 1. Navigate to the “Config” tab in the [KOTS Admin Console](../management/infrastructure-management/admin-console.md) and update the PostgreSQL password. 2. Save the configuration. 3. Deploy the updated configuration. ![Deploying the updated configuration](/img/self-hosting/security/kots-deploy.png) ### Helm-Based Installation :::caution Do not directly modify values within the Kubernetes secret `gim-secrets`, as such changes will be overridden by subsequent Helm upgrades. ::: 1. For secrets management, ensure updates are made in the appropriate location based on your setup. Look at your values file under the `postgresql` section to find how the password is stored. For further details, see [Helm sensitive information management](../installation/helm-secrets). - If you use a secret manager, change the required values in it. - If you use a secret inside the namespace, patch it: ```bash kubectl patch secret --namespace \ -p "{\"data\": { \"pg_client.key\": \"$(base64 -w0 ./tls.key)\", \"pg_client.crt\": \"$(base64 -w0 ./tls.crt)\"}}" ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). 2. Once the new certificate & key are set you can redeploy the application: `helm upgrade -n -f local-values.yaml` Replace `` with the release name you specified during the initial installation (use `helm ls` to find it). If needed, specify the Kubernetes namespace with `-n` (default namespace is used if not specified). Stick to the same version using the `--version` flag. ## Update PostgreSQL Data Encryption Key Rotating the encryption key (Django Secret Key) is a critical process that involves several steps. :::caution Encryption key rotation is an intensive process that may: - Take significant time to complete, fully occupying a Celery worker. - Generate constant read/write load on the database. - Increase database disk space usage (it's recommended to ensure at least 5GB of free disk space). ::: ### KOTS-Based Installation The [gitguardian_secret_key.sh](https://raw.githubusercontent.com/GitGuardian/ggtools/refs/heads/main/secret-key-rotation/scripts/gitguardian_secret_key.sh) script enables you to rotate the database encryption key. **Prerequisites**: - `kubectl` and `kots` CLI (refer to the [installation documentation](https://docs.replicated.com/reference/kots-cli-getting-started)). - Access to the Kubernetes namespace where the GitGuardian application is installed. Ensure these requirements are met before running the script. Install the script using the following command: ```bash curl -O https://raw.githubusercontent.com/GitGuardian/ggtools/refs/heads/main/secret-key-rotation/scripts/gitguardian_secret_key.sh chmod +x gitguardian_secret_key.sh ``` The script has two actions, `status` and `rotate`. `status` will output current key(s) hashes, and `rotate` will update the configuration. ```bash bash gitguardian_secret_key.sh rotate --namespace ``` Specify the Kubernetes namespace with `--namespace`. ![Script to add new data encryption key](/img/self-hosting/security/key-rotation-script.png) After configuration update, the script will launch the [KOTS Admin Console](../management/infrastructure-management/admin-console.md) where you will need to deploy the updated configuration. ![Deploying the updated configuration](/img/self-hosting/security/kots-deploy.png) ### Helm-Based Installation :::caution Do not directly modify values within the Kubernetes secret `gim-secrets`, as such changes will be overridden by subsequent Helm upgrades. ::: 1. Generate a New Key: While any string is technically acceptable, we advise using a long (minimum 50 characters), high-entropy string for enhanced security. Update the namespace `gg_namespace` as needed. ```bash gg_namespace= new_django_key=$(LC_ALL=C tr -dc A-Za-z0-9 \ -p "{\"data\":{\"DJANGO_SECRET_KEY\":\"${new_django_key}\"}}" kubectl patch secret -n $gg_namespace \ -p "{\"data\":{\"ENCRYPTION_KEYS\":\"${new_encryption_keys}\"}}" ``` 3. Once the new password is set you can redeploy the application: `helm upgrade -n -f local-values.yaml` Replace `` with the release name you specified during the initial installation (use `helm ls` to find it). If needed, specify the Kubernetes namespace with `-n` (default namespace is used if not specified). Stick to the same version using the `--version` flag. ### Initiating data encryption key rotation Once at least two encryption keys are set in your settings: 1. Navigate to the Encryption Key Rotation page in the [Admin area](../management/application-management/admin-area.md): ![Encryption Key Rotation Page](/img/self-hosting/security/key-rotation-admin-area.png) 2. If no rotation has been initiated for the recently added key, start by triggering the creation of rotation jobs. Click the “Prepare Key Rotation” button. ![Prepare Key Rotation](/img/self-hosting/security/key-rotation-prepare.png) 3. Activate the key rotation jobs :::caution Be aware that these jobs may take a long time and will fully occupy one Celery worker. ::: ![Activate Jobs](/img/self-hosting/security/key-rotation-activate-jobs.png) 4. The jobs will run automatically. All that's left is to wait for their completion. You have the option to stop or restart the jobs as needed. ![Jobs Running](/img/self-hosting/security/key-rotation-activate-jobs-running.png) --- ## Security recommendations and information ## Common Vulnerabilities and Exposures GitGuardian builds its self-hosted images on top of [Chainguard](https://www.chainguard.dev/) hardened Base-OS images, which significantly reduces the CVE surface of the frontend and backend containers and targets a zero-CVE goal in production. [KOTS admin](https://docs.replicated.com/release-notes/rn-app-manager#improvements-1-104-3) and [Replicated SDK](https://docs.replicated.com/release-notes/rn-replicated-sdk#improvements-0-0-1-beta-2) images use a distroless Chainguard base image. **Runtime image configuration:** The runtime image is based on the Python image (with an optional FIPS-enabled variant for Helm), and ships the following additional packages: `src-fingerprint`, `libxml2`, `libxslt`, `xmlsec`, `xmlsec-openssl`, and `git`. ### FIPS 140-3 cryptographic modules (Helm only) FIPS 140-3 approved cryptographic modules are available as an **optional** feature for Helm-based installations. When enabled, GitGuardian uses the FIPS-compliant variants of its application images to encrypt sensitive data at rest and in transit. To activate FIPS in your Helm installation, set the following in `values.yaml`: ```yaml global: fips: enabled: true ``` For air-gapped environments, see the [Airgap Installation Guide](../installation/airgap-installation-existing-cluster-helm#fips-compliance-for-airgap-installations) for the FIPS-specific image list. Learn more about [Chainguard's FIPS validation process](https://www.chainguard.dev/unchained/forging-ahead-in-federal-compliance-chainguards-fips-140-3-and-186-5-milestones) and see [Chainguard's FIPS Commitment](https://www.chainguard.dev/legal/fips-commitment) for warranty and certified cryptographic module details. ### GitGuardian images for CVE scanning The table below lists the images shipped in the current release so you can feed them into your CVE scanner (Trivy, Grype, Snyk, etc.) or vulnerability management pipeline. FIPS variants have a `-fips` suffix on the same repository.
Current release image list | Image Type | Repository and Image Name | 2026.8.1 | | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | GitGuardian Frontend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-static-chainguard | 2026.8.1 | | GitGuardian Backend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard | 2026.8.1 | | Helm Tooling — preflights, support bundle, and upgrade path check (until 2026.4.0) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-helm-tooling | 2026.8.1 | | Replicated SDK — [licensing](/self-hosting/license-management) | proxy.replicated.com/proxy/gitguardian/docker.io/replicated/replicated-sdk | 1.19.10 | | [Machine Learning](/self-hosting/management/application-management/machine-learning) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/ml-secret-engine-app-chainguard | 2.0.0 | | [File Scanner](/self-hosting/management/application-management/non-vcs-sources) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/apache-tika | 3.3 | | [Analytics](/platform/analytics/overview) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/basalt-onprem-analytics | 0.8.1 | | [ggscout](/ggscout-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/ggscout/chainguard | 0.31.1 | | [MCP Server](/ggmcp-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/mcp-server | 0.7.0 | | [ClickHouse](/self-hosting/management/infrastructure-management/clickhouse/overview) | proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com/cgr.dev/gitguardian.com/clickhouse-iamguarded | 26.2 | | [ClickHouse backup sidecar](/self-hosting/management/infrastructure-management/clickhouse/backup-restore) | proxy.replicated.com/proxy/gitguardian/docker.io/altinity/clickhouse-backup | 2.8.0 | | [Log collector](/self-hosting/troubleshoot/logs) — fluent-bit | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/fluent-bit | 4.2.4 | | [Log collector](/self-hosting/troubleshoot/logs) — loki | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/loki | 3.7.7 | | [Log collector](/self-hosting/troubleshoot/logs) — minio | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/minio | 0.20260717 | | Bash — [Custom CA](/self-hosting/security/custom-ca) and upgrade path check (starting 2026.5.0) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/bash | 5.3 | The MCP Server and both ClickHouse images are only needed if you enable those components (`mcpServer.enabled` and `clickhouse.enabled`, both `false` by default). :::caution ClickHouse backup sidecar The backup sidecar is the one image the chart does not resolve through `global.imageRegistry`, because it is declared as a plain container in `clickhouse-server.sidecars`. Mirroring it into your private registry is not enough: you also have to point the sidecar at your copy by overriding `clickhouse-server.sidecars` in your values file. :::
The full history of released tags and the private-registry directory layout are maintained in the [Airgap Installation Guide](../installation/airgap-installation-existing-cluster-helm#download-gitguardian-images). ### Analytics image: CVE risk assessment The [Analytics](/platform/analytics/overview) feature image (`gitguardian/basalt-onprem-analytics`) relies on a Python-based data analytics stack whose transitive dependency tree presents ongoing patching challenges inherent to this class of software. The security risk is minimal. The image runs as a nightly Kubernetes `CronJob` with **no webserver, no network listener, and no inbound connections** of any kind. It only writes to internal cluster databases (PostgreSQL) and processes internal GitGuardian metadata — not customer secrets or source code. The vast majority of CVEs in this image describe vulnerabilities that require an exposed network interface or interactive access to exploit, neither of which is present here. GitGuardian monitors this image continuously and will prioritize remediation for any CVE that presents a realistic exploitation path. ## Cosign for image signing GitGuardian has enhanced the security of our images through the implementation of Cosign for image signing, aligning with [SLSA 2](https://slsa.dev/get-started#slsa-2) standards. This ensures all images are secure from their creation to deployment. All GitGuardian images can be verified following the method described below, except for the Replicated SDK which uses a different verification process (see [Verify SDK Image Integrity](https://docs.replicated.com/vendor/replicated-sdk-slsa-validating#verify-sdk-image-integrity)). :::info You can enhance your Kubernetes security by using the Sigstore Policy Controller. For more details, please visit the [Sigstore Policy Controller documentation](https://docs.sigstore.dev/policy-controller/overview/). ::: **Before You Start**: Download Cosign for image verification: [Download Cosign](https://docs.sigstore.dev/cosign/system_config/installation/) **Verification Steps:** 1. Save the provided public key into a file named `gg_cosign.pub`. ```shell echo "-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnVzZQr8D9OgkgZcf9z0v67yrd2pg +yQtJur1OgetAwij8T8g8VH+IegI6Y+1E3ZEqMast934R35UCzOiiyIadQ== -----END PUBLIC KEY-----" > gg_cosign.pub ``` 2. Retrieve your License ID from your license file, where it's labeled as `licenseID`. Use this ID to authenticate with the GitGuardian image repository by executing the commands below. ```shell printf "Enter your License ID: " && read LICENSE_ID docker login registry.replicated.com --username "${LICENSE_ID}" --password "${LICENSE_ID}" docker login proxy.replicated.com --username "${LICENSE_ID}" --password "${LICENSE_ID}" ``` 3. Execute the following command, replacing `:` with the image's name and tag. ```shell cosign verify --key gg_cosign.pub : ``` This command verifies the image against the signatures stored with it, using the provided public key.
Images you can verify with Cosign | Image Type | Repository and Image Name | 2026.8.1 | | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | GitGuardian Frontend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-static-chainguard | 2026.8.1 | | GitGuardian Backend | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard | 2026.8.1 | | Helm Tooling — preflights, support bundle, and upgrade path check (until 2026.4.0) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-helm-tooling | 2026.8.1 | | Replicated SDK — [licensing](/self-hosting/license-management) | proxy.replicated.com/proxy/gitguardian/docker.io/replicated/replicated-sdk | 1.19.10 | | [Machine Learning](/self-hosting/management/application-management/machine-learning) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/ml-secret-engine-app-chainguard | 2.0.0 | | [File Scanner](/self-hosting/management/application-management/non-vcs-sources) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/apache-tika | 3.3 | | [Analytics](/platform/analytics/overview) | proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/basalt-onprem-analytics | 0.8.1 | | [ggscout](/ggscout-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/ggscout/chainguard | 0.31.1 | | [MCP Server](/ggmcp-docs/self-hosted-configuration) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/mcp-server | 0.7.0 | | [ClickHouse](/self-hosting/management/infrastructure-management/clickhouse/overview) | proxy.replicated.com/proxy/gitguardian/513715405986.dkr.ecr.us-west-2.amazonaws.com/cgr.dev/gitguardian.com/clickhouse-iamguarded | 26.2 | | [ClickHouse backup sidecar](/self-hosting/management/infrastructure-management/clickhouse/backup-restore) | proxy.replicated.com/proxy/gitguardian/docker.io/altinity/clickhouse-backup | 2.8.0 | | [Log collector](/self-hosting/troubleshoot/logs) — fluent-bit | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/fluent-bit | 4.2.4 | | [Log collector](/self-hosting/troubleshoot/logs) — loki | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/loki | 3.7.7 | | [Log collector](/self-hosting/troubleshoot/logs) — minio | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/minio | 0.20260717 | | Bash — [Custom CA](/self-hosting/security/custom-ca) and upgrade path check (starting 2026.5.0) | proxy.replicated.com/proxy/gitguardian/ghcr.io/gitguardian/wolfi/bash | 5.3 | The MCP Server and both ClickHouse images are only needed if you enable those components (`mcpServer.enabled` and `clickhouse.enabled`, both `false` by default). :::caution ClickHouse backup sidecar The backup sidecar is the one image the chart does not resolve through `global.imageRegistry`, because it is declared as a plain container in `clickhouse-server.sidecars`. Mirroring it into your private registry is not enough: you also have to point the sidecar at your copy by overriding `clickhouse-server.sidecars` in your values file. :::
The private-registry directory layout for the same images is in the [Upload GitGuardian Images](../installation/airgap-installation-existing-cluster-helm#upload-gitguardian-images) section of the airgap installation guide. Example: ```shell cosign verify --key gg_cosign.pub proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard:2026.4.0 | jq . Verification for proxy.replicated.com/proxy/gitguardian/docker.io/gitguardian/prm-app-chainguard:2026.4.0 -- The following checks were performed on each of these signatures: - The cosign claims were validated - Existence of the claims in the transparency log was verified offline - The signatures were verified against the specified public key ``` Expected output: ```yaml [ { 'critical': { 'identity': { 'docker-reference': 'docker.io/gitguardian/prm-app-chainguard', }, 'image': { 'docker-manifest-digest': 'sha256:b842813ffb597a67c...' }, 'type': 'cosign container image signature', }, 'optional': { 'Bundle': { 'SignedEntryTimestamp': '', 'Payload': { 'body': '', 'integratedTime': 1709632488, 'logIndex': 75773529, 'logID': 'c0d23d6ad406...', }, }, }, }, ] ``` ## TLS certificate The application mandates HTTPS access to safeguard sensitive information such as secrets and source code. **A TLS certificate is required to start the installation.** Use a valid certificate that matches your Fully Qualified Domain Name (FQDN), for example `dashboard.gitguardian.mycorp.local`. For configuration, see the [TLS certificate setup](./tls-certificates). By default, GitGuardian serves a cipher suite supporting only TLS 1.2 and TLS 1.3, which is compatible with modern browsers. When the FIPS 140-3 option is enabled, the following protocols and ciphers are used and are FIPS 140-3 compliant: - **Protocols:** `TLS 1.2` / `TLS 1.3` - **Ciphers:** - **TLS 1.3:** `TLS_AES_256_GCM_SHA384` - **TLS 1.2:** `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384` ### Self-signed certificates Using a self-signed certificate requires additional SSL validation handling for GitLab or GitHub webhooks. SSL verification is enabled by default and must be disabled when integrating with GitLab or GitHub via a self-signed certificate. ## Encryption and Access Control Considering the database will hold sensitive data (like source code and leaks), we strongly recommend encrypting the file system. Additionally, access to the host running the application should be limited to essential personnel (e.g., host and application deployment managers). ## Signup restrictions By default, joining the GitGuardian workspace requires a sign-up via SSO or an invitation link. Disabling signup restrictions means **anyone** within the instance network can join your workspace and potentially access secrets. Should you opt to disable these restrictions, ensure your GitGuardian instance is only accessible within a restricted network, not from the Internet. --- ## TLS certificates TLS certificates need to be defined so that the domain on referring to your GitGuardian instance is correctly authenticated and secured. The TLS certificate's Common Name must match the domain set for your GitGuardian instance hostname. You can use self-signed certificates to test the deployment of the application, be aware that this may lead to integration issues with VCS and is not recommended beyond initial testing. You need to configure TLS certificates for: 1. **KOTS Admin Console**: used for the KOTS Admin Console user access. 2. **GitGuardian Application**: used for the GitGuardian application user access (sometimes also referred to as _NGINX_). 3. **SAML SSO**: used for Single Sign-On (or SSO) to manage your organization’s entire membership via a third-party provider. :::caution We strongly recommend revoking any certificate being replaced, regardless of its expiration status, to maintain system security. ::: ## KOTS Admin Console To update the TLS certificate for the KOTS Admin Console, follow these [instructions](https://docs.replicated.com/embedded-cluster/v2/embedded-tls-certs#update-using-the-admin-console). :::caution Adding the `acceptAnonymousUploads` annotation temporarily creates a vulnerability for an attacker to maliciously upload TLS certificates. After TLS certificates have been uploaded, the vulnerability is closed again. ::: Short version: ```bash NAMESPACE=kotsadm kubectl --namespace "${NAMESPACE}" annotate secret kotsadm-tls acceptAnonymousUploads=1 kubectl --namespace "${NAMESPACE}" delete pod -l app=kurl-proxy-kotsadm ``` If needed, specify another Kubernetes namespace (default namespace is used if not specified). After the pod has restarted, direct your browser to `http://:30000/tls` and go through the upload process in the user interface. ## GitGuardian Application :::caution When using self-signed or **[custom CA](./custom-ca)** certificates, ensure to disable SSL verification for the GitHub webhook. ::: ### KOTS-based installation TLS Certificates are configured in the **TLS certificates** section. You have the option to use the self signed TLS certificates, or you can provide your own certificates as shown below. The recommended method is to use an [existing secret](../installation/helm-secrets#existing-secret). ![generic-tls.png](/img/self-hosting/security/generic-tls.png) For existing clusters, in scenarios where the TLS certificate is managed by your cloud provider's infrastructure, you may reference it directly in your Ingress or Service annotations, depending on your specific cloud provider's requirements. To upload new certificates, replace the previously uploaded files in the KOTS Admin Console. After updating the configuration, deploy the new version which includes only the configuration changes: ![Deploying the updated configuration](/img/self-hosting/security/kots-deploy.png) ### Helm-based installation In Helm installation, the certificate can be set in the `front.ingress.tls` section. You may provide TLS certificates as existing secret (recommended) or raw certificate. ```yaml ingress: enabled: true ingressClassName: 'nginx' tls: enabled: true existingSecret: my-gitguardian-certificate ``` :::caution When using **[certificate-based authentication](../management/infrastructure-management/cert-based-auth.md)**, the TLS configuration is located in `tls.clientAuth`. ::: #### Using cert-manager In Helm installation, you can use [cert-manager](https://cert-manager.io/) to issue the TLS certificates automatically. Cert-manager [must be correctly installed](https://cert-manager.io/docs/installation/) and configured in your cluster, with [an Issuer or a ClusterIssuer resource](https://cert-manager.io/docs/concepts/issuer/). The certificates are created in a Kubernetes secret, and can be used by either Istio Ingress or a classic Ingress. The private key is PKCS#1 with 2048 length. The configuration is done in the local values file with the `tls` section: ```yaml tls: certManager: enabled: true issuer: kind: ClusterIssuer name: my-cluster-issuer certificatesSecret: my-gitguardian-certificate ``` If using a [classic ingress](../management/infrastructure-management/ingress) with `front.ingress` values, the secret name of the certificate must be specified in `front.ingress.tls.secretName`. ## SAML SSO This guide outlines the steps to update the SSO X509 certificate used by GitGuardian for authentication with a third-party SSO provider. For more detailed information on configuring SAML SSO, refer to the [Configure SAML SSO](../../platform/enterprise-administration/saml-sso-configuration) page. If you install GitGuardian using Helm, generate a new SSO certificate, and then edit your Helm values file. For more details, refer to the [Helm Sensitive Information Management](../installation/helm-secrets#existing-secret) page. ### Generate a Self-Signed Certificate To rotate the SSO certificate, start by generating a new self-signed certificate: 1. Generate a new RSA private key: Generate a new 2048-bit RSA private key using OpenSSL with the following command: ```bash openssl genrsa -out gitguardian.key 2048 ``` 2. Create a Certificate Signing Request (CSR): Use the generated private key to create a CSR. Replace `` with the Fully Qualified Domain Name of your self-hosted instance. ```bash openssl req -new -subj '/CN=' \ -key gitguardian.key \ -out gitguardian.csr ``` 3. Create a self-signed certificate: Use the CSR to create a self-signed certificate valid for 365 days (or as required): ```bash openssl x509 -req -days 365 -in gitguardian.csr \ -signkey gitguardian.key -out gitguardian.crt ``` ### Preparing the KOTS Configuration File Create or update your `config.yaml` to include the new certificate and key: ```yaml apiVersion: kots.io/v1beta1 kind: ConfigValues spec: values: embedded_certificate: values: | embedded_key: values: | ``` ### Update KOTS Configuration Values Update the KOTS configuration with the new certificate and private key: ```bash kubectl kots set config gitguardian --namespace \ --config-file config.yaml \ --merge ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ### Connect to the KOTS Admin Console To apply the changes, connect to the KOTS admin console: ```bash kubectl kots --namespace admin-console ``` If needed, specify the Kubernetes namespace with `--namespace` (default namespace is used if not specified). ### Deploy the New Version After updating the configuration, deploy the new version which includes only the configuration changes: ![Deploying the updated configuration](/img/self-hosting/security/kots-deploy.png) :::info If you encounter 403 errors after attempting to "Login with Okta," clearing your web browser's cache may resolve the issue. ::: --- ## Traffic encryption For some usecase, you may want to enable traffic encryption between pods to enhance security in your Kubernetes namespace. The best approach to do this is by using a Service Mesh that will automatically manage mTLS for all TCP traffic between the pods. In this guide, we will go through the two most famous ones, **Istio** and **LinkerD**. ## Prerequisites Both Istio and LinkerD rely on the concept of sidecar containers to encrypt traffic. For Gitguardian application to work properly, we need [Sidecar containers](https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/). 1. The "native" (i.e included natively in Kubernetes) Sidecar container feature is available from **Kubernetes 1.29**. It is mandatory to have this minimum version for our mesh to work properly. 2. You need either [Istio](https://istio.io/latest/docs/setup/install/) or [LinkerD](https://linkerd.io/docs/) installed. :::info It is not recommended to use a Mesh with databases. As we will apply the Mesh to the whole Gitguardian namespace, if your databases (PostgreSQL and Redis) are embedded in the same namespace, you will need to add annotations to exclude them from the Mesh. ::: ## Istio This example assumes you are using Istio in [Sidecar mode](https://istio.io/latest/docs/overview/dataplane-modes/) (which is the "default" one). 1. Label your Gitguardian namespace to tell Istio we want to enable the Mesh: ```bash kubectl label namespace istio-injection=enabled ``` 2. If a database lies in the same namespace, use the annotation `sidecar.istio.io/inject: "false"` in related pod to exclude it from the Mesh 3. Add the following to your Helm value file to enable Kubernetes native sidecars in Istio: ```yaml migration: podAnnotations: sidecar.istio.io/nativeSidecar: "true" ``` :::info This will use native sidecars only for Jobs, which is enough to make the Gitguardian application to work. You may add this annotations to any pod in the namespace. ::: 4. Create a `PeerAuthentication` object to force mTLS over the namespace: ```yaml apiVersion: security.istio.io/v1 kind: PeerAuthentication metadata: name: default namespace: spec: mtls: mode: STRICT ``` 5. If you already installed the Gitguardian application, you will have to restart all pods to inject the sidecar: ```bash kubectl rollout restart deployment -n ``` 6. You should now see all pods carrying, at least, 2 containers, one for the application itself, one for the Istio sidecar. ## LinkerD 1. Annotate your Gitguardian namespace to tell LinkerD we want to enable the Mesh and use native sidecars mode: ```bash kubectl annotate namespace linkerd.io/inject=enabled kubectl annotate namespace config.alpha.linkerd.io/proxy-enable-native-sidecar=true ``` 2. If a database lies in the same namespace, use the annotation `linkerd.io/inject: "disabled"` in related pod to exclude it from the Mesh 5. If you already installed the Gitguardian application, you will have to restart all pods to inject the sidecar: ```bash kubectl rollout restart deployment -n ``` 6. You should now see all pods carrying, at least, 2 containers, one for the application itself, one for the LinkerD sidecar. --- ## System requirements The self-hosted version of GitGuardian is deployed as a Kubernetes application. We recommend installing GitGuardian on an **existing cluster using Helm**. You can find more information on how to [choose your installation method](./installation/choose-embedded-existing) on our dedicated page. ## Hardware requirements ### Architecture GitGuardian Platform self-hosted supports the following CPU architectures: - AMD64: Fully supported across all installation methods - ARM64: Supported for Helm-based installations only (Existing Cluster with Helm). KOTS and Embedded Cluster installations are AMD64-only All container images are published as multi-architecture (multi-arch) manifests. You do not need to specify a Docker `--platform` flag; the appropriate image variant will be selected automatically based on the node architecture. ### Existing Kubernetes cluster installation For sizing recommendations, refer to our [Scaling GitGuardian](./management/infrastructure-management/scaling) page. ### Embedded Kubernetes cluster installation The embedded cluster is a single-node installation that runs the full GitGuardian stack, including the embedded PostgreSQL and Redis, on one virtual machine. Because everything runs on a single node, you should size the machine according to the volume you plan to scan during your trial or Proof of Concept (PoC). The following tiers are a starting point for PoC deployments. They mirror the **Small / Medium / Large** profiles from the **[Scaling](./management/infrastructure-management/scaling)** page (including the embedded PostgreSQL and Redis), consolidated onto a single node with reduced worker replica counts suitable for a PoC: | Tier | Comparable Scaling profile | CPU | Memory | Root disk space | | :----- | :------------------------------------------ | :------- | :----- | :-------------- | | Small | Small (up to ~2,000 repositories) | 16 cores | 64 GB | 400 GB | | Medium | Medium (up to ~10,000 repositories) | 32 cores | 128 GB | 600 GB | | Large | Large (up to ~40,000 repositories, or document sources such as Slack, MS Teams, SharePoint, OneDrive) | 64 cores | 256 GB | 1 TB | :::caution Large-volume PoCs The embedded cluster cannot scale horizontally and is best suited for small to medium PoCs. If you need to scan a large volume of data (high repository counts, or document sources such as SharePoint and OneDrive, which require significant ephemeral storage), we recommend an **[existing cluster installation](./installation/choose-embedded-existing#what-is-an-existing-cluster-installation)** instead. See the **[Scaling](./management/infrastructure-management/scaling)** page for detailed, component-level sizing. ::: This installation has some limitations: - Multi-node support is in beta - Changing node hostnames is not supported - Automatic updates not supported - Support bundles over 100MB in the Admin Console - Installing on STIG- and CIS-hardened OS images is not supported More details on [Replicated](https://docs.replicated.com/vendor/embedded-overview#limitations). ## Software requirements ### Kubernetes for Existing Clusters For Existing Cluster installations, GitGuardian supports the following Kubernetes versions: 1.30 to 1.35. GitGuardian needs a dedicated namespace. :::note If you plan to install GitGuardian on an OpenShift cluster, please refer to the **[detailed guidelines for OpenShift cluster installation](./installation/openshift)**. ::: ### GCP Marketplace The [GCP Marketplace](https://console.cloud.google.com/marketplace/product/gitguardian-public/gitguardiansaas) deployment uses Helm, providing all the benefits of Helm-based installations with consolidated billing through your GCP account. The initial deployment is done through the GCP console, but upgrades are performed directly with Helm. The same Helm requirements below apply. For database setup instructions, see [Cloud SQL: PostgreSQL on GCP](./installation/databases/postgres-cloudsql) and [Memorystore: Redis on GCP](./installation/databases/redis-memorystore). For GCP-specific deployment details, see the [GCP Marketplace deployment guide](https://github.com/GitGuardian/gcpmarketplace). ### Helm The [Existing Cluster with Helm](./installation/installation-existing-cluster-helm) installation method requires [Helm](https://helm.sh) version **3.13+**. :::caution - Helm version 3.18.0 is not supported due to a bug in Helm, which is fixed in 3.18.1 and later versions. ::: Use a Helm version that aligns with your Kubernetes version to avoid compatibility issues. Refer to the [Helm version support policy](https://helm.sh/docs/topics/version_skew/) for the list of compatible versions. :::info FIPS Compliance **FIPS 140-3 (Federal Information Processing Standards) compliance is available exclusively for Helm-based installations.** If you require FIPS 140-3 compliant cryptographic modules for regulatory compliance, you must choose the Helm installation method and set `global.fips.enabled: true` in your Helm values. For airgap installations, additional image renaming steps are required. For more details, see the [Security Recommendations](./security/recommendations) page. ::: Helm installation also supports some optional custom resources. If you wish to use them, you must have the appropriate controllers and operators: - **IngressController:** we provide an example of an `ingress` controller. You can also configure any other [Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) class. Read our [Ingress Configuration](./management/infrastructure-management/ingress) topic. - **Istio:** we support Istio for traffic routing and end-to-end encryption (sidecars). - **Prometheus Operator:** we can deploy ServiceMonitors to expose observability metrics on our application. - **Vault:** we allow the use of Vault through [external-secrets](https://external-secrets.io/) SecretStore. - **CertManager:** we allow certificate management through [cert-manager](https://cert-manager.io/) ClusterIssuer. ### PostgreSQL GitGuardian currently supports PostgreSQL 15 to 18, with PostgreSQL 17 being the recommended version. :::caution PostgreSQL versions 13 and 14 are not supported anymore starting 2025.1.0 release. We strongly recommend upgrading to PostgreSQL 16+ at your earliest convenience. ::: You'll need to install the following extensions: | Extension | Usage | Minimal Version | | --------- | --------------------------------------------------------------------------------------------------------- | --------------- | | btree_gin | Provides GIN capability to base datatypes (int, timestamp, ...) so all columns can be used in GIN indexes | 1.3 | | pg_trgm | Provides functions and operators enabling fast searching for similar strings using GiST and GIN indexes | 1.5 | | plpgsql | Allows the creation of stored procedures and triggers using the procedural programming language PL/pgSQL | 1.0 | | pgvector | Provides vector similarity search using new types, functions, operators and indexes | 0.7.0 (0.8.0 recommended) | Depending on your installation, extensions may already be available. This is the case for the major cloud managed PostgreSQL databases. Otherwise, you might have to carry out some extra actions: * plpgsql extension is installed by default. * btree_gin and pg_trgm extensions are available in the _postgresql-contrib_ package. * [pgvector](https://github.com/pgvector/pgvector?tab=readme-ov-file#installation) extension is available as a package for Debian, Ubuntu or Yum based OSes. If you are using Docker, you can use the available [docker image](https://hub.docker.com/r/pgvector/pgvector). You can also install it via the [pgxn](https://pypi.org/project/pgxnclient/) client. To make these extensions available in your database, you must run the following commands while connected as a `superuser` on the database instance: ```sql CREATE EXTENSION IF NOT EXISTS btree_gin; CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE EXTENSION IF NOT EXISTS plpgsql; CREATE EXTENSION IF NOT EXISTS vector; ``` For additional guidance on databases, see [Configure your database](./installation/databases/database-config). For sizing recommendations, refer to our [Scaling GitGuardian](./management/infrastructure-management/scaling) page. :::tip High Availability and Databases For large-scale deployments, we recommend using an **external PostgreSQL database** and leveraging your provider's replication mechanisms for high availability. ::: :::warning Connection Poolers We recommend avoiding connection poolers (such as [PgBouncer](https://www.pgbouncer.org)) with GitGuardian, as they may cause unexpected behavior or impact performance. Direct connections to PostgreSQL are recommended. ::: ### Redis GitGuardian currently supports Redis 6 to 8, with Redis 7 being the recommended version. Additionally, we support **Valkey** (a Redis-compatible fork of Redis 7.2) as an alternative Redis implementation. **How GitGuardian Uses Redis**: Redis serves as the message broker for distributed job processing (Celery), caches frequently accessed data, and stores temporary scan results. For large-scale deployment, we highly recommend using an external Redis. For sizing recommendations, refer to our [Scaling GitGuardian](./management/infrastructure-management/scaling) page. For High Availability, we support [Redis Sentinel](https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/) for Existing cluster. **Redis Cluster is not supported**. :::warning The Redis instance must be dedicated exclusively to the GitGuardian application. Sharing the instance with other applications may lead to unexpected behavior, data corruption, and performance issues. ::: :::info The `FLUSHDB` command must be enabled on the Redis instance, as it is essential for the proper functioning of certain features in our application. Ensure that this command is not shadowed in your Redis configuration (e.g., `rename-command "FLUSHDB" ""`). Be aware that if Redis has an eviction policy set (such as `noeviction`, `allkeys-lru`, etc.), and the policy is set to `noeviction`, Redis will not evict any data. This can cause new writes to fail when the memory limit is reached, so choose your eviction policy carefully. ::: ### KOTS The "Existing cluster with KOTS" installation method is using [KOTS](https://kots.io/). We use the latest KOTS version available to validate our releases. You can find version compatibility on the [KOTS compatibility page](https://docs.replicated.com/enterprise/installing-general-requirements#kubernetes-version-compatibility). The [KOTS Admin Console](./management/infrastructure-management/admin-console) will have full control over this namespace. The following role needs to be created: ```bash Name: kotsadm-role Labels: kots.io/kotsadm=true Annotations: PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- *.* [] [] [*] ``` We are using the following objects: - **PersistentVolumeClaims:** we are using persistent volume claims for KOTS, workers and the embedded databases. - **IngressController:** we can provide a default ingress, an [Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) is needed to handle it. You need to have the appropriate controllers and operators to handle them. ### Kubernetes and OS for Embedded Clusters For Embedded Kubernetes cluster installations, please note that these setups are intended primarily for trial or Proof of Concept (PoC) purposes and are not recommended for production use. #### Kubernetes For **Embedded cluster installations (instances installed in 2025 or after)**, Kubernetes is upgraded automatically when updating the GitGuardian application through the KOTS Admin Console. For **Embedded cluster legacy (kURL) installations (instances installed in 2024 or before)**, follow the [upgrade procedure](./management/infrastructure-management/upgrade-kots#upgrading-kubernetes-on-embedded-cluster-legacy-kurl-instances-installed-in-2024-or-before) to update your Kubernetes version. #### Operating system Ensure that you adhere to the [Replicated](https://docs.replicated.com/enterprise/installing-general-requirements) and [Embedded Cluster](https://docs.replicated.com/enterprise/installing-embedded-requirements) system requirements. :::note We strongly recommend applying the latest patches available for your operating system distribution before beginning the installation. ::: ### ClickHouse Some features require [ClickHouse](./management/infrastructure-management/clickhouse/overview), an optional in-cluster component shipped as part of the GitGuardian Helm chart. It requires local persistent volumes and object storage (S3-compatible, Azure Blob Storage, or GCS) that you provide: see [ClickHouse storage](./management/infrastructure-management/clickhouse/storage) and [Sizing and hardening](./management/infrastructure-management/clickhouse/sizing). ## Domain name requirements You will need a Fully Qualified Domain Name (FQDN) to install the application (ex: `gitguardian.mycorp.local`). This cannot be an IP. You will also need a TLS certificate for HTTPS access or use the default self-signed certificates. --- ## Environment health The **Health Check** page provides an overview of all your GitGuardian self-hosted instance. On this page, you can have access to the status of the services used by GitGuardian. The page also provides you with information on VCS integration connected to GitGuardian and the Readiness REST endpoint. ## GitGuardian Services This section shows you the status of services used by your GitGuardian instance to function. In case one of those services is somehow unreachable or broken, it will be indicated as such. ![Health Check page](/img/self-hosting/troubleshoot/health_check_services.png) ## Readiness The REST endpoint checks the readiness of your GitGuardian instance. The URL of that endpoint is displayed on the Health Check page. The endpoint is protected, you can use it only with an API key (refer to the [API authentication documentation](../../api-docs/authentication)) It is easy to use the endpoint, for instance using curl (`XXXX` should be replaced with your API key): ```bash curl -H "Authorization: Token XXXX" https://gitguardian.example.com/exposed/v1/readiness ``` Example of the reply: ``` { "db": "ok", "redis": "ok", "status": "ok" } ``` ## Integration Connectivity Integration health checks ([VCS](../../internal-monitoring/integrate-sources/vcs-integrations/github), [Messaging](../../internal-monitoring/integrate-sources/messaging-integrations/slack), [Ticketing](../../internal-monitoring/integrate-sources/ticketing-integrations/jira-cloud), ...) are accessible through _Settings > Workspace > Integrations_, providing an overview of the **source integration status and any errors** encountered. In the event of an integration failure, detailed information on resolving the issue will be displayed. Additionally, there's an option to manually re-check the integration connection, along with timestamps indicating the last execution and the most recent successful connection. You can set up your account to receive email alerts when an integration fails. Find more information [here](../../platform/user-account/email-preferences). The interval between periodic health checks can be customized using the `spread_periodic_range_minutes` preference in [the Health Checks section of the admin area preferences](../../self-hosting/management/application-management/preferences.md). ### Example of Failure ![Health Check Failure](/img/self-hosting/troubleshoot/health_check_vcs_failure.png) ### Example of Success ![Health Check Success](/img/self-hosting/troubleshoot/health_check_vcs_success.png) ## Public Monitoring If [Public Monitoring](../../public-monitoring/self-hosted) is enabled on your instance, two additional health checks confirm the integration with GitGuardian's hosted Public Monitoring service: - **Credentials:** confirms the Public Monitoring credentials are set. - **Connectivity:** confirms the credentials are valid and the hosted service is reachable. The credentials are configured in the Admin area; see [Configure the connection](../../public-monitoring/self-hosted#2-configure-the-connection) for the setup flow. Use these checks to verify the feature is working after setup, and to diagnose it if public secret incidents stop being retrieved. --- ## Logs and debug ## Viewing logs in pods :::tip Enhanced Kubernetes Management with k9s For a more interactive and user-friendly way to navigate Kubernetes pods and view logs, consider using **[k9s](https://k9scli.io)**. This tool provides an efficient and visual way to manage Kubernetes applications directly from the command line, enhancing the experience of viewing logs and managing resources. ::: To view logs in a pod, use the kubectl logs command. Replace `[POD_NAME]` with the specific name of your pod: ```bash kubectl logs [POD_NAME] -n [NAMESPACE] ``` If you're unsure of the pod's name, first list all pods with: ```bash kubectl get pods -n [NAMESPACE] ``` ## Debug pod :::info Please note that to be able to run the debug command, your kubectl version must be >= 1.27. ::: To initiate a debug session for an existing pod, execute the `kubectl debug` command as shown below, using the `internal-api` pod as an example (replace `[NAMESPACE]` with the correct one and find the names of other pods on the [Application topology](./topology) page): ```bash kubectl debug \ --namespace=[NAMESPACE] \ --profile=restricted \ --share-processes \ --container=app \ --copy-to=webapp-debug \ --image=$(kubectl --namespace=[NAMESPACE] get pods -l app.kubernetes.io/component=internal-api -o jsonpath='{.items[0].spec.containers[0].image}')-debug \ $(kubectl --namespace=[NAMESPACE] get pods -l app.kubernetes.io/component=internal-api -o jsonpath='{.items[0].metadata.name}') ``` Where: - `--profile=restricted`: Mounts all volumes, config maps, and secrets from the original pod with limited capabilities. - `--container`: Specifies the debug container. - `--copy-to`: Names the new debug pod. - `--image`: Sets the debug image, modifying the original image's tag with a `--debug` suffix. Upon execution, a debug pod named `webapp-debug` will be created in your designated namespace, containing a single `app` container running the debug image: To interact with the debug container, use `kubectl exec`: ```bash kubectl exec -it webapp-debug -- bash ``` For diagnostics, you may run: ```bash kubectl exec -it webapp-debug -- python manage.py diagnose_instance ``` After completing your debugging tasks, remove the debug pod with this command: ```bash kubectl delete pod webapp-debug ``` ## Log collector Self-hosted GitGuardian deployments now feature a built-in log collector, designed to streamline troubleshooting and support. This system leverages Loki, MinIO, and Fluent Bit to automatically collect, store, and centralize logs from your GitGuardian application. Log collection is enabled by default for all installation types (Helm or KOTS), ensuring that all relevant logs are readily available for diagnostics without requiring manual configuration. By default, we retain 3 days of logs. ![Log collector](/img/self-hosting/troubleshoot/log_collector.png) ### Helm-based installation In the `values.yaml` file, set the `logCollector.enabled` parameter to `false` to deactivate the log collector. By default, when generating the Support Bundle, we retrieve **3 days** of application logs. This duration is configurable via the Helm parameter: `logCollector.supportBundle.since` using this format: `<0-9>+`, and must not exceed 7 days. #### Loki Configuration You may need to configure Loki resource limits and pod labels to comply with your organization's policies: **Resource Limits:** ```yaml loki: singlyBinary: resources: limits: # Specify CPU limits for Loki cpu: 1000m # Specify Memory limits for Loki memory: 1024Mi requests: cpu: 500m memory: 512Mi ``` **Pod Labels:** ```yaml loki: podLabels: env: production team: infrastructure ``` #### Additional pipelines The LogCollector can be extended with custom pipelines to forward application logs to external log aggregation systems. This allows you to integrate GitGuardian's logs with your existing observability infrastructure. **Supported outputs**: The LogCollector leverages Fluent Bit's extensive output plugin ecosystem, enabling integration with popular log management platforms including: - Splunk - Enterprise log management and analytics - Loki - Grafana's log aggregation system - Elasticsearch - Search and analytics engine - Kafka - Distributed streaming platform - Datadog - Cloud-based monitoring services For the complete list of available outputs and their configuration options, refer to the [Fluent Bit outputs documentation](https://docs.fluentbit.io/manual/pipeline/outputs). **Configuration**: Additional pipelines are configured through the `logCollector.pipelines` section in your values file. Each pipeline can include: - Filters - Transform, enrich, or modify log records before output - Outputs - Define destination systems and connection parameters **Example: Splunk integration** The following configuration demonstrates how to send logs to a Splunk HTTP Event Collector (HEC) endpoint: ```yaml logCollector: envFrom: - secretRef: # Secret containing token (SPLUNK_TOKEN) name: splunk pipelines: splunk: filters: - | name modify add index my-splunk-index outputs: - | name splunk host port 8088 splunk_token ${SPLUNK_TOKEN} tls on tls.verify off ``` ### KOTS-based installation In the [KOTS Admin Console](../management/infrastructure-management/admin-console), deactivate the log collector. ![Log collector](/img/self-hosting/troubleshoot/replicated_log_collector.png) ## Embedded cluster In Embedded cluster, you need an additional step to be able to do `kubectl` commands. ``` sudo ./gitguardian shell ``` Now you can operate the cluster. ## Worker Tasks To monitor task activity, worker counts, and usage, visit the tasks page in the [admin area](../management/application-management/admin-area#tasks). --- ## Support bundle ## Generate from the admin area (in-cluster) GitGuardian provides a built-in **Support Bundle** page in the admin area. This allows administrators to generate, download, and optionally upload support bundles directly to GitGuardian. It is available for both **Helm-based** and **KOTS-based** installations. ![Support Bundle admin area page](/img/self-hosting/troubleshoot/admin_area_support_bundle.png) :::note The configuration sections below apply to **Helm-based installations** only. ::: ### Configuration In-cluster support bundle generation is **enabled by default** with all RBAC resources managed by the chart. No additional configuration is needed for a standard deployment. | Key | Default | Effect | | ----------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------- | | `rbac.enabled` | `true` | Creates the GIM role with pod-management permissions | | `replicated.supportBundle.rbac.createPodRole` | `true` | Adds pod create/get/delete rules to the GIM role | | `replicated.supportBundle.rbac.serviceAccount.create` | `true` | Creates a dedicated `support-bundle` SA for the collector pod | | `replicated.supportBundle.rbac.role.create` | `true` | Creates the namespace-scoped Role for the collector pod | | `replicated.supportBundle.rbac.clusterRole.create` | `true` | Creates a ClusterRole for cluster-wide diagnostics (nodes, CRDs, etc.) | | `replicated.supportBundle.admissionPolicy.enabled` | `true` | Deploys a ValidatingAdmissionPolicy restricting pod creation (requires Kubernetes 1.30+) | Common scenarios: - **Disable in-cluster generation entirely** — set `replicated.supportBundle.rbac.createPodRole: false`. This removes the pod-management permissions from the GIM role, preventing the application from spawning support-bundle pods. You can still [generate bundles from the CLI](#helm-based-installation). - **Manage the support-bundle SA yourself** — create the service account and its bindings outside of Helm, then reference it with `existingServiceAccountName` and set `role.create` and `clusterRole.create` to `false`: ```yaml replicated: supportBundle: rbac: serviceAccount: create: false existingServiceAccountName: 'my-custom-support-bundle-sa' role: create: false clusterRole: create: false ``` - **Disable the ValidatingAdmissionPolicy** (requires **Kubernetes 1.30+**) — set `replicated.supportBundle.admissionPolicy.enabled: false`. This removes the guardrail that restricts what the GIM SA can create, meaning any compromise of the application could allow arbitrary pod creation in the namespace. Only disable this if your cluster does not support Kubernetes 1.30+, and consider replacing it with an equivalent policy using OPA/Gatekeeper, Kyverno, or any other admission controller. ### How it works When you click **Generate new support bundle**, the application creates a short-lived pod in the same namespace. This pod: 1. Runs the `kubectl support-bundle` command against a pre-defined spec to collect logs, cluster resources, and diagnostic data. 2. Serves the resulting `.tar.gz` archive over an internal HTTP endpoint so the application can stream it back to your browser. 3. Optionally uploads the bundle directly to Replicated for remote analysis by the GitGuardian support team. The pod has a fixed lifetime of **1 hour** (`activeDeadlineSeconds: 3600`). After that, Kubernetes terminates it automatically. ### Security architecture In-cluster bundle generation uses **two separate service accounts** with strictly separated permissions: | Service account | Used by | Purpose | | ------------------------------------ | ----------------------------- | ---------------------------------------------------------------- | | **GIM service account** | `webapp-internal-api` pods | Creates, monitors, and deletes the support-bundle pod | | **`support-bundle` service account** | The support-bundle pod itself | Read-only access to namespace and (optionally) cluster resources | The GIM SA never holds the broad read permissions needed by the collector, and the collector never holds pod-management permissions. When `admissionPolicy.enabled` is `true`, the chart deploys a **ValidatingAdmissionPolicy** (requires **Kubernetes 1.30+**) that restricts what the GIM SA can create. Only the exact expected pod (name, service account, images, commands, environment variables) is allowed. This is **strongly recommended** — disable only if your cluster does not support it. #### RBAC details The full GIM role definition (including pod-management rules) is documented in the [Kubernetes Application RBAC](../installation/installation-existing-cluster-helm#kubernetes-application-rbac) section. The support-bundle service account requires: **Role (namespace-scoped, required):** ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: support-bundle namespace: rules: - apiGroups: ['*'] resources: ['*'] verbs: ['get', 'list', 'watch'] - apiGroups: [''] resources: ['pods/exec'] verbs: ['create'] ``` **ClusterRole (cluster-scoped, optional)** — the name is suffixed with the namespace (`support-bundle-`) to avoid collisions in multi-tenant clusters: ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: support-bundle- rules: - apiGroups: [''] resources: ['namespaces', 'nodes'] verbs: ['get', 'list', 'watch'] - apiGroups: ['apiextensions.k8s.io'] resources: ['customresourcedefinitions'] verbs: ['get', 'list', 'watch'] - apiGroups: ['storage.k8s.io'] resources: ['storageclasses'] verbs: ['get', 'list', 'watch'] ``` #### Self-managed RBAC If your organization requires RBAC to be provisioned outside of Helm, disable the chart-managed resources using the scenarios described in the [Configuration](#configuration) section and create the service account, roles, and bindings yourself using the definitions above. ### Upload credentials To enable **Upload bundle directly to Replicated**, the chart creates a `support-bundle-credentials` secret containing the Replicated license ID and upload domain. To manage this secret yourself: ```yaml replicated: supportBundle: credentials: existingSecret: 'my-support-bundle-credentials' ``` The secret must contain the keys `license-id` and `upload-domain`. upload-domain should be `replicated.app` by default and might be different in the future. ### Resource limits You can configure resource requests and limits for both containers in the support-bundle pod: ```yaml replicated: supportBundle: resources: initContainer: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi mainContainer: requests: cpu: 50m memory: 32Mi limits: cpu: 100m memory: 64Mi ``` #### Sizing the init container The init container collects and compresses the support bundle. Its **memory consumption scales linearly with the bundle size** — roughly **~45 Mi per MB** of generated bundle (1 MB → ~45 Mi, 4 MB → ~175 Mi, 10 MB → ~400 Mi). If the init container exceeds its memory limit, it is OOMKilled (exit code 137) and bundle generation fails. Increasing the **CPU limit** reduces compression time but does not affect memory. The defaults are kept low (`500m`) to minimize impact on other workloads. To determine the right values, first [generate a bundle from the CLI](#helm-based-installation) and check its size: ```bash ls -lh support-bundle-*.tar.gz ``` Then adjust resources: 1. **Memory limit**: estimated peak (~45 Mi × bundle size in MB) × 1.5 for headroom. 2. **Memory request**: half the limit (1:2 request-to-limit ratio). 3. **CPU limit**: increase if you want faster generation and can afford the burst. For example, if your test bundle is 8 MB (estimated peak ~360 Mi): ```yaml replicated: supportBundle: resources: initContainer: requests: cpu: 100m memory: 256Mi limits: cpu: 500m memory: 640Mi ``` :::tip Bundles that include verbose Loki or application logs tend to be significantly larger. If you increase `replicated.supportBundle.logs.maxLines`, regenerate a test bundle to reassess the size before adjusting resource limits. ::: ## Generate from CLI (kubectl) ### Helm-based installation For Helm-based installations, you can also generate a support bundle from the command line using the [Krew package manager](https://krew.dev/): 1. [Install the Krew plugin](https://krew.sigs.k8s.io/docs/user-guide/setup/install/). 2. Install the support-bundle utility: `kubectl krew install support-bundle`. 3. Run: `kubectl support-bundle --load-cluster-specs --namespace `. This command will create a `.tar.gz` support bundle in your current directory. You can then send it to GitGuardian support, or [upload it from the CLI](#upload-a-bundle-from-the-cli). To customize the number of log lines captured, set the `maxLines` parameter as shown below. Adjust the value to capture more or fewer logs as needed: ```yaml replicated: supportBundle: logs: maxLines: 100000 # Maximum number of log lines ``` If you are not a `cluster-admin` in your Kubernetes cluster, you will need to apply the RBAC configuration described in the [RBAC details](#rbac-details) section above to your targeted namespace. ### KOTS-based installation :::caution If you previously installed GitGuardian on an existing cluster using KOTS and either lack `cluster-admin` rights in your Kubernetes cluster or wish to limit permissions for the KOTS Admin Console, you must apply the configuration in your targeted namespace as described in **[Kubernetes Application RBAC](../installation/installation-existing-cluster-kots#kubernetes-application-rbac)**. ::: The **KOTS Admin Console** includes a diagnosis tool for generating a support bundle to identify common issues. Sensitive information is automatically redacted. You can also get a command to manually generate a support bundle from a CLI. ![create support bundle](/img/self-hosting/troubleshoot/replicated_trigger_analysis.png) Once generated, you can preview the contents and send it directly to GitGuardian for analysis. ![send support bundle](/img/self-hosting/troubleshoot/replicated_analysis_report.png) To customize the number of log lines captured in the support bundle, go in the **KOTS Admin Console** and set the **Maximum number of lines in logs** field in the Support Bundle section of the configuration section. ![send support bundle](/img/self-hosting/troubleshoot/replicated_max_lines_support_bundle.png) Then save the configuration, and **Deploy** the application to apply the new configuration. ## Upload a bundle from the CLI Bundles generated from the CLI can be sent to GitGuardian support without going through the admin area. Add `--auto-upload` to upload the bundle as soon as it is generated: ```bash kubectl support-bundle --load-cluster-specs --namespace --auto-upload ``` If the machine that generates the bundle has no Internet access, generate it first, then upload the archive from a machine that does: ```bash kubectl support-bundle upload support-bundle-.tar.gz ``` Both commands read the license ID and the application slug from the bundle itself. If they cannot be found, pass them explicitly: | Flag | Effect | | ----------------- | ---------------------------------------------------------- | | `--license-id` | License ID used to authenticate the upload | | `--app-slug` | Application slug of your GitGuardian license | | `--upload-domain` | Custom upload domain, defaults to `replicated.app` | :::note Uploading requires outbound HTTPS access to `replicated.app` on port 443, and the `support-bundle` plugin must be installed on the machine performing the upload. In air-gapped environments, copy the archive to a machine with Internet access and upload it from there. Sending the archive to GitGuardian support manually is a last resort, as bundles often exceed the attachment size limit of our support portal. ::: ## Generate a support bundle when the Kubernetes cluster is down When debugging an offline Kubernetes cluster, you can utilize host collectors to generate a support bundle even without access to the Admin Console. To begin, install the support bundle tool on a host with access to the cluster you need to debug: ```bash curl -L https://github.com/replicatedhq/troubleshoot/releases/latest/download/support-bundle_linux_amd64.tar.gz | tar xzvf - ``` Next, generate the support bundle using the following command: ```bash ./support-bundle --interactive=false https://raw.githubusercontent.com/replicatedhq/troubleshoot-specs/main/host/default.yaml ``` :::note If your current user lacks the necessary access to gather information for a specific collector, you may need to run the above command with `sudo`. For air gap environments, download the YAML file and copy it to the air gap machine. ::: For more details, refer to [Replicated Documentation](https://docs.replicated.com/enterprise/troubleshooting-an-app#generate-a-host-support-bundle). --- ## Application topology GitGuardian application consists of several Kubernetes resources. Each `nginx` pod runs an `nginx` container serving the dashboard frontend and acting as a proxy for the backend, and a number of different containers serving all backend tasks. | Kind | Deployment Name | Usage | | ---------- |---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Front | `nginx` | Dashboard Frontend and proxy for backend | | Backend | `internal-api` | Backend for the Dashboard | | Backend | `internal-api-long` | Backend for the Dashboard (long requests, no timeout) | | Backend | `public-api` | Public API and ggshield scans | | Backend | `hook` | VCS webhooks events receiver | | Backend | `app-exporter` | Prometheus exporter for applicative metrics | | Backend | `ml-secret-engine` | Machine Learning secret engine | | Backend | `apache-tika` | File scanner for non-VCS sources scanning | | Scheduler | `beat` | Celery Beat task scheduler | | Worker | `worker-worker` | General-purpose worker managing real-time scans, retries, honeytoken tasks, reports (queues: `check_run`, `realtime`, `realtime_retry`, `honeytoken`, `reports`, `core_default`, `sources_default`, `incidents_default`, `individual_validity_check`). | | Worker | `worker-check-runs` | Optional dedicated worker for check run processing (queue: `check_run`). Disabled by default; enable to offload `check_run` from `worker-worker`. | | Worker | `worker-email` | Handles email notifications and messaging (queues: `email`, `notifier`). | | Worker | `worker-scanners` | Performs historical scans for repositories (queues: `basic_repo_scan`, `premium_repo_scan`, `manual_repo_scan`, `code_fixing`). | | Worker | `worker-long` | Processes long-running tasks such as validity checks and NHI ingestion (queues: `background_validity_check`, `update_sources_state`, `nhi_ingestion`, `hmsl`, `core_long`, `sources_long`, `incidents_long`, `ml_backpopulate`, `endpoints`). | | Worker | `worker-automatic-severities` | Dedicated worker for automatic severity computation (queue: `automatic_severities`). 1 replica by default, autoscales up to 3. | | Worker | `worker-realtime-ods` | Handles real-time processing for non-VCS sources like Slack and Jira (queues: `realtime_ods`, `realtime_retry_ods`). | | Worker | `worker-long-ods` | Processes long-running tasks for non-VCS sources (queue: `long_ods`). | | Worker | `worker-long-ods-io` | Focuses on IO-intensive long-running tasks for non-VCS sources (queue: `long_ods_io`). | | Worker | `worker-scanners-ods` | Executes non-VCS historical scans for Jira, Confluence, etc. (queue: `ods_scan`). | | Worker | `worker-scanners-ods-highdisk` | Handles high storage tasks for non-VCS sources (queue: `ods_scan_highdisk`). | | Worker | `worker-scanners-slack` | Executes Slack historical scans (queue: `slack_scan`). | | Worker | `worker-container-registries` | Handles secret scanning in Container registries (queue: `container_registries`). | | Worker | `worker-business-contribution` | Handles business contribution tasks (queue: `business_contribution`). | | Worker | `worker-ml-api-priority` | Prioritizes machine learning API-related tasks (queue: `ml_api_priority`). | | Job | `inapp-analytics` | Computes metrics and aggregates data for [Advanced Analytics](../../platform/analytics/internal-monitoring) dashboards. | | Job | `pre-deploy` | Pre-deployment job performing database migrations | | Job | `post-deploy` | Post-deployment job performing long data migrations | | Replicated | `replicated` | License management and [usage data collection](../management/application-management/metrics#usage-data) | | Replicated | `kotsadm` | [KOTS Admin Console](../management/infrastructure-management/admin-console) (KOTS-based installation only) | :::info We have set a 30-days TTL (Time To Live) for `pre-deploy` and `post-deploy` jobs to allow for log retrieval if needed. It is recommended not to delete these pods, as they can be useful for troubleshooting. ::: --- ## ClickHouse and object storage in GitGuardian self-hosted *Issued on July 29, 2026* Starting with the **2026.8 self-hosted release**, GitGuardian ships [ClickHouse](https://clickhouse.com/), an open-source column-oriented database, as a new component of the self-hosted deployment. ClickHouse powers features that require fast analytics over large volumes of data, starting with machine and endpoint secret occurrence analytics, and progressively more datasets in the dashboard. Starting with release **2027.1.0**, ClickHouse and its object storage backend become mandatory for all self-hosted deployments. PostgreSQL remains the primary datastore for the rest of the application. ClickHouse is only involved for the specific features that need it. ## Why ClickHouse Endpoint scanning gives you a strong assessment of the level of underlying vulnerabilities on the machines you own, and it generates a huge amount of data. To synthesize that data and present a meaningful overview of the findings, GitGuardian needs a column-oriented database. Upcoming features of the GitGuardian suite will also need either ClickHouse or object storage, such as in-app analytics, which currently relies on daily runs on dedicated PostgreSQL tables. ## What's changing - **A new in-cluster component**: ClickHouse runs as a dedicated stateful workload inside your Kubernetes cluster, deployed as a single node by default. Unlike PostgreSQL or Redis, there is no "bring your own external ClickHouse" option at this time. - **Object storage is required**: ClickHouse relies on external object storage for durable data storage. S3-compatible storage (AWS S3, MinIO, on-prem S3 gateways...), Azure Blob Storage, and Google Cloud Storage are supported. - **Two local persistent volumes**: ClickHouse also needs two SSD-backed persistent volumes, one for metadata and one for a filesystem cache in front of object storage. HDD-class storage and network filesystems (NFS, EFS, Azure Files) are not supported. - **Automated backups**: a backup sidecar runs alongside ClickHouse and takes scheduled full and incremental backups to your object storage. There is no separate cron job to configure. ## Who's affected **All self-hosted customers.** ClickHouse first powers endpoint findings analytics, and more features will rely on it over time. Starting with release **2027.1.0**, ClickHouse becomes a mandatory component of every self-hosted deployment. ## How to prepare 1. **Provision an S3-compatible bucket**: confirm your organization can provide object storage reachable from your cluster. Air-gapped or fully on-prem environments can use MinIO or an on-prem S3 gateway. 2. **Plan authentication to the bucket**: workload identity (IRSA on AWS, Microsoft Entra Workload ID on Azure) is preferred; static credentials are passed through a Kubernetes secret, never inline in Helm values. 3. **Check your StorageClass**: make sure an SSD or NVMe-backed StorageClass (for example `gp3` on AWS, `Premium_LRS` on Azure, `pd-ssd` on GCP) is available for the metadata and cache volumes. 4. **Plan node capacity**: as a starting point, budget 4 cores and 16 GiB of RAM for ~100 active endpoints, up to 8+ cores and 32 GiB+ for ~10,000. Schedule ClickHouse on a dedicated (not shared with other workloads), stable, on-demand node rather than spot or preemptible instances. 5. **Pick a backup destination**: backups are written to object storage you configure. We recommend a separate bucket from ClickHouse's data, though a separate path prefix in the same bucket also works. ## Timeline - **2026.8**: ClickHouse ships with the self-hosted release, required for the features backed by it (starting with endpoint findings analytics). Full deployment, sizing, and backup documentation will be published in the [self-hosting documentation](/self-hosting/home) alongside the release. - **2027.1.0**: ClickHouse and its object storage backend become mandatory for all self-hosted deployments. ## Questions Reach out to your Customer Success Manager or email us at [support@gitguardian.com](mailto:support@gitguardian.com). --- ## Ending automatic token renewal for Jira and Confluence Data Center *Issued on July 29, 2026* GitGuardian is removing the system that automatically renews Personal Access Tokens (PATs) for **Jira Data Center** and **Confluence Data Center** integrations. If your integration still relies on it, update its token from the GitGuardian dashboard with a long-lived PAT before the deadline below. ## What's changing Until now, GitGuardian renewed the PAT behind your Jira Data Center and Confluence Data Center integrations before it expired. We are retiring this renewal system. Going forward, your integration uses the PAT you provide, and your team manages its lifecycle: GitGuardian no longer renews or replaces it. ## Who's affected - **SaaS**: Jira Data Center and Confluence Data Center integrations (sources and Jira notifiers) installed before **April 3, 2026**. - **Self-hosted**: all deployments using these integrations. Integrations installed after April 3, 2026 on SaaS, or whose token was already updated through the update flow, are not affected. ## What you need to do Update the token on your existing integration. **Do not reinstall the integration**: updating the token in place keeps your configuration and monitored perimeter intact. 1. Create a new PAT in Jira or Confluence, with a **long expiry or no expiry date**. For [Jira Data Center](/internal-monitoring/integrate-sources/ticketing-integrations/jira-data-center) and [Confluence Data Center](/internal-monitoring/integrate-sources/documentation-integrations/confluence-data-center) source integrations, the PAT must belong to an **administrator**. For the [Jira Data Center notifier](/platform/configure-alerting/issue-tracking-integrations/jira-data-center), any user with access to the target projects works. 2. In the GitGuardian dashboard, open the integration's settings and update its token with the new PAT. GitGuardian validates the token and runs a health check, so an unhealthy integration recovers immediately. 3. If you use both a source integration and a notifier, update the token on **each of them separately**. Once updated, the integration permanently leaves the renewal system. Make sure your team rotates the PAT before it expires, or use a non-expiring one. ## Timeline - **SaaS**: update your tokens before **August 31, 2026**. After this date, automatic renewal is removed and integrations still relying on it stop working when their token expires. - **Self-hosted**: update your tokens before upgrading to release **2026.9.0**, which removes the renewal system. ## Questions Reach out to your Customer Success Manager or email us at [support@gitguardian.com](mailto:support@gitguardian.com). --- ## Deprecation of kURL embedded cluster and KOTS existing cluster installations *Issued on August 10, 2026* Two installation methods for GitGuardian self-hosted are **deprecated since the June 2026 release (version 2026.6.0)** and will be **completely removed in the 2027.1 release**: - **[kURL embedded cluster](/self-hosting/installation/installation-embedded-cluster)**: replaced by the new [Embedded Cluster installation](/self-hosting/installation/installation-embedded-cluster-v2). - **[KOTS on an existing cluster](/self-hosting/installation/installation-existing-cluster-kots)**: replaced by the [Helm installation on an existing cluster](/self-hosting/installation/installation-existing-cluster-helm). ## What this means for you Deprecated installation methods no longer receive the latest platform improvements. For example, [ClickHouse and object storage](./clickhouse-object-storage-self-hosted), which power the new high-scale analytics features, are only available on Helm and the new Embedded Cluster installations. Until the 2027.1 release, deprecated installations continue to receive upgrades and support, but they miss new capabilities. After 2027.1, they will no longer be able to upgrade. ## Who's affected - Self-hosted customers running the **kURL embedded cluster** installation. - Self-hosted customers running **KOTS on an existing Kubernetes cluster** (including air-gapped KOTS installations). Customers already on Helm or the new Embedded Cluster installation are not affected. ## How to migrate We recommend migrating as soon as possible: - **kURL embedded cluster**: migrate to the new [Embedded Cluster installation](/self-hosting/installation/installation-embedded-cluster-v2). It provides the same all-in-one, single-node experience with the KOTS Admin Console. - **KOTS on an existing cluster**: migrate to the [Helm installation](/self-hosting/installation/installation-existing-cluster-helm). Air-gapped? Follow the [air gap Helm installation](/self-hosting/installation/airgap-installation-existing-cluster-helm). Reach out to [support@gitguardian.com](mailto:support@gitguardian.com) for guidance on your migration. ## Timeline - **2026.6.0**: kURL embedded cluster and KOTS existing cluster installation methods are deprecated. They keep working but no longer receive new platform capabilities. - **2027.1**: both installation methods are removed. Migration to the new Embedded Cluster or Helm is required to keep upgrading. ## Questions Reach out to your Customer Success Manager or email us at [support@gitguardian.com](mailto:support@gitguardian.com). --- ## MFA for email and password logins *Issued on March 9, 2026* Starting **March 9, 2026**, we are adding multi-factor authentication (MFA) to all GitGuardian SaaS accounts that use email and password to log in. ## What's changing When you log in or modify sensitive settings (like integrations, API tokens, or user permissions), you receive a 6-digit code by email. Enter the code, and you're in. ## Who's affected This applies to anyone who logs in to **GitGuardian SaaS** with **email and password**. Logins through GitHub authentication or SSO are unaffected, and self-hosted deployments are not concerned by this change. ## What you need to do Nothing. The system prompts you for a verification code once the change is live. :::tip Make sure the email address on your GitGuardian account is one you can access: verification codes are sent there. ::: ## Questions Email us at [support@gitguardian.com](mailto:support@gitguardian.com).