mirror of
https://github.com/morten-olsen/homelab-nuclei-operator.git
synced 2026-02-08 02:16:23 +01:00
ci: add helm and publish
This commit is contained in:
23
charts/nuclei-operator/.helmignore
Normal file
23
charts/nuclei-operator/.helmignore
Normal file
@@ -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/
|
||||
21
charts/nuclei-operator/Chart.yaml
Normal file
21
charts/nuclei-operator/Chart.yaml
Normal file
@@ -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"
|
||||
233
charts/nuclei-operator/README.md
Normal file
233
charts/nuclei-operator/README.md
Normal file
@@ -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)
|
||||
44
charts/nuclei-operator/templates/NOTES.txt
Normal file
44
charts/nuclei-operator/templates/NOTES.txt
Normal file
@@ -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: <ingress-uid>
|
||||
targets:
|
||||
- https://example.com
|
||||
|
||||
To view scan results:
|
||||
|
||||
$ kubectl get nucleiscans -A
|
||||
$ kubectl describe nucleiscan <scan-name>
|
||||
|
||||
{{- 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
|
||||
71
charts/nuclei-operator/templates/_helpers.tpl
Normal file
71
charts/nuclei-operator/templates/_helpers.tpl
Normal file
@@ -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 }}
|
||||
322
charts/nuclei-operator/templates/crds/nucleiscan-crd.yaml
Normal file
322
charts/nuclei-operator/templates/crds/nucleiscan-crd.yaml
Normal file
@@ -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: {}
|
||||
99
charts/nuclei-operator/templates/deployment.yaml
Normal file
99
charts/nuclei-operator/templates/deployment.yaml
Normal file
@@ -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
|
||||
18
charts/nuclei-operator/templates/metrics-service.yaml
Normal file
18
charts/nuclei-operator/templates/metrics-service.yaml
Normal file
@@ -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 }}
|
||||
192
charts/nuclei-operator/templates/rbac.yaml
Normal file
192
charts/nuclei-operator/templates/rbac.yaml
Normal file
@@ -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 }}
|
||||
13
charts/nuclei-operator/templates/serviceaccount.yaml
Normal file
13
charts/nuclei-operator/templates/serviceaccount.yaml
Normal file
@@ -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 }}
|
||||
25
charts/nuclei-operator/templates/servicemonitor.yaml
Normal file
25
charts/nuclei-operator/templates/servicemonitor.yaml
Normal file
@@ -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 }}
|
||||
133
charts/nuclei-operator/values.yaml
Normal file
133
charts/nuclei-operator/values.yaml
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user