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:
131
.github/workflows/gh-pages.yml
vendored
Normal file
131
.github/workflows/gh-pages.yml
vendored
Normal file
@@ -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'
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nuclei Operator Helm Repository</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
h1 { color: #333; }
|
||||
code {
|
||||
background: #f4f4f4;
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
pre {
|
||||
background: #f4f4f4;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
a { color: #0066cc; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔬 Nuclei Operator Helm Repository</h1>
|
||||
<p>
|
||||
This is the Helm chart repository for the
|
||||
<a href="https://github.com/morten-olsen/homelab-nuclei-operator">Nuclei Operator</a>.
|
||||
</p>
|
||||
|
||||
<h2>Usage</h2>
|
||||
<p>Add this repository to Helm:</p>
|
||||
<pre><code>helm repo add nuclei-operator https://morten-olsen.github.io/homelab-nuclei-operator
|
||||
helm repo update</code></pre>
|
||||
|
||||
<p>Install the chart:</p>
|
||||
<pre><code>helm install nuclei-operator nuclei-operator/nuclei-operator \
|
||||
--namespace nuclei-operator-system \
|
||||
--create-namespace</code></pre>
|
||||
|
||||
<h2>Available Charts</h2>
|
||||
<ul>
|
||||
<li><strong>nuclei-operator</strong> - A Kubernetes operator that automatically scans Ingress and VirtualService resources using Nuclei security scanner</li>
|
||||
</ul>
|
||||
|
||||
<h2>Links</h2>
|
||||
<ul>
|
||||
<li><a href="https://github.com/morten-olsen/homelab-nuclei-operator">GitHub Repository</a></li>
|
||||
<li><a href="./index.yaml">Helm Repository Index</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
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
|
||||
165
.github/workflows/release.yml
vendored
Normal file
165
.github/workflows/release.yml
vendored
Normal file
@@ -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
|
||||
111
README.md
111
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=<your-registry>/nuclei-operator:tag
|
||||
@@ -72,11 +137,18 @@ make deploy IMG=<your-registry>/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=<your-registry>/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=<your-registry>/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
|
||||
|
||||
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