> For the complete documentation index, see [llms.txt](https://docs.opsmx.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opsmx.com/remediation-agents/kubernetes-agent-delegate/scanning.md).

# Scanning

## On-Demand Scanning

On-Demand Scanning is the capability that allows security teams to configure and trigger vulnerability scans **directly from the Delivery Shield dashboard** — without needing to configure webhooks, push events, or wait for pipeline triggers.

**How On-Demand Scanning Works**

1. **Create a Scan Config** — Define what to scan (repository or registry), which scanners to use, and an optional schedule
2. **Config Sent to Agent** — The gateway sends the configuration to the selected agent via gRPC; the agent stores it as a `ScanConfig` CRD in the Kubernetes cluster
3. **Trigger a Scan** — Click **Run** for an immediate scan, or let the cron schedule handle automatic execution
4. **View Results** — Scan results appear on the **Reports page** once the agent completes the scan and reports back to the gateway

**Creating a Scan Config**

Navigate to **Scan Configs** → click **New Scan Config** and provide:

| Field                      | Description                                                                                                                |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Agent**                  | Select a connected agent that will execute the scan                                                                        |
| **Scan Type**              | Choose **Repository** (Git source code) or **Registry** (container images)                                                 |
| **Provider & Credentials** | Select your provider (GitHub, GitLab, Docker) and enter the Kubernetes secret name containing access tokens                |
| **Target**                 | Enter the repository URL or registry URL — use discovery dropdowns to browse available repos if credentials are configured |
| **Scanners**               | Select one or more scanners: **Trivy**, **Grype**, **Semgrep**                                                             |

**Supported Scanners**

| Scanner     | Scan Type             | What It Detects                                                              |
| ----------- | --------------------- | ---------------------------------------------------------------------------- |
| **Trivy**   | Repository + Registry | OS vulnerabilities, application dependencies, IaC misconfigurations, secrets |
| **Grype**   | Repository + Registry | Container image and artifact vulnerability scanning                          |
| **Semgrep** | Repository            | SAST — source code security patterns and coding vulnerabilities              |

***

#### Triggering Scans

Once a Scan Config is created, scans can be triggered in three ways:

| Trigger Method | How                                                               | Best Used For                                                  |
| -------------- | ----------------------------------------------------------------- | -------------------------------------------------------------- |
| **Manual**     | Click the green **Run** button on the Scan Configs page           | Ad hoc scans, immediate investigation, one-off security checks |
| **Scheduled**  | Set a cron expression — runs automatically on agent side          | Periodic baseline scanning, compliance schedules               |
| **Polling**    | Enable outbound polling — agent detects changes and auto-triggers | Repos without webhook access, registry monitoring              |

***

#### Scheduled Scans

Scheduled scans run **on the agent side** — independently of the gateway. This means scheduled scans continue to execute even if the gateway is temporarily unavailable.

**Schedule Options**

| Preset                | Cron Expression           | Use Case                                     |
| --------------------- | ------------------------- | -------------------------------------------- |
| **Manual only**       | —                         | No automatic scheduling; manual trigger only |
| **Every hour**        | `0 * * * *`               | Active development repos                     |
| **Daily at midnight** | `0 0 * * *`               | Nightly baseline security check              |
| **Weekly (Monday)**   | `0 0 * * 1`               | Stable or release repositories               |
| **Custom**            | Any standard 5-field cron | Org-specific compliance schedules            |

**Cron Expression Format**

bash

```bash
# ┌─────────── minute (0–59)
# │ ┌─────────── hour (0–23)
# │ │ ┌─────────── day of month (1–31)
# │ │ │ ┌─────────── month (1–12)
# │ │ │ │ ┌─────────── day of week (0–6, Sun=0)
# │ │ │ │ │
  * * * * *

# Common examples:
0 6 * * 1-5     # Weekdays at 6:00 AM
0 0 1 * *       # First day of every month
*/15 * * * *    # Every 15 minutes
0 9,17 * * *    # At 9:00 AM and 5:00 PM
```

**How Scheduling Works**

* Schedules are managed by the agent using the internal cron library and persist as `ScanConfig` CRDs
* On agent restart, all schedules are **automatically reloaded** from existing CRDs — no reconfiguration needed
* If the agent is down during a scheduled time, that execution is **skipped** and resumes on the next scheduled tick
* Scheduled scans create `ScanJob` CRDs just like webhook-triggered or manually triggered scans

**Scheduling Best Practices**

* **Stagger schedules** — avoid scheduling all scans at the same time to prevent resource spikes on the cluster
* **Use daily scans for baseline** — a daily midnight scan provides a consistent, comparable security baseline over time
* **Combine with polling** — use scheduled scans for full periodic checks and polling for change-driven scans
* **Set appropriate timeouts** — large repositories may need longer timeout values (default: 1800 seconds)

***

#### Polling Watchers

For repositories and registries where webhooks cannot be configured, **Polling Watchers** periodically check for changes and automatically trigger scans when new commits, tags, or images are detected.

**When to Use Polling**

* **No webhook access** — cannot configure webhooks on the repository (e.g., third-party or read-only repos)
* **Firewall restrictions** — the agent cluster is not reachable from the internet for webhook delivery
* **Registry monitoring** — watching for new container image tags pushed to a registry
* **Supplement webhooks** — use polling as a safety net alongside webhooks to catch missed events

**Enabling Polling**

In the scan config form, check **Enable Outbound Polling** in the Schedule & Polling section:

| Setting              | Description                                                           | Default      |
| -------------------- | --------------------------------------------------------------------- | ------------ |
| **Polling Interval** | How often to check for changes (in seconds)                           | 300s (5 min) |
| **Branch Patterns**  | Which branches to monitor for new commits (e.g., `main`, `release/*`) | —            |

**What Polling Detects**

* **New commits** — detects when the HEAD of a monitored branch changes
* **New tags** — detects new Git tags (e.g., release tags)
* **New images** — detects new image tags or digest changes in container registries

> **Note:** The first poll establishes a baseline — no scans are triggered until subsequent polls detect changes.

**Recommended Polling Intervals**

| Repository Type                 | Recommended Interval               |
| ------------------------------- | ---------------------------------- |
| Active development repositories | 300 seconds (5 minutes)            |
| Stable / release repositories   | 900–3600 seconds (15 min – 1 hour) |
| Container registries            | 600 seconds (10 minutes)           |

> Shorter intervals increase API rate limit consumption. Ensure your token has sufficient rate limits for the number of monitored repositories.

***

#### Polling vs Webhooks vs Scheduled Scans

| Feature               | Webhooks                             | Polling                       | Scheduled                    |
| --------------------- | ------------------------------------ | ----------------------------- | ---------------------------- |
| **Trigger**           | Push event                           | Change detected               | Cron schedule                |
| **Latency**           | Immediate                            | Up to poll interval           | Fixed schedule               |
| **Setup Required**    | Webhook config on provider           | Credential secret only        | Credential secret only       |
| **Network Direction** | Inbound to agent                     | Outbound from agent           | Outbound from agent          |
| **Best For**          | Active pipelines with webhook access | Repos without webhook support | Periodic compliance baseline |

***

#### Repository & Registry Discovery

The **Discovery** feature lets teams browse organizations, repositories, and branches directly from the Delivery Shield dashboard — without manually entering URLs.

**How Discovery Works**

1. The gateway sends a discovery request to the selected agent via gRPC
2. The agent reads the specified Kubernetes Secret to obtain the access token
3. The agent calls the provider API (GitHub, GitLab, or Docker Registry) to list available resources
4. Results are sent back to the gateway and displayed as dropdown options in the Scan Config UI

> **Security:** Credentials stay entirely within your Kubernetes cluster. The gateway never sees or stores tokens — it only receives the list of discovered resource names.

***

#### Credentials Setup

All credentials for accessing private repositories and registries are stored as Kubernetes Secrets in the agent's cluster namespace — never transmitted to the gateway.

**GitHub / GitLab Token**

yaml

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: github-token
  namespace: ssd-system
type: Opaque
stringData:
  username: "<github-username>"
  password: "<personal-access-token>"
```

**Required permissions:** `repo` (read access to code)

**Docker Registry Credentials**

bash

```bash
kubectl create secret docker-registry docker-registry \
  --namespace ssd-system \
  --docker-server=<registry-url> \
  --docker-username=<username> \
  --docker-password=<password>
```

**AWS ECR Credentials**

bash

```bash
aws ecr get-login-password --region <region> | \
  kubectl create secret docker-registry ecr-registry \
    --namespace ssd-system \
    --docker-server=<account>.dkr.ecr.<region>.amazonaws.com \
    --docker-username=AWS \
    --docker-password-stdin
```

> **Note:** ECR tokens expire after 12 hours. Use a CronJob or External Secrets Operator for automatic token rotation.

**Referencing Credentials in ScanConfig**

yaml

```yaml
apiVersion: ssd.opsmx.io/v1
kind: ScanConfig
metadata:
  name: default
  namespace: ssd-system
spec:
  credentials:
    git:
      name: github-token
      namespace: ssd-system
    registry:
      name: docker-registry
      namespace: ssd-system
  scanners:
  - name: trivy
    enabled: true
```

***

#### Managing Scan Configs via kubectl

Since scan configs are stored as Kubernetes CRDs, they can be managed directly via `kubectl` alongside the dashboard:

bash

```bash
# List all on-demand scan configs
kubectl get scanconfigs -n ssd-system

# View a specific scan config
kubectl describe scanconfig <name> -n ssd-system

# List all scan jobs
kubectl get scanjobs -n ssd-system

# View a specific scan job status
kubectl describe scanjob <job-name> -n ssd-system
```

***

#### Troubleshooting

**Check Agent Logs**

bash

```bash
# Controller logs — gateway communication and job management
kubectl logs -n ssd-system -l app.kubernetes.io/component=controller -f

# Collector logs — webhook handling and event processing
kubectl logs -n ssd-system -l app.kubernetes.io/component=collector -f

# Check for errors in the last hour
kubectl logs -n ssd-system -l app.kubernetes.io/name=ssd-shield-agent \
  --since=1h | grep -i error
```

**Verify CRDs Are Installed**

bash

```bash
kubectl get crds | grep ssd.opsmx.io
# Expected:
# scanconfigs.ssd.opsmx.io
# scanjobs.ssd.opsmx.io
```

**Test RBAC Permissions**

bash

```bash
kubectl auth can-i create scanjobs.ssd.opsmx.io \
  --as system:serviceaccount:ssd-system:ssd-shield-agent
# Expected: yes
```

**Verify Gateway Connectivity**

bash

```bash
# Check configured gateway endpoint
kubectl get configmap ssd-agent-config -n ssd-system -o yaml | grep endpoint

# Test mTLS certificate validity
kubectl exec -n ssd-system deploy/ssd-shield-agent -- \
  openssl x509 -in /etc/ssd-agent/certs/tls.crt -noout -dates
```

**Common Issues & Resolutions**

| Symptom                             | Likely Cause                              | Resolution                                                                 |
| ----------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------- |
| Scan not triggering                 | Agent not connected to gateway            | Check gateway endpoint config and mTLS cert validity                       |
| ScanJob created but not progressing | Resource constraints or RBAC missing      | Check pod logs and verify service account permissions                      |
| Discovery dropdowns empty           | Invalid credentials or wrong secret name  | Verify secret exists in `ssd-system` namespace and has correct permissions |
| Scheduled scan not running          | Agent was restarted and CRDs missing      | Reapply CRDs; schedules reload automatically on next restart               |
| Webhook not received                | Network/firewall blocking inbound traffic | Verify collector service is reachable; use polling as alternative          |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.opsmx.com/remediation-agents/kubernetes-agent-delegate/scanning.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
