Files
nuclei-operator/api/v1alpha1/zz_generated.deepcopy.go
Morten Olsen 335689da22 feat: implement pod-based scanning architecture
This major refactor moves from synchronous subprocess-based scanning to
asynchronous pod-based scanning using Kubernetes Jobs.

## Architecture Changes
- Scanner jobs are now Kubernetes Jobs with TTLAfterFinished for automatic cleanup
- Jobs have owner references for garbage collection when NucleiScan is deleted
- Configurable concurrency limits, timeouts, and resource requirements

## New Features
- Dual-mode binary: --mode=controller (default) or --mode=scanner
- Annotation-based configuration for Ingress/VirtualService resources
- Operator-level configuration via environment variables
- Startup recovery for orphaned scans after operator restart
- Periodic cleanup of stuck jobs

## New Files
- DESIGN.md: Comprehensive architecture design document
- internal/jobmanager/: Job Manager for creating/monitoring scanner jobs
- internal/scanner/runner.go: Scanner mode implementation
- internal/annotations/: Annotation parsing utilities
- charts/nuclei-operator/templates/scanner-rbac.yaml: Scanner RBAC

## API Changes
- Added ScannerConfig struct for per-scan scanner configuration
- Added JobReference struct for tracking scanner jobs
- Added ScannerConfig field to NucleiScanSpec
- Added JobRef and ScanStartTime fields to NucleiScanStatus

## Supported Annotations
- nuclei.homelab.mortenolsen.pro/enabled
- nuclei.homelab.mortenolsen.pro/templates
- nuclei.homelab.mortenolsen.pro/severity
- nuclei.homelab.mortenolsen.pro/schedule
- nuclei.homelab.mortenolsen.pro/timeout
- nuclei.homelab.mortenolsen.pro/scanner-image

## RBAC Updates
- Added Job and Pod permissions for operator
- Created separate scanner service account with minimal permissions

## Documentation
- Updated README, user-guide, api.md, and Helm chart README
- Added example annotated Ingress resources
2025-12-12 20:51:23 +01:00

318 lines
8.6 KiB
Go

//go:build !ignore_autogenerated
/*
Copyright 2025.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
import (
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Finding) DeepCopyInto(out *Finding) {
*out = *in
if in.ExtractedResults != nil {
in, out := &in.ExtractedResults, &out.ExtractedResults
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Reference != nil {
in, out := &in.Reference, &out.Reference
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
*out = make([]string, len(*in))
copy(*out, *in)
}
in.Timestamp.DeepCopyInto(&out.Timestamp)
if in.Metadata != nil {
in, out := &in.Metadata, &out.Metadata
*out = new(runtime.RawExtension)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Finding.
func (in *Finding) DeepCopy() *Finding {
if in == nil {
return nil
}
out := new(Finding)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JobReference) DeepCopyInto(out *JobReference) {
*out = *in
if in.StartTime != nil {
in, out := &in.StartTime, &out.StartTime
*out = (*in).DeepCopy()
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JobReference.
func (in *JobReference) DeepCopy() *JobReference {
if in == nil {
return nil
}
out := new(JobReference)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NucleiScan) DeepCopyInto(out *NucleiScan) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NucleiScan.
func (in *NucleiScan) DeepCopy() *NucleiScan {
if in == nil {
return nil
}
out := new(NucleiScan)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *NucleiScan) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NucleiScanList) DeepCopyInto(out *NucleiScanList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]NucleiScan, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NucleiScanList.
func (in *NucleiScanList) DeepCopy() *NucleiScanList {
if in == nil {
return nil
}
out := new(NucleiScanList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *NucleiScanList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NucleiScanSpec) DeepCopyInto(out *NucleiScanSpec) {
*out = *in
out.SourceRef = in.SourceRef
if in.Targets != nil {
in, out := &in.Targets, &out.Targets
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Templates != nil {
in, out := &in.Templates, &out.Templates
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Severity != nil {
in, out := &in.Severity, &out.Severity
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ScannerConfig != nil {
in, out := &in.ScannerConfig, &out.ScannerConfig
*out = new(ScannerConfig)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NucleiScanSpec.
func (in *NucleiScanSpec) DeepCopy() *NucleiScanSpec {
if in == nil {
return nil
}
out := new(NucleiScanSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NucleiScanStatus) DeepCopyInto(out *NucleiScanStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]metav1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.LastScanTime != nil {
in, out := &in.LastScanTime, &out.LastScanTime
*out = (*in).DeepCopy()
}
if in.CompletionTime != nil {
in, out := &in.CompletionTime, &out.CompletionTime
*out = (*in).DeepCopy()
}
if in.NextScheduledTime != nil {
in, out := &in.NextScheduledTime, &out.NextScheduledTime
*out = (*in).DeepCopy()
}
if in.Summary != nil {
in, out := &in.Summary, &out.Summary
*out = new(ScanSummary)
(*in).DeepCopyInto(*out)
}
if in.Findings != nil {
in, out := &in.Findings, &out.Findings
*out = make([]Finding, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.LastRetryTime != nil {
in, out := &in.LastRetryTime, &out.LastRetryTime
*out = (*in).DeepCopy()
}
if in.JobRef != nil {
in, out := &in.JobRef, &out.JobRef
*out = new(JobReference)
(*in).DeepCopyInto(*out)
}
if in.ScanStartTime != nil {
in, out := &in.ScanStartTime, &out.ScanStartTime
*out = (*in).DeepCopy()
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NucleiScanStatus.
func (in *NucleiScanStatus) DeepCopy() *NucleiScanStatus {
if in == nil {
return nil
}
out := new(NucleiScanStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ScanSummary) DeepCopyInto(out *ScanSummary) {
*out = *in
if in.FindingsBySeverity != nil {
in, out := &in.FindingsBySeverity, &out.FindingsBySeverity
*out = make(map[string]int, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScanSummary.
func (in *ScanSummary) DeepCopy() *ScanSummary {
if in == nil {
return nil
}
out := new(ScanSummary)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ScannerConfig) DeepCopyInto(out *ScannerConfig) {
*out = *in
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = new(v1.ResourceRequirements)
(*in).DeepCopyInto(*out)
}
if in.Timeout != nil {
in, out := &in.Timeout, &out.Timeout
*out = new(metav1.Duration)
**out = **in
}
if in.TemplateURLs != nil {
in, out := &in.TemplateURLs, &out.TemplateURLs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Tolerations != nil {
in, out := &in.Tolerations, &out.Tolerations
*out = make([]v1.Toleration, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScannerConfig.
func (in *ScannerConfig) DeepCopy() *ScannerConfig {
if in == nil {
return nil
}
out := new(ScannerConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SourceReference) DeepCopyInto(out *SourceReference) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceReference.
func (in *SourceReference) DeepCopy() *SourceReference {
if in == nil {
return nil
}
out := new(SourceReference)
in.DeepCopyInto(out)
return out
}