diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
new file mode 100644
index 0000000..3392041
--- /dev/null
+++ b/.github/workflows/gh-pages.yml
@@ -0,0 +1,131 @@
+name: GitHub Pages
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
+# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Install Helm
+ uses: azure/setup-helm@v4
+ with:
+ version: v3.14.0
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v5
+
+ - name: Create Helm packages directory
+ run: mkdir -p _site
+
+ - name: Package Helm chart
+ run: |
+ helm package charts/nuclei-operator -d _site
+
+ - name: Generate Helm repo index
+ run: |
+ helm repo index _site --url https://morten-olsen.github.io/homelab-nuclei-operator
+
+ - name: Create index.html
+ run: |
+ cat > _site/index.html << 'EOF'
+
+
+
+
+
+ Nuclei Operator Helm Repository
+
+
+
+ 🔬 Nuclei Operator Helm Repository
+
+ This is the Helm chart repository for the
+ Nuclei Operator.
+
+
+ Usage
+ Add this repository to Helm:
+ helm repo add nuclei-operator https://morten-olsen.github.io/homelab-nuclei-operator
+ helm repo update
+
+ Install the chart:
+ helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace
+
+ Available Charts
+
+ - nuclei-operator - A Kubernetes operator that automatically scans Ingress and VirtualService resources using Nuclei security scanner
+
+
+ Links
+
+
+
+ EOF
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: _site
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..51359f8
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,165 @@
+name: Release
+
+on:
+ push:
+ branches:
+ - main
+ tags:
+ - 'v*'
+ pull_request:
+ branches:
+ - main
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ build-and-push:
+ name: Build and Push Container Image
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to Container Registry
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ tags: |
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ platforms: linux/amd64,linux/arm64
+ push: ${{ github.event_name != 'pull_request' }}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+
+ release-helm-chart:
+ name: Release Helm Chart
+ runs-on: ubuntu-latest
+ needs: build-and-push
+ if: startsWith(github.ref, 'refs/tags/v')
+ permissions:
+ contents: write
+ pages: write
+ id-token: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Configure Git
+ run: |
+ git config user.name "$GITHUB_ACTOR"
+ git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
+
+ - name: Install Helm
+ uses: azure/setup-helm@v4
+ with:
+ version: v3.14.0
+
+ - name: Extract version from tag
+ id: version
+ run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
+
+ - name: Update Chart version and appVersion
+ run: |
+ sed -i "s/^version:.*/version: ${{ steps.version.outputs.VERSION }}/" charts/nuclei-operator/Chart.yaml
+ sed -i "s/^appVersion:.*/appVersion: \"${{ steps.version.outputs.VERSION }}\"/" charts/nuclei-operator/Chart.yaml
+
+ - name: Package Helm chart
+ run: |
+ helm package charts/nuclei-operator -d .helm-packages
+
+ - name: Checkout gh-pages branch
+ uses: actions/checkout@v4
+ with:
+ ref: gh-pages
+ path: gh-pages
+
+ - name: Update Helm repository
+ run: |
+ cp .helm-packages/*.tgz gh-pages/
+ cd gh-pages
+ helm repo index . --url https://morten-olsen.github.io/homelab-nuclei-operator
+ git add .
+ git commit -m "Release Helm chart ${{ steps.version.outputs.VERSION }}"
+ git push
+
+ create-release:
+ name: Create GitHub Release
+ runs-on: ubuntu-latest
+ needs: build-and-push
+ if: startsWith(github.ref, 'refs/tags/v')
+ permissions:
+ contents: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install Helm
+ uses: azure/setup-helm@v4
+ with:
+ version: v3.14.0
+
+ - name: Install kustomize
+ run: |
+ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
+ sudo mv kustomize /usr/local/bin/
+
+ - name: Extract version from tag
+ id: version
+ run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
+
+ - name: Generate install manifests
+ run: |
+ cd config/manager && kustomize edit set image controller=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
+ cd ../..
+ kustomize build config/default > install.yaml
+
+ - name: Package Helm chart
+ run: |
+ sed -i "s/^version:.*/version: ${{ steps.version.outputs.VERSION }}/" charts/nuclei-operator/Chart.yaml
+ sed -i "s/^appVersion:.*/appVersion: \"${{ steps.version.outputs.VERSION }}\"/" charts/nuclei-operator/Chart.yaml
+ helm package charts/nuclei-operator
+
+ - name: Create Release
+ uses: softprops/action-gh-release@v2
+ with:
+ generate_release_notes: true
+ files: |
+ install.yaml
+ nuclei-operator-*.tgz
\ No newline at end of file
diff --git a/README.md b/README.md
index 121f5e1..c54f29a 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,71 @@ The Nuclei Operator watches for Ingress and VirtualService resources in your Kub
## Installation
+### Using Helm (Recommended)
+
+The easiest way to install the Nuclei Operator is using Helm:
+
+```bash
+# Add the Helm repository
+helm repo add nuclei-operator https://morten-olsen.github.io/homelab-nuclei-operator
+helm repo update
+
+# Install the operator
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace
+```
+
+#### Helm Configuration
+
+You can customize the installation by providing values:
+
+```bash
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace \
+ --set replicaCount=1 \
+ --set resources.limits.memory=4Gi \
+ --set nuclei.rescanAge=72h
+```
+
+Or create a `values.yaml` file:
+
+```yaml
+replicaCount: 1
+
+resources:
+ limits:
+ cpu: "2"
+ memory: "4Gi"
+ requests:
+ cpu: "500m"
+ memory: "1Gi"
+
+nuclei:
+ timeout: "1h"
+ rescanAge: "72h"
+
+serviceMonitor:
+ enabled: true
+```
+
+```bash
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace \
+ -f values.yaml
+```
+
+### Using Container Image from GitHub Container Registry
+
+The container images are available at:
+
+```
+ghcr.io/morten-olsen/homelab-nuclei-operator:latest
+ghcr.io/morten-olsen/homelab-nuclei-operator:v0.1.0 # specific version
+```
+
### Using kubectl/kustomize
1. **Install the CRDs:**
@@ -63,7 +128,7 @@ make install
```bash
# Using the default image
-make deploy IMG=ghcr.io/mortenolsen/nuclei-operator:latest
+make deploy IMG=ghcr.io/morten-olsen/homelab-nuclei-operator:latest
# Or build and deploy your own image
make docker-build docker-push IMG=/nuclei-operator:tag
@@ -72,11 +137,18 @@ make deploy IMG=/nuclei-operator:tag
### Using a Single YAML File
-Generate and apply a consolidated installation manifest:
+Download and apply the installation manifest from the GitHub release:
+
+```bash
+# Download from the latest release
+kubectl apply -f https://github.com/morten-olsen/homelab-nuclei-operator/releases/latest/download/install.yaml
+```
+
+Or generate it locally:
```bash
# Generate the installer
-make build-installer IMG=/nuclei-operator:tag
+make build-installer IMG=ghcr.io/morten-olsen/homelab-nuclei-operator:latest
# Apply to your cluster
kubectl apply -f dist/install.yaml
@@ -86,8 +158,8 @@ kubectl apply -f dist/install.yaml
```bash
# Clone the repository
-git clone https://github.com/mortenolsen/nuclei-operator.git
-cd nuclei-operator
+git clone https://github.com/morten-olsen/homelab-nuclei-operator.git
+cd homelab-nuclei-operator
# Build the binary
make build
@@ -103,8 +175,20 @@ make docker-push IMG=/nuclei-operator:tag
### 1. Deploy the Operator
+Using Helm (recommended):
+
```bash
-make deploy IMG=ghcr.io/mortenolsen/nuclei-operator:latest
+helm repo add nuclei-operator https://morten-olsen.github.io/homelab-nuclei-operator
+helm repo update
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace
+```
+
+Or using kustomize:
+
+```bash
+make deploy IMG=ghcr.io/morten-olsen/homelab-nuclei-operator:latest
```
### 2. Create an Ingress Resource
@@ -371,6 +455,21 @@ curl localhost:8080/metrics
## Uninstallation
+### Using Helm
+
+```bash
+# Uninstall the operator
+helm uninstall nuclei-operator -n nuclei-operator-system
+
+# Remove the namespace (optional)
+kubectl delete namespace nuclei-operator-system
+
+# Remove CRDs (optional - this will delete all NucleiScan resources)
+kubectl delete crd nucleiscans.nuclei.homelab.mortenolsen.pro
+```
+
+### Using kubectl/kustomize
+
```bash
# Remove all NucleiScan resources
kubectl delete nucleiscans --all --all-namespaces
diff --git a/charts/nuclei-operator/.helmignore b/charts/nuclei-operator/.helmignore
new file mode 100644
index 0000000..691fa13
--- /dev/null
+++ b/charts/nuclei-operator/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
\ No newline at end of file
diff --git a/charts/nuclei-operator/Chart.yaml b/charts/nuclei-operator/Chart.yaml
new file mode 100644
index 0000000..3daaf59
--- /dev/null
+++ b/charts/nuclei-operator/Chart.yaml
@@ -0,0 +1,21 @@
+apiVersion: v2
+name: nuclei-operator
+description: A Kubernetes operator that automatically scans Ingress and VirtualService resources using Nuclei security scanner
+type: application
+version: 0.1.0
+appVersion: "0.1.0"
+home: https://github.com/morten-olsen/homelab-nuclei-operator
+sources:
+ - https://github.com/morten-olsen/homelab-nuclei-operator
+maintainers:
+ - name: Morten Olsen
+ url: https://github.com/morten-olsen
+keywords:
+ - kubernetes
+ - operator
+ - security
+ - nuclei
+ - scanner
+ - ingress
+ - virtualservice
+kubeVersion: ">=1.26.0-0"
\ No newline at end of file
diff --git a/charts/nuclei-operator/README.md b/charts/nuclei-operator/README.md
new file mode 100644
index 0000000..0a66621
--- /dev/null
+++ b/charts/nuclei-operator/README.md
@@ -0,0 +1,233 @@
+# Nuclei Operator Helm Chart
+
+A Helm chart for deploying the Nuclei Operator - a Kubernetes operator that automatically scans Ingress and VirtualService resources using Nuclei security scanner.
+
+## Prerequisites
+
+- Kubernetes 1.26+
+- Helm 3.0+
+
+## Installation
+
+### Add the Helm Repository
+
+```bash
+helm repo add nuclei-operator https://morten-olsen.github.io/homelab-nuclei-operator
+helm repo update
+```
+
+### Install the Chart
+
+```bash
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace
+```
+
+### Install with Custom Values
+
+```bash
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace \
+ -f values.yaml
+```
+
+## Configuration
+
+The following table lists the configurable parameters of the Nuclei Operator chart and their default values.
+
+### General
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `replicaCount` | Number of replicas | `1` |
+| `nameOverride` | Override the name of the chart | `""` |
+| `fullnameOverride` | Override the full name of the chart | `""` |
+
+### Image
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `image.repository` | Container image repository | `ghcr.io/morten-olsen/homelab-nuclei-operator` |
+| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
+| `image.tag` | Image tag (defaults to chart appVersion) | `""` |
+| `imagePullSecrets` | Image pull secrets | `[]` |
+
+### Service Account
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `serviceAccount.create` | Create a service account | `true` |
+| `serviceAccount.annotations` | Service account annotations | `{}` |
+| `serviceAccount.name` | Service account name | `""` |
+
+### Pod Configuration
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `podAnnotations` | Pod annotations | `{}` |
+| `podLabels` | Pod labels | `{}` |
+| `podSecurityContext.runAsNonRoot` | Run as non-root | `true` |
+| `podSecurityContext.seccompProfile.type` | Seccomp profile type | `RuntimeDefault` |
+
+### Container Security Context
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `securityContext.readOnlyRootFilesystem` | Read-only root filesystem | `false` |
+| `securityContext.allowPrivilegeEscalation` | Allow privilege escalation | `false` |
+| `securityContext.runAsNonRoot` | Run as non-root | `true` |
+| `securityContext.runAsUser` | User ID | `65532` |
+| `securityContext.capabilities.drop` | Dropped capabilities | `["ALL"]` |
+
+### Resources
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `resources.limits.cpu` | CPU limit | `"2"` |
+| `resources.limits.memory` | Memory limit | `"2Gi"` |
+| `resources.requests.cpu` | CPU request | `"500m"` |
+| `resources.requests.memory` | Memory request | `"512Mi"` |
+
+### Scheduling
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `nodeSelector` | Node selector | `{}` |
+| `tolerations` | Tolerations | `[]` |
+| `affinity` | Affinity rules | `{}` |
+
+### Leader Election
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `leaderElection.enabled` | Enable leader election | `true` |
+
+### Health Probes
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `healthProbes.livenessProbe.httpGet.path` | Liveness probe path | `/healthz` |
+| `healthProbes.livenessProbe.httpGet.port` | Liveness probe port | `8081` |
+| `healthProbes.livenessProbe.initialDelaySeconds` | Initial delay | `15` |
+| `healthProbes.livenessProbe.periodSeconds` | Period | `20` |
+| `healthProbes.readinessProbe.httpGet.path` | Readiness probe path | `/readyz` |
+| `healthProbes.readinessProbe.httpGet.port` | Readiness probe port | `8081` |
+| `healthProbes.readinessProbe.initialDelaySeconds` | Initial delay | `5` |
+| `healthProbes.readinessProbe.periodSeconds` | Period | `10` |
+
+### Metrics
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `metrics.enabled` | Enable metrics endpoint | `true` |
+| `metrics.service.type` | Metrics service type | `ClusterIP` |
+| `metrics.service.port` | Metrics service port | `8443` |
+
+### Nuclei Scanner Configuration
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `nuclei.binaryPath` | Path to nuclei binary | `/usr/local/bin/nuclei` |
+| `nuclei.templatesPath` | Path to nuclei templates | `/nuclei-templates` |
+| `nuclei.timeout` | Scan timeout | `30m` |
+| `nuclei.rescanAge` | Age before automatic rescan | `168h` |
+| `nuclei.backoff.initial` | Initial backoff interval | `10s` |
+| `nuclei.backoff.max` | Maximum backoff interval | `10m` |
+| `nuclei.backoff.multiplier` | Backoff multiplier | `2.0` |
+
+### ServiceMonitor (Prometheus Operator)
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `serviceMonitor.enabled` | Enable ServiceMonitor | `false` |
+| `serviceMonitor.labels` | Additional labels | `{}` |
+| `serviceMonitor.interval` | Scrape interval | `30s` |
+| `serviceMonitor.scrapeTimeout` | Scrape timeout | `10s` |
+
+### Network Policy
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `networkPolicy.enabled` | Enable network policy | `false` |
+
+## Examples
+
+### Basic Installation
+
+```bash
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace
+```
+
+### With Prometheus Monitoring
+
+```yaml
+# values.yaml
+metrics:
+ enabled: true
+
+serviceMonitor:
+ enabled: true
+ labels:
+ release: prometheus
+```
+
+```bash
+helm install nuclei-operator nuclei-operator/nuclei-operator \
+ --namespace nuclei-operator-system \
+ --create-namespace \
+ -f values.yaml
+```
+
+### With Custom Resource Limits
+
+```yaml
+# values.yaml
+resources:
+ limits:
+ cpu: "4"
+ memory: "4Gi"
+ requests:
+ cpu: "1"
+ memory: "1Gi"
+
+nuclei:
+ timeout: "1h"
+ rescanAge: "24h"
+```
+
+### With Node Affinity
+
+```yaml
+# values.yaml
+affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: kubernetes.io/arch
+ operator: In
+ values:
+ - amd64
+ - arm64
+```
+
+## Uninstallation
+
+```bash
+helm uninstall nuclei-operator -n nuclei-operator-system
+```
+
+To also remove the CRDs:
+
+```bash
+kubectl delete crd nucleiscans.nuclei.homelab.mortenolsen.pro
+```
+
+## Links
+
+- [GitHub Repository](https://github.com/morten-olsen/homelab-nuclei-operator)
+- [Nuclei Scanner](https://github.com/projectdiscovery/nuclei)
\ No newline at end of file
diff --git a/charts/nuclei-operator/templates/NOTES.txt b/charts/nuclei-operator/templates/NOTES.txt
new file mode 100644
index 0000000..17fe52d
--- /dev/null
+++ b/charts/nuclei-operator/templates/NOTES.txt
@@ -0,0 +1,44 @@
+Thank you for installing {{ .Chart.Name }}!
+
+Your release is named {{ .Release.Name }}.
+
+To learn more about the release, try:
+
+ $ helm status {{ .Release.Name }}
+ $ helm get all {{ .Release.Name }}
+
+The nuclei-operator is now watching for Ingress and VirtualService resources.
+
+To create a NucleiScan manually, you can apply a resource like:
+
+ apiVersion: nuclei.homelab.mortenolsen.pro/v1alpha1
+ kind: NucleiScan
+ metadata:
+ name: example-scan
+ spec:
+ sourceRef:
+ apiVersion: networking.k8s.io/v1
+ kind: Ingress
+ name: my-ingress
+ namespace: default
+ uid:
+ targets:
+ - https://example.com
+
+To view scan results:
+
+ $ kubectl get nucleiscans -A
+ $ kubectl describe nucleiscan
+
+{{- if .Values.metrics.enabled }}
+
+Metrics are enabled. The metrics service is available at:
+ {{ include "nuclei-operator.fullname" . }}-metrics-service:{{ .Values.metrics.service.port }}
+
+{{- if .Values.serviceMonitor.enabled }}
+A ServiceMonitor has been created for Prometheus Operator integration.
+{{- end }}
+{{- end }}
+
+For more information, visit:
+ https://github.com/morten-olsen/homelab-nuclei-operator
\ No newline at end of file
diff --git a/charts/nuclei-operator/templates/_helpers.tpl b/charts/nuclei-operator/templates/_helpers.tpl
new file mode 100644
index 0000000..1c1be69
--- /dev/null
+++ b/charts/nuclei-operator/templates/_helpers.tpl
@@ -0,0 +1,71 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "nuclei-operator.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "nuclei-operator.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "nuclei-operator.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "nuclei-operator.labels" -}}
+helm.sh/chart: {{ include "nuclei-operator.chart" . }}
+{{ include "nuclei-operator.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "nuclei-operator.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "nuclei-operator.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+control-plane: controller-manager
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "nuclei-operator.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "nuclei-operator.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create the image name
+*/}}
+{{- define "nuclei-operator.image" -}}
+{{- $tag := default .Chart.AppVersion .Values.image.tag }}
+{{- printf "%s:%s" .Values.image.repository $tag }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/nuclei-operator/templates/crds/nucleiscan-crd.yaml b/charts/nuclei-operator/templates/crds/nucleiscan-crd.yaml
new file mode 100644
index 0000000..11bc39c
--- /dev/null
+++ b/charts/nuclei-operator/templates/crds/nucleiscan-crd.yaml
@@ -0,0 +1,322 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.19.0
+ name: nucleiscans.nuclei.homelab.mortenolsen.pro
+ labels: { { - include "nuclei-operator.labels" . | nindent 4 } }
+spec:
+ group: nuclei.homelab.mortenolsen.pro
+ names:
+ kind: NucleiScan
+ listKind: NucleiScanList
+ plural: nucleiscans
+ shortNames:
+ - ns
+ - nscan
+ singular: nucleiscan
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .status.phase
+ name: Phase
+ type: string
+ - jsonPath: .status.summary.totalFindings
+ name: Findings
+ type: integer
+ - jsonPath: .spec.sourceRef.kind
+ name: Source
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: NucleiScan is the Schema for the nucleiscans API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: NucleiScanSpec defines the desired state of NucleiScan
+ properties:
+ schedule:
+ description: |-
+ Schedule for periodic rescanning in cron format
+ If empty, scan runs once
+ type: string
+ severity:
+ description: Severity filters scan results by severity level
+ items:
+ type: string
+ type: array
+ sourceRef:
+ description:
+ SourceRef references the Ingress or VirtualService being
+ scanned
+ properties:
+ apiVersion:
+ description: APIVersion of the source resource
+ type: string
+ kind:
+ description: Kind of the source resource - Ingress or VirtualService
+ enum:
+ - Ingress
+ - VirtualService
+ type: string
+ name:
+ description: Name of the source resource
+ type: string
+ namespace:
+ description: Namespace of the source resource
+ type: string
+ uid:
+ description: UID of the source resource for owner reference
+ type: string
+ required:
+ - apiVersion
+ - kind
+ - name
+ - namespace
+ - uid
+ type: object
+ suspend:
+ description: Suspend prevents scheduled scans from running
+ type: boolean
+ targets:
+ description:
+ Targets is the list of URLs to scan, extracted from the
+ source resource
+ items:
+ type: string
+ minItems: 1
+ type: array
+ templates:
+ description: |-
+ Templates specifies which Nuclei templates to use
+ If empty, uses default templates
+ items:
+ type: string
+ type: array
+ required:
+ - sourceRef
+ - targets
+ type: object
+ status:
+ description: NucleiScanStatus defines the observed state of NucleiScan
+ properties:
+ completionTime:
+ description: CompletionTime is when the last scan completed
+ format: date-time
+ type: string
+ conditions:
+ description: Conditions represent the latest available observations
+ items:
+ description:
+ Condition contains details for one aspect of the current
+ state of this API Resource.
+ properties:
+ lastTransitionTime:
+ description: |-
+ lastTransitionTime is the last time the condition transitioned from one status to another.
+ This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: |-
+ message is a human readable message indicating details about the transition.
+ This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: |-
+ observedGeneration represents the .metadata.generation that the condition was set based upon.
+ For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
+ with respect to the current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: |-
+ reason contains a programmatic identifier indicating the reason for the condition's last transition.
+ Producers of specific condition types may define expected values and meanings for this field,
+ and whether the values are considered a guaranteed API.
+ The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ findings:
+ description: |-
+ Findings contains the array of scan results from Nuclei JSONL output
+ Each element is a parsed JSON object from Nuclei output
+ items:
+ description: Finding represents a single Nuclei scan finding
+ properties:
+ description:
+ description: Description provides details about the finding
+ type: string
+ extractedResults:
+ description:
+ ExtractedResults contains any data extracted by
+ the template
+ items:
+ type: string
+ type: array
+ host:
+ description: Host that was scanned
+ type: string
+ matchedAt:
+ description:
+ MatchedAt is the specific URL or endpoint where
+ the issue was found
+ type: string
+ metadata:
+ description: Metadata contains additional template metadata
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ reference:
+ description:
+ Reference contains URLs to additional information
+ about the finding
+ items:
+ type: string
+ type: array
+ severity:
+ description: Severity of the finding
+ type: string
+ tags:
+ description: Tags associated with the finding
+ items:
+ type: string
+ type: array
+ templateId:
+ description: TemplateID is the Nuclei template identifier
+ type: string
+ templateName:
+ description: TemplateName is the human-readable template name
+ type: string
+ timestamp:
+ description: Timestamp when the finding was discovered
+ format: date-time
+ type: string
+ type:
+ description: Type of the finding - http, dns, ssl, etc.
+ type: string
+ required:
+ - host
+ - severity
+ - templateId
+ - timestamp
+ type: object
+ type: array
+ lastError:
+ description: LastError contains the error message if the scan failed
+ type: string
+ lastRetryTime:
+ description:
+ LastRetryTime is when the last availability check retry
+ occurred
+ format: date-time
+ type: string
+ lastScanTime:
+ description: LastScanTime is when the last scan was initiated
+ format: date-time
+ type: string
+ nextScheduledTime:
+ description:
+ NextScheduledTime is when the next scheduled scan will
+ run
+ format: date-time
+ type: string
+ observedGeneration:
+ description:
+ ObservedGeneration is the generation observed by the
+ controller
+ format: int64
+ type: integer
+ phase:
+ description: Phase represents the current scan phase
+ enum:
+ - Pending
+ - Running
+ - Completed
+ - Failed
+ type: string
+ retryCount:
+ description: |-
+ RetryCount tracks the number of consecutive availability check retries
+ Used for exponential backoff when waiting for targets
+ type: integer
+ summary:
+ description: Summary provides aggregated scan statistics
+ properties:
+ durationSeconds:
+ description: DurationSeconds is the duration of the scan in seconds
+ format: int64
+ type: integer
+ findingsBySeverity:
+ additionalProperties:
+ type: integer
+ description:
+ FindingsBySeverity breaks down findings by severity
+ level
+ type: object
+ targetsScanned:
+ description:
+ TargetsScanned is the number of targets that were
+ scanned
+ type: integer
+ totalFindings:
+ description: TotalFindings is the total number of findings
+ type: integer
+ required:
+ - targetsScanned
+ - totalFindings
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/charts/nuclei-operator/templates/deployment.yaml b/charts/nuclei-operator/templates/deployment.yaml
new file mode 100644
index 0000000..72e7044
--- /dev/null
+++ b/charts/nuclei-operator/templates/deployment.yaml
@@ -0,0 +1,99 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-controller-manager
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+spec:
+ replicas: {{ .Values.replicaCount }}
+ selector:
+ matchLabels:
+ {{- include "nuclei-operator.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ annotations:
+ kubectl.kubernetes.io/default-container: manager
+ {{- with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "nuclei-operator.selectorLabels" . | nindent 8 }}
+ {{- with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "nuclei-operator.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: manager
+ image: {{ include "nuclei-operator.image" . }}
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ command:
+ - /manager
+ args:
+ {{- if .Values.leaderElection.enabled }}
+ - --leader-elect
+ {{- end }}
+ - --health-probe-bind-address=:8081
+ {{- if .Values.metrics.enabled }}
+ - --metrics-bind-address=:8443
+ - --metrics-secure=true
+ {{- end }}
+ env:
+ - name: NUCLEI_BINARY_PATH
+ value: {{ .Values.nuclei.binaryPath | quote }}
+ - name: NUCLEI_TEMPLATES_PATH
+ value: {{ .Values.nuclei.templatesPath | quote }}
+ - name: NUCLEI_TIMEOUT
+ value: {{ .Values.nuclei.timeout | quote }}
+ - name: NUCLEI_RESCAN_AGE
+ value: {{ .Values.nuclei.rescanAge | quote }}
+ - name: NUCLEI_BACKOFF_INITIAL
+ value: {{ .Values.nuclei.backoff.initial | quote }}
+ - name: NUCLEI_BACKOFF_MAX
+ value: {{ .Values.nuclei.backoff.max | quote }}
+ - name: NUCLEI_BACKOFF_MULTIPLIER
+ value: {{ .Values.nuclei.backoff.multiplier | quote }}
+ ports: []
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ {{- with .Values.healthProbes.livenessProbe }}
+ livenessProbe:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ {{- with .Values.healthProbes.readinessProbe }}
+ readinessProbe:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ resources:
+ {{- toYaml .Values.resources | nindent 10 }}
+ volumeMounts:
+ - name: nuclei-templates
+ mountPath: {{ .Values.nuclei.templatesPath }}
+ readOnly: true
+ - name: nuclei-cache
+ mountPath: /home/nonroot/.nuclei
+ volumes:
+ - name: nuclei-templates
+ emptyDir: {}
+ - name: nuclei-cache
+ emptyDir: {}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ terminationGracePeriodSeconds: 10
\ No newline at end of file
diff --git a/charts/nuclei-operator/templates/metrics-service.yaml b/charts/nuclei-operator/templates/metrics-service.yaml
new file mode 100644
index 0000000..3533201
--- /dev/null
+++ b/charts/nuclei-operator/templates/metrics-service.yaml
@@ -0,0 +1,18 @@
+{{- if .Values.metrics.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-metrics-service
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.metrics.service.type }}
+ ports:
+ - name: https
+ port: {{ .Values.metrics.service.port }}
+ protocol: TCP
+ targetPort: 8443
+ selector:
+ {{- include "nuclei-operator.selectorLabels" . | nindent 4 }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/nuclei-operator/templates/rbac.yaml b/charts/nuclei-operator/templates/rbac.yaml
new file mode 100644
index 0000000..341ef3c
--- /dev/null
+++ b/charts/nuclei-operator/templates/rbac.yaml
@@ -0,0 +1,192 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-manager-role
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - patch
+- apiGroups:
+ - networking.istio.io
+ resources:
+ - virtualservices
+ verbs:
+ - get
+ - list
+ - watch
+- apiGroups:
+ - networking.istio.io
+ resources:
+ - virtualservices/status
+ verbs:
+ - get
+- apiGroups:
+ - networking.k8s.io
+ resources:
+ - ingresses
+ verbs:
+ - get
+ - list
+ - watch
+- apiGroups:
+ - networking.k8s.io
+ resources:
+ - ingresses/status
+ verbs:
+ - get
+- apiGroups:
+ - nuclei.homelab.mortenolsen.pro
+ resources:
+ - nucleiscans
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - nuclei.homelab.mortenolsen.pro
+ resources:
+ - nucleiscans/finalizers
+ verbs:
+ - update
+- apiGroups:
+ - nuclei.homelab.mortenolsen.pro
+ resources:
+ - nucleiscans/status
+ verbs:
+ - get
+ - patch
+ - update
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-manager-rolebinding
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "nuclei-operator.fullname" . }}-manager-role
+subjects:
+- kind: ServiceAccount
+ name: {{ include "nuclei-operator.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+---
+# Leader election role
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-leader-election-role
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+- apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - patch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-leader-election-rolebinding
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ include "nuclei-operator.fullname" . }}-leader-election-role
+subjects:
+- kind: ServiceAccount
+ name: {{ include "nuclei-operator.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+{{- if .Values.metrics.enabled }}
+---
+# Metrics auth role
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-metrics-auth-role
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - authentication.k8s.io
+ resources:
+ - tokenreviews
+ verbs:
+ - create
+- apiGroups:
+ - authorization.k8s.io
+ resources:
+ - subjectaccessreviews
+ verbs:
+ - create
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-metrics-auth-rolebinding
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "nuclei-operator.fullname" . }}-metrics-auth-role
+subjects:
+- kind: ServiceAccount
+ name: {{ include "nuclei-operator.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+---
+# Metrics reader role
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-metrics-reader
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+rules:
+- nonResourceURLs:
+ - /metrics
+ verbs:
+ - get
+{{- end }}
\ No newline at end of file
diff --git a/charts/nuclei-operator/templates/serviceaccount.yaml b/charts/nuclei-operator/templates/serviceaccount.yaml
new file mode 100644
index 0000000..ffaf1d5
--- /dev/null
+++ b/charts/nuclei-operator/templates/serviceaccount.yaml
@@ -0,0 +1,13 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "nuclei-operator.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/nuclei-operator/templates/servicemonitor.yaml b/charts/nuclei-operator/templates/servicemonitor.yaml
new file mode 100644
index 0000000..cc071df
--- /dev/null
+++ b/charts/nuclei-operator/templates/servicemonitor.yaml
@@ -0,0 +1,25 @@
+{{- if and .Values.metrics.enabled .Values.serviceMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ include "nuclei-operator.fullname" . }}-metrics-monitor
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "nuclei-operator.labels" . | nindent 4 }}
+ {{- with .Values.serviceMonitor.labels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - path: /metrics
+ port: https
+ scheme: https
+ bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
+ interval: {{ .Values.serviceMonitor.interval }}
+ scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }}
+ tlsConfig:
+ insecureSkipVerify: true
+ selector:
+ matchLabels:
+ {{- include "nuclei-operator.selectorLabels" . | nindent 6 }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/nuclei-operator/values.yaml b/charts/nuclei-operator/values.yaml
new file mode 100644
index 0000000..3bc1e17
--- /dev/null
+++ b/charts/nuclei-operator/values.yaml
@@ -0,0 +1,133 @@
+# Default values for nuclei-operator.
+
+# Number of replicas for the controller manager
+replicaCount: 1
+
+image:
+ # Container image repository
+ repository: ghcr.io/morten-olsen/homelab-nuclei-operator
+ # Image pull policy
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion
+ tag: ""
+
+# Image pull secrets for private registries
+imagePullSecrets: []
+
+# Override the name of the chart
+nameOverride: ""
+# Override the full name of the chart
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+# Pod annotations
+podAnnotations: {}
+
+# Pod labels
+podLabels: {}
+
+# Pod security context
+podSecurityContext:
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+
+# Container security context
+securityContext:
+ readOnlyRootFilesystem: false # Nuclei needs to write temporary files
+ allowPrivilegeEscalation: false
+ runAsNonRoot: true
+ runAsUser: 65532
+ capabilities:
+ drop:
+ - ALL
+
+# Resource limits and requests
+resources:
+ limits:
+ cpu: "2"
+ memory: "2Gi"
+ requests:
+ cpu: "500m"
+ memory: "512Mi"
+
+# Node selector for pod scheduling
+nodeSelector: {}
+
+# Tolerations for pod scheduling
+tolerations: []
+
+# Affinity rules for pod scheduling
+affinity: {}
+
+# Leader election configuration
+leaderElection:
+ enabled: true
+
+# Health probe configuration
+healthProbes:
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: 8081
+ initialDelaySeconds: 15
+ periodSeconds: 20
+ readinessProbe:
+ httpGet:
+ path: /readyz
+ port: 8081
+ initialDelaySeconds: 5
+ periodSeconds: 10
+
+# Metrics configuration
+metrics:
+ # Enable metrics endpoint
+ enabled: true
+ # Service configuration for metrics
+ service:
+ type: ClusterIP
+ port: 8443
+
+# Nuclei scanner configuration
+nuclei:
+ # Path to nuclei binary inside the container
+ binaryPath: "/usr/local/bin/nuclei"
+ # Path to nuclei templates
+ templatesPath: "/nuclei-templates"
+ # Scan timeout duration
+ timeout: "30m"
+ # Rescan age - how old scan results can be before triggering automatic rescan
+ # Set to "0" to disable automatic rescans based on age
+ rescanAge: "168h"
+ # Backoff configuration for target availability checks
+ backoff:
+ # Initial retry interval
+ initial: "10s"
+ # Maximum retry interval
+ max: "10m"
+ # Multiplier for exponential backoff
+ multiplier: "2.0"
+
+# ServiceMonitor for Prometheus Operator
+serviceMonitor:
+ # Enable ServiceMonitor creation
+ enabled: false
+ # Additional labels for the ServiceMonitor
+ labels: {}
+ # Scrape interval
+ interval: 30s
+ # Scrape timeout
+ scrapeTimeout: 10s
+
+# Network policies
+networkPolicy:
+ # Enable network policy
+ enabled: false
\ No newline at end of file