@@ -29,6 +29,8 @@ import (
2929 "github.com/go-logr/logr"
3030 batch "k8s.io/api/batch/v1"
3131 corev1 "k8s.io/api/core/v1"
32+ rbacv1 "k8s.io/api/rbac/v1"
33+ apierrors "k8s.io/apimachinery/pkg/api/errors"
3234 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3335 "k8s.io/apimachinery/pkg/runtime"
3436 "k8s.io/apimachinery/pkg/types"
@@ -58,6 +60,9 @@ type ScanReconciler struct {
5860// +kubebuilder:rbac:groups=scans.experimental.securecodebox.io,resources=parsedefinitions,verbs=get;list;watch
5961// +kubebuilder:rbac:groups=scans.experimental.securecodebox.io,resources=persistenceproviders,verbs=get;list;watch
6062// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete
63+ // +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;watch;create
64+ // +kubebuilder:rbac:groups=rbac,resources=roles,verbs=get;watch;create
65+ // +kubebuilder:rbac:groups=rbac,resources=rolebindings,verbs=get;watch;create
6166
6267// Reconcile compares the scan object against the state of the cluster and updates both if needed
6368func (r * ScanReconciler ) Reconcile (req ctrl.Request ) (ctrl.Result , error ) {
@@ -131,6 +136,20 @@ func (r *ScanReconciler) startScan(scan *scansv1.Scan) error {
131136 }
132137 log .Info ("Matching ScanTemplate Found" , "ScanTemplate" , scanTemplate .Name )
133138
139+ rules := []rbacv1.PolicyRule {
140+ rbacv1.PolicyRule {
141+ APIGroups : []string {"" },
142+ Resources : []string {"pods" },
143+ Verbs : []string {"get" },
144+ },
145+ }
146+ r .EnsureServiceAccountExists (
147+ scan .Namespace ,
148+ "lurcher" ,
149+ "Lurcher is used to extract results from secureCodeBox Scans. It needs rights to get and watch the status of pods to see when the scans have finished." ,
150+ rules ,
151+ )
152+
134153 job , err := r .constructJobForScan (scan , & scanTemplate )
135154 if err != nil {
136155 log .Error (err , "unable to create job object ScanTemplate" )
@@ -238,6 +257,20 @@ func (r *ScanReconciler) startParser(scan *scansv1.Scan) error {
238257 return err
239258 }
240259
260+ rules := []rbacv1.PolicyRule {
261+ rbacv1.PolicyRule {
262+ APIGroups : []string {"scans.experimental.securecodebox.io" },
263+ Resources : []string {"scans" },
264+ Verbs : []string {"get" , "update" },
265+ },
266+ }
267+ r .EnsureServiceAccountExists (
268+ scan .Namespace ,
269+ "parser" ,
270+ "Parser need to access the status of Scans to update how many findings have been identified" ,
271+ rules ,
272+ )
273+
241274 automountServiceAccountToken := false
242275 job := & batch.Job {
243276 ObjectMeta : metav1.ObjectMeta {
@@ -495,6 +528,20 @@ func (r *ScanReconciler) startPersistenceProvider(scan *scansv1.Scan) error {
495528 return nil
496529 }
497530
531+ rules := []rbacv1.PolicyRule {
532+ rbacv1.PolicyRule {
533+ APIGroups : []string {"scans.experimental.securecodebox.io" },
534+ Resources : []string {"scans" },
535+ Verbs : []string {"get" },
536+ },
537+ }
538+ r .EnsureServiceAccountExists (
539+ scan .Namespace ,
540+ "persistence" ,
541+ "PersistenceProvider need to access the current scan to view where its results are stored" ,
542+ rules ,
543+ )
544+
498545 for _ , persistenceProvider := range persistenceProviders .Items {
499546 rawFileURL , err := r .PresignedGetURL (scan .UID , scan .Status .RawResultFile )
500547 if err != nil {
@@ -614,6 +661,93 @@ func (r *ScanReconciler) checkIfPersistingIsCompleted(scan *scansv1.Scan) error
614661 return nil
615662}
616663
664+ func (r * ScanReconciler ) EnsureServiceAccountExists (namespace , serviceAccountName , description string , policyRules []rbacv1.PolicyRule ) error {
665+ ctx := context .Background ()
666+
667+ var serviceAccount corev1.ServiceAccount
668+ err := r .Get (ctx , types.NamespacedName {Name : serviceAccountName , Namespace : namespace }, & serviceAccount )
669+ if apierrors .IsNotFound (err ) {
670+ r .Log .Info ("Service Account doesn't exist creating now" )
671+ serviceAccount = corev1.ServiceAccount {
672+ ObjectMeta : metav1.ObjectMeta {
673+ Name : serviceAccountName ,
674+ Namespace : namespace ,
675+ Annotations : map [string ]string {
676+ "description" : description ,
677+ },
678+ },
679+ }
680+ err := r .Create (ctx , & serviceAccount )
681+ if err != nil {
682+ r .Log .Error (err , "Failed to create ServiceAccount" )
683+ return err
684+ }
685+ } else if err != nil {
686+ r .Log .Error (err , "Unexpected error while checking if a ServiceAccount exists" )
687+ return err
688+ }
689+
690+ var role rbacv1.Role
691+ err = r .Get (ctx , types.NamespacedName {Name : serviceAccountName , Namespace : namespace }, & role )
692+ if apierrors .IsNotFound (err ) {
693+ r .Log .Info ("Role doesn't exist creating now" )
694+ role = rbacv1.Role {
695+ ObjectMeta : metav1.ObjectMeta {
696+ Name : serviceAccountName ,
697+ Namespace : namespace ,
698+ Annotations : map [string ]string {
699+ "description" : description ,
700+ },
701+ },
702+ Rules : policyRules ,
703+ }
704+ err := r .Create (ctx , & role )
705+ if err != nil {
706+ r .Log .Error (err , "Failed to create Role" )
707+ return err
708+ }
709+ } else if err != nil {
710+ r .Log .Error (err , "Unexpected error while checking if a Role exists" )
711+ return err
712+ }
713+
714+ var roleBinding rbacv1.RoleBinding
715+ err = r .Get (ctx , types.NamespacedName {Name : serviceAccountName , Namespace : namespace }, & roleBinding )
716+ if apierrors .IsNotFound (err ) {
717+ r .Log .Info ("RoleBinding doesn't exist creating now" )
718+ roleBinding = rbacv1.RoleBinding {
719+ ObjectMeta : metav1.ObjectMeta {
720+ Name : serviceAccountName ,
721+ Namespace : namespace ,
722+ Annotations : map [string ]string {
723+ "description" : description ,
724+ },
725+ },
726+ Subjects : []rbacv1.Subject {
727+ rbacv1.Subject {
728+ Kind : "ServiceAccount" ,
729+ Name : serviceAccountName ,
730+ },
731+ },
732+ RoleRef : rbacv1.RoleRef {
733+ Kind : "Role" ,
734+ Name : serviceAccountName ,
735+ APIGroup : "rbac.authorization.k8s.io" ,
736+ },
737+ }
738+ err := r .Create (ctx , & roleBinding )
739+ if err != nil {
740+ r .Log .Error (err , "Failed to create RoleBinding" )
741+ return err
742+ }
743+ } else if err != nil {
744+ r .Log .Error (err , "Unexpected error while checking if a RoleBinding exists" )
745+ return err
746+ }
747+
748+ return nil
749+ }
750+
617751// SetupWithManager initializes the controller
618752func (r * ScanReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
619753 endpoint := os .Getenv ("S3_ENDPOINT" )
0 commit comments