/
setup.go
112 lines (103 loc) · 3.5 KB
/
setup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package reconcilers
import (
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/tinyzimmer/vault-rbac-controller/internal/vault"
)
// Options are the options for configuring the reconcilers.
type Options struct {
AuthMount string
Namespaces []string
ExcludeNamespaces []string
IncludeSystemNamespaces bool
UseFinalizers bool
}
// SetupWithManager sets up all reconcilers with the given manager.
func SetupWithManager(mgr ctrl.Manager, opts *Options) error {
policies := vault.NewPolicyManager()
roles := vault.NewRoleManager(opts.AuthMount)
recorder := mgr.GetEventRecorderFor("vault-rbac-controller")
roleReconciler := &RoleReconciler{
Client: mgr.GetClient(),
recorder: recorder,
policies: policies,
useFinalizers: opts.UseFinalizers,
}
rbReconciler := &RoleBindingReconciler{
Client: mgr.GetClient(),
recorder: recorder,
policies: policies,
roles: roles,
useFinalizers: opts.UseFinalizers,
}
saReconciler := &ServiceAccountReconciler{
Client: mgr.GetClient(),
recorder: recorder,
policies: policies,
roles: roles,
useFinalizers: opts.UseFinalizers,
}
eventFilter := checkNamespacesPredicate(opts.Namespaces, opts.ExcludeNamespaces, opts.IncludeSystemNamespaces)
for reconciler, builder := range map[reconcile.Reconciler]*builder.Builder{
roleReconciler: ctrl.NewControllerManagedBy(mgr).
For(&rbacv1.Role{}).
WithEventFilter(eventFilter),
rbReconciler: ctrl.NewControllerManagedBy(mgr).
For(&rbacv1.RoleBinding{}).
WithEventFilter(eventFilter),
saReconciler: ctrl.NewControllerManagedBy(mgr).
For(&corev1.ServiceAccount{}).
WithEventFilter(eventFilter),
} {
if err := builder.Complete(reconciler); err != nil {
return err
}
}
return nil
}
func checkNamespacesPredicate(namespaces []string, excludeNamespaces []string, includeKubeSystem bool) predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return checkObject(e.Object, namespaces, excludeNamespaces, includeKubeSystem)
},
DeleteFunc: func(e event.DeleteEvent) bool {
return checkObject(e.Object, namespaces, excludeNamespaces, includeKubeSystem)
},
UpdateFunc: func(e event.UpdateEvent) bool {
return checkObject(e.ObjectNew, namespaces, excludeNamespaces, includeKubeSystem)
},
GenericFunc: func(e event.GenericEvent) bool {
return checkObject(e.Object, namespaces, excludeNamespaces, includeKubeSystem)
},
}
}
func checkObject(obj client.Object, namespaces []string, excludeNamespaces []string, includeKubeSystem bool) bool {
ns := obj.GetNamespace()
if !includeKubeSystem && isSystemNamespace(ns) {
return false
}
return (len(namespaces) == 0 || contains(namespaces, ns)) &&
!contains(excludeNamespaces, ns)
}
func isSystemNamespace(ns string) bool {
return ns == "kube-system" || ns == "kube-public" || ns == "kube-node-lease"
}
func contains[T comparable](s []T, e T) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}