2022-11-14 12:00:40 +01:00
package main
2022-11-14 18:30:12 +01:00
import (
2022-12-12 19:39:29 +01:00
"context"
"errors"
2022-12-07 11:30:47 +01:00
"flag"
2022-11-14 18:30:12 +01:00
"os"
2022-11-25 15:29:45 +05:30
"sync"
2022-11-14 18:30:12 +01:00
"time"
2023-08-02 20:17:40 +05:30
"github.com/kyverno/kyverno/api/kyverno"
2023-08-03 06:48:10 +02:00
policyhandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/admission/policy"
resourcehandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/admission/resource"
2022-12-07 11:30:47 +01:00
cleanuphandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/cleanup"
2022-11-18 15:21:15 +01:00
"github.com/kyverno/kyverno/cmd/internal"
2022-11-25 15:29:45 +05:30
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
2022-11-14 18:30:12 +01:00
"github.com/kyverno/kyverno/pkg/config"
2022-12-13 16:43:17 +01:00
"github.com/kyverno/kyverno/pkg/controllers/certmanager"
2022-11-25 15:29:45 +05:30
"github.com/kyverno/kyverno/pkg/controllers/cleanup"
2023-03-16 18:17:21 +01:00
genericloggingcontroller "github.com/kyverno/kyverno/pkg/controllers/generic/logging"
2022-12-22 07:13:32 +01:00
genericwebhookcontroller "github.com/kyverno/kyverno/pkg/controllers/generic/webhook"
2023-08-02 18:24:26 +02:00
ttlcontroller "github.com/kyverno/kyverno/pkg/controllers/ttl"
2023-07-18 13:01:09 +03:00
"github.com/kyverno/kyverno/pkg/event"
2023-06-22 14:14:53 +02:00
"github.com/kyverno/kyverno/pkg/informers"
2022-12-12 19:39:29 +01:00
"github.com/kyverno/kyverno/pkg/leaderelection"
2023-07-18 13:01:09 +03:00
"github.com/kyverno/kyverno/pkg/logging"
2022-12-12 19:39:29 +01:00
"github.com/kyverno/kyverno/pkg/tls"
2022-12-09 18:12:37 +01:00
"github.com/kyverno/kyverno/pkg/webhooks"
2022-12-22 07:13:32 +01:00
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
2022-11-14 18:30:12 +01:00
corev1 "k8s.io/api/core/v1"
2023-08-02 20:17:40 +05:30
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2022-11-14 18:30:12 +01:00
kubeinformers "k8s.io/client-go/informers"
)
const (
2023-08-02 20:17:40 +05:30
resyncPeriod = 15 * time . Minute
webhookWorkers = 2
policyWebhookControllerName = "policy-webhook-controller"
ttlWebhookControllerName = "ttl-webhook-controller"
2022-11-14 18:30:12 +01:00
)
2023-08-28 16:05:49 +02:00
var (
caSecretName string
tlsSecretName string
)
2022-12-09 18:12:37 +01:00
// TODO:
2022-12-12 19:39:29 +01:00
// - helm review labels / selectors
2022-12-09 18:12:37 +01:00
// - implement probes
// - supports certs in cronjob
type probes struct { }
2023-06-21 15:35:43 +02:00
func ( probes ) IsReady ( context . Context ) bool {
2022-12-09 18:12:37 +01:00
return true
}
2023-06-21 15:35:43 +02:00
func ( probes ) IsLive ( context . Context ) bool {
2022-12-09 18:12:37 +01:00
return true
}
2022-11-14 12:00:40 +01:00
func main ( ) {
2022-12-09 18:12:37 +01:00
var (
2023-07-18 13:01:09 +03:00
dumpPayload bool
serverIP string
servicePort int
maxQueuedEvents int
2023-08-02 20:17:40 +05:30
interval time . Duration
2022-12-09 18:12:37 +01:00
)
2022-12-07 11:30:47 +01:00
flagset := flag . NewFlagSet ( "cleanup-controller" , flag . ExitOnError )
2022-12-09 18:12:37 +01:00
flagset . BoolVar ( & dumpPayload , "dumpPayload" , false , "Set this flag to activate/deactivate debug mode." )
2022-12-22 07:13:32 +01:00
flagset . StringVar ( & serverIP , "serverIP" , "" , "IP address where Kyverno controller runs. Only required if out-of-cluster." )
2023-01-29 00:54:29 +01:00
flagset . IntVar ( & servicePort , "servicePort" , 443 , "Port used by the Kyverno Service resource and for webhook configurations." )
2023-07-18 13:01:09 +03:00
flagset . IntVar ( & maxQueuedEvents , "maxQueuedEvents" , 1000 , "Maximum events to be queued." )
2023-08-02 20:17:40 +05:30
flagset . DurationVar ( & interval , "ttlReconciliationInterval" , time . Minute , "Set this flag to set the interval after which the resource controller reconciliation should occur" )
2023-08-28 16:05:49 +02:00
flagset . StringVar ( & caSecretName , "caSecretName" , "" , "Name of the secret containing CA." )
flagset . StringVar ( & tlsSecretName , "tlsSecretName" , "" , "Name of the secret containing TLS pair." )
2022-11-18 15:21:15 +01:00
// config
2022-11-23 11:36:15 +01:00
appConfig := internal . NewConfiguration (
internal . WithProfiling ( ) ,
2022-11-29 10:16:07 +01:00
internal . WithMetrics ( ) ,
2022-11-23 11:36:15 +01:00
internal . WithTracing ( ) ,
internal . WithKubeconfig ( ) ,
2023-04-11 19:44:49 +02:00
internal . WithLeaderElection ( ) ,
2023-04-14 11:00:52 +02:00
internal . WithKyvernoClient ( ) ,
internal . WithKyvernoDynamicClient ( ) ,
2023-06-26 16:57:23 +02:00
internal . WithConfigMapCaching ( ) ,
2023-06-27 07:44:15 +02:00
internal . WithDeferredLoading ( ) ,
2023-08-02 20:17:40 +05:30
internal . WithMetadataClient ( ) ,
2023-08-28 16:05:49 +02:00
internal . WithFlagSets ( flagset ) ,
2022-11-23 11:36:15 +01:00
)
2022-11-14 18:30:12 +01:00
// parse flags
2022-11-24 20:57:01 +01:00
internal . ParseFlags ( appConfig )
2023-04-11 15:32:17 +02:00
// setup
ctx , setup , sdown := internal . Setup ( appConfig , "kyverno-cleanup-controller" , false )
2022-11-29 10:16:07 +01:00
defer sdown ( )
2023-06-22 14:14:53 +02:00
// certificates informers
2023-08-28 16:05:49 +02:00
caSecret := informers . NewSecretInformer ( setup . KubeClient , config . KyvernoNamespace ( ) , caSecretName , resyncPeriod )
tlsSecret := informers . NewSecretInformer ( setup . KubeClient , config . KyvernoNamespace ( ) , tlsSecretName , resyncPeriod )
2023-06-22 14:14:53 +02:00
if ! informers . StartInformersAndWaitForCacheSync ( ctx , setup . Logger , caSecret , tlsSecret ) {
setup . Logger . Error ( errors . New ( "failed to wait for cache sync" ) , "failed to wait for cache sync" )
os . Exit ( 1 )
}
2022-12-12 19:39:29 +01:00
// setup leader election
le , err := leaderelection . New (
2023-04-11 14:05:20 +02:00
setup . Logger . WithName ( "leader-election" ) ,
2022-12-12 19:39:29 +01:00
"kyverno-cleanup-controller" ,
config . KyvernoNamespace ( ) ,
2023-04-11 19:44:49 +02:00
setup . LeaderElectionClient ,
2022-12-12 19:39:29 +01:00
config . KyvernoPodName ( ) ,
2023-04-11 19:44:49 +02:00
internal . LeaderElectionRetryPeriod ( ) ,
2022-12-12 19:39:29 +01:00
func ( ctx context . Context ) {
2023-04-11 14:05:20 +02:00
logger := setup . Logger . WithName ( "leader" )
2022-12-12 19:39:29 +01:00
// informer factories
2023-04-11 14:05:20 +02:00
kubeInformer := kubeinformers . NewSharedInformerFactoryWithOptions ( setup . KubeClient , resyncPeriod )
2023-04-14 11:00:52 +02:00
kyvernoInformer := kyvernoinformer . NewSharedInformerFactory ( setup . KyvernoClient , resyncPeriod )
2022-12-12 19:39:29 +01:00
// controllers
2022-12-13 16:43:17 +01:00
renewer := tls . NewCertRenewer (
2023-04-11 14:05:20 +02:00
setup . KubeClient . CoreV1 ( ) . Secrets ( config . KyvernoNamespace ( ) ) ,
2022-12-13 16:43:17 +01:00
tls . CertRenewalInterval ,
tls . CAValidityDuration ,
tls . TLSValidityDuration ,
2023-04-25 12:50:46 +02:00
serverIP ,
2023-08-25 13:24:52 +02:00
config . KyvernoServiceName ( ) ,
2023-08-28 17:34:37 +05:30
config . DnsNames ( config . KyvernoServiceName ( ) , config . KyvernoNamespace ( ) ) ,
2023-08-25 13:24:52 +02:00
config . KyvernoNamespace ( ) ,
2023-08-28 16:05:49 +02:00
caSecretName ,
tlsSecretName ,
2022-12-13 16:43:17 +01:00
)
certController := internal . NewController (
certmanager . ControllerName ,
certmanager . NewController (
2023-06-22 14:14:53 +02:00
caSecret ,
tlsSecret ,
2022-12-13 16:43:17 +01:00
renewer ,
2023-08-28 16:05:49 +02:00
caSecretName ,
tlsSecretName ,
2023-08-28 17:34:37 +05:30
config . KyvernoNamespace ( ) ,
2022-12-13 16:43:17 +01:00
) ,
certmanager . Workers ,
)
2023-08-02 20:17:40 +05:30
policyValidatingWebhookController := internal . NewController (
policyWebhookControllerName ,
2022-12-22 07:13:32 +01:00
genericwebhookcontroller . NewController (
2023-08-02 20:17:40 +05:30
policyWebhookControllerName ,
2023-04-11 14:05:20 +02:00
setup . KubeClient . AdmissionregistrationV1 ( ) . ValidatingWebhookConfigurations ( ) ,
2022-12-13 16:43:17 +01:00
kubeInformer . Admissionregistration ( ) . V1 ( ) . ValidatingWebhookConfigurations ( ) ,
2023-06-22 14:14:53 +02:00
caSecret ,
2022-12-22 07:13:32 +01:00
config . CleanupValidatingWebhookConfigurationName ,
config . CleanupValidatingWebhookServicePath ,
serverIP ,
2023-01-29 00:54:29 +01:00
int32 ( servicePort ) ,
2023-08-02 20:17:40 +05:30
nil ,
[ ] admissionregistrationv1 . RuleWithOperations {
{
Rule : admissionregistrationv1 . Rule {
APIGroups : [ ] string { "kyverno.io" } ,
APIVersions : [ ] string { "v2alpha1" } ,
Resources : [ ] string {
"cleanuppolicies/*" ,
"clustercleanuppolicies/*" ,
} ,
} ,
Operations : [ ] admissionregistrationv1 . OperationType {
admissionregistrationv1 . Create ,
admissionregistrationv1 . Update ,
2022-12-22 07:13:32 +01:00
} ,
} ,
2023-08-02 20:17:40 +05:30
} ,
2022-12-22 07:13:32 +01:00
genericwebhookcontroller . Fail ,
genericwebhookcontroller . None ,
2023-04-11 14:05:20 +02:00
setup . Configuration ,
2023-08-28 16:05:49 +02:00
caSecretName ,
2022-12-13 16:43:17 +01:00
) ,
2022-12-22 07:13:32 +01:00
webhookWorkers ,
2022-12-13 16:43:17 +01:00
)
2023-08-02 20:17:40 +05:30
ttlWebhookController := internal . NewController (
ttlWebhookControllerName ,
genericwebhookcontroller . NewController (
ttlWebhookControllerName ,
setup . KubeClient . AdmissionregistrationV1 ( ) . ValidatingWebhookConfigurations ( ) ,
kubeInformer . Admissionregistration ( ) . V1 ( ) . ValidatingWebhookConfigurations ( ) ,
caSecret ,
config . TtlValidatingWebhookConfigurationName ,
config . TtlValidatingWebhookServicePath ,
serverIP ,
int32 ( servicePort ) ,
& metav1 . LabelSelector {
MatchExpressions : [ ] metav1 . LabelSelectorRequirement {
{
Key : kyverno . LabelCleanupTtl ,
Operator : metav1 . LabelSelectorOpExists ,
} ,
} ,
} ,
[ ] admissionregistrationv1 . RuleWithOperations {
{
Rule : admissionregistrationv1 . Rule {
APIGroups : [ ] string { "*" } ,
APIVersions : [ ] string { "*" } ,
Resources : [ ] string { "*" } ,
} ,
Operations : [ ] admissionregistrationv1 . OperationType {
admissionregistrationv1 . Create ,
admissionregistrationv1 . Update ,
} ,
} ,
} ,
genericwebhookcontroller . Ignore ,
genericwebhookcontroller . None ,
setup . Configuration ,
2023-08-28 16:05:49 +02:00
caSecretName ,
2023-08-02 20:17:40 +05:30
) ,
webhookWorkers ,
)
2022-12-13 16:43:17 +01:00
cleanupController := internal . NewController (
2022-12-12 19:39:29 +01:00
cleanup . ControllerName ,
cleanup . NewController (
2023-04-11 14:05:20 +02:00
setup . KubeClient ,
2022-12-12 19:39:29 +01:00
kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . ClusterCleanupPolicies ( ) ,
kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . CleanupPolicies ( ) ,
kubeInformer . Batch ( ) . V1 ( ) . CronJobs ( ) ,
"https://" + config . KyvernoServiceName ( ) + "." + config . KyvernoNamespace ( ) + ".svc" ,
) ,
cleanup . Workers ,
)
2023-08-02 20:17:40 +05:30
ttlManagerController := internal . NewController (
ttlcontroller . ControllerName ,
ttlcontroller . NewManager (
setup . MetadataClient ,
setup . KubeClient . Discovery ( ) ,
setup . KubeClient . AuthorizationV1 ( ) ,
interval ,
) ,
ttlcontroller . Workers ,
)
2022-12-12 19:39:29 +01:00
// start informers and wait for cache sync
2023-06-22 14:14:53 +02:00
if ! internal . StartInformersAndWaitForCacheSync ( ctx , logger , kyvernoInformer , kubeInformer ) {
2022-12-12 19:39:29 +01:00
logger . Error ( errors . New ( "failed to wait for cache sync" ) , "failed to wait for cache sync" )
os . Exit ( 1 )
}
// start leader controllers
var wg sync . WaitGroup
2022-12-13 16:43:17 +01:00
certController . Run ( ctx , logger , & wg )
2023-08-02 20:17:40 +05:30
policyValidatingWebhookController . Run ( ctx , logger , & wg )
ttlWebhookController . Run ( ctx , logger , & wg )
2022-12-13 16:43:17 +01:00
cleanupController . Run ( ctx , logger , & wg )
2023-08-02 20:17:40 +05:30
ttlManagerController . Run ( ctx , logger , & wg )
2022-12-12 19:39:29 +01:00
wg . Wait ( )
} ,
nil ,
)
if err != nil {
2023-04-11 14:05:20 +02:00
setup . Logger . Error ( err , "failed to initialize leader election" )
2022-12-12 19:39:29 +01:00
os . Exit ( 1 )
}
2022-11-29 10:16:07 +01:00
// informer factories
2023-04-11 14:05:20 +02:00
kubeInformer := kubeinformers . NewSharedInformerFactoryWithOptions ( setup . KubeClient , resyncPeriod )
2023-04-14 11:00:52 +02:00
kyvernoInformer := kyvernoinformer . NewSharedInformerFactory ( setup . KyvernoClient , resyncPeriod )
2022-12-12 19:39:29 +01:00
// listers
2022-12-08 12:45:47 +01:00
cpolLister := kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . ClusterCleanupPolicies ( ) . Lister ( )
polLister := kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . CleanupPolicies ( ) . Lister ( )
2022-12-08 11:31:28 +01:00
nsLister := kubeInformer . Core ( ) . V1 ( ) . Namespaces ( ) . Lister ( )
2023-03-16 18:17:21 +01:00
// log policy changes
genericloggingcontroller . NewController (
2023-04-11 14:05:20 +02:00
setup . Logger . WithName ( "cleanup-policy" ) ,
2023-03-16 18:17:21 +01:00
"CleanupPolicy" ,
kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . CleanupPolicies ( ) ,
genericloggingcontroller . CheckGeneration ,
)
genericloggingcontroller . NewController (
2023-04-11 14:05:20 +02:00
setup . Logger . WithName ( "cluster-cleanup-policy" ) ,
2023-03-16 18:17:21 +01:00
"ClusterCleanupPolicy" ,
kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . ClusterCleanupPolicies ( ) ,
genericloggingcontroller . CheckGeneration ,
)
2023-07-18 13:01:09 +03:00
eventGenerator := event . NewEventCleanupGenerator (
setup . KyvernoDynamicClient ,
kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . ClusterCleanupPolicies ( ) ,
kyvernoInformer . Kyverno ( ) . V2alpha1 ( ) . CleanupPolicies ( ) ,
maxQueuedEvents ,
logging . WithName ( "EventGenerator" ) ,
)
2022-11-16 18:41:33 +05:30
// start informers and wait for cache sync
2023-06-22 14:14:53 +02:00
if ! internal . StartInformersAndWaitForCacheSync ( ctx , setup . Logger , kubeInformer , kyvernoInformer ) {
2022-11-16 18:41:33 +05:30
os . Exit ( 1 )
}
2023-07-18 13:01:09 +03:00
// start event generator
var wg sync . WaitGroup
go eventGenerator . Run ( ctx , 3 , & wg )
2022-12-07 11:30:47 +01:00
// create handlers
2023-08-03 06:48:10 +02:00
admissionHandlers := policyhandlers . New ( setup . KyvernoDynamicClient )
2023-06-26 16:57:23 +02:00
cmResolver := internal . NewConfigMapResolver ( ctx , setup . Logger , setup . KubeClient , resyncPeriod )
cleanupHandlers := cleanuphandlers . New (
setup . Logger . WithName ( "cleanup-handler" ) ,
setup . KyvernoDynamicClient ,
cpolLister ,
polLister ,
nsLister ,
cmResolver ,
setup . Jp ,
2023-07-18 13:01:09 +03:00
eventGenerator ,
2023-06-26 16:57:23 +02:00
)
2022-12-07 11:30:47 +01:00
// create server
2022-11-14 18:30:12 +01:00
server := NewServer (
func ( ) ( [ ] byte , [ ] byte , error ) {
2023-08-28 16:05:49 +02:00
secret , err := tlsSecret . Lister ( ) . Secrets ( config . KyvernoNamespace ( ) ) . Get ( tlsSecretName )
2022-11-14 18:30:12 +01:00
if err != nil {
return nil , nil , err
}
return secret . Data [ corev1 . TLSCertKey ] , secret . Data [ corev1 . TLSPrivateKeyKey ] , nil
} ,
2022-12-07 11:30:47 +01:00
admissionHandlers . Validate ,
2023-08-03 06:48:10 +02:00
resourcehandlers . Validate ,
2022-12-07 11:30:47 +01:00
cleanupHandlers . Cleanup ,
2023-04-11 14:05:20 +02:00
setup . MetricsManager ,
2022-12-09 18:12:37 +01:00
webhooks . DebugModeOptions {
DumpPayload : dumpPayload ,
} ,
probes { } ,
2023-04-11 14:05:20 +02:00
setup . Configuration ,
2022-11-14 18:30:12 +01:00
)
2022-12-07 11:30:47 +01:00
// start server
2022-11-24 20:57:01 +01:00
server . Run ( ctx . Done ( ) )
2023-04-03 17:17:44 +02:00
// start leader election
le . Run ( ctx )
2022-11-14 12:00:40 +01:00
}