Skip to content
This repository was archived by the owner on Oct 14, 2020. It is now read-only.

Commit 6e3f35b

Browse files
committed
Create roles for lurcher, parser and persistenceprovider on the fly
1 parent 0026ffa commit 6e3f35b

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

operator/config/rbac/role.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,30 @@ rules:
1818
- patch
1919
- update
2020
- watch
21+
- apiGroups:
22+
- ""
23+
resources:
24+
- serviceaccounts
25+
verbs:
26+
- create
27+
- get
28+
- watch
29+
- apiGroups:
30+
- rbac
31+
resources:
32+
- rolebindings
33+
verbs:
34+
- create
35+
- get
36+
- watch
37+
- apiGroups:
38+
- rbac
39+
resources:
40+
- roles
41+
verbs:
42+
- create
43+
- get
44+
- watch
2145
- apiGroups:
2246
- scans.experimental.securecodebox.io
2347
resources:

operator/controllers/scan_controller.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
6368
func (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
618752
func (r *ScanReconciler) SetupWithManager(mgr ctrl.Manager) error {
619753
endpoint := os.Getenv("S3_ENDPOINT")

0 commit comments

Comments
 (0)